summaryrefslogtreecommitdiffstats
path: root/lib/util/charset
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/util/charset/codepoints.c15
-rw-r--r--lib/util/charset/tests/charset.c31
-rw-r--r--lib/util/charset/util_str.c9
3 files changed, 36 insertions, 19 deletions
diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c
index ea2c4be..8022627 100644
--- a/lib/util/charset/codepoints.c
+++ b/lib/util/charset/codepoints.c
@@ -26,6 +26,7 @@
#include "dynconfig/dynconfig.h"
#include "lib/util/debug.h"
#include "lib/util/byteorder.h"
+#include "lib/util/tsort.h"
#ifdef strcasecmp
#undef strcasecmp
@@ -16479,11 +16480,23 @@ _PUBLIC_ bool isupper_m(codepoint_t val)
*/
_PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
{
+ /*
+ * FIXME: this is unsuitable for use in a sort, as the
+ * comparison is intransitive.
+ *
+ * The problem is toupper_m() is only called on equality case,
+ * which has strange effects.
+ *
+ * Consider {'a', 'A', 'B'}.
+ * 'a' == 'A'
+ * 'a' > 'B' (lowercase letters come after upper)
+ * 'A' < 'B'
+ */
if (c1 == c2 ||
toupper_m(c1) == toupper_m(c2)) {
return 0;
}
- return c1 - c2;
+ return NUMERIC_CMP(c1, c2);
}
diff --git a/lib/util/charset/tests/charset.c b/lib/util/charset/tests/charset.c
index 547dc51..bca5449 100644
--- a/lib/util/charset/tests/charset.c
+++ b/lib/util/charset/tests/charset.c
@@ -72,16 +72,19 @@ static bool test_strcasecmp_m(struct torture_context *tctx)
const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 };
/* file.{accented e} in utf8 */
const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 };
- torture_assert_int_equal(tctx, strcasecmp_m("foo", "bar"), 4, "different strings both lower");
- torture_assert_int_equal(tctx, strcasecmp_m("foo", "Bar"), 4, "different strings lower/upper");
- torture_assert_int_equal(tctx, strcasecmp_m("Foo", "bar"), 4, "different strings upper/lower");
- torture_assert_int_equal(tctx, strcasecmp_m("AFoo", "_bar"), 2, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", "bar"), 0, "different strings both lower");
+ torture_assert_int_less(tctx, strcasecmp_m("bar", "foo"), 0, "different strings both lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", "Bar"), 0, "different strings lower/upper");
+ torture_assert_int_greater(tctx, strcasecmp_m("Foo", "bar"), 0, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strcasecmp_m("AFoo", "_bar"), 0, "different strings upper/lower");
torture_assert_int_equal(tctx, strcasecmp_m("foo", "foo"), 0, "same case strings");
torture_assert_int_equal(tctx, strcasecmp_m("foo", "Foo"), 0, "different case strings");
- torture_assert_int_equal(tctx, strcasecmp_m(NULL, "Foo"), -1, "one NULL");
- torture_assert_int_equal(tctx, strcasecmp_m("foo", NULL), 1, "other NULL");
+ torture_assert_int_greater(tctx, strcasecmp_m("food", "Foo"), 0, "strings differ towards the end");
+ torture_assert_int_less(tctx, strcasecmp_m("food", "Fool"), 0, "strings differ towards the end");
+ torture_assert_int_less(tctx, strcasecmp_m(NULL, "Foo"), 0, "one NULL");
+ torture_assert_int_greater(tctx, strcasecmp_m("foo", NULL), 0, "other NULL");
torture_assert_int_equal(tctx, strcasecmp_m(NULL, NULL), 0, "both NULL");
- torture_assert_int_equal(tctx, strcasecmp_m(file_iso8859_1, file_utf8), 38,
+ torture_assert_int_greater(tctx, strcasecmp_m(file_iso8859_1, file_utf8), 0,
"file.{accented e} should differ");
return true;
}
@@ -151,19 +154,19 @@ static bool test_strncasecmp_m(struct torture_context *tctx)
const char file_iso8859_1[7] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xe9, 0 };
/* file.{accented e} in utf8 */
const char file_utf8[8] = { 0x66, 0x69, 0x6c, 0x65, 0x2d, 0xc3, 0xa9, 0 };
- torture_assert_int_equal(tctx, strncasecmp_m("foo", "bar", 3), 4, "different strings both lower");
- torture_assert_int_equal(tctx, strncasecmp_m("foo", "Bar", 3), 4, "different strings lower/upper");
- torture_assert_int_equal(tctx, strncasecmp_m("Foo", "bar", 3), 4, "different strings upper/lower");
- torture_assert_int_equal(tctx, strncasecmp_m("AFoo", "_bar", 4), 2, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", "bar", 3), 0, "different strings both lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", "Bar", 3), 0, "different strings lower/upper");
+ torture_assert_int_greater(tctx, strncasecmp_m("Foo", "bar", 3), 0, "different strings upper/lower");
+ torture_assert_int_greater(tctx, strncasecmp_m("AFoo", "_bar", 4), 0, "different strings upper/lower");
torture_assert_int_equal(tctx, strncasecmp_m("foo", "foo", 3), 0, "same case strings");
torture_assert_int_equal(tctx, strncasecmp_m("foo", "Foo", 3), 0, "different case strings");
torture_assert_int_equal(tctx, strncasecmp_m("fool", "Foo", 3),0, "different case strings");
torture_assert_int_equal(tctx, strncasecmp_m("fool", "Fool", 40), 0, "over size");
torture_assert_int_equal(tctx, strncasecmp_m("BLA", "Fool", 0),0, "empty");
- torture_assert_int_equal(tctx, strncasecmp_m(NULL, "Foo", 3), -1, "one NULL");
- torture_assert_int_equal(tctx, strncasecmp_m("foo", NULL, 3), 1, "other NULL");
+ torture_assert_int_less(tctx, strncasecmp_m(NULL, "Foo", 3), 0, "one NULL");
+ torture_assert_int_greater(tctx, strncasecmp_m("foo", NULL, 3), 0, "other NULL");
torture_assert_int_equal(tctx, strncasecmp_m(NULL, NULL, 3), 0, "both NULL");
- torture_assert_int_equal(tctx, strncasecmp_m(file_iso8859_1, file_utf8, 6), 38,
+ torture_assert_int_greater(tctx, strncasecmp_m(file_iso8859_1, file_utf8, 6), 0,
"file.{accented e} should differ");
return true;
}
diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c
index 1650c9b..c52b773 100644
--- a/lib/util/charset/util_str.c
+++ b/lib/util/charset/util_str.c
@@ -26,6 +26,7 @@
#include "system/locale.h"
#include "charset.h"
#include "lib/util/fault.h"
+#include "lib/util/tsort.h"
#ifdef strcasecmp
#undef strcasecmp
@@ -79,10 +80,10 @@ _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
continue;
}
- return l1 - l2;
+ return NUMERIC_CMP(l1, l2);
}
- return *s1 - *s2;
+ return NUMERIC_CMP(*s1, *s2);
}
/**
@@ -156,14 +157,14 @@ _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
continue;
}
- return l1 - l2;
+ return NUMERIC_CMP(l1, l2);
}
if (n == 0) {
return 0;
}
- return *s1 - *s2;
+ return NUMERIC_CMP(*s1, *s2);
}
/**