-
Content Count
2268 -
Joined
-
Last visited
-
Days Won
46
Everything posted by Fr0sT.Brutal
-
Blogged : Advice for Delphi library authors
Fr0sT.Brutal replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
Pity. I thought it was intended for such cases -
10.4.2 Released today - available to download
Fr0sT.Brutal replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
I'm already glad they dropped dependency on that odd Visual J++ 😄 -
Micro optimization: Split strings
Fr0sT.Brutal replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Well, I thought hard on this nuance as well. Vote "for" is when string is constructed by dumb but simple loop `s := s + part + sep`, it will contain last sep that actually doesn't designate an element. Vote "against" is logic: if there's a separator - then an element must follow. -
Micro optimization: Split strings
Fr0sT.Brutal replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yep, here it is (on DUnitX facilities) TStrArray is array<string> and DefListDelim is ';' // Split/Join/GetElement procedure TTest_Utils.TestSplit; var arr: TStrArray; procedure CheckEquals(const CompArr: array of string; const TestDescr: string); var i: Integer; begin Assert.AreEqual(Integer(Length(CompArr)), Integer(Length(arr)), TestDescr + ' check lengths'); for i := 0 to Length(CompArr) - 1 do Assert.AreEqual(CompArr[i], arr[i], TestDescr + ' compare items #'+IntToStr(i)); end; begin arr := Split(''); CheckEquals([], 'Empty'); arr := Split('qq'); CheckEquals(['qq'], 'Single'); arr := Split('qq;ww;ee'); CheckEquals(['qq','ww','ee'], 'Normal'); arr := Split('qq;ww;ee;'); CheckEquals(['qq','ww','ee'], 'Sep on end'); arr := Split('qq;ww;;;ee', DefListDelim, True); CheckEquals(['qq','ww','','','ee'], 'Empty items -- allow'); arr := Split('qq;ww;;;ee', DefListDelim, False); CheckEquals(['qq','ww','ee'], 'Empty items -- deny'); arr := Split('qq==ww==ee=', '=='); CheckEquals(['qq','ww','ee='], 'Multichar sep'); arr := Split('qq;ww;"ee;ll"', ';', True); CheckEquals(['qq','ww','"ee','ll"'], 'LastIdx 1'); arr := Split('qq;ww;"ee;ll"', ';', True, 0); CheckEquals(['qq;ww;"ee;ll"'], 'LastIdx 1'); arr := Split('qq;ww;"ee;ll"', ';', True, 1); CheckEquals(['qq','ww;"ee;ll"'], 'LastIdx 1'); arr := Split('qq;ww;"ee;ll"', ';', True, 2); CheckEquals(['qq','ww','"ee;ll"'], 'LastIdx 2'); end; -
Blogged : Advice for Delphi library authors
Fr0sT.Brutal replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
Hmm, wasn't that a mistake in that package? And how did it happen, its dev didn't try to build it? Not exactly what I was talking about. Packages are good, but in many cases personal package project files for every version are excess. Delphi has pretty cool compatibility with older versions so one project file for all XEs should be enough (honestly I just dislike all those huge listings of <name>_D<whatever>.dproj files that are completely identical in fact). IMHO component packages should not bother about installation process at all. Let IDE decide how and where to build them! There are plenty of libs that suggest to install themselves in Program files, or C:\, or %APPDATA%, or %ALLUSERSPROFILE%... sometimes they don't even ask for path and silently install where they decide! My opinion here: custom installers for component libs are evil. Doesn't upgrade from GetIt solve this issue? -
Micro optimization: Split strings
Fr0sT.Brutal replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Well, for values that accept anything >= 0, "-1" is short "default"/"not set" magic constant. It's not intended for use in code anyway because it's declared as default parameter (in decl section that I didn't copy). I guess you're right and MaxInt constant will do better; moreover it will eliminate one condition in code. And it's aligned to parameters of Copy(). Nice note! -
Blogged : Advice for Delphi library authors
Fr0sT.Brutal replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
Package Names I guess many projects don't even require personal package files for every Delphi version. Not talking about DPK files which mainly are the same. Use Search Paths for includes Tend to disagree. This makes package files obligatory while otherwise they're optional. Moreover, you won't be able to explore that include file from unit code unless you loaded the package project. What's wrong with relational paths? -
Hiding a public property in a descendant class
Fr0sT.Brutal replied to Cristian Peța's topic in RTL and Delphi Object Pascal
Good though there's still a chance you miss some cases procedure TForm1.EditOnChange(Sender: TObject); begin with TEdit(Sender) do Text := Text + 'lol'; end; -
Hmm don't you know that uppercase letters occupy more memory causing overall slowdown?! 😄
-
Micro optimization: Split strings
Fr0sT.Brutal replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
function Split(const Str: string; const Delim: string; AllowEmpty: Boolean; LastIdx: Integer): TStrArray; var CurrDelim, NextDelim, CurrIdx: Integer; begin if Str = '' then begin SetLength(Result, 0); Exit; end; CurrDelim := 1; CurrIdx := 0; SetLength(Result, 16); repeat if CurrIdx = Length(Result) then SetLength(Result, CurrIdx + 16); // check if array if full and extend if needed if (LastIdx <> -1) and (CurrIdx = LastIdx) then // last index reached - write all up to end begin NextDelim := Length(Str)+1; end else begin NextDelim := Pos(Delim, Str, CurrDelim); // next delim if NextDelim = 0 then // string is finished - write all up to end NextDelim := Length(Str)+1; end; Result[CurrIdx] := Copy(Str, CurrDelim, NextDelim - CurrDelim); CurrDelim := NextDelim + Length(Delim); // if fragment is not empty or empty are OK - inc index if (Result[CurrIdx] <> '') or AllowEmpty then Inc(CurrIdx) else Continue; until CurrDelim > Length(Str); SetLength(Result, CurrIdx); // cut the array down end; - any string as delimiter - customize if empty elements will be extracted ("foo;;;bar" & AllowEmpty=False => ["foo", "bar"]) - optional stop splitting after N elements found (mainly for name-value pairs like "login: user:pass" & LastIdx=1 => ["login", "user:pass"]) -
Read and reapply design time properties to specific controls - runtime
Fr0sT.Brutal replied to aehimself's topic in VCL
If you only want to restore Visible and Bounds, then saving original props in a list is the simplest option. -
Hiding a public property in a descendant class
Fr0sT.Brutal replied to Cristian Peța's topic in RTL and Delphi Object Pascal
Probably because TControl.SetText is implemented via sending WM_SETTEXT so nothing prevents one from sending it directly if he wants to. -
Hiding a public property in a descendant class
Fr0sT.Brutal replied to Cristian Peța's topic in RTL and Delphi Object Pascal
(YourEdit as TCustomEdit).Text := 'ahaha' -
Hmm, what's the problem in transparent labels? I personally never used non-transparent ones because they look ugly. He has issue with default property value so there's no `Transparent: True` line in DFM; probably sed could handle such nested insert but I suspect the resulting script could summon a daemon in case of any mistake :)) Won't ParentDoubleBuffered help you better?
-
Quickly zero all local variables?
Fr0sT.Brutal replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
-
Quickly zero all local variables?
Fr0sT.Brutal replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
An intrinsic that would be called only when told so? Sounds useful. -
Quickly zero all local variables?
Fr0sT.Brutal replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
procedure test; var first: NativeInt; a: integer; f: double; rec: TSearchRec; last: NativeInt; begin FillChar(first, PByte(@first)-PByte(@last), 0); // Alas won't work :( readln; end; I thought about something like above but compiler appeared too smart and placed "last" right after "first". -
Undocumented language enhancements
Fr0sT.Brutal replied to vfbb's topic in RTL and Delphi Object Pascal
"Static variables" inside procedures function Counter: Integer; {$J+} const I: Integer = 0; {$J-} begin I := I + 1; Result := I; end; When you declare a const with a type, Delphi allocates memory for the constant. The program can change the value of the “constant,” just as though it were a variable. The difference between a typed constant and a local variable is that a typed constant in a subroutine keeps its value across subroutine calls. If you disable the $WriteableConst directive, you can prevent any assignments to a typed constant, thereby making the constant truly constant. There is no substitute for typed constants in a subroutine, though, so disable $WriteableConst with care. Disable only specific constants whose value you want to protect, and do not disable this directive globally in a project or an entire file. Short init of record constants type TR = record a: string; b: string; end; Const TR_Empty: TR = (); Const TR_A: TR = (a: 'foo'); (not undocumented but non-obvious ones) -
Is Delphi still taught in schools?
Fr0sT.Brutal replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
Ah, you're talking about CE, that's right -
Not completely. Copying with pointers was my option if using IntToStr (because it requires strings). When you implement inttostr manually, there's no need in copying - just convert the chars pointers point at. Also, try-except blocks add significant boilerplate and should be avoided in perf-critical routines. TryEncode* are the right way to do. Well, that's your vision from the point of app's logic. But you should trust numbers only - because conversion operations could take just a small part of the whole cycle, f.ex., receiving + parsing + preprocessing + handling result. As a very simple test you could measure perf with empty handling phase (just receiving) and take this number as an ideal. Then add your logic and see what has changed. Then use your optimized functions and check again. Btw, now that you're not protected from invalid data by Copy+IntToStr, don't forget to check input. If source string has expected length, if chars belong to expected range and so on. I see no problems here
-
Is Delphi still taught in schools?
Fr0sT.Brutal replied to Mike Torrettinni's topic in Tips / Blogs / Tutorials / Videos
Why? -
...but not an option if performance is important
-
Integer overflow in tStringList.SaveToFile
Fr0sT.Brutal replied to Jud's topic in RTL and Delphi Object Pascal
On the one hand, I agree 2 Gb strings are close to nonsense. On the other hand, I see no strong reasons why the limit couldn't be at least 4 Gb (using signed integers for length, seriously?) or even 2^64 just like for dynarrays -
Why not just use TDateTime(0)? Well, first you should check and ensure that date parsing is the reason of slowdown in your workflow. There won't be much sense in extreme optimization of this routine if you have only 1 date value in 1Mb file. Then, avoiding string copy is the must-do when reaching the best performance. In your case for such short and fixed-length numbers there's no necessity in Copy SetLength(s, 2); s[1] := src[1]; s[2] := src[2]; IntToStr(s); s[1] := src[3]; s[2] := src[4]; IntToStr(s); ... Going deeper, var s: String; pSrc, pDest: PChar; begin SetLength(s, 2); pSrc := Pointer(src); pDest := Pointer(s); pDest^ := pSrc^; (pDest+1)^ := (pSrc+1)^; gives 2280% (!) perf gain over Copy when running in a loop (not an strictly clean test though because I allocated a string once and looped 30k times, but you have 5 2-char parts so reusing still makes sense). Further, instead of filling string + IntToStr, you could just do `DatePart := CharToDigit(Str[1])*10 + CharToDigit(Str[2])` where CharToDigit is *inline* function that does `Result := Ord(aChar) - Ord('0')` Of course, some validations should be added but that's the idea.
-
How to crash the ICS web server
Fr0sT.Brutal replied to Angus Robertson's topic in ICS - Internet Component Suite
Hmm, what's the request was in fact? Is that was 'Host: xxx' header field?