memutil.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2017 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/strings/internal/memutil.h"
  15. #include <cstdlib>
  16. namespace absl {
  17. ABSL_NAMESPACE_BEGIN
  18. namespace strings_internal {
  19. int memcasecmp(const char* s1, const char* s2, size_t len) {
  20. const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1);
  21. const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2);
  22. for (size_t i = 0; i < len; i++) {
  23. const int diff =
  24. int{static_cast<unsigned char>(absl::ascii_tolower(us1[i]))} -
  25. int{static_cast<unsigned char>(absl::ascii_tolower(us2[i]))};
  26. if (diff != 0) return diff;
  27. }
  28. return 0;
  29. }
  30. char* memdup(const char* s, size_t slen) {
  31. void* copy;
  32. if ((copy = malloc(slen)) == nullptr) return nullptr;
  33. memcpy(copy, s, slen);
  34. return reinterpret_cast<char*>(copy);
  35. }
  36. char* memrchr(const char* s, int c, size_t slen) {
  37. for (const char* e = s + slen - 1; e >= s; e--) {
  38. if (*e == c) return const_cast<char*>(e);
  39. }
  40. return nullptr;
  41. }
  42. size_t memspn(const char* s, size_t slen, const char* accept) {
  43. const char* p = s;
  44. const char* spanp;
  45. char c, sc;
  46. cont:
  47. c = *p++;
  48. if (slen-- == 0) return p - 1 - s;
  49. for (spanp = accept; (sc = *spanp++) != '\0';)
  50. if (sc == c) goto cont;
  51. return p - 1 - s;
  52. }
  53. size_t memcspn(const char* s, size_t slen, const char* reject) {
  54. const char* p = s;
  55. const char* spanp;
  56. char c, sc;
  57. while (slen-- != 0) {
  58. c = *p++;
  59. for (spanp = reject; (sc = *spanp++) != '\0';)
  60. if (sc == c) return p - 1 - s;
  61. }
  62. return p - s;
  63. }
  64. char* mempbrk(const char* s, size_t slen, const char* accept) {
  65. const char* scanp;
  66. int sc;
  67. for (; slen; ++s, --slen) {
  68. for (scanp = accept; (sc = *scanp++) != '\0';)
  69. if (sc == *s) return const_cast<char*>(s);
  70. }
  71. return nullptr;
  72. }
  73. // This is significantly faster for case-sensitive matches with very
  74. // few possible matches. See unit test for benchmarks.
  75. const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
  76. size_t neelen) {
  77. if (0 == neelen) {
  78. return phaystack; // even if haylen is 0
  79. }
  80. if (haylen < neelen) return nullptr;
  81. const char* match;
  82. const char* hayend = phaystack + haylen - neelen + 1;
  83. // A static cast is used here to work around the fact that memchr returns
  84. // a void* on Posix-compliant systems and const void* on Windows.
  85. while ((match = static_cast<const char*>(
  86. memchr(phaystack, pneedle[0], hayend - phaystack)))) {
  87. if (memcmp(match, pneedle, neelen) == 0)
  88. return match;
  89. else
  90. phaystack = match + 1;
  91. }
  92. return nullptr;
  93. }
  94. } // namespace strings_internal
  95. ABSL_NAMESPACE_END
  96. } // namespace absl