Jump to content

Fr0sT.Brutal

Members
  • Content Count

    2268
  • Joined

  • Last visited

  • Days Won

    46

Everything posted by Fr0sT.Brutal

  1. TLineReader will help. Or old-school ReadLn
  2. Fr0sT.Brutal

    VM and Legacy apps

    VirtualBox is my choice
  3. Fr0sT.Brutal

    moving a class implementation from desktop to server

    I've never did things like these but I'd start with wrapping the methods into some abstract class keeping in mind it could be of any nature. In your example, that TDataset wrapper shouldn't rely on sync behavior to incorporate async REST requests later (you unlikely want to have sync REST requests). Or it could leave async things for the caller app. Anyway that's what the whole encapsulation and module division is about - have the single function call and don't care what's inside.
  4. Playing with ReturnAddress I discovered that it will be pretty easy to implement retrieval of name of an object's method without any RTTI or debug info. Could be useful for logging. Alas, it relies on class layout internals but that's the only way to do. Code bases on TObject.MethodAddress // Get address of currently executed code function GetCurrentAddress: Pointer; begin Result := ReturnAddress; end; // Get name of class method that contains the given address. // Note that it has to utilize some internals function GetMethodName(AClass: TClass; Address: Pointer): string; overload; type // copy declaration from System's impl section PMethRec = ^MethRec; MethRec = packed record recSize: Word; methAddr: Pointer; nameLen: Byte; { nameChars[nameLen]: AnsiChar } end; var LMethTablePtr: Pointer; LMethCount: Word; LMethEntry, LResultMethEntry: PMethRec; begin Result := ''; { Obtain the method table and count } LMethTablePtr := PPointer(PByte(AClass) + vmtMethodTable)^; if LMethTablePtr = nil then // no methods... Exit; LMethCount := PWord(LMethTablePtr)^; if LMethCount = 0 then // no methods... Exit; Inc(PWord(LMethTablePtr)); // Get all method entries and find max method entry addr that is less (or equal - very unlikely tho) than Address LMethEntry := LMethTablePtr; LResultMethEntry := nil; while LMethCount > 0 do begin // Only consider methods starting before the Address if PByte(LMethEntry.methAddr) <= PByte(Address) then begin // Not assigned yet if (LResultMethEntry = nil) or // Current entry is closer to Address, reassign the variable (PByte(LMethEntry.methAddr) > PByte(LResultMethEntry.methAddr)) then LResultMethEntry := LMethEntry; end; Dec(LMethCount); LMethEntry := Pointer(PByte(LMethEntry) + LMethEntry.recSize); // get next end; if LResultMethEntry <> nil then Result := string(PShortString(@LResultMethEntry.nameLen)^); end; // Get name of object's method that contains the given address function GetMethodName(AObject: TObject; Address: Pointer): string; overload; begin Result := GetMethodName(AObject.ClassType, Address); end; Test cases: program Project2; {$APPTYPE CONSOLE} {$R *.res} type TBaseClass = class procedure method; virtual; end; TTestClass = class(TBaseClass) procedure foo; procedure method; override; procedure method1; inline; procedure bar; class procedure classMethod; end; procedure TBaseClass.method; begin end; procedure TTestClass.method; var s: string; begin Assert(GetMethodName(Self, GetCurrentAddress) = 'method', 'override'); // do some stuff to get another address str(123, s); Assert(GetMethodName(Self, GetCurrentAddress) = 'method', 'override'); end; procedure TTestClass.foo; begin Assert(GetMethodName(Self, GetCurrentAddress) = 'foo', 'usual - 1st'); end; procedure TTestClass.bar; begin Assert(GetMethodName(Self, GetCurrentAddress) = 'bar', 'usual - last'); end; procedure TTestClass.method1; begin Assert(GetMethodName(Self, GetCurrentAddress) <> 'method1', 'inline'); end; class procedure TTestClass.classMethod; begin Assert(GetMethodName(Self, GetCurrentAddress) = 'classMethod', 'class method'); end; var cl: TTestClass; begin cl := TTestClass.Create; cl.foo; cl.method; cl.method1; // ! inlined methods won't be detected ! cl.bar; cl.classMethod; TTestClass.classMethod; Writeln('All tests OK'); readln; end.
  5. Fr0sT.Brutal

    Get method's name as string from the code inside that method

    No idea currently but I'll take a look
  6. Fr0sT.Brutal

    Get method's name as string from the code inside that method

    Glad to help! Check out this topic for MAP file reader routines
  7. Fr0sT.Brutal

    Get method's name as string from the code inside that method

    Sure Addresses in MAP file are given as offsets to segments
  8. Fr0sT.Brutal

    Get method's name as string from the code inside that method

    Not exactly. They're = published when compiled with typeinfo, otherwise = public
  9. Fr0sT.Brutal

    Get method's name as string from the code inside that method

    Compile the class with {M+} option. Sorry to misinform, I must have had type info in my project option enabled so I thought this works by default. Actually this will work for published members and for public members if a class is compiled inside {$M+} (== TYPEINFO ON) directive. For other members, as Anders said, MAP file or debug info should be used
  10. Fr0sT.Brutal

    Zeos on Delphi 11.2

    Updating a library used by some 3rd party software mostly turns out to be bad idea. In theory this should allow getting updates and patches independently from vendor but in fact libs tend to ignore backward compatibility (not saying any names but it is you, OpenSSL). And a host app could be using some quirks that become non-actual in newer lib versions. So this is the highway to DLL hell. Look at MSVCR, you have to keep all major versions of this crap just to run a wide range of software.
  11. Fr0sT.Brutal

    Zeos on Delphi 11.2

    That's religious question and so discussions are useless. There are pro's and contra's for both options, however I'm the fan of portable self-sufficient apps personally
  12. Fr0sT.Brutal

    JSON text validation...

    I suspect you'll have to modify some existing parser to achieve the goal. You can even write your own - JSON syntax isn't rocket science and you only need passthrough checker (no document structure).
  13. Fr0sT.Brutal

    Zeos on Delphi 11.2

    I was sure the manner of trashing Windows folder with 3rd party libs have gone long ago.
  14. Fr0sT.Brutal

    JSON text validation...

    JSON has no restrictions regarding lines, it could even be one-liner. However, with custom or somewhat controllable parser you'll be able to skip invalid lines unless they influence following lines { "foo": [ invalid, "valid": "ok" ] }
  15. How about line endings? IDE goes crazy if there's some lonely CR's in sources
  16. Test project - the same?
  17. Fr0sT.Brutal

    Zeos on Delphi 11.2

    Also probably the library itself is OK but required MSVCR shit is missing
  18. Fr0sT.Brutal

    JSON text validation...

    Okay how will you catch all errors here: { "foo": "bar, quz deg } when parser will stop after ","?
  19. Fr0sT.Brutal

    Find usage of indexed default property

    If checking at runtime is acceptable, you can add stack trace output to GetItems
  20. Fr0sT.Brutal

    Exception call stacks on Windows with only a few LOCs

    Update: * Total redesign of reading. Minimized string allocations which allowed to gain x3,5 perf boost on MAP file loading + Demo project: add comments and messages, add sample of random callstack, add demo for GetMethodName https://github.com/Fr0sT-Brutal/Delphi_StackTraces
  21. Probably but it's unfair. I use Zeos instead of FireDAC and ICS instead of REST, why should I bother about them. I'm sure even Canto and Hodges or whoever is the Delphi mastermind haven't learned and used all classes in RTL.
  22. Fr0sT.Brutal

    Zeos on Delphi 11.2

    If LoadLibrary on that DLL being executed in an empty project works?
  23. Fr0sT.Brutal

    Regex help please..

    For these purposes simple NonSpace{1,}@NonSpace{1,}.NonSpace{2,} will be enough IMHO
  24. Yeah, we got it for several years already. 0.9l milk, 900g rice, even 9-egg pack. And finally what I consider the absolute evil - 0.4l beer!
×