/root/doris/be/src/gutil/strings/memutil.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (C) 2001 and onwards Google, Inc. |
3 | | // |
4 | | |
5 | | #include "gutil/strings/memutil.h" |
6 | | |
7 | | #include <stdlib.h> // for malloc, NULL |
8 | | |
9 | | #include "gutil/strings/ascii_ctype.h" // for ascii_tolower |
10 | | |
11 | 0 | int memcasecmp(const char* s1, const char* s2, size_t len) { |
12 | 0 | const unsigned char* us1 = reinterpret_cast<const unsigned char*>(s1); |
13 | 0 | const unsigned char* us2 = reinterpret_cast<const unsigned char*>(s2); |
14 | |
|
15 | 0 | for (int i = 0; i < len; i++) { |
16 | 0 | const int diff = static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) - |
17 | 0 | static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i]))); |
18 | 0 | if (diff != 0) return diff; |
19 | 0 | } |
20 | 0 | return 0; |
21 | 0 | } |
22 | | |
23 | 0 | char* memdup(const char* s, size_t slen) { |
24 | 0 | void* copy; |
25 | 0 | if ((copy = malloc(slen)) == nullptr) return nullptr; |
26 | 0 | memcpy(copy, s, slen); |
27 | 0 | return reinterpret_cast<char*>(copy); |
28 | 0 | } |
29 | | |
30 | 0 | char* memrchr(const char* s, int c, size_t slen) { |
31 | 0 | for (const char* e = s + slen - 1; e >= s; e--) { |
32 | 0 | if (*e == c) return const_cast<char*>(e); |
33 | 0 | } |
34 | 0 | return nullptr; |
35 | 0 | } |
36 | | |
37 | 0 | size_t memspn(const char* s, size_t slen, const char* accept) { |
38 | 0 | const char *p = s, *spanp; |
39 | 0 | char c, sc; |
40 | |
|
41 | 0 | cont: |
42 | 0 | c = *p++; |
43 | 0 | if (slen-- == 0) return p - 1 - s; |
44 | 0 | for (spanp = accept; (sc = *spanp++) != '\0';) |
45 | 0 | if (sc == c) goto cont; |
46 | 0 | return p - 1 - s; |
47 | 0 | } |
48 | | |
49 | 0 | size_t memcspn(const char* s, size_t slen, const char* reject) { |
50 | 0 | const char *p = s, *spanp; |
51 | 0 | char c, sc; |
52 | |
|
53 | 0 | while (slen-- != 0) { |
54 | 0 | c = *p++; |
55 | 0 | for (spanp = reject; (sc = *spanp++) != '\0';) |
56 | 0 | if (sc == c) return p - 1 - s; |
57 | 0 | } |
58 | 0 | return p - s; |
59 | 0 | } |
60 | | |
61 | 0 | char* mempbrk(const char* s, size_t slen, const char* accept) { |
62 | 0 | const char* scanp; |
63 | 0 | int sc; |
64 | |
|
65 | 0 | for (; slen; ++s, --slen) { |
66 | 0 | for (scanp = accept; (sc = *scanp++) != '\0';) |
67 | 0 | if (sc == *s) return const_cast<char*>(s); |
68 | 0 | } |
69 | 0 | return nullptr; |
70 | 0 | } |
71 | | |
72 | | template <bool case_sensitive> |
73 | 0 | const char* int_memmatch(const char* phaystack, size_t haylen, const char* pneedle, size_t neelen) { |
74 | 0 | if (0 == neelen) { |
75 | 0 | return phaystack; // even if haylen is 0 |
76 | 0 | } |
77 | 0 | const unsigned char* haystack = (const unsigned char*)phaystack; |
78 | 0 | const unsigned char* hayend = (const unsigned char*)phaystack + haylen; |
79 | 0 | const unsigned char* needlestart = (const unsigned char*)pneedle; |
80 | 0 | const unsigned char* needle = (const unsigned char*)pneedle; |
81 | 0 | const unsigned char* needleend = (const unsigned char*)pneedle + neelen; |
82 | |
|
83 | 0 | for (; haystack < hayend; ++haystack) { |
84 | 0 | unsigned char hay = |
85 | 0 | case_sensitive ? *haystack : static_cast<unsigned char>(ascii_tolower(*haystack)); |
86 | 0 | unsigned char nee = |
87 | 0 | case_sensitive ? *needle : static_cast<unsigned char>(ascii_tolower(*needle)); |
88 | 0 | if (hay == nee) { |
89 | 0 | if (++needle == needleend) { |
90 | 0 | return (const char*)(haystack + 1 - neelen); |
91 | 0 | } |
92 | 0 | } else if (needle != needlestart) { |
93 | | // must back up haystack in case a prefix matched (find "aab" in "aaab") |
94 | 0 | haystack -= needle - needlestart; // for loop will advance one more |
95 | 0 | needle = needlestart; |
96 | 0 | } |
97 | 0 | } |
98 | 0 | return nullptr; |
99 | 0 | } Unexecuted instantiation: _Z12int_memmatchILb1EEPKcS1_mS1_m Unexecuted instantiation: _Z12int_memmatchILb0EEPKcS1_mS1_m |
100 | | |
101 | | // explicit template instantiations |
102 | | template const char* int_memmatch<true>(const char* phaystack, size_t haylen, const char* pneedle, |
103 | | size_t neelen); |
104 | | template const char* int_memmatch<false>(const char* phaystack, size_t haylen, const char* pneedle, |
105 | | size_t neelen); |
106 | | |
107 | | // This is significantly faster for case-sensitive matches with very |
108 | | // few possible matches. See unit test for benchmarks. |
109 | 2.70k | const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, size_t neelen) { |
110 | 2.70k | if (0 == neelen) { |
111 | 0 | return phaystack; // even if haylen is 0 |
112 | 0 | } |
113 | 2.70k | if (haylen < neelen) return nullptr; |
114 | | |
115 | 2.70k | const char* match; |
116 | 2.70k | const char* hayend = phaystack + haylen - neelen + 1; |
117 | | // A C-style cast is used here to work around the fact that memchr returns a |
118 | | // void* on Posix-compliant systems and const void* on Windows. |
119 | 2.70k | while ((match = (const char*)(memchr(phaystack, pneedle[0], hayend - phaystack)))) { |
120 | 2.10k | if (memcmp(match, pneedle, neelen) == 0) |
121 | 2.10k | return match; |
122 | 0 | else |
123 | 0 | phaystack = match + 1; |
124 | 2.10k | } |
125 | 605 | return nullptr; |
126 | 2.70k | } |