aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'string/strcoll.c')
-rw-r--r--string/strcoll.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/string/strcoll.c b/string/strcoll.c
new file mode 100644
index 0000000000..ed4b35f80d
--- /dev/null
+++ b/string/strcoll.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <localeinfo.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Compare S1 and S2, returning less than, equal to or
+ greater than zero if the collated form of S1 is lexiographically
+ less than, equal to or greater than the collated form of S2. */
+int
+DEFUN(strcoll, (s1, s2), CONST char *s1 AND CONST char *s2)
+{
+ if (_collate_info == NULL || _collate_info->values == NULL)
+ return strcmp(s1, s2);
+ else
+ {
+ CONST unsigned char *CONST values = _collate_info->values;
+ CONST unsigned char *CONST offsets = _collate_info->offsets;
+
+ while (*s1 != '\0' && *s2 != '\0')
+ {
+ CONST unsigned char c1 = *s1++, c2 = *s2++;
+ CONST unsigned char v1 = values[c1], v2 = values[c2];
+ CONST unsigned char o1 = offsets[c1], o2 = offsets[c2];
+
+ if (v1 == UCHAR_MAX && o1 == 0)
+ /* This is a non-collating element. Skip it. */
+ --s2;
+ else if (v2 == UCHAR_MAX && o2 == 0)
+ --s1;
+ else if (v1 == UCHAR_MAX && o1 == CHAR_MAX)
+ {
+ /* This element collates lower than anything else. */
+ if (v2 != UCHAR_MAX || o2 != CHAR_MAX)
+ return -1;
+ }
+ else if (v2 == UCHAR_MAX && o2 == CHAR_MAX)
+ return 1;
+ else if (v1 != v2)
+ return v1 - v2;
+ else if (o1 != o2)
+ return o1 - o2;
+ }
+
+ if (*s1 == '\0')
+ return *s2 == '\0' ? 0 : -1;
+ else if (*s2 == '\0')
+ return 1;
+ return 0;
+ }
+}