2 * Copyright (c) 2004 Max Bowsher
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Max Bowsher
15 #include "version_compare.h"
17 static inline bool isdigit(char c
) { return (c
>= '0' && c
<= '9'); }
19 /* Sort two version numbers, comparing equivalently seperated strings of
22 * Returns a positive number if (a > b)
23 * Returns a negative number if (a < b)
24 * Returns zero if (a == b)
26 * Inspired but not equivalent to rpmvercmp().
28 int version_compare (std::string a
, std::string b
)
32 size_t apos1
, apos2
= 0, bpos1
, bpos2
= 0;
33 size_t alen
= a
.length(), blen
= b
.length();
37 while (apos2
< alen
&& bpos2
< blen
)
42 if (isdigit(a
[apos2
]))
44 while (apos2
< alen
&& isdigit(a
[apos2
])) apos2
++;
45 while (bpos2
< blen
&& isdigit(b
[bpos2
])) bpos2
++;
50 while (apos2
< alen
&& !isdigit(a
[apos2
])) apos2
++;
51 while (bpos2
< blen
&& !isdigit(b
[bpos2
])) bpos2
++;
55 /* if (apos1 == apos2) { a logical impossibility has happened; } */
57 /* isdigit(a[0]) != isdigit(b[0])
58 * arbitrarily sort the non-digit first */
59 if (bpos1
== bpos2
) return (isnum
? 1 : -1);
63 /* skip numeric leading zeros */
64 while (apos1
< alen
&& a
[apos1
] == '0') apos1
++;
65 while (bpos1
< blen
&& b
[bpos1
] == '0') bpos1
++;
67 /* if one number has more digits, it is greater */
68 if (apos2
-apos1
> bpos2
-bpos1
) return 1;
69 if (apos2
-apos1
< bpos2
-bpos1
) return -1;
72 /* do an ordinary lexicographic string comparison */
73 cval
= a
.compare(apos1
, apos2
-apos1
, b
, bpos1
, bpos2
-bpos1
);
74 if (cval
) return (cval
< 1 ? -1 : 1);
77 /* ran out of characters in one string, without finding a difference */
79 /* maybe they were the same version, but with different leading zeros */
80 if (apos2
== alen
&& bpos2
== blen
) return 0;
82 /* the version with a suffix remaining is greater */
83 return (apos2
< alen
? 1 : -1);
86 #ifdef TESTING_VERSION_COMPARE
97 static version_pair test_data
[] =
103 { "2.456", "2.1000" },
104 { "2.1000", "3.111" },
110 int main(int argc
, char* argv
[])
112 version_pair
*i
= test_data
;
116 cout
<< setw(10) << i
->a
<< ", " << setw(10) << i
->b
<< " : "
117 << version_compare(i
->a
, i
->b
) << ", " << version_compare(i
->b
, i
->a
)