Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 06/18/25 in all areas

  1. TOML is a "config file format for humans", that has gained a lot of traction in the python and rust communities among others. It is basically the INI file format on steroids. It compares quite well to alternative formats such as JSON, YAML and XML. Compared to JSON is way more readable and compact. Since I could not find any Delphi library for processing TOML, I have created my own: toml-delphi. Features: TOML v1.0.0 compliant. Passes all 734 (valid/invalid) official validation tests. Fast. Single stream tokenizer and lexer that doesn't use regex. Converts TOML documents to Delphi's RTL's TJSONObject, thus allowing for easy traversal, manipulation and query of the generated documents. Includes TTOMLWriter for converting TJSONObjects back to TOML. Provides for easy (de)serialization of Delphi objects and records from/to TOML. This is the interface of the main unit: TJSONObjectHelper = class helper for TJSONObject function ToTOML(MultilineStrings: Boolean = False; Indent: Integer = 4): string; procedure StreamTOML(Stream: TStream; MultilineStrings: Boolean = False; Indent: Integer = 4); procedure SaveTOMLtoFile(const FileName: string; MultilineStrings: Boolean = False; Indent: Integer = 4); class function FromTOML(const Contents: string): TJSONObject; overload; class function FromTOML(Contents: TBytes): TJSONObject; overload; class function FromTOML(Stream: TStream): TJSONObject; overload; class function FromTOMLFile(const FileName: string): TJSONObject; end; ETOMLSerializer = class(Exception); TTOMLSerializer = class class function Serialize<T>(const AValue: T): string; overload; class function Deserialize<T>(const ATOML: string): T; overload; end; Example usage: You can convert TOML source to TJSONObject using one of the FromTOML functions. For example to parse a TOML file you use: var JsonObject := TJSONObject.FromTOMLFile(FileName); //or for parsing a TOML string: var JsonObject := TJSONObject.FromTOML(TOMLstring); To convert a TJSONObject to TOML you use one of the methods ToTOML, StreamTOML or SaveTOMLToFile. For example: TOMLString := JsonObject.ToTOML; // or JsonObject.SaveTOMLToFile(FileName); Example serialization: type TTestRec = record IntValue: Integer; FloatValue: double; StringValue: string; DateValue: TDateTime; ArrayValue: TArray<string>; end; procedure TestSerializer; var Rec: TTestRec; TOMLString: string; begin Rec.IntValue := 123; Rec.FloatValue := 3.14; Rec.StringValue := 'abc'; Rec.DateValue := Now; Rec.ArrayValue := ['A', 'B', 'C']; Writeln('Serialized record:'); WriteLn('=================='); TOMLString := TTOMLSerializer.Serialize(Rec); Writeln(TOMLString); Writeln('Record deserialized and serialized again:'); Writeln('========================================='); Rec := TTOMLSerializer.Deserialize<TTestRec>(TOMLString); TOMLString := TTOMLSerializer.Serialize(Rec); Writeln(TOMLString); end; Output: Serialized record: ================== IntValue = 123 FloatValue = 3.14 StringValue = "abc" DateValue = "2025-06-18T05:37:02.110+03:00" ArrayValue = [ "A", "B", "C" ] Record deserialized and serialized again: ========================================= IntValue = 123 FloatValue = 3.14 StringValue = "abc" DateValue = "2025-06-18T05:37:02.110+03:00" ArrayValue = [ "A", "B", "C" ] I hope you find it useful.
  2. Mark-

    What .PAS file does a form use?

    Using search, search all files in the project for the reporter component name and the unusual file name will be it.
  3. @Pat Heuvel- Thanks. I tried the (relatively) new version from github and it works!
  4. Die Holländer

    Retrieving outlook contact emails

    I found some old code to retrieve the list of a group, like "Global Address List" The code here is based on to put the addresses in a TreeView. I checked the code and it is still running OK but I noticed that I don't see the e-mail addresses anymore but instead it reports a string like: "/o=ExchangeLabs/ou=....." Maybe this is because of the exchange server configuration in my environment. see: how-to-get-email-address-from-o-exchangelabs-ou-exchange-administrative-group You have to play with it to see if you get the proper info you want. Maybe you can post the final answer here if you find the proper addresses.. Note that the code has a filter to only show two groups: If (CurGroupName='All Groups') or (CurGroupName='Global Address List') Then... //Uses Outlook2000; Procedure TMailTrans.CreateGALTreeForSendMailItem(aTreeView : TTreeView); Var pProp : PSPropValue; MP : IMAPIProp; strAddress : String; i, j, Check: Integer; myAddressList: AddressList; myAddressLists: AddressLists; myAddressEntries: AddressEntries; myAddressEntry: AddressEntry; CurNode, ChildNode, DetailNode :TTreeNode; CurGroupName : String; begin If NmSpace=NIL Then Begin OutlookApplication1.Connect; NmSpace:=OutlookApplication1.GetNamespace('MAPI'); NmSpace.Logon('', '', False, False); End; myAddressLists := IUnknown(NmSpace.AddressLists) as AddressLists; aTreeView.Items.BeginUpdate; aTreeView.Items.Clear; for i := 1 to myAddressLists.Count do begin CurGroupName:=myAddressLists.Item(i).Name; If (CurGroupName='All Groups') or (CurGroupName='Global Address List') Then Begin CurNode:=aTreeView.Items.Add(Nil,myAddressLists.Item(i).Name); CurNode.ImageIndex:=2; CurNode.SelectedIndex:=2; myAddressList := myAddressLists.Item(i); if Assigned(myAddressList.AddressEntries) then Begin myAddressEntries := myAddressList.AddressEntries; for j := 1 to myAddressEntries.Count do begin strAddress:='Unknown'; myAddressEntry := myAddressEntries.Item(j); if Assigned(myAddressEntry) then Begin if myAddressEntry.MAPIOBJECT<>NIL then Begin if Assigned(myAddressEntry.MAPIOBJECT) then Begin { Check:=IUnknown(myAddressEntry.MAPIOBJECT).QueryInterface(IMailUser,MP); If Check=0 then MP:=IUnknown(myAddressEntry.MAPIOBJECT) as IMailUser else MP:= IUnknown(myAddressEntry.MAPIOBJECT) as IDistList; if S_OK = HrGetOneProp(MP, $39FE001E, pProp) then begin strAddress:=String(pProp.Value.lpszA); MAPIFreeBuffer(pProp); end; // else strAddress:=myAddressEntry.Address; } strAddress:=myAddressEntry.Address; ChildNode:=aTreeView.Items.AddChild( CurNode, myAddressEntry.Name); ChildNode.ImageIndex:=7; ChildNode.SelectedIndex:=7; DetailNode:=aTreeView.Items.AddChild( ChildNode, strAddress); DetailNode.ImageIndex:=6; DetailNode.SelectedIndex:=6; End; End; { DetailNode:=aTreeView.Items.AddChild( ChildNode, myAddressEntry.Address); DetailNode.ImageIndex:=6; DetailNode.SelectedIndex:=6; } End; End; End; end; //Application.Processmessages; end; aTreeView.Items.EndUpdate; end;
  5. dummzeuch

    TOML delphi parser, writer and serializer

    My only problem with that is the license: GPL simply makes it useless for me. But since it's based on another GPL library you probably didn't have a choice.
  6. Spent more than 4 hours on this, not because i already witnessed this many times, but just i wanted to refresh my frustration with this pile of sh** called Delphi 64bit debugger, Here i want to make few things clear 1) The Delphi debugger 32bit and 64bit does have parts are the least can be called masterpiece, so it is not useless in whole, but the smart people worked on it, either left and the debugger stuck with different people, who have least knowledge about the existing code should be or those who wrote that beautiful debugger loop, have no idea on what to do as next step. 2) I have XE8 so it might be different from modern IDEs, as Embarcadero in the last decade have the phrase "lets make Delphi great again" rephrased a little, and from readin they are focusing on LSP and making it great again, good luck with that ! considering they are just adding process and memory allocation, it is the exact thing that will be impossible to squeeze performance from, on the contrary it will be worse with every step in that direction. Now back to the subject, and most likely i will rant again about the debugger, @lucarnet you said it takes 2.5 minutes under debugging while it takes 1-2 seconds without a debugger, my CPU is Sandy Bridge i5-2500 from more that decade and half, the these times is strangely close, yes it takes between 2.5-5 minutes and i am talking about just loading the model, not even loading the recognizer. Out of intrigue i looked at this VOSK library and using their documentation i download the binaries with pyhon pip, so far so good, browsed the demos and liked this one https://github.com/alphacep/vosk-api/blob/master/c/test_vosk.c so translated the needed headers, and easier than that there is none const VOSK_LIBNAME = 'libvosk.dll'; type PVoskModel = Pointer; PVoskRecognizer = Pointer; function vosk_model_new(const model_path: PAnsiChar): PVoskModel; external VOSK_LIBNAME name 'vosk_model_new'; procedure vosk_model_free(model: PVoskModel); external VOSK_LIBNAME name 'vosk_model_free'; function vosk_recognizer_new(model: PVoskModel; sample_rate: Double): PVoskRecognizer; external VOSK_LIBNAME name 'vosk_recognizer_new'; procedure vosk_recognizer_free(rec: PVoskRecognizer); external VOSK_LIBNAME name 'vosk_recognizer_free'; function vosk_recognizer_accept_waveform(rec: PVoskRecognizer; const data: Pointer; len: Integer): Integer; external VOSK_LIBNAME name 'vosk_recognizer_accept_waveform'; function vosk_recognizer_result(rec: PVoskRecognizer): PAnsiChar; external VOSK_LIBNAME name 'vosk_recognizer_result'; function vosk_recognizer_partial_result(rec: PVoskRecognizer): PAnsiChar; external VOSK_LIBNAME name 'vosk_recognizer_partial_result'; function vosk_recognizer_final_result(rec: PVoskRecognizer): PAnsiChar; external VOSK_LIBNAME name 'vosk_recognizer_final_result'; great, now i need a model and wave file, so https://alphacephei.com/vosk/models and grabbed the first and smallest model 40mb from https://github.com/alphacep/vosk-api/tree/master/python/example grabbed the wave file 256kb so far so good build i the same demo and low and behold modelPath := 'vosk-model-small-en-us'; model := vosk_model_new(PAnsiChar(modelPath)); if model = nil then begin Log('Error loadin model'); Exit; end; This model loading takes minutes under debugger while takes something less then 3 minutes a little, and without the debugger it literally takes 400ms (milliseconds) it is 0.4 second ! So i am confirming your problem with debugger, later on this will write something. Now to your other problem, loading the model and recognizer doesn't even create a single background thread, as vosk_recognizer_accept_waveform kept failing and hugging the CPU, i couldn't make it work, but also didn't create threads ! So the threads in the log of yours is coming from your own miss using something somewhere, may be in handling wave file or microphone, fix these as these threads will only make the debugger even slower. Also the demo is somehow wrong in assuming and feeding 3200 bytes and didn't read the header right way to check for sample rate and channels every thing else, but it should work i guess, yet it didn't work on my device. Recommendation, Delphi debugger is useless and i am talking specifically about 64bit, it is wrong and doing wrong on so many levels 1) The demo and this library do allocate 4-5 chunks of memory each are 128mb, and will add more chunks for the recognizer and will increase but there is no memory leak, just huge amount of memory is needed, and it is expected. 2) The debugger utilize for unknown reason, well may be there was valid reasons 20 years ago, to have two processes to perform the debugging, but i can't justify having a sentinel process calling DebugBreak, WHY ? who knows. 3) Now comes the fun part, the debugger must be 64bit while the IDE 32bit so an IPC is due, great, so lets take one and never look back, so they choose TCP, TCP (WTF), even on loopback it is TCP packets, no shared memory ?! no no shared memory ! 4) Now the debugger perform ReadProcessMemory as like every debugger out there, but wait we mist do it differently, see since the dawn of computers half century ago there was pages and they are 4kb and on Windows an address is valid if the page is valid, so lets perform the reading on 512byte ! 5) 512bytes is somehow still better than 1 byte, so lets perform reading on 1 byte, we must not gave up, and in case we wrote the breakpoint by using WriteProcessMemory at single byte which is fine and justified, lets do all the breaks points to make sure and even the API is success, success means it does wrote the memory, we must be sure and read them all again , !! 6) OK we have the memory read in small chunks we need to ship them to the IDE and the IDE debugger, lets send them in 1,8,12,16 bytes, genius !, so hundred of thousands of send over TCP in the smallest way possible, notice TCP require ACK, so switching to UDP will enhance the throughput, we are against that, and still no shared memory ! 7) how to handle sockets in Turbo Pascal way over dialup modem, every IOCTLSocket (the successful ones) should be followed be WSAGetLastError for no freaking reason, and lets mix Select with WSAAsyncSelect to create an abomination, just to make sure, while the IDE and its UI will block for every packet, so the IDE should freeze showing it is busy, great ideas and great design. .. So many things to be angry about, as i can't be unbiased here, but the IPC between IDE and real debugging process is wrong and outdated, it can work and debug a 10 lines project, not a real life semi-heavy application. Now i am angry 😪 @lucarnet there is no way to debug such heavy memory usage application using very, yes very outdated debugger, the Delphi debugger, you should fix the threads creation as i mentioned above, as it is has nothing to do with VOSK library, and skip debugging on Delphi, use logging instead, i am guessing here, those thread are coming form your different library you are using to handle microphone or wave file reading. And good luck ! Ps: looking at the assembly generated for 64bit it is a sight to see NOP there between the instruction serving literally nothing, and even one of them was ducking up the alignment in the freaking loop, wow just wow.
  7. TECNativeMap is a 100% Delphi mapping component that uses neither browser nor javascript, and is available on all Delphi-supported platforms. Compatible since Delphi 7 for VCL and XE3 for Firemonkey. Download the trial version for Delphi 12
  8. Vandrovnik

    Recommendation on VCL development on 4k monitor

    You can try running Delphi in DPI-unaware mode. It's blurry, but from what I've tested, it's the least problematic.
  9. David Heffernan

    Rapid.Generics revamp

    No library developer would test things like this. I mean why stop at FMX/VCL? What about database frameworks. Does it have dependencies on any of them? Does it work in a Windows service? Should there be a test for that? It's simple to see by inspecting the uses clause, so the developer just does not need to do any of that.
  10. Uwe Raabe

    About the compiler (not) finding the DFM files

    Not quite, that setting is stored as BRCC_IncludePath. DCC_ResourcePath is indeed the correct way to provide the paths to look for the DFM resources. Unfortunately there is no UI to edit that. Manually editing the dproj file adding a node like <DCC_ResourcePath>..\lib\Source;$(DCC_ResourcePath)</DCC_ResourcePath> under the appropriate PropertyGroup will make the DFM files located in ..\lib\source to be found without exposing the PAS files in that folder.
  11. Stefan Glienke

    Virtual class methods and properties

    It appears that Marco lacks the technical understanding to evaluate this issue. I left a comment.
  12. You keep demonstrating for us that you do not even understand the API. Your original question would have been answered by just looking at the documentation for ShowModal, or by examining the source code to see how the modal loop is implemented. You wouldn't bother to do that, and you feel qualified to make pronouncements on the overall design quality. Maybe let it go.
  13. Huh? var Msg: TMsg; while (PeekMessage(Msg, 0, WM_SETCURSOR, WM_SETCURSOR, PM_REMOVE)) do begin if (Msg.message = WM_QUIT) then begin PostQuitMessage(Msg.wParam); exit; end; DispatchMessage(Msg); end;
  14. To improve rendering performance, set StorePaintBuffer to True on parent controls from the package. By default it is True in some controls, in some False.
  15. Delphi in order to survive must ASAP include the method to close a modalForm or we will die. As a Quick Fix they should include the class helper for all the existing versions: type TFormHelper = class helper for TCustomForm public procedure EndDialog(PModulResult: TModalResult); end; { TFormHelper } procedure TFormHelper.EndDialog(PModulResult: TModalResult); begin modalResult:=PModulResult; end; I can only hope that somebody from Embarcadero will read this thread and will push these changes directly to the TForm not to require a class helper for such an important issue to be fixed. (For years I was using the modalResult to close modal forms without a single issue. This thread made me realize that Delphi is dying because it does not have such a method.)
  16. jeanmilost

    SVG Magic released

    Hi the Delphi Praxis community, I'm happy to announce to you that since now the SVGMagic component library is open-source and free for commercial and non-commercial use, under the MIT license. Please find the source code here: https://github.com/Jeanmilost/SVGMagic And the website was migrated here: https://jeanmilost.github.io/svgmagic.web/
  17. bazzer747

    What .PAS file does a form use?

    Uwe, OK, more clarity :-). When I run my project, one of the buttons runs an Ace Report with a "sctRepCustList.Run" command. This runs the report which is on a form. I don't get to see the form, just the report output. It isn't like I have the report form open in the IDE where I would know know exactly what it is called and what name I save it with. Mark, A global search in all files doesn't show anything other than the form where I run the Ace Report from.
×