14536c563SJohn Marino /* Optimized case-insensitive string comparison in C locale.
2*6ea1f93eSDaniel Fojt    Copyright (C) 2001-2002, 2007, 2009-2018 Free Software Foundation, Inc.
34536c563SJohn Marino 
44536c563SJohn Marino    This program is free software: you can redistribute it and/or modify it
54536c563SJohn Marino    under the terms of the GNU General Public License as published
64536c563SJohn Marino    by the Free Software Foundation; either version 3 of the License, or
74536c563SJohn Marino    (at your option) any later version.
84536c563SJohn Marino 
94536c563SJohn Marino    This program is distributed in the hope that it will be useful,
104536c563SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
114536c563SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
124536c563SJohn Marino    General Public License for more details.
134536c563SJohn Marino 
144536c563SJohn Marino    You should have received a copy of the GNU General Public License
15*6ea1f93eSDaniel Fojt    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
164536c563SJohn Marino 
174536c563SJohn Marino /* Written by Bruno Haible <bruno@clisp.org>.  */
184536c563SJohn Marino 
194536c563SJohn Marino #include "c-strcase.h"
204536c563SJohn Marino #include "c-ctype.h"
214536c563SJohn Marino 
224536c563SJohn Marino /* STRCASEEQ allows to optimize string comparison with a small literal string.
234536c563SJohn Marino      STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
244536c563SJohn Marino    is semantically equivalent to
254536c563SJohn Marino      c_strcasecmp (s, "UTF-8") == 0
264536c563SJohn Marino    just faster.  */
274536c563SJohn Marino 
284536c563SJohn Marino /* Help GCC to generate good code for string comparisons with
294536c563SJohn Marino    immediate strings. */
304536c563SJohn Marino #if defined (__GNUC__) && defined (__OPTIMIZE__)
314536c563SJohn Marino 
324536c563SJohn Marino /* Case insensitive comparison of ASCII characters.  */
334536c563SJohn Marino # if C_CTYPE_ASCII
344536c563SJohn Marino #  define CASEEQ(other,upper) \
354536c563SJohn Marino      (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
364536c563SJohn Marino # else
374536c563SJohn Marino #  define CASEEQ(other,upper) \
384536c563SJohn Marino      (c_toupper (other) == (upper))
394536c563SJohn Marino # endif
404536c563SJohn Marino 
414536c563SJohn Marino static inline int
strcaseeq9(const char * s1,const char * s2)424536c563SJohn Marino strcaseeq9 (const char *s1, const char *s2)
434536c563SJohn Marino {
444536c563SJohn Marino   return c_strcasecmp (s1 + 9, s2 + 9) == 0;
454536c563SJohn Marino }
464536c563SJohn Marino 
474536c563SJohn Marino static inline int
strcaseeq8(const char * s1,const char * s2,char s28)484536c563SJohn Marino strcaseeq8 (const char *s1, const char *s2, char s28)
494536c563SJohn Marino {
504536c563SJohn Marino   if (CASEEQ (s1[8], s28))
514536c563SJohn Marino     {
524536c563SJohn Marino       if (s28 == 0)
534536c563SJohn Marino         return 1;
544536c563SJohn Marino       else
554536c563SJohn Marino         return strcaseeq9 (s1, s2);
564536c563SJohn Marino     }
574536c563SJohn Marino   else
584536c563SJohn Marino     return 0;
594536c563SJohn Marino }
604536c563SJohn Marino 
614536c563SJohn Marino static inline int
strcaseeq7(const char * s1,const char * s2,char s27,char s28)624536c563SJohn Marino strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
634536c563SJohn Marino {
644536c563SJohn Marino   if (CASEEQ (s1[7], s27))
654536c563SJohn Marino     {
664536c563SJohn Marino       if (s27 == 0)
674536c563SJohn Marino         return 1;
684536c563SJohn Marino       else
694536c563SJohn Marino         return strcaseeq8 (s1, s2, s28);
704536c563SJohn Marino     }
714536c563SJohn Marino   else
724536c563SJohn Marino     return 0;
734536c563SJohn Marino }
744536c563SJohn Marino 
754536c563SJohn Marino static inline int
strcaseeq6(const char * s1,const char * s2,char s26,char s27,char s28)764536c563SJohn Marino strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
774536c563SJohn Marino {
784536c563SJohn Marino   if (CASEEQ (s1[6], s26))
794536c563SJohn Marino     {
804536c563SJohn Marino       if (s26 == 0)
814536c563SJohn Marino         return 1;
824536c563SJohn Marino       else
834536c563SJohn Marino         return strcaseeq7 (s1, s2, s27, s28);
844536c563SJohn Marino     }
854536c563SJohn Marino   else
864536c563SJohn Marino     return 0;
874536c563SJohn Marino }
884536c563SJohn Marino 
894536c563SJohn Marino static inline int
strcaseeq5(const char * s1,const char * s2,char s25,char s26,char s27,char s28)904536c563SJohn Marino strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
914536c563SJohn Marino {
924536c563SJohn Marino   if (CASEEQ (s1[5], s25))
934536c563SJohn Marino     {
944536c563SJohn Marino       if (s25 == 0)
954536c563SJohn Marino         return 1;
964536c563SJohn Marino       else
974536c563SJohn Marino         return strcaseeq6 (s1, s2, s26, s27, s28);
984536c563SJohn Marino     }
994536c563SJohn Marino   else
1004536c563SJohn Marino     return 0;
1014536c563SJohn Marino }
1024536c563SJohn Marino 
1034536c563SJohn Marino static inline int
strcaseeq4(const char * s1,const char * s2,char s24,char s25,char s26,char s27,char s28)1044536c563SJohn Marino strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
1054536c563SJohn Marino {
1064536c563SJohn Marino   if (CASEEQ (s1[4], s24))
1074536c563SJohn Marino     {
1084536c563SJohn Marino       if (s24 == 0)
1094536c563SJohn Marino         return 1;
1104536c563SJohn Marino       else
1114536c563SJohn Marino         return strcaseeq5 (s1, s2, s25, s26, s27, s28);
1124536c563SJohn Marino     }
1134536c563SJohn Marino   else
1144536c563SJohn Marino     return 0;
1154536c563SJohn Marino }
1164536c563SJohn Marino 
1174536c563SJohn Marino static inline int
strcaseeq3(const char * s1,const char * s2,char s23,char s24,char s25,char s26,char s27,char s28)1184536c563SJohn Marino strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
1194536c563SJohn Marino {
1204536c563SJohn Marino   if (CASEEQ (s1[3], s23))
1214536c563SJohn Marino     {
1224536c563SJohn Marino       if (s23 == 0)
1234536c563SJohn Marino         return 1;
1244536c563SJohn Marino       else
1254536c563SJohn Marino         return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
1264536c563SJohn Marino     }
1274536c563SJohn Marino   else
1284536c563SJohn Marino     return 0;
1294536c563SJohn Marino }
1304536c563SJohn Marino 
1314536c563SJohn Marino static inline int
strcaseeq2(const char * s1,const char * s2,char s22,char s23,char s24,char s25,char s26,char s27,char s28)1324536c563SJohn Marino strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
1334536c563SJohn Marino {
1344536c563SJohn Marino   if (CASEEQ (s1[2], s22))
1354536c563SJohn Marino     {
1364536c563SJohn Marino       if (s22 == 0)
1374536c563SJohn Marino         return 1;
1384536c563SJohn Marino       else
1394536c563SJohn Marino         return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
1404536c563SJohn Marino     }
1414536c563SJohn Marino   else
1424536c563SJohn Marino     return 0;
1434536c563SJohn Marino }
1444536c563SJohn Marino 
1454536c563SJohn Marino static inline int
strcaseeq1(const char * s1,const char * s2,char s21,char s22,char s23,char s24,char s25,char s26,char s27,char s28)1464536c563SJohn Marino strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
1474536c563SJohn Marino {
1484536c563SJohn Marino   if (CASEEQ (s1[1], s21))
1494536c563SJohn Marino     {
1504536c563SJohn Marino       if (s21 == 0)
1514536c563SJohn Marino         return 1;
1524536c563SJohn Marino       else
1534536c563SJohn Marino         return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
1544536c563SJohn Marino     }
1554536c563SJohn Marino   else
1564536c563SJohn Marino     return 0;
1574536c563SJohn Marino }
1584536c563SJohn Marino 
1594536c563SJohn Marino static inline int
strcaseeq0(const char * s1,const char * s2,char s20,char s21,char s22,char s23,char s24,char s25,char s26,char s27,char s28)1604536c563SJohn Marino strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
1614536c563SJohn Marino {
1624536c563SJohn Marino   if (CASEEQ (s1[0], s20))
1634536c563SJohn Marino     {
1644536c563SJohn Marino       if (s20 == 0)
1654536c563SJohn Marino         return 1;
1664536c563SJohn Marino       else
1674536c563SJohn Marino         return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
1684536c563SJohn Marino     }
1694536c563SJohn Marino   else
1704536c563SJohn Marino     return 0;
1714536c563SJohn Marino }
1724536c563SJohn Marino 
1734536c563SJohn Marino #define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
1744536c563SJohn Marino   strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
1754536c563SJohn Marino 
1764536c563SJohn Marino #else
1774536c563SJohn Marino 
1784536c563SJohn Marino #define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
1794536c563SJohn Marino   (c_strcasecmp (s1, s2) == 0)
1804536c563SJohn Marino 
1814536c563SJohn Marino #endif
182