c-strcaseeq.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Optimized case-insensitive string comparison in C locale.
  2. Copyright (C) 2001-2002, 2007, 2009-2023 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file 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
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser 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