This source file includes following definitions.
- match_suffix
- order
- verrevcmp
- filevercmp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <sys/types.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <limits.h>
26
27 #include "lib/strutil.h"
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 static const char *
49 match_suffix (const char **str)
50 {
51 const char *match = NULL;
52 gboolean read_alpha = FALSE;
53
54 while (**str != '\0')
55 {
56 if (read_alpha)
57 {
58 read_alpha = FALSE;
59 if (!g_ascii_isalpha (**str) && **str != '~')
60 match = NULL;
61 }
62 else if (**str == '.')
63 {
64 read_alpha = TRUE;
65 if (match == NULL)
66 match = *str;
67 }
68 else if (!g_ascii_isalnum (**str) && **str != '~')
69 match = NULL;
70 (*str)++;
71 }
72
73 return match;
74 }
75
76
77
78
79 static int
80 order (unsigned char c)
81 {
82 if (g_ascii_isdigit (c))
83 return 0;
84 if (g_ascii_isalpha (c))
85 return c;
86 if (c == '~')
87 return -1;
88 return (int) c + UCHAR_MAX + 1;
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 static int
110 verrevcmp (const char *s1, size_t s1_len, const char *s2, size_t s2_len)
111 {
112 size_t s1_pos = 0;
113 size_t s2_pos = 0;
114
115 while (s1_pos < s1_len || s2_pos < s2_len)
116 {
117 int first_diff = 0;
118
119 while ((s1_pos < s1_len && !g_ascii_isdigit (s1[s1_pos]))
120 || (s2_pos < s2_len && !g_ascii_isdigit (s2[s2_pos])))
121 {
122 int s1_c = 0;
123 int s2_c = 0;
124
125 if (s1_pos != s1_len)
126 s1_c = order (s1[s1_pos]);
127 if (s2_pos != s2_len)
128 s2_c = order (s2[s2_pos]);
129
130 if (s1_c != s2_c)
131 return (s1_c - s2_c);
132
133 s1_pos++;
134 s2_pos++;
135 }
136
137 while (s1[s1_pos] == '0')
138 s1_pos++;
139 while (s2[s2_pos] == '0')
140 s2_pos++;
141
142 while (g_ascii_isdigit (s1[s1_pos]) && g_ascii_isdigit (s2[s2_pos]))
143 {
144 if (first_diff == 0)
145 first_diff = s1[s1_pos] - s2[s2_pos];
146
147 s1_pos++;
148 s2_pos++;
149 }
150
151 if (g_ascii_isdigit (s1[s1_pos]))
152 return 1;
153 if (g_ascii_isdigit (s2[s2_pos]))
154 return -1;
155 if (first_diff != 0)
156 return first_diff;
157 }
158
159 return 0;
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173 int
174 filevercmp (const char *s1, const char *s2)
175 {
176 const char *s1_pos, *s2_pos;
177 const char *s1_suffix, *s2_suffix;
178 size_t s1_len, s2_len;
179 int simple_cmp, result;
180
181
182 simple_cmp = strcmp (s1, s2);
183 if (simple_cmp == 0)
184 return 0;
185
186
187 if (*s1 == '\0')
188 return -1;
189 if (*s2 == '\0')
190 return 1;
191 if (DIR_IS_DOT (s1))
192 return -1;
193 if (DIR_IS_DOT (s2))
194 return 1;
195 if (DIR_IS_DOTDOT (s1))
196 return -1;
197 if (DIR_IS_DOTDOT (s2))
198 return 1;
199
200
201 if (*s1 == '.' && *s2 != '.')
202 return -1;
203 if (*s1 != '.' && *s2 == '.')
204 return 1;
205 if (*s1 == '.' && *s2 == '.')
206 {
207 s1++;
208 s2++;
209 }
210
211
212 s1_pos = s1;
213 s2_pos = s2;
214 s1_suffix = match_suffix (&s1_pos);
215 s2_suffix = match_suffix (&s2_pos);
216 s1_len = (s1_suffix != NULL ? s1_suffix : s1_pos) - s1;
217 s2_len = (s2_suffix != NULL ? s2_suffix : s2_pos) - s2;
218
219
220 if ((s1_suffix != NULL || s2_suffix != NULL) && (s1_len == s2_len)
221 && strncmp (s1, s2, s1_len) == 0)
222 {
223 s1_len = s1_pos - s1;
224 s2_len = s2_pos - s2;
225 }
226
227 result = verrevcmp (s1, s1_len, s2, s2_len);
228
229 return result == 0 ? simple_cmp : result;
230 }
231
232