Jump to content

Mike Torrettinni

Members
  • Content Count

    1166
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Mike Torrettinni

  1. Looking for Android apps developed with Delphi. Is there a list of them anywhere? Thinking of developing an app and want to see examples of whats possible, not business, but consumer apps. Thanks for any suggestions what I can look at, paid or free apps available through Play store.
  2. I'm refactoring usage of various different look-up tables and I'm trying to come with 1 fast look-up table design. Most of them have 1 thing in common: search by integer (ID) and search by string (Name). All data is sorted. So, I bench-marked TArray.BinarySearch, TDictionary and custom binary search. Even though a flaw in design was pointed out for TArray.BinarySearch, (see https://en.delphipraxis.net/topic/4575-why-is-tarraybinarysearch-slower-than-normal-binary-search-function/), I still wanted to compare results: For search by integer, custom binary search seems to be a little faster than TDictionary, until large tables: For search by string, custom binary search wins even more, still for not large tables: Interesting is that for smaller searches, 10 records, a sequential search is faster than TDictionary. I also tried TGpStringHash (by Primoz Gabrielcic), which is very fast, but unfortunately no implementation for integers. TSynDictionary (from mORMot) is also very fast, but I don't use mORMotand license is not friendly for my commercial project. Is there any other fast search implementations that is not too specialized and ready to use out of the box, that I can try?
  3. Mike Torrettinni

    Whatsapp solution for Delphi

    I'm sure it can be used for spamming... but for me it was an idea to use it on my computer while working, I can communicate through Whatsapp without the need for a phone. The notifications that I was interested in would notify me when messages from some people come and I can check. This would eliminated usage of phone by a lot! 🙂 I thought it was a simple project I can use for $$ and not a commercial solution for $$$...
  4. Mike Torrettinni

    [Source code for sale] Automated Whatsapp server

    This is interesting, I could use that if it works well. Can you send or publish demo app? I thought this was small project and not a commercial solution:
  5. That is interesting. Do you use it, for what cases you prefer using it? I can't find Delphi implementation. Do you know does it exist?
  6. Mike Torrettinni

    List of usable RegEx for source code

    A new one: trim(left|right|)\(trim(left|right|)\( this will check for all combinations of TrimLeft(TrimRight())... I did find a few of these in some open source projects, There is one that has it's own LTrim and RTrim implementations, I assume they were implemented before TrimLeft/Right were introduced in Delphi. Of course it's using them as LTrim(RTrim(str)).
  7. As we can see in Range Check Error ERangeError topic (https://en.delphipraxis.net/topic/4825-range-check-error-erangeerror/), a RegEx script could find the issue. So, I wanted to share my 3 simple scripts I run on my code every now and then to make sure I don't make mistakes: 1. To find all array increments by 1, like SetLength(array, Length(array)+1): SetLength.*\(.*Length\(.*\).*\+.*1 2. and when using High() - this is error anyway, so good to find it! SetLength.*\(.*High\(.*\).*\+.*1 3. If I forgot to add -1 when iterating array (although I use High most of the time, I still use Length() - 1 sometimes): 0 to Length\(.*\).do If anybody wants to share any scripts they use, please do!
  8. Mike Torrettinni

    Pos

    Apart from TrimRight, there is also TrimLeft (trim spaces from left side) and Trim (trim spaces from both sides): TrimLeft(' LoremIpsum') -> 'LoremIpsum' Trim(' LoremIpsum ') -> 'LoremIpsum' Just try to avoid using TrimLeft and TrimRight in combination like this: s := TrimLeft(TrimRight(' LoremIpsum ')); // or TrimRight(TrimLeft()) this is wasteful and unnecessary complicated. Just use Trim instead.
  9. Mike Torrettinni

    List of usable RegEx for source code

    I got another one, although this one is probably useful for small number of developers who prefer begin and end in their own lines: ((if)|(while)|(for)).*\sbegin This finds all lines where begin is in the same line as if/for/while statements. I prefer: if condition then begin ... ... end; and not the 'advanced/pro' way: if condition then begin ... ... end; For me, easy readable is preferred over reducing 1 line of code.
  10. I have an old example of RegEx usage and noticed with one customer becomes a bottleneck. So, I did some benchmarking and it was very slow because I create RegEx expressions on each call. So, I optimized it to only create RegEx when is needed. I also took a chance to see if I can get rid of RegEx and using Pos and string iteration is faster of course. The purpose of RegEx is to find if Function() exists in string. The problem is that sometimes there are spaces before bracket, like Function (). The most I found was 4 spaces before I implemented RegEx to replace If 'Function(' or 'Function (' or 'Function (' or 'Function (' is in string, with RegEx: '\b' + vFunc + '[ ]*\(' So, I'm happy to get rid of RegEx for this example. But still wanted to show the code, perhaps I'm using RegEx the wrong way and someone has a suggestion. Here are the timings (ms): 32bit: In 64bit optimized RegEx is a little faster: And code: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.RegularExpressions, System.Diagnostics; const cNoHit: string = 'Testing string just for testing and more testing.'; cShort: string = 'FunctionA(x)'; cMedium: string = 'Testing FunctionA (1) or Writeln(FunctionB (1+1)) and Not FunctionC( FunctionD(y))'; cLong: string = 'Lorem ipsum dolor FunctionA(a)sit amet, consectetur adipiscing FunctionB(FunctionC (2)) elit. Ut enim neque, dictum vel sodales molestie, FunctionD (10)pretium in neque. Quisque FunctionA (10)rhoncus. Alma e alma de penatibus et FunctionA(99)'; cLoop: integer = 100000; cFunctions: array[1..5] of string = ('FunctionA', 'FunctionB', 'FunctionC', 'FunctionD', 'FunctionN'); // FunctionN is not in test cases function IsFunctionInString_RegEx(const aFunction, aStr: string): boolean; var vRegEx: TRegEx; begin // aFunction can have none or multple spaces between bracket // aFunction(), aFunction (), aFunction ()... vRegEx.Create('\b' + aFunction + '[ ]*\('); Result := vRegEx.IsMatch(aStr); end; function IsFunctionInString_RegEx_Optimized(const aRegEx: TRegEx; const aFunction, aStr: string): boolean; begin // Optimized: aRegEx compiled only once Result := aRegEx.IsMatch(aStr); end; function IsFunctionInString(const aFunction, aStr: string): boolean; var vPos, i: Integer; begin // aFunction can have none or multple spaces between bracket // aFunction(), aFunction (), aFunction ()... // 1. Find aFunction and check if next character is '(', skipping any spaces vPos := Pos(aFunction, aStr); if vPos = 0 then Exit(false); for i := vPos + aFunction.Length to aStr.Length do begin if aStr[i] = '(' then Exit(True); if aStr[i] <> ' ' then Exit(false); end; end; procedure Test_RegEx(const aStr: string); var vSW: TStopWatch; s, vFunc: string; b: boolean; i: Integer; begin vSW := TStopWatch.StartNew; for vFunc in cFunctions do for i := 1 to cLoop do b := IsFunctionInString_RegEx(vFunc, cNoHit); Writeln(' RegEx: ' + vSW.ElapsedMilliseconds.ToString); end; procedure Test_RegEx_Optimized(const aStr: string); var vSW: TStopWatch; s, vFunc: string; b: boolean; i: Integer; vRegEx: TRegEx; begin vSW := TStopWatch.StartNew; for vFunc in cFunctions do begin vRegEx.Create('\b' + vFunc + '[ ]*\('); for i := 1 to cLoop do b := IsFunctionInString_RegEx_Optimized(vRegEx, vFunc, cNoHit); end; Writeln(' RegEx Optimized: ' + vSW.ElapsedMilliseconds.ToString); end; procedure Test(const aStr: string); var vSW: TStopWatch; s, vFunc: string; b: boolean; i: Integer; begin vSW := TStopWatch.StartNew; for i := 1 to cLoop do for vFunc in cFunctions do b := IsFunctionInString(vFunc, cNoHit); Writeln(' Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure Validate; var vStrings: array of string; s, vFunc: string; vRegEx: TRegEx; begin vStrings := [cNoHit, cShort, cMedium, cLong]; for s in vStrings do for vFunc in cFunctions do begin vRegEx.Create('\b' + vFunc + '[ ]*\('); if (IsFunctionInString(vFunc, s) <> IsFunctionInString_RegEx(vFunc, s)) or (IsFunctionInString(vFunc, s) <> IsFunctionInString_RegEx_Optimized(vRegEx, vFunc, s)) then raise Exception.Create('Error validating: ' + vFunc + ' in ' + s); end; end; begin Validate; Writeln('No hit str:'); Test_RegEx(cNoHit); Test_RegEx_Optimized(cNoHit); Test(cNoHit); Writeln(''); Writeln('Short str:'); Test_RegEx(cShort); Test_RegEx_Optimized(cShort); Test(cShort); Writeln(''); Writeln('Medium str:'); Test_RegEx(cMedium); Test_RegEx_Optimized(cMedium); Test(cMedium); Writeln(''); Writeln('Long str:'); Test_RegEx(cLong); Test_RegEx_Optimized(cLong); Test(cLong); Writeln(''); Writeln('done...'); Readln; end.
  11. Mike Torrettinni

    RegEx performance

    Thanks! The website kind of proves my point why I'm removing all (most) regex. Funny how comments show so many feel so strongly about email regex 😉 Yes, this annoys me too, especially websites requesting email for just basic info. My projects are not like website, so validation is only for typos. It's part of licensing form, so no problem with understanding the purpose.
  12. Mike Torrettinni

    RegEx performance

    Seems like the only RegEx left in my apps will be for email validation. But this is called only once on user entry, so no performance needed. The rest of RegEx will probably phase out slowly.
  13. Mike Torrettinni

    RegEx performance

    Thanks! It doesn't make sense to use RegEx for such example, right? OK, I see it's usable for a few calls, but for anything that searches lost of data, is pretty slow.
  14. Mike Torrettinni

    List of usable RegEx for source code

    OK, the expressions can become quite hard to manage, so I can see why people are not really that enthusiastic about regex, but here is now my complete list: SetLength\s*\(.*Length\(.*\)\s*\+\s*1 -> SetLength(arr, Length(arr) + 1) SetLength\s*\(.*High\s*\(.*\)\s*\+\s*1 -> SetLength(arr, High(arr) + 1) 0\s*to\s*.*Count\s*do -> 0 to List.Count do 0\s*to\s*.*Length\s*\(.*\)\s*do -> 0 to Length(arr) do raise Exception\( -> raise Exception() (missing .Create like in raise Exception.Create) Exception\.Create\( -> Exception.Create( (verify that Raise is in front ) Full exp: (SetLength\s*\(.*Length\(.*\)\s*\+\s*1)|(SetLength\s*\(.*High\s*\(.*\)\s*\+\s*1)|(0\s*to\s*.*Count\s*do)|(0\s*to\s*.*Length\s*\(.*\)\s*do)|(raise Exception\()|(Exception\.Create\() And of course Delphi's IDE is special and requires a little subtle changes: Delphi IDE: SetLength\s*\(.*Length\(.*\)\s*.*\+\s*.*1 SetLength\s*\(.*High\s*\(.*\)\s*.*\+\s*.*1 0\s*.*to\s*.*.*Count\s*.*do 0\s*.*to\s*.*Length\s*\(.*\)\s*.*do Full exp: (SetLength\s*\(.*Length\(.*\)\s*.*\+\s*.*1)|(SetLength\s*\(.*High\s*\(.*\)\s*.*\+\s*.*1)|(0\s*.*to\s*.*.*Count\s*.*do)|(0\s*.*to\s*.*Length\s*\(.*\)\s*.*do)|(raise Exception\()|(Exception\.Create\()
  15. Mike Torrettinni

    Delphi IDE on AMD cpu?

    I'm thinking of switching from Intel to AMD. I know the Delphi compiled projects work on AMD cpus, but I worry about Delphi IDE. Especially after 10.4.2 release. Is anybody actively using Delphi IDE on latest AMD cpu 5000 or previous 3000 series, desktop series of course, and can confirm no issues because of AMD cpu?
  16. Mike Torrettinni

    Delphi IDE on AMD cpu?

    Yes, I think I will go for it. Current 32GB was enough, but got close to the max often. So, 64GB should be enough for next 5 years or so.
  17. Mike Torrettinni

    Delphi IDE on AMD cpu?

    Thanks, good to know! Little disappointing with Intel's 11 gen, so looking at AMD. 5900x seems to be a good choice, anything above is overkill for my work.
  18. Mike Torrettinni

    Delphi IDE on AMD cpu?

    Thanks. I agree about the hardware stuff, If you are a developer and someone has to suggest SSD and good cooling, you are wasting time and money on a PC of your choosing, unless someone who knows about this stuff helps you. That's probably not going to be enough for running VMs. Not sure which cpu I will choose, but out of all the software I use, I'm concerned most about Delphi IDE.
  19. Mike Torrettinni

    Delphi IDE on AMD cpu?

    Thanks, good to hear! Do you have Intel in your laptop? A comparable cpu, or 20-30% slower than 5600x? Interesting. Those topics for 10.4.2, on this forum, kind of indicate it could be anything, as consistently inconsistent LSP is working.
  20. Mike Torrettinni

    List of usable RegEx for source code

    Is Delphi IDE using some different than normal regex? Why would IDE not work with this expression: to find all SetLength(arr, Length(arr) + 1) FileLocator and regexr.com work with this: SetLength\s*\(.*Length\(.*\)\s*\+\s*1 But for Delphi IDE I need to add .* after some \s* : SetLength\s*\(.*Length\(.*\)\s*.*\+\s*.*1 not found: SetLength\s*\(.*Length\(.*\)\s*\+\s*1 works Ok with extra \s*.*: SetLength\s*\(.*Length\(.*\)\s*.*\+\s*.*1
  21. Mike Torrettinni

    List of usable RegEx for source code

    It would be nice if IDE would allow to search multiple expressions at once, like regex list: search regex(s) = "SetLength.*\(.*Length\(.*\).*\+.*1 "," SetLength.*\(.*High\(.*\).*\+.*1 "," 0 to Length\(.*\).do "," 0 to .*Count[ ]do "," raise e[a-z]*\( " So you can run such check every now and then with simple copy paste of a list. File Locator/Agent Ransack is missing such options, too, shame.
  22. Mike Torrettinni

    List of usable RegEx for source code

    Hm, Ok, I didn't know that. Maybe my original case was a bit different but eventually proved a bottleneck with constant calling Length()+1.
  23. Mike Torrettinni

    List of usable RegEx for source code

    Well, yes, of course. But it can bite you really fast when suddenly you have a customer who has different data and instead of 10K items at 1-10 properties per item (using Length + 1), turns into 10 items with 10K properties each. Then it becomes a bottleneck suddenly.
  24. Mike Torrettinni

    List of usable RegEx for source code

    I used to have a lot of cases where I would increase array size by +1, when adding new records, instead of pre-allocate x records and increase only if needed. Perhaps it's specific to my old ways of doing things, but now I try not to. Of course if I know its going to be only a few records, then I make this known in comments. But I try to avoid it.
  25. Mike Torrettinni

    List of usable RegEx for source code

    With this one I found, in 3rd party libraries, few cases of : ItemsCount := Items.Count - 1; ... for i := 0 to ItemsCount do Valid code, I guess, but tricky.
×