MarkShark
Members-
Content Count
84 -
Joined
-
Last visited
Everything posted by MarkShark
-
CompareString function for UTF8 strings or buffers?
MarkShark posted a topic in RTL and Delphi Object Pascal
Hi all! Is there a library routine or api function that will compare two utf8 strings or buffers without converting them to UTF16? I'm looking for something analogous to AnsiCompareStr. Thanks! -Mark -
I did a lot of trial and error while working on the scrollbars for SynEdit and setting min to 1 seemed necessary. The code I ended up with is in SynEditScrollBars. The official documentation did seem a bit off in some cases. -Mark
-
Is this with Delphi 12 - Athens? Could it be related to this issue mentioned on Stack Overflow? To test if that's the issue just try changing #13#10 to + #13 + #10 to see if it makes a difference. Stack Overflow: Issue related to character literals: https://stackoverflow.com/a/78186835/113128
-
I currently have a background worker that I use to serialize a queue of workitems. The code to create the worker is: FWorker := Parallel.BackgroundWorker .NumTasks(1) .Execute(HandleWorkItem); In this case the HandleWorkItem method is just a dummy method as I actually pass in the workitem code when I schedule the workitem. E.g.: FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.FromRecord(MyWorkItemDataRec)), FWorker.Config.OnExecute( procedure(const workItem: IOmniWorkItem) var TaskResult: TTaskResult; begin // Do a bunch of work here in a background thread // Now set the Result TOmniValue from a record. workItem.Result := TOmniValue.FromRecord(TaskResult); end) .OnRequestDone(DoneMethod) ); end; This works extremely well, but I'd like to notify the calling thread of the progress. I thought maybe that IOmniWorkItemConfig would have an OnMessage(eventHandler: TOmniTaskMessageEvent) that I could set during the Schedule call (much like OnRequestDone) but I haven't figured out how to do that. Any help or suggestions appreciated.
-
Notification message from an OmniWorkItem
MarkShark replied to MarkShark's topic in OmniThreadLibrary
Just wanted to mention that I realize I can add a notification handler to the entire FWorker with: FWorker := Parallel.BackgroundWorker .NumTasks(1) .TaskConfig(Parallel.TaskConfig.OnMessage(HandleTaskNotification)) .Execute(HandleQueryWorkItem); But I'm wondering if I can do a WorkItem specific handler with the Schedule() call. -
Blast from the past! I worked at the Lab of Computer Science at Mass General Hospital right out of College (a great place with wonderful people.) I worked on Mumps for a few years back then. The database for Mumps/M is a hieratical database and it's not easy to do a direct translation to a relational database (based on knowledge from 30 years ago so it might be completely out of date! lol) In any case, I might look at Zeoslib instead of Firedac since it's open source and might be easier to create a new driver with. Sorry to not be more helpful!
-
SearchBuf issue since Delphi 11.2 fix for wholeword searching.
MarkShark posted a topic in RTL and Delphi Object Pascal
As of Delphi 11.2 they fixed the wholeword option handing (https://quality.embarcadero.com/browse/RSP-20731) however they changed the way that SelStart works when searching backwards (its' now -1 based instead of zero based..) To fix it to match the earlier behavior you have to do something like: if soDown in StringOptions then Result := SearchBuf(Buf, BufLen, SelStart, SelLength, SearchString, StringOptions) else Result := SearchBuf(Buf, BufLen, SelStart - 1, SelLength, SearchString, StringOptions); Basically, when searching backwards a SelStart of zero means to start the search at char position 1. Maybe there's some reason to make it work that way, but it's a change from earlier versions where searching forwards and backwards used the easier to understand base of zero as the start of the search. I haven't created a bug report for this as I had some problems with attempting to do it recently. Also is there a way to do an ifdef specific to 11.2? -
SearchBuf issue since Delphi 11.2 fix for wholeword searching.
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
Issue #78 and my pull request to start to fix it is #79. I have it fixed and tested, just needed that last bit of info about the 11.2 problem. Works great in my testing so far. -
SearchBuf issue since Delphi 11.2 fix for wholeword searching.
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
Thanks! Is using Searchbuf (unfortunately with the $if to fix this issue) ok to use as a solution to the SynEdit search engine issue I've been working on? Otherwise, we'd need a reverse version of the current "Next" function which looks like it might be a Boyer-Moore implementation? -
Using SetLength(Self) inside a record helper for TBytes
MarkShark posted a topic in RTL and Delphi Object Pascal
I was writing a simple record helper for TBytes and realized that some of my routines call SetLength. I'm wondering if this is a problem since the array could/will be reallocated in memory. Simple example: TTestBytesHelper = record helper for TBytes private function GetLength: Integer; inline; public function ReadFromStream(AStream: TStream; ACount: Integer): Integer; property Length: Integer read GetLength; end; { TTestBytesHelper } function TTestBytesHelper.GetLength: Integer; begin Result := System.Length(Self); end; function TTestBytesHelper.ReadFromStream(AStream: TStream; ACount: Integer): Integer; begin // Wondering about this SetLength call! System.SetLength(Self, ACount); Result := AStream.Read(Self, ACount); end; In my testing the ReadFromStream function does seem to work fine. I'm just wondering if calling SetLength on Self while in a record helper is ok to do. Thanks for any insight! -
I use Project Magician, but I don't use custom manifests, so this may or may not be helpful! In the help file it mentions that the child configurations cleaning setting "Application Settings" affects Icons, Manifest File, Output Settings and Appearance, and so that setting is probably what's clearing the child settings in this case. You can clear that setting to see if it helps. What I'd love is for Uwe to open source the tool, but it's definitely been useful to me "as is". I use addition custom .optset files to set version info and such but doing so is undocumented at best.
-
SynEdit - Get current SQL command block
MarkShark replied to aehimself's topic in Delphi Third-Party
Hey @aehimself SynEdit does have the SQLHighlighter which can give you some context information about the SQL, but it doesn't really have a full SQL script processor. Have you looked at the one in ZeosLib? I don't use it for my stuff as I had written one for Oracle's scripting language way back and then adopted it for the other databases with my newer products. Note that you will have to use some sort of statement terminator (which can be as simple as a semicolon or it can be super complex with Oracle's SQLPlus syntax or less complex with a standard "set terminator" type statement.) My tools are Golden (for Oracle) and GoldSqall (for Oracle, PostgresSQL, Firebird, MySQL, etc) and they all have to do exactly what you're doing. -Mark Ford Benthic Software -
SynEdit (https://github.com/TurboPack/SynEdit) can handle huge files and has an XML highlighter (Note: I haven't used that highlighter myself.)
-
My testing with MaxUndo = 1 (to most closely match a TMemo) doesn't show any leaks. I've also tested the other scenarios with no leak issues that I could detect. It's very true that the default settings can chew through a lot of memory for the undo stuff, so in the case of a log like this you must limit or manage the undo. On a related note: Am I correct that LockUndo/UnlockUndo must always be followed by a ClearUndo in order to keep everything in sync? I wasn't' sure if that happened automatically or perhaps is just not an issue. -Mark @pyscripter I'm very impressed by how few issues there have been for such a major rewrite! Well done!
-
I've used: SVGIconImageList also: Image32 Good stuff!
-
Hey all. I use SynEdit in a few projects and I was wondering if anyone has insight on which of the various version is the preferred one to use. I'm on 10.4 and don't need backwards compatibility btw. The one that is on "GetIt" appears to be an older version (1.5.) The one listed as SynEdit2 on github by pyscripter appears to be active, includes some nice changes (ole drag and drop for example) lots of fixes and cleanup (some related to removing support for older Delphi versions.) The one listed as SynEdit/SynEdit on github which seems to be more actively developed then the other two. I've worked with the second two and, as always, it seems when working with third party components I have to make a few changes to the source (adding some missing properties, fixing the extra space on word wrap lines (thanks to a stack overflow answer) and a few other minor issues) which have to be merged into each new update, so picking the "correct" one will obviously help. On a side note I have a feeling that the correct answer might be that there is no correct answer... Just looking for any feedback or thoughts. And this post wouldn't be complete without thanking and acknowledging all the great work people have done on these projects! -Mark
-
Encoding an n-dimensional array given dimensions and a list of items.
MarkShark posted a topic in Algorithms, Data Structures and Class Design
This is going to sound like a homework assignment, but it's actually needed for some ZeosLib code to handle PostgreSQL client library digital array format. The array information is the following: NDims: The number of dimensions: Example: 3 DimArray: An array of dimension sizes. Example [1,2,2] ItemsArray: An array of data items (say Integer.) Example: [1,2,3,4] I'm trying to figure out an algorithm to turn the information above into a string that has a format like: {{{1,2},{3,4}}}. I've got it working for 1 and 2 dimensions, but it seems like I'm brute forcing it when it seems like a more clever approach should be possible. Any tips, hints, or psuedo-code (or actual code!) appreciated! -
Encoding an n-dimensional array given dimensions and a list of items.
MarkShark replied to MarkShark's topic in Algorithms, Data Structures and Class Design
@PeterBelow Thank you for that! It works perfectly. -
Legacy (bad) code issues on Delphi 11.1 on 64bit VCL apps related to new ASLR linker flags
MarkShark replied to Davide Angeli's topic in Delphi IDE and APIs
A good way to test or discover this kind of bug is to use FastMM's allocate TopDown feature. -
It sounds like it's a component streaming property error. Make sure to open each form that has a SynEdit on it in the Delphi IDE and then save the form. That should fix any of those types of errors. Another thought is to make sure you have the latest version and to build and install the packages.
-
Trying to avoid using SetString when doing a token lookup in a TDictionary
MarkShark posted a topic in RTL and Delphi Object Pascal
Hi all! I often find myself needing to look up a string token in a dictionary. Usually, the token is part of a larger string being parsed. Currently I take a copy of that portion of the string using SetString or Copy and use that new string for the lookup. The code looks something like this: // Not shown: parse some source string and get a pointer to the first char of the token and the length of said token // Now get a copy of that token so we can look it up in the dictionary SetString(TempToken, FTokenStart, FTokenLength); if not FTokenDictionary.TryGetValue(TempToken, Result) then Result := UnknownToken; I'm wondering if there's any way to avoid the SetString part of this. Thanks for any ideas! -
Trying to avoid using SetString when doing a token lookup in a TDictionary
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
I realized in my benchmarking above that I was comparing a case insensitive dictionary to a case sensitive one. After correcting that the performance improvement for using this technique is 30%, which is still significant, but not what I reported above for sure lol. I do notice something odd. I'm loading about 300 SQL keywords (select, from, etc.) into a dictionary<string, integer> and if I check FKeywords.Collisions I'm getting a result of 90. Looking at the code for TDictionary it looks like they take the results of the hash and convert it a positive integer for the array of buckets (I hope that's the correct terminology.) I *think* that's where the collisions come in. It looks like Spring4d doesn't have the collisions property, so I haven't been able to do a sanity check against it. -
Trying to avoid using SetString when doing a token lookup in a TDictionary
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
@Stefan Glienke Thank you! My code is very close to yours, which is a nice validation for me lol. I also put the "stored" string in the record (@Frost I also tested keeping them in a separate list to remove the record being managed, but it didn't seem to make any difference when I benchmarked it.) I would be using Spring4D for this in my own code, however it may end up in SynEdit's highlighters and so I'm trying to keep dependencies down and to leverage the rtl as much as possible. -
Trying to avoid using SetString when doing a token lookup in a TDictionary
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
Excellent, thank you! I realize now that this is what Frost meant in his initial suggestion above and thank you Remy for that confirmation and link. I've done exactly what was suggested with the record as key and a custom equality comparer. Seems to work great and is still three times faster than my original version. Awesome! -
Trying to avoid using SetString when doing a token lookup in a TDictionary
MarkShark replied to MarkShark's topic in RTL and Delphi Object Pascal
My technique above (using a hash as the key in a TDictionary) seems to work, however, it assumes that hashing my tokens will always give a unique value. Am I correct that that's a problem? Any thoughts on how to handle it?