* (newer) 124-1
*/
- if (isempty(a) || isempty(b))
- return CMP(strcmp_ptr(a, b), 0);
+ a = strempty(a);
+ b = strempty(b);
for (;;) {
const sd_char *aa, *bb;
}
if (is_digit(*a) || is_digit(*b)) {
- /* Skip leading '0', to make 00123 equivalent to 123. */
- while (*a == '0')
- a++;
- while (*b == '0')
- b++;
-
/* Find the leading numeric segments. One may be an empty string. So,
* numeric segments are always newer than alpha segments. */
for (aa = a; is_digit(*aa); aa++)
for (bb = b; is_digit(*bb); bb++)
;
+ /* Check if one of the strings was empty, but the other not. */
+ r = CMP(a != aa, b != bb);
+ if (r != 0)
+ return r;
+
+ /* Skip leading '0', to make 00123 equivalent to 123. */
+ while (*a == '0')
+ a++;
+ while (*b == '0')
+ b++;
+
/* To compare numeric segments without parsing their values, first compare the
* lengths of the segments. Eg. 12345 vs 123, longer is newer. */
r = CMP(aa - a, bb - b);
TEST(strverscmp_improved) {
static const char * const versions[] = {
- "",
"~1",
+ "",
"ab",
"abb",
"abc",
/* invalid characters */
assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
+ /* some corner cases */
+ assert_se(strverscmp_improved("123.", "123") > 0); /* One more version segment */
+ assert_se(strverscmp_improved("12_3", "123") < 0); /* 12 < 123 */
+ assert_se(strverscmp_improved("12_3", "12") > 0); /* 3 > '' */
+ assert_se(strverscmp_improved("12_3", "12.3") > 0); /* 3 > '' */
+ assert_se(strverscmp_improved("123.0", "123") > 0); /* 0 > '' */
+ assert_se(strverscmp_improved("123_0", "123") > 0); /* 0 > '' */
+ assert_se(strverscmp_improved("123..0", "123.0") < 0); /* '' < 0 */
+
+ /* empty strings or strings with ignored characters only */
+ assert_se(strverscmp_improved("", NULL) == 0);
+ assert_se(strverscmp_improved(NULL, "") == 0);
+ assert_se(strverscmp_improved("0_", "0") == 0);
+ assert_se(strverscmp_improved("_0_", "0") == 0);
+ assert_se(strverscmp_improved("_0", "0") == 0);
+ assert_se(strverscmp_improved("0", "0___") == 0);
+ assert_se(strverscmp_improved("", "_") == 0);
+ assert_se(strverscmp_improved("_", "") == 0);
+ assert_se(strverscmp_improved("_", "_") == 0);
+ assert_se(strverscmp_improved("", "~") > 0);
+ assert_se(strverscmp_improved("~", "") < 0);
+ assert_se(strverscmp_improved("~", "~") == 0);
+
/* non-ASCII digits */
(void) setlocale(LC_NUMERIC, "ar_YE.utf8");
assert_se(strverscmp_improved("1٠١٢٣٤٥٦٧٨٩", "1") == 0);