Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_STRING_SPBYTESREADER_H_
25 : #define STAPPLER_CORE_STRING_SPBYTESREADER_H_
26 :
27 : #include "SPCharGroup.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler {
30 :
31 : template <typename _CharType>
32 : class BytesReader {
33 : public:
34 : using CharType = _CharType;
35 :
36 : template <CharType ... Args>
37 : using Chars = chars::Chars<CharType, Args...>;
38 :
39 : template <CharType First, CharType Last>
40 : using Range = chars::Range<CharType, First, Last>;
41 :
42 : template <CharGroupId Group>
43 : using CharGroup = chars::CharGroup<CharType, Group>;
44 :
45 : template <typename ... Args>
46 : using Compose = chars::Compose<CharType, Args ...>;
47 :
48 1289230 : constexpr BytesReader() : ptr(nullptr), len(0) { }
49 1074870694 : constexpr BytesReader(const CharType *p, size_t l) : ptr(p), len(l) { }
50 :
51 : BytesReader & set(const CharType *p, size_t l) { ptr = p; len = l; return *this; }
52 :
53 16708969 : void offset(size_t l) { if (l > len) { len = 0; } else { ptr += l; len -= l; } }
54 :
55 112950 : bool equals(const CharType *d, size_t l) const { return (l == len && memcmp(ptr, d, l * sizeof(CharType)) == 0); }
56 105225 : bool equals(const CharType *d) const { return equals(d, std::char_traits<CharType>::length(d)); }
57 :
58 1856277 : bool prefix(const CharType *d, size_t l) const { return (l <= len && memcmp(ptr, d, l * sizeof(CharType)) == 0); }
59 :
60 38325 : bool starts_with(const BytesReader<CharType> &str) const { return prefix(str.data(), str.size()); }
61 1338 : bool starts_with(const CharType *d, size_t l) const { return prefix(d, l); }
62 873080 : bool starts_with(const CharType *d) const { return prefix(d, std::char_traits<CharType>::length(d)); }
63 :
64 : bool ends_with(const BytesReader<CharType> &str) const { return ends_with(str.data(), str.size()); }
65 7800 : bool ends_with(const CharType *d, size_t l) const { return (l <= len && memcmp(ptr + (len - l), d, l * sizeof(CharType)) == 0); }
66 7800 : bool ends_with(const CharType *d) const { return ends_with(d, std::char_traits<CharType>::length(d)); }
67 :
68 1214520662 : constexpr const CharType *data() const { return ptr; }
69 :
70 1326160082 : constexpr size_t size() const { return len; }
71 :
72 : size_t find(const CharType *s, size_t pos, size_t n) const;
73 : size_t find(CharType c, size_t pos = 0) const;
74 :
75 : size_t rfind(const CharType *s, size_t pos, size_t n) const;
76 : size_t rfind(CharType c, size_t pos = maxOf<size_t>()) const;
77 :
78 : size_t find(const BytesReader<CharType> &str, size_t pos = 0) const { return this->find(str.data(), pos, str.size()); }
79 3338 : size_t find(const CharType *s, size_t pos = 0) const { return this->find(s, pos, std::char_traits<CharType>::length(s)); }
80 :
81 : size_t rfind(const BytesReader<CharType> &str, size_t pos = maxOf<size_t>()) const { return this->rfind(str.data(), pos, str.size()); }
82 : size_t rfind(const CharType *s, size_t pos = maxOf<size_t>()) const { return this->rfind(s, pos, std::char_traits<CharType>::length(s)); }
83 :
84 41075 : bool is(const CharType &c) const { return len > 0 && *ptr == c; };
85 :
86 700 : bool operator > (const size_t &val) const { return len > val; }
87 32800 : bool operator >= (const size_t &val) const { return len >= val; }
88 : bool operator < (const size_t &val) const { return len < val; }
89 : bool operator <= (const size_t &val) const { return len <= val; }
90 :
91 91511 : const CharType & front() const { return *ptr; }
92 56175 : const CharType & back() const { return ptr[len - 1]; }
93 :
94 40669 : const CharType & at(const size_t &s) const { return ptr[s]; }
95 76701793 : const CharType & operator[] (const size_t &s) const { return ptr[s]; }
96 11020 : const CharType & operator * () const { return *ptr; }
97 :
98 30650 : void clear() { len = 0; }
99 485849830 : bool empty() const { return len == 0 || !ptr; }
100 :
101 115624 : bool terminated() const { return ptr[len] == 0; }
102 :
103 : protected:
104 : const CharType *ptr;
105 : size_t len;
106 : };
107 :
108 : template <typename CharType> inline size_t
109 3338 : BytesReader<CharType>::find(const CharType * __s, size_t __pos, size_t __n) const {
110 : using traits_type = std::char_traits<CharType>;
111 3338 : const size_t __size = this->size();
112 3338 : const CharType* __data = data();
113 :
114 3338 : if (__n == 0) {
115 0 : return __pos <= __size ? __pos : maxOf<size_t>();
116 3338 : } else if (__n <= __size) {
117 13857 : for (; __pos <= __size - __n; ++__pos)
118 13619 : if (traits_type::eq(__data[__pos], __s[0])
119 13619 : && traits_type::compare(__data + __pos + 1,
120 : __s + 1, __n - 1) == 0)
121 0 : return __pos;
122 : }
123 3338 : return maxOf<size_t>();
124 : }
125 :
126 : template <typename CharType> inline size_t
127 10475 : BytesReader<CharType>::find(CharType __c, size_t __pos) const {
128 : using traits_type = std::char_traits<CharType>;
129 10475 : size_t __ret = maxOf<size_t>();
130 10475 : const size_t __size = this->size();
131 10475 : if (__pos < __size) {
132 10475 : const CharType * __data = data();
133 10475 : const size_t __n = __size - __pos;
134 10475 : const CharType * __p = traits_type::find(__data + __pos, __n, __c);
135 10475 : if (__p)
136 10475 : __ret = __p - __data;
137 : }
138 10475 : return __ret;
139 : }
140 :
141 : template <typename CharType> inline size_t
142 : BytesReader<CharType>::rfind(const CharType* __s, size_t __pos, size_t __n) const {
143 : using traits_type = std::char_traits<CharType>;
144 : const size_t __size = this->size();
145 : if (__n <= __size) {
146 : __pos = min(size_t(__size - __n), __pos);
147 : const CharType* __data = data();
148 : do {
149 : if (traits_type::compare(__data + __pos, __s, __n) == 0)
150 : return __pos;
151 : }
152 : while (__pos-- > 0);
153 : }
154 : return maxOf<size_t>();
155 : }
156 :
157 : template <typename CharType> inline size_t
158 45775 : BytesReader<CharType>::rfind(CharType __c, size_t __pos) const {
159 : using traits_type = std::char_traits<CharType>;
160 45775 : size_t __size = this->size();
161 45775 : if (__size) {
162 45775 : if (--__size > __pos)
163 0 : __size = __pos;
164 444654 : for (++__size; __size-- > 0; )
165 444629 : if (traits_type::eq(data()[__size], __c))
166 45750 : return __size;
167 : }
168 25 : return maxOf<size_t>();
169 : }
170 :
171 : }
172 :
173 : #endif /* STAPPLER_CORE_STRING_SPBYTESREADER_H_ */
|