exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / mbmemcasecmp.c
bloba6091c750a43af54ed5f82c8ead02f5f34231519
1 /* Compare two memory areas with possibly different lengths, case-insensitive.
2 Copyright (C) 1998-1999, 2005-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2009,
4 based on earlier glibc code.
6 This file is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation, either version 3 of the
9 License, or (at your option) any later version.
11 This file is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>. */
19 #include <config.h>
21 /* Specification. */
22 #include "mbmemcasecmp.h"
24 #include <ctype.h>
25 #include <limits.h>
26 #include <stdlib.h>
28 #if GNULIB_MCEL_PREFER
29 # include "mcel.h"
30 #else
31 # include "mbiterf.h"
32 #endif
34 int
35 mbmemcasecmp (const char *s1, size_t n1, const char *s2, size_t n2)
37 if (s1 == s2)
38 return _GL_CMP (n1, n2);
40 const char *iter1 = s1;
41 const char *iter2 = s2;
42 const char *s1_end = s1 + n1;
43 const char *s2_end = s2 + n2;
45 if (MB_CUR_MAX > 1)
47 #if GNULIB_MCEL_PREFER
48 while ((iter1 < s1_end) & (iter2 < s2_end))
50 mcel_t g1 = mcel_scan (iter1, s1_end); iter1 += g1.len;
51 mcel_t g2 = mcel_scan (iter2, s2_end); iter2 += g2.len;
52 int cmp = mcel_tocmp (c32tolower, g1, g2);
53 if (cmp)
54 return cmp;
56 return (iter1 < s1_end) - (iter2 < s2_end);
57 #else
58 mbif_state_t state1;
59 mbif_init (state1);
61 mbif_state_t state2;
62 mbif_init (state2);
64 while (mbif_avail (state1, iter1, s1_end)
65 && mbif_avail (state2, iter2, s2_end))
67 mbchar_t cur1 = mbif_next (state1, iter1, s1_end);
68 mbchar_t cur2 = mbif_next (state2, iter2, s2_end);
69 int cmp = mb_casecmp (cur1, cur2);
71 if (cmp != 0)
72 return cmp;
74 iter1 += mb_len (cur1);
75 iter2 += mb_len (cur2);
77 if (mbif_avail (state1, iter1, s1_end))
78 /* s2 terminated before s1. */
79 return 1;
80 if (mbif_avail (state2, iter2, s2_end))
81 /* s1 terminated before s2. */
82 return -1;
83 return 0;
84 #endif
86 else
88 while (iter1 < s1_end && iter2 < s2_end)
90 unsigned char c1 = *iter1++;
91 unsigned char c2 = *iter2++;
92 /* On machines where 'char' and 'int' are types of the same size,
93 the difference of two 'unsigned char' values - including
94 the sign bit - doesn't fit in an 'int'. */
95 int cmp = UCHAR_MAX <= INT_MAX ? c1 - c2 : _GL_CMP (c1, c2);
96 if (cmp != 0)
98 c1 = tolower (c1);
99 if (c1 != c2)
101 c2 = tolower (c2);
102 cmp = UCHAR_MAX <= INT_MAX ? c1 - c2 : _GL_CMP (c1, c2);
103 if (cmp != 0)
104 return cmp;
108 if (iter1 < s1_end)
109 /* s2 terminated before s1. */
110 return 1;
111 if (iter2 < s2_end)
112 /* s1 terminated before s2. */
113 return -1;
114 return 0;