105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Optimized case-insensitive string comparison in C locale.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2001-2002, 2007, 2009-2012 Free Software Foundation, Inc.
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software: you can redistribute it and/or modify it
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   under the terms of the GNU General Public License as published
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   by the Free Software Foundation; either version 3 of the License, or
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (at your option) any later version.
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   General Public License for more details.
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Written by Bruno Haible <bruno@clisp.org>.  */
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "c-strcase.h"
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "c-ctype.h"
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* STRCASEEQ allows to optimize string comparison with a small literal string.
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   is semantically equivalent to
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     c_strcasecmp (s, "UTF-8") == 0
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   just faster.  */
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Help GCC to generate good code for string comparisons with
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   immediate strings. */
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined (__GNUC__) && defined (__OPTIMIZE__)
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Case insensitive comparison of ASCII characters.  */
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if C_CTYPE_ASCII
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define CASEEQ(other,upper) \
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define CASEEQ(other,upper) \
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' : (other) == (upper))
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#  define CASEEQ(other,upper) \
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     (c_toupper (other) == (upper))
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq9 (const char *s1, const char *s2)
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return c_strcasecmp (s1 + 9, s2 + 9) == 0;
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq8 (const char *s1, const char *s2, char s28)
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[8], s28))
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s28 == 0)
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq9 (s1, s2);
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq7 (const char *s1, const char *s2, char s27, char s28)
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[7], s27))
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s27 == 0)
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq8 (s1, s2, s28);
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[6], s26))
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s26 == 0)
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq7 (s1, s2, s27, s28);
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[5], s25))
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s25 == 0)
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq6 (s1, s2, s26, s27, s28);
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[4], s24))
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s24 == 0)
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq5 (s1, s2, s25, s26, s27, s28);
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[3], s23))
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s23 == 0)
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[2], s22))
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s22 == 0)
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[1], s21))
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s21 == 0)
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline int
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstrcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (CASEEQ (s1[0], s20))
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (s20 == 0)
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return 1;
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return 0;
17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  (c_strcasecmp (s1, s2) == 0)
18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
185