strcase.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. #include "curl_setup.h"
  23. #include <curl/curl.h>
  24. #include "strcase.h"
  25. static char raw_tolower(char in);
  26. /* Portable, consistent toupper. Do not use toupper() because its behavior is
  27. altered by the current locale. */
  28. char Curl_raw_toupper(char in)
  29. {
  30. if(in >= 'a' && in <= 'z')
  31. return (char)('A' + in - 'a');
  32. return in;
  33. }
  34. /* Portable, consistent tolower. Do not use tolower() because its behavior is
  35. altered by the current locale. */
  36. static char raw_tolower(char in)
  37. {
  38. if(in >= 'A' && in <= 'Z')
  39. return (char)('a' + in - 'A');
  40. return in;
  41. }
  42. /*
  43. * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is
  44. * meant to be locale independent and only compare strings we know are safe
  45. * for this. See
  46. * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some
  47. * further explanation to why this function is necessary.
  48. *
  49. * @unittest: 1301
  50. */
  51. int Curl_strcasecompare(const char *first, const char *second)
  52. {
  53. while(*first && *second) {
  54. if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
  55. /* get out of the loop as soon as they don't match */
  56. break;
  57. first++;
  58. second++;
  59. }
  60. /* we do the comparison here (possibly again), just to make sure that if the
  61. loop above is skipped because one of the strings reached zero, we must not
  62. return this as a successful match */
  63. return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
  64. }
  65. int Curl_safe_strcasecompare(const char *first, const char *second)
  66. {
  67. if(first && second)
  68. /* both pointers point to something then compare them */
  69. return Curl_strcasecompare(first, second);
  70. /* if both pointers are NULL then treat them as equal */
  71. return (NULL == first && NULL == second);
  72. }
  73. /*
  74. * @unittest: 1301
  75. */
  76. int Curl_strncasecompare(const char *first, const char *second, size_t max)
  77. {
  78. while(*first && *second && max) {
  79. if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
  80. break;
  81. }
  82. max--;
  83. first++;
  84. second++;
  85. }
  86. if(0 == max)
  87. return 1; /* they are equal this far */
  88. return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
  89. }
  90. /* Copy an upper case version of the string from src to dest. The
  91. * strings may overlap. No more than n characters of the string are copied
  92. * (including any NUL) and the destination string will NOT be
  93. * NUL-terminated if that limit is reached.
  94. */
  95. void Curl_strntoupper(char *dest, const char *src, size_t n)
  96. {
  97. if(n < 1)
  98. return;
  99. do {
  100. *dest++ = Curl_raw_toupper(*src);
  101. } while(*src++ && --n);
  102. }
  103. /* Copy a lower case version of the string from src to dest. The
  104. * strings may overlap. No more than n characters of the string are copied
  105. * (including any NUL) and the destination string will NOT be
  106. * NUL-terminated if that limit is reached.
  107. */
  108. void Curl_strntolower(char *dest, const char *src, size_t n)
  109. {
  110. if(n < 1)
  111. return;
  112. do {
  113. *dest++ = raw_tolower(*src);
  114. } while(*src++ && --n);
  115. }
  116. /* Compare case-sensitive NUL-terminated strings, taking care of possible
  117. * null pointers. Return true if arguments match.
  118. */
  119. bool Curl_safecmp(char *a, char *b)
  120. {
  121. if(a && b)
  122. return !strcmp(a, b);
  123. return !a && !b;
  124. }
  125. /* --- public functions --- */
  126. int curl_strequal(const char *first, const char *second)
  127. {
  128. return Curl_strcasecompare(first, second);
  129. }
  130. int curl_strnequal(const char *first, const char *second, size_t max)
  131. {
  132. return Curl_strncasecompare(first, second, max);
  133. }