Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezStr is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #ifndef EZ_STR
30 : : #define EZ_STR
31 : : #endif // EZ_STR
32 : :
33 : : #include <ios>
34 : : #include <set>
35 : : #include <list>
36 : : #include <cmath>
37 : : #include <vector>
38 : : #include <limits>
39 : : #include <string>
40 : : #include <sstream>
41 : : #include <iomanip>
42 : : #include <cstdint>
43 : : #include <cstdarg> // variadic
44 : : #include <clocale> // std::setlocale
45 : : #include <locale> // toupper, tolower (with locale)
46 : :
47 : : #include "ezOS.hpp"
48 : :
49 : : #ifdef WINDOWS_OS
50 : : #include <cwchar>
51 : : #include "Windows.h"
52 : : #endif
53 : :
54 : :
55 : : ////////////////////////////////////////////////////////////////////////////
56 : : ////////////////////////////////////////////////////////////////////////////
57 : : ////////////////////////////////////////////////////////////////////////////
58 : :
59 : : #if defined(_MSC_VER) || defined(__MINGW32__)
60 : : #pragma warning(push)
61 : : #pragma warning(disable : 4244) // Conversion from 'double' to 'float', possible loss of data
62 : : #pragma warning(disable : 4305) // Truncation from 'double' to 'float'
63 : : #elif defined(__GNUC__) || defined(__clang__)
64 : : #pragma GCC diagnostic push
65 : : #pragma GCC diagnostic ignored "-Wconversion"
66 : : #pragma GCC diagnostic ignored "-Wfloat-conversion"
67 : : #endif
68 : :
69 : : ////////////////////////////////////////////////////////////////////////////
70 : : ////////////////////////////////////////////////////////////////////////////
71 : : ////////////////////////////////////////////////////////////////////////////
72 : :
73 : : namespace ez {
74 : : namespace str {
75 : :
76 : 0 : inline std::list<std::string> splitStringToList(const std::string& text, const std::string& delimiters, bool pushEmpty = false, bool vInversion = false) {
77 : 0 : std::list<std::string> arr;
78 : 0 : if (!text.empty()) {
79 : 0 : std::string::size_type start = 0;
80 : 0 : std::string::size_type end = text.find_first_of(delimiters, start);
81 : 0 : while (end != std::string::npos) {
82 : 0 : std::string token = text.substr(start, end - start);
83 : 0 : if (!token.empty() || (token.empty() && pushEmpty)) {
84 : 0 : if (vInversion)
85 : 0 : arr.emplace_front(token);
86 : 0 : else
87 : 0 : arr.emplace_back(token);
88 : 0 : }
89 : 0 : start = end + 1;
90 : 0 : end = text.find_first_of(delimiters, start);
91 : 0 : }
92 : 0 : std::string token = text.substr(start);
93 : 0 : if (!token.empty() || (token.empty() && pushEmpty)) {
94 : 0 : if (vInversion)
95 : 0 : arr.emplace_front(token);
96 : 0 : else
97 : 0 : arr.emplace_back(token);
98 : 0 : }
99 : 0 : }
100 : 0 : return arr;
101 : 0 : }
102 : :
103 : 0 : inline std::vector<std::string> splitStringToVector(const std::string& text, const std::string& delimiters, bool pushEmpty = false) {
104 : 0 : std::vector<std::string> arr;
105 : 0 : if (!text.empty()) {
106 : 0 : std::string::size_type start = 0;
107 : 0 : std::string::size_type end = text.find_first_of(delimiters, start);
108 : 0 : while (end != std::string::npos) {
109 : 0 : std::string token = text.substr(start, end - start);
110 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
111 : 0 : arr.emplace_back(token);
112 : 0 : start = end + 1;
113 : 0 : end = text.find_first_of(delimiters, start);
114 : 0 : }
115 : 0 : std::string token = text.substr(start);
116 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
117 : 0 : arr.emplace_back(token);
118 : 0 : }
119 : 0 : return arr;
120 : 0 : }
121 : :
122 : 0 : inline std::set<std::string> splitStringToSet(const std::string& text, const std::string& delimiters, bool pushEmpty = false) {
123 : 0 : std::set<std::string> arr;
124 : 0 : if (!text.empty()) {
125 : 0 : std::string::size_type start = 0;
126 : 0 : std::string::size_type end = text.find_first_of(delimiters, start);
127 : 0 : while (end != std::string::npos) {
128 : 0 : std::string token = text.substr(start, end - start);
129 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
130 : 0 : arr.emplace(token);
131 : 0 : start = end + 1;
132 : 0 : end = text.find_first_of(delimiters, start);
133 : 0 : }
134 : 0 : std::string token = text.substr(start);
135 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
136 : 0 : arr.emplace(token);
137 : 0 : }
138 : 0 : return arr;
139 : 0 : }
140 : :
141 : 0 : inline std::list<std::string> splitStringToList(const std::string& text, char delimiter, bool pushEmpty = false, bool vInversion = false) {
142 : 0 : std::list<std::string> arr;
143 : 0 : if (!text.empty()) {
144 : 0 : std::string::size_type start = 0;
145 : 0 : std::string::size_type end = text.find(delimiter, start);
146 : 0 : while (end != std::string::npos) {
147 : 0 : std::string token = text.substr(start, end - start);
148 : 0 : if (!token.empty() || (token.empty() && pushEmpty)) {
149 : 0 : if (vInversion)
150 : 0 : arr.emplace_front(token);
151 : 0 : else
152 : 0 : arr.emplace_back(token);
153 : 0 : }
154 : 0 : start = end + 1;
155 : 0 : end = text.find(delimiter, start);
156 : 0 : }
157 : 0 : std::string token = text.substr(start);
158 : 0 : if (!token.empty() || (token.empty() && pushEmpty)) {
159 : 0 : if (vInversion)
160 : 0 : arr.emplace_front(token);
161 : 0 : else
162 : 0 : arr.emplace_back(token);
163 : 0 : }
164 : 0 : }
165 : 0 : return arr;
166 : 0 : }
167 : :
168 : 252 : inline std::vector<std::string> splitStringToVector(const std::string& text, char delimiter, bool pushEmpty = false) {
169 : 252 : std::vector<std::string> arr;
170 [ + - ]: 252 : if (!text.empty()) {
171 : 252 : std::string::size_type start = 0;
172 : 252 : std::string::size_type end = text.find(delimiter, start);
173 [ + + ]: 434 : while (end != std::string::npos) {
174 : 182 : std::string token = text.substr(start, end - start);
175 [ + + ][ + - ]: 182 : if (!token.empty() || (token.empty() && pushEmpty))
[ - + ]
176 : 175 : arr.emplace_back(token);
177 : 182 : start = end + 1;
178 : 182 : end = text.find(delimiter, start);
179 : 182 : }
180 : 252 : std::string token = text.substr(start);
181 [ + + ][ + - ]: 252 : if (!token.empty() || (token.empty() && pushEmpty))
[ - + ]
182 : 245 : arr.emplace_back(token);
183 : 252 : }
184 : 252 : return arr;
185 : 252 : }
186 : :
187 : 0 : inline std::set<std::string> splitStringToSet(const std::string& text, char delimiter, bool pushEmpty = false) {
188 : 0 : std::set<std::string> arr;
189 : 0 : if (!text.empty()) {
190 : 0 : std::string::size_type start = 0;
191 : 0 : std::string::size_type end = text.find(delimiter, start);
192 : 0 : while (end != std::string::npos) {
193 : 0 : std::string token = text.substr(start, end - start);
194 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
195 : 0 : arr.emplace(token);
196 : 0 : start = end + 1;
197 : 0 : end = text.find(delimiter, start);
198 : 0 : }
199 : 0 : std::string token = text.substr(start);
200 : 0 : if (!token.empty() || (token.empty() && pushEmpty))
201 : 0 : arr.emplace(token);
202 : 0 : }
203 : 0 : return arr;
204 : 0 : }
205 : :
206 : : template <typename T>
207 : : inline bool stringToNumber(const std::string& vText, T& vNumber) {
208 : : try {
209 : : std::stringstream ss(vText);
210 : : ss >> vNumber;
211 : : } catch (std::exception&) {
212 : : return false;
213 : : }
214 : : return true;
215 : : }
216 : :
217 : : template <typename T>
218 : : inline std::vector<T> stringToNumberVector(const std::string& text, char delimiter) {
219 : : std::vector<T> arr;
220 : : std::string::size_type start = 0;
221 : : std::string::size_type end = text.find(delimiter, start);
222 : : T value = 0;
223 : : while (end != std::string::npos) {
224 : : std::string token = text.substr(start, end - start);
225 : : if (stringToNumber<T>(token, value)) {
226 : : arr.emplace_back(value);
227 : : }
228 : : start = end + 1;
229 : : end = text.find(delimiter, start);
230 : : }
231 : : if (stringToNumber<T>(text.substr(start).c_str(), value)) {
232 : : arr.emplace_back(value);
233 : : }
234 : : return arr;
235 : : }
236 : :
237 : 4 : inline std::string toStr(const char* fmt, ...) {
238 : 4 : va_list args;
239 : 4 : va_start(args, fmt);
240 : 4 : char TempBuffer[3072 + 1]; // 3072 = 1024 * 3
241 : 4 : const int w = vsnprintf(TempBuffer, 3072, fmt, args);
242 : 4 : va_end(args);
243 [ + - ]: 4 : if (w) {
244 : 4 : return std::string(TempBuffer, (size_t)w);
245 : 4 : }
246 : 0 : return std::string();
247 : 4 : }
248 : :
249 : : template< size_t MaxSize>
250 : : inline std::string toStr(const char* fmt, ...) {
251 : : va_list args;
252 : : va_start(args, fmt);
253 : : char TempBuffer[MaxSize+1];
254 : : const int w = vsnprintf(TempBuffer, MaxSize, fmt, args);
255 : : va_end(args);
256 : : if (w) {
257 : : return std::string(TempBuffer, (size_t)w);
258 : : }
259 : : return std::string();
260 : : }
261 : :
262 : 0 : inline std::string toUpper(const std::string& vStr, const std::locale& vLocale = {}) {
263 : 0 : std::string str = vStr;
264 : 0 : for (size_t i = 0U; i < str.size(); ++i) {
265 : 0 : str[i] = ::std::toupper(str[i], vLocale);
266 : 0 : }
267 : 0 : return str;
268 : 0 : }
269 : :
270 : 0 : inline std::string toLower(const std::string& vStr, const std::locale& vLocale = {}) {
271 : 0 : std::string str = vStr;
272 : 0 : for (size_t i = 0U; i < str.size(); ++i) {
273 : 0 : str[i] = ::std::tolower(str[i], vLocale);
274 : 0 : }
275 : 0 : return str;
276 : 0 : }
277 : :
278 : 0 : inline std::string toHex(const std::string& vStr) {
279 : 0 : if (!vStr.empty()) {
280 : 0 : std::stringstream ss;
281 : 0 : ss << std::setfill('0') << std::setw(2) << std::hex;
282 : 0 : for (const auto& c : vStr) {
283 : 0 : ss << (0xff & (unsigned int)c);
284 : 0 : }
285 : 0 : return ss.str();
286 : 0 : }
287 : 0 : return {};
288 : 0 : }
289 : :
290 : : template <typename T>
291 : : inline std::string toStrFromArray(T* arr, size_t n, char delimiter = ';') {
292 : : if (arr) {
293 : : std::ostringstream os;
294 : : for (size_t i = 0; i < n; ++i) {
295 : : os << arr[i];
296 : : if (i < n - 1)
297 : : os << delimiter;
298 : : }
299 : : return os.str();
300 : : }
301 : : return "";
302 : : }
303 : :
304 : : template <typename T>
305 : 290 : inline std::string toStr(T t) {
306 : 290 : std::ostringstream os;
307 : 290 : os << t;
308 : 290 : return os.str();
309 : 290 : }
310 : :
311 : : template <typename T>
312 : : inline std::string toHexStr(T t) {
313 : : std::ostringstream os;
314 : : os << std::hex << t;
315 : : return os.str();
316 : : }
317 : :
318 : : template <typename T>
319 : : inline std::string toDecStr(T t) {
320 : : std::ostringstream os;
321 : : os << std::dec << t;
322 : : return os.str();
323 : : }
324 : :
325 : 0 : inline std::vector<std::string::size_type> strContains(const std::string& text, const std::string& word) {
326 : 0 : std::vector<std::string::size_type> result;
327 : 0 : std::string::size_type loc = 0;
328 : 0 : while ((loc = text.find(word, loc)) != std::string::npos) {
329 : 0 : result.emplace_back(loc);
330 : 0 : loc += word.size();
331 : 0 : }
332 : 0 : return result;
333 : 0 : }
334 : :
335 : 144 : inline bool replaceString(std::string& str, const std::string& oldStr, const std::string& newStr) {
336 : 144 : bool found = false;
337 : 144 : size_t pos = 0;
338 [ + + ]: 166 : while ((pos = str.find(oldStr, pos)) != std::string::npos) {
339 : 22 : found = true;
340 : 22 : str.replace(pos, oldStr.length(), newStr);
341 : 22 : pos += newStr.length();
342 : 22 : }
343 : 144 : return found;
344 : 144 : }
345 : :
346 : 0 : inline size_t getCountOccurence(const std::string& vSrcString, const std::string& vStringToCount) {
347 : 0 : size_t count = 0;
348 : 0 : size_t pos = 0;
349 : 0 : const auto len = vStringToCount.length();
350 : 0 : while ((pos = vSrcString.find(vStringToCount, pos)) != std::string::npos) {
351 : 0 : ++count;
352 : 0 : pos += len;
353 : 0 : }
354 : 0 : return count;
355 : 0 : }
356 : 0 : inline size_t getCountOccurenceInSection(const std::string& vSrcString, size_t vStartPos, size_t vEndpos, const std::string& vStringToCount) {
357 : 0 : size_t count = 0;
358 : 0 : size_t pos = vStartPos;
359 : 0 : const auto len = vStringToCount.length();
360 : 0 : while (pos < vEndpos && (pos = vSrcString.find(vStringToCount, pos)) != std::string::npos) {
361 : 0 : if (pos < vEndpos) {
362 : 0 : ++count;
363 : 0 : pos += len;
364 : 0 : }
365 : 0 : }
366 : 0 : return count;
367 : 0 : }
368 : :
369 : : // can be more fast if char is used
370 : 0 : inline size_t getCountOccurence(const std::string& vSrcString, const char& vStringToCount) {
371 : 0 : size_t count = 0;
372 : 0 : size_t pos = 0;
373 : 0 : while ((pos = vSrcString.find(vStringToCount, pos)) != std::string::npos) {
374 : 0 : ++count;
375 : 0 : pos++;
376 : 0 : }
377 : 0 : return count;
378 : 0 : }
379 : :
380 : : // can be more fast if char is used
381 : 0 : inline size_t getCountOccurenceInSection(const std::string& vSrcString, size_t vStartPos, size_t vEndpos, const char& vStringToCount) {
382 : 0 : size_t count = 0;
383 : 0 : size_t pos = vStartPos;
384 : 0 : while (pos < vEndpos && (pos = vSrcString.find(vStringToCount, pos)) != std::string::npos) {
385 : 0 : if (pos < vEndpos) {
386 : 0 : ++count;
387 : 0 : pos++;
388 : 0 : }
389 : 0 : }
390 : 0 : return count;
391 : 0 : }
392 : :
393 : : // std::wstring to std::string
394 : : // std::wstring(unicode/multibytes/char16/wchar_t) to std::string(char)
395 : 0 : inline std::string wstringToString(const std::wstring& wstr) {
396 : 0 : std::mbstate_t state = std::mbstate_t();
397 : 0 : const std::size_t len = wstr.size();
398 : 0 : std::vector<char> mbstr(len);
399 : 0 : const wchar_t* wptr = wstr.c_str();
400 : 0 : #ifdef _MSC_VER
401 : 0 : size_t res = 0;
402 : 0 : /*errno_t err = */ wcsrtombs_s(&res, &mbstr[0], len, &wptr, mbstr.size(), &state);
403 : 0 : #else
404 : 0 : std::wcsrtombs(&mbstr[0], &wptr, mbstr.size(), &state);
405 : 0 : #endif
406 : 0 : return std::string(mbstr.data(), mbstr.size());
407 : 0 : }
408 : :
409 : : // std::string to std::wstring
410 : : // std::string(char) to std::wstring(unicode/multibytes/char16/wchar_t)
411 : 0 : inline std::wstring stringToWstring(const std::string& mbstr) {
412 : 0 : std::mbstate_t state = std::mbstate_t();
413 : 0 : const std::size_t len = mbstr.size();
414 : 0 : std::vector<wchar_t> wstr(len);
415 : 0 : const char* ptr = mbstr.c_str();
416 : 0 : #ifdef _MSC_VER
417 : 0 : size_t res = 0;
418 : 0 : /*errno_t err = */ mbsrtowcs_s(&res, &wstr[0], len, &ptr, wstr.size(), &state);
419 : 0 : #else
420 : 0 : std::mbsrtowcs(&wstr[0], &ptr, wstr.size(), &state);
421 : 0 : #endif
422 : 0 : return std::wstring(wstr.data(), wstr.size());
423 : 0 : }
424 : :
425 : 6 : inline size_t getDigitsCountOfAIntegralNumber(const int64_t vNum) {
426 [ + + ]: 6 : size_t res = (vNum == 0) ? 1 : static_cast<int>(log10(abs(vNum))) + 1;
427 [ + + ]: 6 : if (vNum < 0) {
428 : 1 : ++res;
429 : 1 : }
430 : 6 : return res;
431 : 6 : }
432 : :
433 : 0 : inline std::string utf8Encode(const std::wstring& wstr) {
434 : 0 : std::string res;
435 : 0 : #ifdef WINDOWS_OS
436 : 0 : if (!wstr.empty()) {
437 : 0 : int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
438 : 0 : if (size_needed) {
439 : 0 : res = std::string(size_needed, 0);
440 : 0 : WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &res[0], size_needed, NULL, NULL);
441 : 0 : }
442 : 0 : }
443 : 0 : #else // WINDOWS_OS
444 : 0 : // Suppress warnings from the compiler.
445 : 0 : (void)wstr;
446 : 0 : #endif // WINDOWS_OS
447 : 0 : return res;
448 : 0 : }
449 : :
450 : : // Convert an UTF8 string to a wide Unicode String
451 : 0 : inline std::wstring utf8Decode(const std::string& str) {
452 : 0 : std::wstring res;
453 : 0 : #ifdef WINDOWS_OS
454 : 0 : if (!str.empty()) {
455 : 0 : int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
456 : 0 : if (size_needed) {
457 : 0 : res = std::wstring(size_needed, 0);
458 : 0 : MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &res[0], size_needed);
459 : 0 : }
460 : 0 : }
461 : 0 : #else // WINDOWS_OS
462 : 0 : (void)str;
463 : 0 : #endif // WINDOWS_OS
464 : 0 : return res;
465 : 0 : }
466 : :
467 : 6 : inline std::string searchForPatternWithWildcards(const std::string& vBuffer, const std::string& vWildcardedPattern, std::pair<size_t, size_t>& vOutPosRange) {
468 : 6 : std::string res;
469 : 6 : auto patterns = splitStringToVector(vWildcardedPattern, '*', false);
470 : 6 : vOutPosRange.first = std::string::npos;
471 : 6 : vOutPosRange.second = 0U;
472 [ + + ]: 14 : for (const std::string& pattern : patterns) {
473 : 14 : auto start = vBuffer.find(pattern, vOutPosRange.second);
474 [ + + ]: 14 : if (start != std::string::npos) {
475 [ + + ]: 12 : if (vOutPosRange.first == std::string::npos) {
476 : 4 : vOutPosRange.first = start;
477 : 4 : }
478 : 12 : vOutPosRange.second = start + pattern.size();
479 : 12 : } else {
480 : 2 : vOutPosRange.first = std::string::npos;
481 : 2 : vOutPosRange.second = std::string::npos;
482 : 2 : break;
483 : 2 : }
484 : 14 : }
485 [ + + ][ + - ]: 6 : if (vOutPosRange.first != std::string::npos && vOutPosRange.second != std::string::npos) {
486 : 4 : res = vBuffer.substr(vOutPosRange.first, vOutPosRange.second - vOutPosRange.first);
487 : 4 : }
488 : 6 : return res;
489 : 6 : }
490 : :
491 : 4 : inline std::string searchForPatternWithWildcards(const std::string& vBuffer, const std::string& vWildcardedPattern) {
492 : 4 : std::pair<size_t, size_t> posRange;
493 : 4 : return searchForPatternWithWildcards(vBuffer, vWildcardedPattern, posRange);
494 : 4 : }
495 : :
496 : 0 : inline std::string encodeBase64(const std::string& in) {
497 : 0 : static constexpr char sEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
498 : 0 : std::string out;
499 : 0 : int val = 0, valb = -6;
500 : 0 : for (uint8_t c : in) {
501 : 0 : val = (val << 8) + c;
502 : 0 : valb += 8;
503 : 0 : while (valb >= 0) {
504 : 0 : out.push_back(sEncodingTable[(val >> valb) & 0x3F]);
505 : 0 : valb -= 6;
506 : 0 : }
507 : 0 : }
508 : 0 : if (valb > -6) {
509 : 0 : out.push_back(sEncodingTable[((val << 8) >> (valb + 8)) & 0x3F]);
510 : 0 : }
511 : 0 : while (out.size() % 4) {
512 : 0 : out.push_back('=');
513 : 0 : }
514 : 0 : return out;
515 : 0 : }
516 : :
517 : : // todo: to test
518 : 1 : inline std::vector<std::string> extractWildcardsFromPattern(const std::string& vBuffer, const std::string& vPattern) {
519 : 1 : std::vector<std::string> res;
520 : 1 : auto patterns = splitStringToVector(vPattern, '*', false);
521 : 1 : std::pair<size_t, size_t> range;
522 : 1 : range.first = std::string::npos;
523 : 1 : range.second = 0U;
524 [ + + ]: 3 : for (const std::string& pattern : patterns) {
525 : 3 : auto start = vBuffer.find(pattern, range.second);
526 [ + - ]: 3 : if (start != std::string::npos) {
527 [ + + ]: 3 : if (range.first != std::string::npos) {
528 : 2 : range.second = start;
529 : 2 : res.push_back(vBuffer.substr(range.first, range.second - range.first));
530 : 2 : }
531 : 3 : range.first = start + pattern.size();
532 : 3 : } else {
533 : 0 : range.first = std::string::npos;
534 : 0 : range.second = std::string::npos;
535 : 0 : break;
536 : 0 : }
537 : 3 : }
538 : 1 : return res;
539 : 1 : }
540 : :
541 : : } // namespace str
542 : : } // namespace ez
543 : :
544 : : ////////////////////////////////////////////////////////////////////////////
545 : : ////////////////////////////////////////////////////////////////////////////
546 : : ////////////////////////////////////////////////////////////////////////////
547 : :
548 : : #ifdef _MSC_VER
549 : : #pragma warning(pop)
550 : : #elif defined(__GNUC__) || defined(__clang__)
551 : : #pragma GCC diagnostic pop
552 : : #endif
553 : :
554 : : ////////////////////////////////////////////////////////////////////////////
555 : : ////////////////////////////////////////////////////////////////////////////
556 : : ////////////////////////////////////////////////////////////////////////////
|