|
1
|
1 #include "pfc-lite.h"
|
|
|
2 #include "string-lite.h"
|
|
|
3 #include "string_base.h"
|
|
|
4
|
|
|
5 namespace pfc {
|
|
|
6 const unsigned alloc_minimum = 128;
|
|
|
7
|
|
|
8 void stringLite::add_string(const char* p_string, t_size p_string_size) {
|
|
|
9 add_string_nc(p_string, strlen_max(p_string, p_string_size));
|
|
|
10 }
|
|
|
11
|
|
|
12 void stringLite::add_string_nc(const char* ptr, size_t length) {
|
|
|
13 if (length > 0) {
|
|
|
14 const size_t base = m_length;
|
|
|
15 const size_t newLen = base + length;
|
|
|
16 makeRoom(newLen);
|
|
|
17 auto p = (char*)m_mem.ptr();
|
|
|
18 memcpy(p + base, ptr, length);
|
|
|
19 p[newLen] = 0;
|
|
|
20 m_length = newLen;
|
|
|
21 m_ptr = p;
|
|
|
22 }
|
|
|
23
|
|
|
24 }
|
|
|
25
|
|
|
26 void stringLite::set_string(const char* p_string, t_size p_length) {
|
|
|
27 set_string_nc(p_string, strlen_max(p_string, p_length));
|
|
|
28 }
|
|
|
29
|
|
|
30 void stringLite::set_string_nc(const char* ptr, size_t length) {
|
|
|
31 if (length > 0) {
|
|
|
32 makeRoom(length);
|
|
|
33 auto p = (char*)m_mem.ptr();
|
|
|
34 memcpy(p, ptr, length);
|
|
|
35 p[length] = 0;
|
|
|
36 m_ptr = p;
|
|
|
37 m_length = length;
|
|
|
38 } else {
|
|
|
39 clear();
|
|
|
40 }
|
|
|
41 }
|
|
|
42
|
|
|
43 void stringLite::truncate(t_size len) {
|
|
|
44 if (len < m_length) {
|
|
|
45 makeRoom(len);
|
|
|
46 if (len > 0) {
|
|
|
47 auto p = (char*)m_mem.ptr();
|
|
|
48 p[len] = 0;
|
|
|
49 m_ptr = p;
|
|
|
50 } else {
|
|
|
51 m_ptr = "";
|
|
|
52 }
|
|
|
53 m_length = len;
|
|
|
54 }
|
|
|
55 }
|
|
|
56
|
|
|
57 char* stringLite::lock_buffer(t_size p_requested_length) {
|
|
|
58 makeRoom(p_requested_length);
|
|
|
59 memset(m_mem.ptr(), 0, m_mem.size());
|
|
|
60 return (char*)m_mem.ptr();
|
|
|
61 }
|
|
|
62 void stringLite::unlock_buffer() {
|
|
|
63 auto p = (char*)m_mem.ptr();
|
|
|
64 m_ptr = p;
|
|
|
65 m_length = strlen(p);
|
|
|
66 }
|
|
|
67
|
|
|
68 void stringLite::clear() noexcept {
|
|
|
69 m_ptr = "";
|
|
|
70 m_length = 0;
|
|
|
71 if (!m_noShrink && m_mem.size() > alloc_minimum) m_mem.clear();
|
|
|
72 }
|
|
|
73 void stringLite::copy(stringLite const& other) {
|
|
|
74 set_string_nc(other.m_ptr, other.m_length);
|
|
|
75 // m_noShrink deliberately NOT transferred
|
|
|
76 }
|
|
|
77 void stringLite::move(stringLite& other) noexcept {
|
|
|
78 m_ptr = other.m_ptr;
|
|
|
79 m_length = other.m_length;
|
|
|
80 m_mem = std::move(other.m_mem);
|
|
|
81 m_noShrink = other.m_noShrink;
|
|
|
82 other._clear();
|
|
|
83 }
|
|
|
84 void stringLite::_clear() noexcept {
|
|
|
85 m_ptr = "";
|
|
|
86 m_length = 0;
|
|
|
87 }
|
|
|
88 void stringLite::makeRoom(size_t newLength) {
|
|
|
89 size_t size = newLength + 1; // null term
|
|
|
90 if (m_mem.size() < size) {
|
|
|
91 size_t target = (size / 2) * 3;
|
|
|
92 if (target < alloc_minimum) target = alloc_minimum;
|
|
|
93 m_mem.resize(target);
|
|
|
94 } else if (!m_noShrink && m_mem.size() / 2 >= size) {
|
|
|
95 size_t target = size;
|
|
|
96 if (target < alloc_minimum) target = alloc_minimum;
|
|
|
97 m_mem.resize(target);
|
|
|
98 }
|
|
|
99 }
|
|
|
100
|
|
|
101 stringLite const& stringLite::operator=(const string_base& src) {
|
|
|
102 set_string_nc(src.c_str(), src.length());
|
|
|
103 return *this;
|
|
|
104 }
|
|
|
105
|
|
|
106 stringLite::stringLite(const string_base& src) {
|
|
|
107 set_string_nc(src.c_str(), src.length());
|
|
|
108 }
|
|
|
109
|
|
|
110 stringLite::stringLite(string_part_ref const& ref) {
|
|
|
111 set_string_nc(ref.m_ptr, ref.m_len);
|
|
|
112 }
|
|
|
113 stringLite const& stringLite::operator=(const string_part_ref& ref) {
|
|
|
114 set_string_nc(ref.m_ptr, ref.m_len); return *this;
|
|
|
115 }
|
|
|
116
|
|
|
117 size_t stringLite::replace_nontext_chars(char p_replace) {
|
|
|
118 auto p = (char*)m_mem.ptr();
|
|
|
119 size_t ret = 0;
|
|
|
120 for (size_t w = 0; w < m_length; ++w) {
|
|
|
121 if ((uint8_t)p[w] < 32) { p[w] = p_replace; ++ret; }
|
|
|
122 }
|
|
|
123 return ret;
|
|
|
124 }
|
|
|
125 size_t stringLite::replace_char(unsigned c1, unsigned c2) {
|
|
|
126 if (c1 < 128 && c2 < 128) return replace_byte((char)c1, (char)c2);
|
|
|
127 else {
|
|
|
128 unsigned start = 0;
|
|
|
129 stringLite temp(get_ptr() + start);
|
|
|
130 truncate(start);
|
|
|
131 const char* ptr = temp;
|
|
|
132 t_size rv = 0;
|
|
|
133 while (*ptr)
|
|
|
134 {
|
|
|
135 unsigned test;
|
|
|
136 t_size delta = utf8_decode_char(ptr, test);
|
|
|
137 if (delta == 0 || test == 0) break;
|
|
|
138 if (test == c1) { test = c2; rv++; }
|
|
|
139 add_char(test);
|
|
|
140 ptr += delta;
|
|
|
141 }
|
|
|
142 return rv;
|
|
|
143 }
|
|
|
144 }
|
|
|
145
|
|
|
146 size_t stringLite::replace_byte(char c1, char c2) {
|
|
|
147 auto p = (char*)m_mem.ptr();
|
|
|
148 size_t ret = 0;
|
|
|
149 for (size_t w = 0; w < m_length; ++w) {
|
|
|
150 if (p[w] == c1) { p[w] = c2; ++ret; }
|
|
|
151 }
|
|
|
152 return ret;
|
|
|
153 }
|
|
|
154
|
|
|
155 void stringLite::set_char(size_t offset, char c) {
|
|
|
156
|
|
|
157 if (offset < m_length) {
|
|
|
158 if (c == 0) {
|
|
|
159 truncate(offset);
|
|
|
160 } else {
|
|
|
161 auto p = (char*)m_mem.ptr();
|
|
|
162 p[offset] = c;
|
|
|
163 }
|
|
|
164 }
|
|
|
165 }
|
|
|
166 void stringLite::prealloc(size_t s) {
|
|
|
167 m_noShrink = true;
|
|
|
168 makeRoom(s);
|
|
|
169 }
|
|
|
170
|
|
|
171 void stringLite::remove_chars(t_size first, t_size count) {
|
|
|
172 if (count == 0) return;
|
|
|
173 if (count == m_length) {
|
|
|
174 clear();
|
|
|
175 } else {
|
|
|
176 PFC_ASSERT(first + count > first);
|
|
|
177 PFC_ASSERT(first + count <= m_length);
|
|
|
178
|
|
|
179 auto p = (char*)m_mem.ptr();
|
|
|
180 size_t last = first + count;
|
|
|
181 size_t trailing = m_length - last;
|
|
|
182 memmove(p + first, p + last, trailing + 1);
|
|
|
183
|
|
|
184 size_t newLen = m_length - count;
|
|
|
185 makeRoom(newLen);
|
|
|
186 m_length = newLen;
|
|
|
187 m_ptr = (char*)m_mem.ptr();
|
|
|
188 }
|
|
|
189 }
|
|
|
190 void stringLite::insert_chars_nc(t_size first, const char* src, t_size count) {
|
|
|
191 if (count == 0) return;
|
|
|
192 if (first > m_length) first = m_length;
|
|
|
193 size_t trailing = m_length - first;
|
|
|
194 size_t newLen = m_length + count;
|
|
|
195 makeRoom(newLen);
|
|
|
196 auto p = (char*)m_mem.ptr();
|
|
|
197 memmove(p + first + count, p + first, trailing + 1);
|
|
|
198 memcpy(p + first, src, count);
|
|
|
199 m_length = newLen;
|
|
|
200 m_ptr = p;
|
|
|
201 }
|
|
|
202 void stringLite::insert_chars(t_size first, const char* src, t_size count) {
|
|
|
203 insert_chars_nc(first, src, strlen_max(src, count));
|
|
|
204 }
|
|
|
205 void stringLite::insert_chars(t_size first, const char* src) {
|
|
|
206 insert_chars_nc(first, src, strlen(src));
|
|
|
207 }
|
|
|
208 bool stringLite::equals(const stringLite& other) const noexcept {
|
|
|
209 return equals(*this, other);
|
|
|
210 }
|
|
|
211 bool stringLite::equals(const char* other) const noexcept {
|
|
|
212 return strcmp(c_str(), other) == 0;
|
|
|
213 }
|
|
|
214 bool stringLite::equals(const stringLite& v1, const stringLite& v2) noexcept {
|
|
|
215 if (v1.m_length != v2.m_length) return false;
|
|
|
216 return memcmp(v1.m_ptr, v2.m_ptr, v1.m_length) == 0;
|
|
|
217 }
|
|
|
218 bool stringLite::greater(const char* v1, size_t s1, const char* v2, size_t s2) noexcept {
|
|
|
219 if (s1 > s2) return true;
|
|
|
220 if (s1 < s2) return false;
|
|
|
221 return memcmp(v1, v2, s1) > 0;
|
|
|
222 }
|
|
|
223 bool stringLite::greater(const stringLite& v1, const stringLite& v2) noexcept {
|
|
|
224 return greater(v1.m_ptr, v1.m_length, v2.m_ptr, v2.m_length);
|
|
|
225 }
|
|
|
226 stringLite stringLite::lowerCase() const {
|
|
|
227 stringLite ret;
|
|
|
228 pfc::stringToLowerAppend(ret, this->c_str(), this->length());
|
|
|
229 return ret;
|
|
|
230 }
|
|
|
231 stringLite stringLite::upperCase() const {
|
|
|
232 stringLite ret;
|
|
|
233 pfc::stringToUpperAppend(ret, this->c_str(), this->length());
|
|
|
234 return ret;
|
|
|
235 }
|
|
|
236
|
|
|
237 stringLite stringLite::subString(t_size base) const {
|
|
|
238 if (base > length()) throw exception_overflow();
|
|
|
239 return string(c_str() + base);
|
|
|
240 }
|
|
|
241 stringLite stringLite::subString(t_size base, t_size count) const {
|
|
|
242 return string(c_str() + base, count);
|
|
|
243 }
|
|
|
244
|
|
|
245
|
|
|
246 t_size stringLite::indexOf(char c, t_size base) const {
|
|
|
247 return pfc::string_find_first(ptr(), c, base);
|
|
|
248 }
|
|
|
249 t_size stringLite::lastIndexOf(char c, t_size base) const {
|
|
|
250 return pfc::string_find_last(ptr(), c, base);
|
|
|
251 }
|
|
|
252 t_size stringLite::indexOf(stringp s, t_size base) const {
|
|
|
253 return pfc::string_find_first(ptr(), s, base);
|
|
|
254 }
|
|
|
255 t_size stringLite::lastIndexOf(stringp s, t_size base) const {
|
|
|
256 return pfc::string_find_last(ptr(), s, base);
|
|
|
257 }
|
|
|
258 t_size stringLite::indexOfAnyChar(stringp _s, t_size base) const {
|
|
|
259 string s(_s);
|
|
|
260 const t_size len = length();
|
|
|
261 const char* content = ptr();
|
|
|
262 for (t_size walk = base; walk < len; ++walk) {
|
|
|
263 if (s.contains(content[walk])) return walk;
|
|
|
264 }
|
|
|
265 return SIZE_MAX;
|
|
|
266 }
|
|
|
267 t_size stringLite::lastIndexOfAnyChar(stringp _s, t_size base) const {
|
|
|
268 string s(_s);
|
|
|
269 const char* content = ptr();
|
|
|
270 for (t_size _walk = min_t<size_t>(base, length()); _walk > 0; --_walk) {
|
|
|
271 const t_size walk = _walk - 1;
|
|
|
272 if (s.contains(content[walk])) return walk;
|
|
|
273 }
|
|
|
274 return SIZE_MAX;
|
|
|
275 }
|
|
|
276 bool stringLite::startsWith(char c) const {
|
|
|
277 return (*this)[0] == c;
|
|
|
278 }
|
|
|
279 bool stringLite::startsWith(stringp s) const {
|
|
|
280 const char* walk = ptr();
|
|
|
281 const char* subWalk = s;
|
|
|
282 for (;;) {
|
|
|
283 if (*subWalk == 0) return true;
|
|
|
284 if (*walk != *subWalk) return false;
|
|
|
285 walk++; subWalk++;
|
|
|
286 }
|
|
|
287 }
|
|
|
288 bool stringLite::endsWith(char c) const {
|
|
|
289 const t_size len = length();
|
|
|
290 if (len == 0) return false;
|
|
|
291 return ptr()[len - 1] == c;
|
|
|
292 }
|
|
|
293 bool stringLite::endsWith(stringp s) const {
|
|
|
294 const t_size len = length(), subLen = stringp_length(s);
|
|
|
295 if (subLen > len) return false;
|
|
|
296 return subString(len - subLen) == s;
|
|
|
297 }
|
|
|
298
|
|
|
299 char stringLite::firstChar() const {
|
|
|
300 return (*this)[0];
|
|
|
301 }
|
|
|
302 char stringLite::lastChar() const {
|
|
|
303 const t_size len = length();
|
|
|
304 return len > 0 ? (*this)[len - 1] : (char)0;
|
|
|
305 }
|
|
|
306 bool stringLite::contains(char c) const { return indexOf(c) != SIZE_MAX; }
|
|
|
307 bool stringLite::contains(stringp s) const { return indexOf(s) != SIZE_MAX; }
|
|
|
308 bool stringLite::containsAnyChar(stringp s) const { return indexOfAnyChar(s) != SIZE_MAX; }
|
|
|
309
|
|
|
310 stringLite stringLite::replace(stringp strOld, stringp strNew) const {
|
|
|
311 stringLite ret;
|
|
|
312 size_t status = this->replace_string_ex(ret, strOld, strNew);
|
|
|
313 if (status == 0) ret = *this;
|
|
|
314 return ret;
|
|
|
315 }
|
|
|
316
|
|
|
317 stringLite stringLite::trim(char c) const {
|
|
|
318 size_t base = 0, end = 0;
|
|
|
319 const char* p = c_str();
|
|
|
320 size_t walk = 0;
|
|
|
321 while (p[walk] == c) ++walk;
|
|
|
322 base = end = walk;
|
|
|
323 while (p[walk] != 0) {
|
|
|
324 if (p[walk] != c) end = walk + 1;
|
|
|
325 ++walk;
|
|
|
326 }
|
|
|
327 stringLite ret;
|
|
|
328 ret.set_string_nc(p + base, end - base);
|
|
|
329 return ret;
|
|
|
330 }
|
|
|
331
|
|
|
332 bool stringLite::operator==(const stringLite& other) const noexcept { return equals(*this, other); }
|
|
|
333 bool stringLite::operator!=(const stringLite& other) const noexcept { return !equals(*this, other); }
|
|
|
334 bool stringLite::operator==(const char* other) const noexcept { return strcmp(c_str(), other) == 0; }
|
|
|
335 bool stringLite::operator!=(const char* other) const noexcept { return strcmp(c_str(), other) != 0; }
|
|
|
336 bool stringLite::operator>(const stringLite& other) const noexcept { return greater(*this, other); }
|
|
|
337 bool stringLite::operator<(const stringLite& other) const noexcept { return greater(other, *this); }
|
|
|
338 bool stringLite::operator>(const char* other) const noexcept { return greater(m_ptr, m_length, other, strlen(other)); }
|
|
|
339 bool stringLite::operator<(const char* other) const noexcept { return greater(other, strlen(other), m_ptr, m_length); }
|
|
|
340 bool stringLite::operator>=(const stringLite& other) const noexcept { return !greater(other, *this); }
|
|
|
341 bool stringLite::operator<=(const stringLite& other) const noexcept { return !greater(*this, other); }
|
|
|
342 bool stringLite::operator>=(const char* other) const noexcept { return !greater(other, strlen(other), m_ptr, m_length); }
|
|
|
343 bool stringLite::operator<=(const char* other) const noexcept { return !greater(m_ptr, m_length, other, strlen(other)); }
|
|
|
344
|
|
|
345 }
|
|
|
346
|
|
|
347
|