diff options
author | Yorhel <git@yorhel.nl> | 2013-06-09 10:22:26 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2013-06-09 10:22:26 +0200 |
commit | a96bbfa5c3cfd2b1e5a4abe13e7940fa9d7e0144 (patch) | |
tree | e443e62376c10cb8b23b425be8bc12e8a54ec301 | |
parent | 0fcec90516b6b8da9e128f39b15f53a139e05b4f (diff) |
util/casestr: casestr_eq() -> casestr_cmp() + define some order
This makes it suitable for more use cases.
-rw-r--r-- | src/util/casestr.c | 13 | ||||
-rw-r--r-- | src/util/casestr.h | 31 | ||||
-rw-r--r-- | test/casestr.c | 8 |
3 files changed, 35 insertions, 17 deletions
diff --git a/src/util/casestr.c b/src/util/casestr.c index dceb1f8..2f694e9 100644 --- a/src/util/casestr.c +++ b/src/util/casestr.c @@ -165,13 +165,14 @@ size_t casestr_len(const char *buf) { } -bool casestr_eq(const char *a, const char *b) { - if(strcmp(a, b) != 0) - return false; +int casestr_cmp(const char *a, const char *b) { + int i = strcmp(a, b); + if(i) + return i; size_t maskoff = strlen(a)+1; /* == strlen(b)+1, after the above check */ - return a[maskoff] != b[maskoff] ? false : a[maskoff] - ? memcmp(a+maskoff, b+maskoff, casestr_masklen(a)) == 0 - : strcmp(a+maskoff, b+maskoff) == 0; + return a[maskoff] != b[maskoff] ? a[maskoff] - b[maskoff] : a[maskoff] + ? memcmp(a+maskoff, b+maskoff, casestr_masklen(a)) + : strcmp(a+maskoff, b+maskoff); } diff --git a/src/util/casestr.h b/src/util/casestr.h index daf586a..538de68 100644 --- a/src/util/casestr.h +++ b/src/util/casestr.h @@ -57,9 +57,9 @@ void casestr_fold(const char *str, kstring_t *dest); * * memcpy(.., dest.s, dest.l) * - * The length of the buffer does not have to be kept around, casestr_orig() can - * work without and it and it can be obtained with casestr_len() when needed. - */ + * The length of the buffer does not have to be kept around, casestr_orig() and + * casestr_cmp() can work without and it and it can be obtained with + * casestr_len() when needed. */ void casestr_create(const char *str, kstring_t *dest); @@ -72,15 +72,32 @@ void casestr_orig(const char *buf, kstring_t *dest); size_t casestr_len(const char *buf); -/* Compare two casestr buffers for equality. This should be equivalent to - * checking for strcmp(a, b) == 0 after obtaining the original strings using - * casestr_orig(), except that this function is faster. +/* Compare two casestr buffers. This is roughly equivalent to strcmp(oa, ob) + * after obtaining the original strings using casestr_orig(), except that this + * function is faster. Note that you can only assume that casestr_cmp(a, b) == + * strcmp(oa, ob) if the two strings are equal. If the strings do not casefold + * to the same string, then the result is equivalent to plain strcmp(a, b). + * Otherwise, if the strings do not have equal case, then which of the two + * strings is considered the largest of the two is somewhat arbitrary, but it + * is guaranteed to be deterministic. + * + * The above properties make this function suitable for two situations: + * 1. Checking whether the two strings are equivalent in a case-sensitive + * fashion, i.e. casestr_cmp(a, b) == 0. + * 2. Sorting a list of casestr buffers while ensuring that the order is + * deterministic even if both strings casefold to the same string. (But, of + * course, not necessarily when two strings compare as totally equal) + * + * This function may not really be suitable for sorting the original strings + * for human output. But then again, a strcmp() on the original strings likely + * isn't, either, since plain strcmp() doesn't understand UTF-8. You probably + * want a proper Unicode collation function for that. * * Note that two strings are NOT considered equivalent if one is represented * with a bitmask and the other with the original string appended to it. This * situation doesn't arise as long as both buffers were created using * casestr_create(). */ -bool casestr_eq(const char *, const char *); +int casestr_cmp(const char *, const char *); #endif /* vim: set noet sw=4 ts=4: */ diff --git a/test/casestr.c b/test/casestr.c index ed23db9..7be4a09 100644 --- a/test/casestr.c +++ b/test/casestr.c @@ -32,7 +32,7 @@ assert(b.l == sizeof out - 1);\ assert(memcmp(b.s, out, b.l) == 0);\ assert(casestr_len(b.s) == b.l);\ - assert(casestr_eq(b.s, out));\ + assert(casestr_cmp(b.s, out) == 0);\ kstring_t o = {};\ casestr_fold(in, &o);\ assert(!*in ? o.s == NULL : strcmp(o.s, b.s) == 0);\ @@ -57,9 +57,9 @@ int main(int argc, char **argv) { T(" 月姫 ≠ вот", " 月姫 ≠ вот\0\1\0"); T("ПрогиШара", "прогишара\0\x43\0"); - assert(!casestr_eq("aaa\0aAa", "aaa\0\5")); - assert( casestr_eq("aaa\0aaa", "aaa\0aaa")); - assert(!casestr_eq("прогишара\0\x43\0", "прогишара\0\x43\1")); + assert(casestr_cmp("aaa\0aAa", "aaa\0\5") > 0); + assert(casestr_cmp("aaa\0aaa", "aaa\0aaa") == 0); + assert(casestr_cmp("прогишара\0\x43\0", "прогишара\0\x43\1") < 0); return 0; } |