Jump to content

Anders Melander

Members
  • Content Count

    2771
  • Joined

  • Last visited

  • Days Won

    147

Everything posted by Anders Melander

  1. Anders Melander

    UCS4StringToWideString broken?

    Yes it does: function UCS4StringToWideString(const S: UCS4String): _WideStr; var I: Integer; CharCount: Integer; begin SetLength(Result, Length(S) * 2 - 1); //Maximum possible number of characters CharCount := 0; I := 0; while I < Length(S) - 1 do begin if S[I] >= $10000 then begin Inc(CharCount); Result[CharCount] := WideChar((((S[I] - $00010000) shr 10) and $000003FF) or $D800); Inc(CharCount); Result[CharCount] := WideChar(((S[I] - $00010000) and $000003FF)or $DC00); end else begin Inc(CharCount); Result[CharCount] := WideChar(S[I]); end; Inc(I); end; SetLength(Result, CharCount); end; The bug is the Length(s)-1 in the while condition (or the < instead of <=). The first SetLength also seems strange. And can't see why it should do a -1 there.
  2. No. Seems like it's gone. Strange.
  3. Anders Melander

    ExtractFileDrive bug

    One could argue that it's equally meaningless to use ExtractFileDrive on that path since whatever comes after the "\\?\" is handled directly by the file system and not by the file namespace parser. I guess the correct thing to do would be to return an empty string as documented: I do not agree with your suggestion that it should attempt to extract anything if the string starts with "\\?\" (or \\.\ for that matter). The result would be meaningless in the context.
  4. Anders Melander

    Is variable value kept after For.. in ... do loop?

    I'd say that if you have records that size then the iterator is not the problem you should be focusing on
  5. I think you might be confusing UTF-8 and Unicode because your example is using unicode strings and not UTF-8 strings. If what you have is in fact unicode and you just want to remove non-printable characters then you can use the TCharacter class: for var i := Length(s)-1 downto 1 do if (not TCharacter.IsValid(s[i])) or (TCharacter.IsControl(s[i])) then Delete(s, i, 1);
  6. Anders Melander

    Is variable value kept after For.. in ... do loop?

    Why would calculating a pointer cause a cache miss?
  7. Anders Melander

    git - do you 'pull' before/after switching branches?

    Sure. For personal projects I rarely use branches at all. It's only when I start on something that I'm not sure I will end up using in the end (e.g. experiments) or some feature that will take so long to implement that I don't want it interfering with whatever else I'm working on) that I use branches. But even for personal projects it's good to be able to go back in time to find out what what you did that broke something. Sometime you can even use the commit message to clear up why some piece of code is there in case you forgot to document it properly with comments in the code. You could say that the individual code comments document the tactic while the commit message document the strategy. Of course it would be best if the code comments did both but we're not all super humans.
  8. Anders Melander

    git - do you 'pull' before/after switching branches?

    You should examine the diff of your changes before you commit them instead of just committing all files that has changed. Practices differ but for example when I have made a change to a form I only commit that specific change - and directly derived changes. All the Explicit* and Original* fluff that the IDE changes are left out. Also adding a file to a project usually result in 40-50 changes (relating to platforms I haven't even installed) of which only one or two need to be committed.
  9. Anders Melander

    git - do you 'pull' before/after switching branches?

    We also do all work in feature branches but our branches are always pushed to remote (and for this reason alone we almost never rebase). We need to have the branches on the remote for several reasons; There are mostly more than one person working on a feature and they need to have access to each others changes. Of course it's up to the individual if they want to create local branches of the feature branches and do their work in those. Personally I just stash and only push when I have something that I know will build. We also to have the branches on the remote in order to have the build server run unit- and integration tests on them. Finally when work on a feature branch is complete we create a pull request to have it merged into the main branch. When QA have tested the build, which they've grabbed from the builder server, someone performs code review on the changes and only then is the PR allowed to be merged into the main branch.
  10. Anders Melander

    string helpers question

    Yeah, that one is one of the more stupid things I've encountered. But what does it have to do with the naming?
  11. Anders Melander

    git - do you 'pull' before/after switching branches?

    I don't think you can push unless you're on the tip of a branch. Your changes would overwrite the changes made between your current commit and the remote tip. I guess the remote could do an automatic merge but would that then be made in a new commit or would it alter the commit you made? Doesn't seem likely.
  12. Anders Melander

    git - do you 'pull' before/after switching branches?

    What problem is that supposed to solve?
  13. Anders Melander

    string helpers question

    1 bit, 2 bit, 3 bit, 4 4 bit, 3 bit, 2 bit, 1 You're bit, he's bit, no bit, none - Eminem
  14. Anders Melander

    string helpers question

    I think maybe she used a 3 bit computer and the "7 days" legend is just the result of the actual count overflowing. Anyway. I was referring to an actual entity, not an imaginary one.
  15. Anders Melander

    string helpers question

    I'm not saying "don't use string helpers". I'm saying that if they had made them 1-based like God intended then there would have been less confusion. Now we have one set of functions that are 1-based and one that is 0-based. How is that improvement? Ironically I had to look at your 1-based example to figure out what you 0-based example did. Here's a 1-based version without the bias: begin Result := Value; if Result.StartsWith(Prefix, IgnoreCase) then Delete(Result, 1, Prefix.Length); end;
  16. In the calls to LoadFromStream set the Size parameter to 0 (zero). That resets the position to zero and copies everything in the source stream.
  17. Anders Melander

    string helpers question

    The manual apparently There's a string.ToLowerInvariant for that purpose. The ancient Egyptians? I think they just used a larger chisel for emphasis That also makes it easier to write the feature specification: Just copy everything that .NET does. In some cases they even copied their documentation verbatim but failed to realize that it referenced stuff that they hadn't copied. I think a big problems with the string helpers is that they operate on zero based string indices. As if we didn't have enough opportunity off-by-one errors already.
  18. Anders Melander

    Project Magician gotcha

    One of the first things I do after a fresh Delphi install is to mark the VCL source read-only. I don't know if that would have prevented it.
  19. Anders Melander

    More performance Stringgrid sorting algorithm help

    or any grid for that matter. Well I thought that was a given and that the excessive row count was just to exacerbate the poor performance for benchmark purposes.
  20. Anders Melander

    Recomended Translation API

    Google doesn't have an API anymore and even if they did it wouldn't be advisable to use it. Microsoft Translator Service has a free tier with a limit of 2 million characters per month. So far I haven't hit their limit with my own personal use. Microsoft Terminology Service is free. I haven't tried DeepL but I have it on my TODO list. They don't have a free tier though so it doesn't have high priority. Of these, for "small application texts", I would recommend the Microsoft Terminology Service. I usually get very good results with it. You can try it out in my translation tool (and look at the source for inspiration): That reminds me that I need to get a new version of BTM uploaded as the current one, compiled with D10.3.3, fails to communicate with the Microsoft Terminology Service SOAP service because of a bug in Delphi's SOAP library. Should be fixed in 10.4.1 AFAIK.
  21. Anders Melander

    More performance Stringgrid sorting algorithm help

    Yes. You are right.
  22. Anders Melander

    git workflow question

    It discards changes to all tracked files. Basically it makes sure that what you have on disk matches what's in your branch. You can also do a mixed reset. That moves the index in your commit history but keeps whatever you have on disk. Then there's a soft reset but I can't remember what that does as I never use it. The reason I'm doing a reset is that otherwise pull will do a merge with whatever I have on disk and that isn't what I want. I'm not actually doing anything since my tool does all this for me, but you get the picture. Personally I prefer Atlassian SourceTree. I have Tortoise Git installed as well because there are a few things it does better (Blame for one). I've not tried any of the commercial GUI clients. There was a thread here a few weeks back where different Git clients were discussed.
  23. Anders Melander

    More performance Stringgrid sorting algorithm help

    If you start with i := 1 then the 0 and 1 elements will always be swapped. If you then also change the test for (i = 0) to (i = 1) then the 0 and 1 elements will never be swapped. Try to run it in your head with just three elements in reverse sort order. iteration elements 0 3 2 1 i=0: inc ^ 1 3 2 1 swap and dec ^ 2 2 3 1 i=0: inc ^ 3 2 3 1 ok: inc ^ 4 2 3 1 swap and dec ^ 5 2 1 3 swap and dec ^ 6 1 2 3 i=0: inc ^ 7 1 2 3 ok: inc ^ 8 1 2 3 ok: inc ^ 9 1 2 3 done ^
  24. Anders Melander

    More performance Stringgrid sorting algorithm help

    Well now that I've had my fun here's a serious suggestion: type TGridCracker = class(TCustomGrid); procedure SortGrid(Grid: TCustomGrid; ACol: integer; Ascending: boolean); begin var Rows := TList<integer>.Create; Rows.Capacity := Grid.RowCount - Grid.FixedRows; // Populate list with row indices for var i := Grid.FixedRows to Grid.RowCount-1 do Rows.Add(i); // Sort the row indices Rows.Sort(TComparer<integer>.Construct( function(const A, B: integer): integer begin Result := AnsiCompareText(Grid.Cells[ACol, A], Grid.Cells[ACol, B]); if (not Ascending) then Result := -Result; end)); // Move the rows in-place to their new position Grid.BeginUpdate; try var ToIndex := Grid.FixedRows; for var FromIndex in Rows do if (FromIndex <> ToIndex) then TGridCracker(Grid).MoveRow(FromIndex, ToIndex); finally Grid.EndUpdate; end; end; I've not used TStringGrid in decades but I think it might be fast enough if you can get it to compile (I haven't tried). I'm assuming that the protected MoveRow method does what we need (i.e. move a whole row in the grid). It might not though. A minor optimization would be to use a TArray<integer> instead of a TList<integer> but the improvement would be minimal.
  25. Anders Melander

    More performance Stringgrid sorting algorithm help

    That won't work. You need to start at zero. That's cheating. Then you might as well just optimize it to use TList.Sort
×