c-strcaseeq.h 4.3 KB

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