Subversion Repositories userdetect2

Rev

Rev 69 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit AlphaNumSort;
  2.  
  3. (*
  4.  * The Alphanum Algorithm is an improved sorting algorithm for strings
  5.  * containing numbers.  Instead of sorting numbers in ASCII order like
  6.  * a standard sort, this algorithm sorts numbers in numeric order.
  7.  *
  8.  * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
  9.  *
  10.  * Translated from Java to Delphi by Daniel Marschall, www.daniel-marschall.de
  11.  * Revision 2015-09-30
  12.  *
  13.  *
  14.  * This library is free software; you can redistribute it and/or
  15.  * modify it under the terms of the GNU Lesser General Public
  16.  * License as published by the Free Software Foundation; either
  17.  * version 2.1 of the License, or any later version.
  18.  *
  19.  * This library is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  22.  * Lesser General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU Lesser General Public
  25.  * License along with this library; if not, write to the Free Software
  26.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  27.  *
  28.  *)
  29.  
  30. interface
  31.  
  32. uses
  33.   SysUtils;
  34.  
  35. function AlphaNumCompare(s1, s2: string): integer;
  36.  
  37. implementation
  38.  
  39. function isDigit(ch: char): boolean;
  40. begin
  41.   result := (ord(ch) >= 48) and (ord(ch) <= 57);
  42. end;
  43.  
  44. // Length of string is passed in for improved efficiency (only need to calculate it once)
  45. function getChunk(s: string; slength, marker: integer): string;
  46. var
  47.   chunk: string;
  48.   c: char;
  49. begin
  50.   c := s[marker+1];
  51.   chunk := chunk + c;
  52.   Inc(marker);
  53.   if isDigit(c) then
  54.   begin
  55.     while marker < slength do
  56.     begin
  57.       c := s[marker+1];
  58.       if not isDigit(c) then break;
  59.       chunk := chunk + c;
  60.       Inc(marker);
  61.     end;
  62.   end
  63.   else
  64.   begin
  65.     while marker < slength do
  66.     begin
  67.       c := s[marker+1];
  68.       if (isDigit(c)) then break;
  69.       chunk := chunk + c;
  70.       Inc(marker);
  71.     end;
  72.   end;
  73.   result := chunk;
  74. end;
  75.  
  76. function AlphaNumCompare(s1, s2: string): integer;
  77. var
  78.   s1Length, s2Length, thisChunkLength: integer;
  79.   thisMarker, thatMarker, i: integer;
  80.   thisChunk, thatChunk: string;
  81. begin
  82.   thisMarker := 0;
  83.   thatMarker := 0;
  84.   s1Length := Length(s1);
  85.   s2Length := Length(s2);
  86.  
  87.   while (thisMarker < s1Length) and (thatMarker < s2Length) do
  88.   begin
  89.     thisChunk := getChunk(s1, s1Length, thisMarker);
  90.     Inc(thisMarker, Length(thisChunk));
  91.  
  92.     thatChunk := getChunk(s2, s2Length, thatMarker);
  93.     Inc(thatMarker, Length(thatChunk));
  94.  
  95.     // If both chunks contain numeric characters, sort them numerically
  96.     if isDigit(thisChunk[1]) and isDigit(thatChunk[1]) then
  97.     begin
  98.       // Simple chunk comparison by length.
  99.       thisChunkLength := Length(thisChunk);
  100.       result := thisChunkLength - Length(thatChunk);
  101.       // If equal, the first different number counts
  102.       if result = 0 then
  103.       begin
  104.         for i := 0 to thisChunkLength-1 do
  105.         begin
  106.           result := ord(thisChunk[i+1]) - ord(thatChunk[i+1]);
  107.           if result <> 0 then Exit;
  108.         end;
  109.       end;
  110.     end
  111.     else
  112.     begin
  113.       result := CompareText(thisChunk, thatChunk);
  114.     end;
  115.  
  116.     if result <> 0 then Exit;
  117.   end;
  118.  
  119.   result := s1Length - s2Length;
  120. end;
  121.  
  122. end.
  123.