Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/userdetect2/trunk/UserDetect2/vcl/AlphaNumSort.pas
Revision: 69
Committed: Wed Sep 30 04:43:31 2015 UTC (6 years, 10 months ago) by daniel-marschall
Content type: text/x-pascal
File size: 3352 byte(s)

File Contents

# Content
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.