Home | History | Annotate | Download | only in lib
      1 /* Optimized case-insensitive string comparison in C locale.
      2    Copyright (C) 2001-2002, 2007, 2009-2012 Free Software Foundation, Inc.
      3 
      4    This program is free software: you can redistribute it and/or modify it
      5    under the terms of the GNU General Public License as published
      6    by the Free Software Foundation; either version 3 of the License, or
      7    (at your option) any later version.
      8 
      9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License
     15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     16 
     17 /* Written by Bruno Haible <bruno (at) clisp.org>.  */
     18 
     19 #include "c-strcase.h"
     20 #include "c-ctype.h"
     21 
     22 /* STRCASEEQ allows to optimize string comparison with a small literal string.
     23      STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
     24    is semantically equivalent to
     25      c_strcasecmp (s, "UTF-8") == 0
     26    just faster.  */
     27 
     28 /* Help GCC to generate good code for string comparisons with
     29    immediate strings. */
     30 #if defined (__GNUC__) && defined (__OPTIMIZE__)
     31 
     32 /* Case insensitive comparison of ASCII characters.  */
     33 # if C_CTYPE_ASCII
     34 #  define CASEEQ(other,upper) \
     35      (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
     36 # elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
     37 #  define CASEEQ(other,upper) \
     38      (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' : (other) == (upper))
     39 # else
     40 #  define CASEEQ(other,upper) \
     41      (c_toupper (other) == (upper))
     42 # endif
     43 
     44 static inline int
     45 strcaseeq9 (const char *s1, const char *s2)
     46 {
     47   return c_strcasecmp (s1 + 9, s2 + 9) == 0;
     48 }
     49 
     50 static inline int
     51 strcaseeq8 (const char *s1, const char *s2, char s28)
     52 {
     53   if (CASEEQ (s1[8], s28))
     54     {
     55       if (s28 == 0)
     56         return 1;
     57       else
     58         return strcaseeq9 (s1, s2);
     59     }
     60   else
     61     return 0;
     62 }
     63 
     64 static inline int
     65 strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
     66 {
     67   if (CASEEQ (s1[7], s27))
     68     {
     69       if (s27 == 0)
     70         return 1;
     71       else
     72         return strcaseeq8 (s1, s2, s28);
     73     }
     74   else
     75     return 0;
     76 }
     77 
     78 static inline int
     79 strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
     80 {
     81   if (CASEEQ (s1[6], s26))
     82     {
     83       if (s26 == 0)
     84         return 1;
     85       else
     86         return strcaseeq7 (s1, s2, s27, s28);
     87     }
     88   else
     89     return 0;
     90 }
     91 
     92 static inline int
     93 strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
     94 {
     95   if (CASEEQ (s1[5], s25))
     96     {
     97       if (s25 == 0)
     98         return 1;
     99       else
    100         return strcaseeq6 (s1, s2, s26, s27, s28);
    101     }
    102   else
    103     return 0;
    104 }
    105 
    106 static inline int
    107 strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
    108 {
    109   if (CASEEQ (s1[4], s24))
    110     {
    111       if (s24 == 0)
    112         return 1;
    113       else
    114         return strcaseeq5 (s1, s2, s25, s26, s27, s28);
    115     }
    116   else
    117     return 0;
    118 }
    119 
    120 static inline int
    121 strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
    122 {
    123   if (CASEEQ (s1[3], s23))
    124     {
    125       if (s23 == 0)
    126         return 1;
    127       else
    128         return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
    129     }
    130   else
    131     return 0;
    132 }
    133 
    134 static inline int
    135 strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
    136 {
    137   if (CASEEQ (s1[2], s22))
    138     {
    139       if (s22 == 0)
    140         return 1;
    141       else
    142         return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
    143     }
    144   else
    145     return 0;
    146 }
    147 
    148 static inline int
    149 strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
    150 {
    151   if (CASEEQ (s1[1], s21))
    152     {
    153       if (s21 == 0)
    154         return 1;
    155       else
    156         return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
    157     }
    158   else
    159     return 0;
    160 }
    161 
    162 static inline int
    163 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)
    164 {
    165   if (CASEEQ (s1[0], s20))
    166     {
    167       if (s20 == 0)
    168         return 1;
    169       else
    170         return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
    171     }
    172   else
    173     return 0;
    174 }
    175 
    176 #define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
    177   strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
    178 
    179 #else
    180 
    181 #define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
    182   (c_strcasecmp (s1, s2) == 0)
    183 
    184 #endif
    185