]>
git.ipfire.org Git - thirdparty/git.git/blob - versioncmp.c
a55c23ad57041a6f01b206e940706afb29cf21af
2 #include "string-list.h"
5 * versioncmp(): copied from string/strverscmp.c in glibc commit
6 * ee9247c38a8def24a59eb5cfb7196a98bef8cfdc, reformatted to Git coding
7 * style. The implementation is under LGPL-2.1 and Git relicenses it
12 * states: S_N: normal, S_I: comparing integral part, S_F: comparing
13 * fractionnal parts, S_Z: idem but with leading Zeroes only
20 /* result_type: CMP: return diff; LEN: compare using len_diff/diff */
24 static const struct string_list
*prereleases
;
25 static int initialized
;
28 * off is the offset of the first different character in the two strings
29 * s1 and s2. If either s1 or s2 contains a prerelease suffix starting
30 * at that offset, it will be forced to be on top.
32 * If both s1 and s2 contain a (different) suffix at that position,
33 * their order is determined by the order of those two suffixes in the
36 * Return non-zero if *diff contains the return value for versioncmp()
38 static int swap_prereleases(const char *s1
,
43 int i
, i1
= -1, i2
= -1;
45 for (i
= 0; i
< prereleases
->nr
; i
++) {
46 const char *suffix
= prereleases
->items
[i
].string
;
47 if (i1
== -1 && starts_with(s1
+ off
, suffix
))
49 if (i2
== -1 && starts_with(s2
+ off
, suffix
))
52 if (i1
== -1 && i2
== -1)
54 if (i1
>= 0 && i2
>= 0)
58 else /* if (i2 >= 0) */
64 * Compare S1 and S2 as strings holding indices/version numbers,
65 * returning less than, equal to or greater than zero if S1 is less
66 * than, equal to or greater than S2 (for more info, see the texinfo
70 int versioncmp(const char *s1
, const char *s2
)
72 const unsigned char *p1
= (const unsigned char *) s1
;
73 const unsigned char *p2
= (const unsigned char *) s2
;
78 * Symbol(s) 0 [1-9] others
79 * Transition (10) 0 (01) d (00) x
81 static const uint8_t next_state
[] = {
83 /* S_N */ S_N
, S_I
, S_Z
,
84 /* S_I */ S_N
, S_I
, S_I
,
85 /* S_F */ S_N
, S_F
, S_F
,
86 /* S_Z */ S_N
, S_F
, S_Z
89 static const int8_t result_type
[] = {
90 /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
92 /* S_N */ CMP
, CMP
, CMP
, CMP
, LEN
, CMP
, CMP
, CMP
, CMP
,
93 /* S_I */ CMP
, -1, -1, +1, LEN
, LEN
, +1, LEN
, LEN
,
94 /* S_F */ CMP
, CMP
, CMP
, CMP
, CMP
, CMP
, CMP
, CMP
, CMP
,
95 /* S_Z */ CMP
, +1, +1, -1, CMP
, CMP
, -1, CMP
, CMP
103 /* Hint: '0' is a digit too. */
104 state
= S_N
+ ((c1
== '0') + (isdigit (c1
) != 0));
106 while ((diff
= c1
- c2
) == 0) {
110 state
= next_state
[state
];
113 state
+= (c1
== '0') + (isdigit (c1
) != 0);
118 prereleases
= git_config_get_value_multi("versionsort.prereleasesuffix");
120 if (prereleases
&& swap_prereleases(s1
, s2
, (const char *) p1
- s1
- 1,
124 state
= result_type
[state
* 3 + (((c2
== '0') + (isdigit (c2
) != 0)))];
131 while (isdigit (*p1
++))
132 if (!isdigit (*p2
++))
135 return isdigit (*p2
) ? -1 : diff
;