This is part two of my previous post. Sadly, yesterday I didn’t know I was writing part one.
Yesterday evening, having taken my ported StrCmpLogicalW code home, I set out to put it through some more rigorous testing. But alas, it didn’t even take 10 seconds to find issues:
- It didn’t sort the same as Windows Explorer, because it included spaces in the comparison.
- Integers can overflow quite easily – it doesn’t require an unreasonably long numeric file name to do so.
So today I share the fixed version.
The updated implementation
Despite my comments yesterday about keeping the same function name as the C code I converted, I decided to do the more sensible and standard thing for managed C# code this time. This is now an extension method on the managed string type, called CompareNumeric. The logic is essentially the same as yesterday’s code, and I will describe my changes below…
- The first thing it now does after checking that the strings are not null, is to remove spaces. (And thus now it sorts exactly the same as Windows Explorer.)
- Following removing characters, out of habit I then check that the strings’ lengths are greater than zero. Of course zero length file names (or file names consisting of only spaces) are illegal anyway. (Still, it’s a good habit.)
- Yesterday I made a joke of deliberately not using a StringBuilder to build strings. This time, I did it properly.
- Yesterday’s code used 32-bit integers. Now it uses 64-bit integers. Any numeric file name string that evaluates to larger than a long integer is now treated as Int64.MaxValue. And if you have more than one in the same directory (Why would anybody do that?) then they will all be considered equal. (This may differ to the Microsoft StrCmpLogicalW implementation, and hence the Windows Explorer sorting. Who knows? Not me. Nor do I care.)
- When parsing the numbers to compare, yesterday’s code included an unnecessary side-effect of converting the C code. That is, the C code used StrToIntEx, which converts all valid characters following the pointer. But the C developer still needed to then increment their original pointer past the already converted characters. (I converted the characters in a for loop, then incremented my index just like they did their pointer.) Looking at it again, this time I just used a simple while loop, incrementing my index at the same time – thus no need for the code denoted by the “Skip” comment of yesterday’s code.
Btw, as mentioned in item 3 (referring the previous code), I reserve the right to do stupid non-standard things in my code, such as building a string from characters using a List<char> instead of a StringBuilder. I always do such things deliberately, and call it out. I trust that anyone who uses my code has enough brains to be aware of such things and be able to modify it if needed, where needed. (I hate when people just copy and paste code, with zero understanding. The fun in programming is in figuring things out yourself, and when you can’t do it yourself, in learning how.)
I hope that this code may be useful to someone…
FYI, this is probably the first and last time that I’ll ever write so much tedious and unnecessary detail. Having been retrenched, but required to work my notice period, I’m sitting here bored out of my mind, waiting for the month to end so that I can start my new job.
The result of sorting this way (in my Windows Forms application)
And lastly, to give this post some colour and show the results of this code, here are a couple of screenshots. First Windows Explorer, then the browser from my RomyView application (the download has been updated with the code from this post) – both showing thumbnail view while sorting by type on the same directory…