]> git.draconx.ca Git - gob-dx.git/blobdiff - src/gob-strcase.c
Allow building against Glib 1.x.
[gob-dx.git] / src / gob-strcase.c
diff --git a/src/gob-strcase.c b/src/gob-strcase.c
new file mode 100644 (file)
index 0000000..87c59a6
--- /dev/null
@@ -0,0 +1,176 @@
+/* c-strcasecmp.c -- case insensitive string comparator in C locale
+   Copyright (C) 1998-1999, 2005-2006, 2009-2021 Free Software Foundation, Inc.
+
+   Character handling in C locale.
+   Copyright (C) 2000-2003, 2006, 2008-2021 Free Software Foundation, Inc.
+
+   Stripped down copy of gnulib c-ctype and c-strcasecmp modules for
+   conditional fallback use.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <limits.h>
+
+#undef HAVE_G_ASCII_STRCASECMP
+#include "util.h"
+
+/* The functions defined in this file assume the "C" locale and a character
+   set without diacritics (ASCII-US or EBCDIC-US or something like that).
+   Even if the "C" locale on a particular system is an extension of the ASCII
+   character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+   is ISO-8859-1), the functions in this file recognize only the ASCII
+   characters.  */
+
+#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+    && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+    && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+    && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+    && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+    && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+    && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+    && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+    && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+    && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+    && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+    && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+    && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+    && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+    && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+    && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+    && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+    && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+    && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+    && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+    && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+    && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+    && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
+/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
+   Testing the value of '\n' and '\r' is not relevant.  */
+# define C_CTYPE_ASCII 1
+#elif ! (' ' == '\x40' && '0' == '\xf0'                     \
+         && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \
+         && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2')
+# error "Only ASCII and EBCDIC are supported"
+#endif
+
+#if 'A' < 0
+# error "EBCDIC and char is signed -- not supported"
+#endif
+
+/* Cases for lowercase hex letters, and lowercase letters, all offset by N.  */
+
+#define C_CTYPE_LOWER_A_THRU_F_N(N) \
+   case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \
+   case 'e' + (N): case 'f' + (N)
+#define C_CTYPE_LOWER_N(N) \
+   C_CTYPE_LOWER_A_THRU_F_N(N): \
+   case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \
+   case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \
+   case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \
+   case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \
+   case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N)
+
+#define C_CTYPE_LOWER C_CTYPE_LOWER_N(0)
+#define C_CTYPE_UPPER C_CTYPE_LOWER_N ('A' - 'a')
+
+
+/* Function definitions.  */
+
+/* Unlike the functions in <ctype.h>, which require an argument in the range
+   of the 'unsigned char' type, the functions here operate on values that are
+   in the 'unsigned char' range or in the 'char' range.  In other words,
+   when you have a 'char' value, you need to cast it before using it as
+   argument to a <ctype.h> function:
+
+         const char *s = ...;
+         if (isalpha ((unsigned char) *s)) ...
+
+   but you don't need to cast it for the functions defined in this file:
+
+         const char *s = ...;
+         if (c_isalpha (*s)) ...
+ */
+
+static int c_tolower(int c)
+{
+       switch (c) {
+       C_CTYPE_UPPER:
+               return c - 'A' + 'a';
+       default:
+               return c;
+       }
+}
+
+static int c_toupper(int c)
+{
+       switch (c) {
+       C_CTYPE_LOWER:
+               return c - 'a' + 'A';
+       default:
+               return c;
+       }
+}
+
+char *gob_strup(char *str)
+{
+       char *s;
+
+       for (s = str; *s; s++)
+               *s = c_toupper(*s);
+
+       return str;
+}
+
+char *gob_strdown(char *str)
+{
+       char *s;
+
+       for (s = str; *s; s++)
+               *s = c_tolower(*s);
+
+       return str;
+}
+
+int gob_strcasecmp(const char *s1, const char *s2)
+{
+       register const unsigned char *p1 = (const unsigned char *)s1;
+       register const unsigned char *p2 = (const unsigned char *)s2;
+       unsigned char c1, c2;
+
+       if (p1 == p2)
+               return 0;
+
+       do {
+               c1 = c_tolower (*p1);
+               c2 = c_tolower (*p2);
+
+               if (c1 == '\0')
+                       break;
+
+               ++p1;
+               ++p2;
+       } while (c1 == c2);
+
+       if (UCHAR_MAX <= INT_MAX) {
+               return c1 - c2;
+       } else {
+               /*
+                * On machines where 'char' and 'int' are types of the
+                * same size, the difference of two 'unsigned char' values
+                * - including the sign bit - doesn't fit in an 'int'.
+                */
+               return _GL_CMP (c1, c2);
+       }
+}