]> Savannah Git Hosting - gnulib.git/commitdiff
string-desc: New function string_desc_c_casecmp.
authorBruno Haible <bruno@clisp.org>
Sun, 13 Oct 2024 10:01:08 +0000 (12:01 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 13 Oct 2024 10:05:39 +0000 (12:05 +0200)
* lib/string-desc.h: New declaration.
* lib/string-desc.c: Include <limits.h>, c-ctype.h.
(string_desc_c_casecmp): New function.
* modules/string-desc (Depends-on): Add c-ctype.
* tests/test-string-desc.c (main): Add tests of string_desc_c_casecmp.

ChangeLog
lib/string-desc.c
lib/string-desc.h
modules/string-desc
tests/test-string-desc.c

index d8aeaa5f51dd1d8bbc4ecca49ec91e25f7d38ef2..465b998ccc33a83c9957c38d63dcdf3d682e4031 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-10-13  Bruno Haible  <bruno@clisp.org>
+
+       string-desc: New function string_desc_c_casecmp.
+       * lib/string-desc.h: New declaration.
+       * lib/string-desc.c: Include <limits.h>, c-ctype.h.
+       (string_desc_c_casecmp): New function.
+       * modules/string-desc (Depends-on): Add c-ctype.
+       * tests/test-string-desc.c (main): Add tests of string_desc_c_casecmp.
+
 2024-10-13  Bruno Haible  <bruno@clisp.org>
 
        string-desc: Fix categorization string_desc_new_addr.
index 58a87e12205a8892569e012be58cae651c46150a..78992729bbc73114d1e08a7a4bd5dfd54e2605e3 100644 (file)
 /* Specification and inline definitions.  */
 #include "string-desc.h"
 
+#include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "c-ctype.h"
 #include "ialloc.h"
 #include "full-write.h"
 
@@ -83,6 +85,28 @@ string_desc_cmp (string_desc_t a, string_desc_t b)
     }
 }
 
+int
+string_desc_c_casecmp (string_desc_t a, string_desc_t b)
+{
+  /* Don't use memcasecmp here, since it uses the current locale, not the
+     "C" locale.  */
+  idx_t an = string_desc_length (a);
+  idx_t bn = string_desc_length (b);
+  const char *ap = string_desc_data (a);
+  const char *bp = string_desc_data (b);
+  idx_t n = (an < bn ? an : bn);
+  idx_t i;
+  for (i = 0; i < n; i++)
+    {
+      int ac = c_tolower ((unsigned char) ap[i]);
+      int bc = c_tolower ((unsigned char) bp[i]);
+      if (ac != bc)
+        return (UCHAR_MAX <= INT_MAX ? ac - bc : _GL_CMP (ac, bc));
+    }
+  /* Here i = n = min (an, bn).  */
+  return _GL_CMP (an, bn);
+}
+
 ptrdiff_t
 string_desc_index (string_desc_t s, char c)
 {
index ff9c86d6a0c29a36a497437598cee184e3f88858..0b8287121fb7ef971b518029998f7ddc69c573dd 100644 (file)
@@ -102,6 +102,12 @@ extern bool string_desc_endswith (string_desc_t s, string_desc_t suffix);
    'unsigned char'.  */
 extern int string_desc_cmp (string_desc_t a, string_desc_t b);
 
+/* Return > 0, == 0, or < 0 if A > B, A == B, A < B.
+   Either A or B must be entirely ASCII.
+   This uses a lexicographic ordering, where the bytes are compared as
+   'unsigned char', ignoring case, in the "C" locale.  */
+extern int string_desc_c_casecmp (string_desc_t a, string_desc_t b);
+
 /* Return the index of the first occurrence of C in S,
    or -1 if there is none.  */
 extern ptrdiff_t string_desc_index (string_desc_t s, char c);
index 047e2d390ca54fbc342af4c6eb7f5a24bf7a272b..e3f092dd09cd6a698ee1db8fd05612bcee170c61 100644 (file)
@@ -9,6 +9,7 @@ lib/string-desc-contains.c
 Depends-on:
 stdbool
 idx
+c-ctype
 ialloc
 extern-inline
 memchr
index c39077c567870c0d5e8eb131e942b418579a8acf..fbe538687bf647f77c266235064783b624804145 100644 (file)
@@ -94,6 +94,23 @@ main (int argc, char *argv[])
   ASSERT (string_desc_cmp (s2, s1) > 0);
   ASSERT (string_desc_cmp (s2, s2) == 0);
 
+  /* Test string_desc_c_casecmp.  */
+  ASSERT (string_desc_c_casecmp (s0, s0) == 0);
+  ASSERT (string_desc_c_casecmp (s0, s1) < 0);
+  ASSERT (string_desc_c_casecmp (s0, s2) < 0);
+  ASSERT (string_desc_c_casecmp (s1, s0) > 0);
+  ASSERT (string_desc_c_casecmp (s1, s1) == 0);
+  ASSERT (string_desc_c_casecmp (s1, s2) < 0);
+  ASSERT (string_desc_c_casecmp (s2, s0) > 0);
+  ASSERT (string_desc_c_casecmp (s2, s1) > 0);
+  ASSERT (string_desc_c_casecmp (s2, s2) == 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("acab"), string_desc_from_c ("AcAB")) == 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("AcAB"), string_desc_from_c ("acab")) == 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("aca"), string_desc_from_c ("AcAB")) < 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("AcAB"), string_desc_from_c ("aca")) > 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("aca"), string_desc_from_c ("Aca\377")) < 0);
+  ASSERT (string_desc_c_casecmp (string_desc_from_c ("Aca\377"), string_desc_from_c ("aca")) > 0);
+
   /* Test string_desc_index.  */
   ASSERT (string_desc_index (s0, 'o') == -1);
   ASSERT (string_desc_index (s2, 'o') == 12);