-
Content Count
1090 -
Joined
-
Last visited
-
Days Won
23
Everything posted by aehimself
-
Sometimes it's good to take a break from something. I went to play with my daughter and realized... D7 doesn't understand Unicode! Maybe it receives the message but it will see only it's first character... Will have to test this theory later out though.
-
tjsoniterator How to fill TListViewItem using TJsonIterator ?
aehimself replied to wright's topic in Network, Cloud and Web
So, the sample data you mentioned is not a valid JSON document, but one separate JSON object per line as far as I can see. Maybe this is why TJSONTextReader fails - I don't know, I never used it. If the data will always arrive in this format and efficiency / optimization is no concern, you can do something like... Var line: String; jo: TJSONObject; // jv: TJSONValue; Begin For line In TFile.ReadAlltext('C:\[...]\restaurants.json') Do Begin jo := TJSONObject(TJSONObject.ParseJSONValue(line)); If Not Assigned(jo) Then Continue; // invalid JSON code in one line Try // ShowMessage(jo.GetValue('borough').Value); // For jv In jo.GetValue('grades') As TJSONArray Do // Begin // ShowMessage((jv As TJSONObject).GetValue('grade').Value); // ((jv As TJSONObject).GetValue('score') As TJSONNumber).AsInt // End; Finally jo.Free; End; End; End; The bad thing about this logic is that it reads the whole contents of the file in the memory, which will stay there until processing is complete. With 12 Mb this is not an issue, but you might hit a barrier if the data is in the GBs range. In that case you can use a TFileStream, read into a String until sLineBreak (or .Position = .Size) and build each JSON object from this. The processing logic can stay the same. -
I'm building a tool which searches for and opens Delphi source files. Until now execution was a simple ShellExecute call to the .pas file and everything was working just file. Now, as a second Delphi version is introduced I had to change the code to support opening said file in a specific Delphi version. My issue is that a simple call to bds.exe will always launch a new Delphi instance, and I need to re-use the one currently running. Basically I need to mimic the IDEs behavior when double-clicking a .pas file in Explorer. Unfortunately I could not find any documentation about the parameters of BDSLauncher, nor any relevant parameters of Bds.exe which could achieve this. I also built a small program which only lists the parameters it was started with and temporarily replaced BdsLauncher.exe and then bds.exe to see what it received when something is double-clicked, but all I got was the full path of bds.exe. Can anyone point me to the right direction? Thanks!
-
How to open a file in the already running IDE?
aehimself replied to aehimself's topic in Delphi IDE and APIs
@Attila Kovacs Your discovery method is inefficient. DDE_INITIATE is meant to be sent to HWND_BROADCAST and whoever supports it will reply. You also can identify the window who replied, as a WM_DDE_ACK message sent as a reply to DDE_INITIATE contains the DDE server window handle as WParam. Basically... Procedure TAEDDEManager.DiscoveryHandler(Var inMessage: TMessage); Var whandle: HWND; pid: Cardinal; Begin If inMessage.Msg <> WM_DDE_ACK Then Exit; whandle := inMessage.WParam; GetWindowThreadProcessId(whandle, pid); // Do something with the PID and the window handle of the process End; Procedure TAEDDEManager.RefreshServers; Var discoverywnd: HWND; serviceatom, topicatom: Word; msg: TMsg; res: Cardinal; Begin discoverywnd := AllocateHWnd(DiscoveryHandler); Try serviceatom := GlobalAddAtom(PChar(_service)); Try topicatom := GlobalAddAtom(PChar(_topic)); Try SendMessageTimeout(HWND_BROADCAST, WM_DDE_INITIATE, discoverywnd, Makelong(serviceatom, topicatom), SMTO_BLOCK, 1, res); While PeekMessage(msg, discoverywnd, 0, 0, PM_REMOVE) Do Begin TranslateMessage(msg); DispatchMessage(msg); End; Finally GlobalDeleteAtom(topicatom); End; Finally GlobalDeleteAtom(serviceatom); End; Finally DeallocateHWnd(_discoverywnd); End; End; And yes, I'll change my logic to window messages too. After long weeks of troubleshooting discovery still locks up after the fourth run when I'm using the DDE API 🙂 -
Again - you are correct but only if said library is redistributed with a software. For example, libmysql and oci is not allowing this (libmariadb might but I never read their EULA) and Oracle is notorious of shipping faulty software. Therefore, I'd update them at all places even if I have issues in only one software. LibSSL is also a good example from this perspective. If a serious security flaw is found, it's easier to update only 2 files per architecture than scanning your entire drive.
-
I completely agree with you there. However, I dislike redundancy. if you have 3 portable 32 bit and 2 portable 64 bit programs using libmysql.dll to connect to a database I'd find it wasteful and harder to maintain in case you are updating the client library. But as you said - it all comes down to user preferences.
-
ClientDataset.Filter ( Non English Character )
aehimself replied to Henry Olive's topic in Databases
If you don't have a chance to upgrade, you can take a look at Zeos. It handles Unicode filters and should be able to connect to your preferred RDBMS. -
Delphi beta testing a "premium" privilege?
aehimself replied to Brandon Staggs's topic in Tips / Blogs / Tutorials / Videos
-
Making sure I add unique records to text file
aehimself replied to karl Jonson's topic in Algorithms, Data Structures and Class Design
This level of nesting is just awful. Please do not use it, instead refactor your DB structure or modify your query to return the data exactly as you expect it. I'm leaving this here only for you to see what spaghetti you need because of bad DB design. Type TDateOfBirthPhoneNumber = TDictionary<TDateTime, String>; TSurnameAndRest = TObjectDictionary<String, TDateOfBirthPhoneNumber>; TUsernameAndRest = TObjectDictionary<String, TSurnameAndRest>; TUserCache = Class strict private _cache: TUsernameAndRest; public Constructor Create; ReIntroduce; Destructor Destroy; Override; Procedure AddRecord(Const inUserName, inSurName: String; Const inDateOfBirth: TDateTime; Const inPhoneNumber: String); Function ContainsRecord(Const inUserName, inSurName: String; Const inDateOfBirth: TDateTime; Const inPhoneNumber: String): Boolean; End; implementation Procedure TUserCache.AddRecord(Const inUserName, inSurName: String; Const inDateOfBirth: TDateTime; Const inPhoneNumber: String); Begin If Not _cache.ContainsKey(inUserName) Then _cache.Add(inUserName, TSurnameAndRest.Create([doOwnsValues])); If Not _cache[inUserName].ContainsKey(inSurname) Then _cache[inUserName].Add(inSurname, TDateOfBirthPhoneNumber.Create); _cache[inUserName][inSurname].AddOrSetValue(inDateOfBirth, inPhoneNumber); End; Function TUserCache.ContainsRecord(Const inUserName, inSurName: String; Const inDateOfBirth: TDateTime; Const inPhoneNumber: String): Boolean; Begin Result := _cache.ContainsKey(inUserName) And _cache[inUserName].ContainsKey(inSurname) And _cache[inUserName][inSurName].ContainsKey(inDateOfBirth) And (_cache[inUserName][inSurName][inDateOfBirth] = inPhoneNumber); End; Constructor TUserCache.Create; Begin inherited; _cache := TUsernameAndRest.Create([doOwnsValues]); End; Destructor TUserCache.Destroy; Begin FreeAndNil(_cache); inherited; End; For your information, I did not try this. High possibility of AVs! -
Copy nodes from a TTreeView with Delphi 4!
aehimself replied to Magno's topic in RTL and Delphi Object Pascal
A TList would be better choice but I'm not sure D4 has it... that's why I settled with an array. -
There's more than enough trash there already even at a clean installation so it doesn't really count 🙂 Anyway, it's the easiest solution to support all your 32 and 64 bit apps with everything they might need. After all, Microsoft is doing the same with msvcr*.dlls-s when you install the runtime...
-
Sorry about it, then. I really thought these methods are already in 10.2. You can check where an exception is raised in System.JSON in that earlier version and then simply backtrack to see what conditions you need to meet. Unfortunately I don't have a 10.2 installation anymore to check.
-
Copy nodes from a TTreeView with Delphi 4!
aehimself replied to Magno's topic in RTL and Delphi Object Pascal
Result: The code was written in D11 but I tried to keep it as simple as possible. I hope D4 supports the below calls... Type TTreeNodes = Array Of TTreeNode; procedure TForm1.Button3Click(Sender: TObject); Var added: TTreeNodes; begin SetLength(added, 0); CopyNodes(Source, Target, added); Target.Expanded := true; end; function TForm1.IsInArray(inTreeNode: TTreeNode; inArray: TTreeNodes): Boolean; Var a: Integer; begin Result := False; For a := 0 To Length(inArray) - 1 Do If inArray[a] = inTreeNode Then Begin Result := True; Exit; End; end; procedure TForm1.CopyNodes(inSource, inDestination: TTreeNode; var inCopied: TTreeNodes); Var a: Integer; tv: TTreeView; tn: TTreeNode; begin tv := inSource.TreeView As TTreeView; For a := 0 To inSource.Count - 1 Do Begin If Not IsInArray(inSource.Item[a], inCopied) Then Begin tn := tv.Items.AddChild(inDestination, inSource.Item[a].Text); // Do data copying, whatever SetLength(inCopied, Length(inCopied) + 1); inCopied[Length(inCopied) - 1] := tn; If inSource.Item[a].Count > 0 Then CopyNodes(inSource.Item[a], tn, inCopied); End; End; end; -
What overloaded versions you have? Any with TJSONParseOptions will do.
-
I only have 10.4.2 so I don't know if this version is available on 10.2, but you can try with var jv: TJSONValue; tb: TBytes; begin tb := TEncoding.UTF8.GetBytes(Edit1.Text); Try jv := TJSONObject.ParseJSONValue(tb, 0, [TJSONObject.TJSONParseOption.IsUTF8, TJSONObject.TJSONParseOption.RaiseExc]); jv.Free; Except On E:EJSONParseException Do Begin ShowMessage('JSON can not be parsed at path ' + E.Path + ', line ' + E.Line.ToString + ', position ' + E.Position.ToString); End Else Raise; End;
-
Aaaah, okay, it's clear now. I thought LibraryLocation isn't working for you for some reason. @miab's version is a lot more elegant though, that way all your apps can access their correct version of DB libs without any further effort.
-
In theory LibraryLocation should work just fine, I'm using it in my main application without issues. There's no reason copying it right next to the executable would be needed. This might worth looking into. Can this be reproduced in a minimal app?
-
Completely. Pure design time packages can only be compiled in 32 bit as the Delphi IDE itself is 32 bit only. If the runtime packages already compiled to 64 bit you are good to go. Just install the design time package and start coding 🙂
-
Does Visual Studio's Intellisense fail as often as Delphi's Code Insight?
aehimself replied to PeaShooter_OMO's topic in Delphi IDE and APIs
We have a fairly large C# solution at work, currently using Visual Studio as an IDE. Slow as hell, sluggish and memory-hog, but Intellisense did not stop to function for me; not even once in the past 4 years. Delphi's LSP was never "stable". I tried D10.2, 10.4, 10.4.2 and now 11.2. Even in relatively small projects (~30-60 units) Code navigation (Ctrl + Click) is uncommon, Code completion usually shows only the default options, wiggly lines everywhere but you still can run your project just fine. I prefer Delphi and do dislike VS as an IDE, but Intellisense is superior in every way in my opinion. LSP is just still immature. -
+1 Also don't forget that some libraries might require LibSSL and LibCrypto to be available.
-
The bug you mention has nothing to do with Zeos. Delphi 11 messed up the default library location and attempted to use 32bit DCUs on Win64 platforms. You can even correct it by hand after installation, there was even a post about it here in the D11 thread. I believe this was the faulty entry, just add "\Win64" after it and it starts to work.
-
I do, on a daily basis; I'm not connecting to PostgreSQL though (Oracle, MsSQL, MySQL and sometimes SQLite are my main targets). I can confirm that Zeos works on 64 bit with D11.2. The error above means that the given library was found but can not be used for whatever reason (LoadLibrary failed). I am playing this with MySQL x86 lately, as probably the DLL is so out-of-date (Oracle is not providing a fresh libmysql.dll for a while) that some needed functions do not exist. If you are absolutely sure the architecture of the DLL matches your project target, try using a more recent version. Or an alternative, if that exists - in my example, libmariadb.dll x86 works just fine. Edit: consider using Zeos 8. It's not yet considered as "release-ready" officially but it's rock solid and brings some great improvements. Afaik, it mostly lacks documentation only. Edit-edit: Zeos 8 comes with a D11 package so you can just double-click and install.
-
As it turns out , manually you can use TJSONValue.ParseValue and TJSONByteReader just like TJSONValue.ParseJSONValue does. But instead of throwing an exception, just mark the wrong items, using TJSONByteReader.OffsetToPos to get the line / character position from the offset. When an error happens, just skip 1 byte in TJSONByteReader and repeat. In theory, this could work.
-
If you use System.JSON and parse with exceptions enabled, it'll tell you where an error is. However, it will only show the first error and not all, but at least it's a built-in option.
-
There can be multiple reasons Wrong database design from the beginning Either the person had no understanding how it should be done or thought that the small amount of data what it will hold won't cause further issues. Then it grew out of control. To be honest (especially in newer applications) developers tend to completely ignore edge cases, lower hardware specs. "It works on my PC" Legacy dragging on This is exactly the case at us at work. Application was created ~20 years ago, when DB backends worked completely different and the architecture was functioning correctly. Now with thousands of tables and TBs of data stored it's not an easy task to start to split these so when a customer complaint comes in, we fix that one. At this speed the redesign won't be done in the next 5 years for sure and expose us to a risk that once done we'll have to start it again due to backend changes. Can't reproduce Not just the amount of data but the data itself can cause issues. Generally speaking, due to GDPR and confidentiality we, the developers aren't allowed to access and work with production data. When an export is needed, data is obfuscated before loaded in our test systems and this obfuscation itself is already changing the data. Once I spent days before figuring out that a rendering issue was caused by a BOM left in a BLOB field (customer just uploaded a file instead of using our editor), which was simply trimmed during obfuscation. As quick as possible, no future in mind This is especially true for commercial software unfortunately. Customers want more and more, quicker and quicker. In lots of occasions new features are added on a "quantity over quality"-basis. Just get it to work, get us paid, customer is happy - at least for now. This isn't necessarily a management issue as recognizing the need for, as well as optimization itself needs knowledge, time and manpower. Depending on the size, a company can lack many of this. These are just my 2 cents. Nothing is unfixable, question is always: at what cost.