17 #ifndef COM_BORA_SOFTWARE__BALAU_UTIL__STRINGS 18 #define COM_BORA_SOFTWARE__BALAU_UTIL__STRINGS 22 #include <Balau/Util/Impl/StringsImpl.hpp> 24 #include <boost/algorithm/string/classification.hpp> 25 #include <boost/algorithm/string/split.hpp> 45 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename PrefixT>
46 static bool startsWith(
const StringT<CharT, T ...> & str,
const PrefixT & prefix) {
47 return startsWith(std::basic_string_view<CharT>{str}, std::basic_string_view<CharT>{prefix});
53 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT>
54 static bool startsWith(
const StringT<CharT, T ...> & str, CharT prefix) {
55 return startsWith(std::basic_string_view<CharT>{str}, prefix);
61 template <
typename CharT,
typename PrefixT>
62 static bool startsWith(
const CharT * str,
const PrefixT & prefix) {
63 return startsWith(std::basic_string_view<CharT>{str}, std::basic_string_view<CharT>{prefix});
69 template <
typename CharT>
70 static bool startsWith(
const CharT * str, CharT prefix) {
71 return startsWith(std::basic_string_view<CharT>{str}, prefix);
77 template <
typename CharT>
78 static bool startsWith(
const std::basic_string_view<CharT> & str,
79 const std::basic_string_view<CharT> & prefix) {
80 return str.find(prefix) == 0;
86 template <
typename CharT>
87 static bool startsWith(
const std::basic_string_view<CharT> & str, CharT prefix) {
88 return str.find(prefix) == 0;
97 if (!std::regex_search(str, match, prefix)) {
101 return match.position(0) == 0;
109 static bool matches(
const std::string & str,
const std::regex & re) {
111 return std::regex_match(str, match, re);
119 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename SuffixT>
120 static bool endsWith(
const StringT<CharT, T ...> & str,
const SuffixT & suffix) {
121 return endsWith(std::basic_string_view<CharT>{str}, std::basic_string_view<CharT>{suffix});
127 template <
typename CharT,
typename SuffixT>
128 static bool endsWith(
const CharT * str,
const SuffixT & suffix) {
129 return endsWith(std::basic_string_view<CharT>{str}, std::basic_string_view<CharT>{suffix});
135 template <
typename CharT>
136 static bool endsWith(
const std::basic_string_view<CharT> & str,
const std::basic_string_view<CharT> & suffix) {
137 return str.length() >= suffix.length() && str.rfind(suffix) == str.length() - suffix.length();
143 static bool endsWith(
const char * str,
const char suffix) {
144 return endsWith(std::string_view{str}, suffix);
150 static bool endsWith(
const std::string_view & str,
const char suffix) {
151 return str.length() >= 1 && str[str.length() - 1] == suffix;
157 static bool endsWith(
const char32_t * str,
const char32_t suffix) {
158 return endsWith(std::u32string_view{str}, suffix);
164 static bool endsWith(
const std::u32string_view & str,
const char32_t suffix) {
165 return str.length() >= 1 && str[str.length() - 1] == suffix;
173 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename SubstrT>
174 static bool contains(
const StringT<CharT, T ...> & str,
const SubstrT & substring) {
175 return str.find(substring) != StringT<CharT, T ...>::npos;
181 template <
typename CharT,
typename SubstrT>
182 static bool contains(
const CharT * str,
const SubstrT & substring) {
183 return contains(std::basic_string_view<CharT>{str}, substring);
189 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT>
190 static bool contains(
const StringT<CharT, T ...> & str,
const CharT & c) {
191 return str.find(c) != StringT<CharT, T ...>::npos;
197 template <
typename CharT>
198 static bool contains(
const CharT * str,
const CharT & c) {
199 return std::basic_string_view<CharT>{str}.find(c) != std::basic_string_view<CharT>::npos;
207 template <
typename CharT,
typename SubstrT>
208 static size_t occurrences(
const CharT * str,
const SubstrT & substring) {
209 return occurrences(std::basic_string_view<CharT>{str}, std::basic_string_view<CharT>{substring});
215 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename SubstrT>
216 static size_t occurrences(
const StringT<CharT, T ...> & str,
const SubstrT & substring) {
220 while ((index = str.find(substring, index)) != StringT<CharT, T ...>::npos) {
221 index += Balau::Util::Impl::length(substring);
233 static size_t occurrences(
const std::string & str,
const std::regex & regex) {
242 static size_t occurrences(
const char * str,
const std::regex & regex) {
251 static size_t occurrences(
const std::string_view & str,
const std::regex & regex) {
253 std::cregex_iterator iter(str.begin(), str.end(), regex);
254 std::cregex_iterator end;
256 while (iter != end) {
271 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename SubstrT>
281 template <
typename CharT,
typename SubstrT>
283 return toLower(std::basic_string_view<CharT>{lhs}) ==
toLower(std::basic_string_view<CharT>{rhs});
297 template <
typename ... T,
template <
typename ...>
class StringT>
298 static std::vector<size_t>
lineLengths(
const StringT<char, T ...> & text,
299 const std::regex & lineBreakRegex,
300 bool includeExtraTextAsLine =
true) {
301 std::vector<size_t> lengths;
303 std::cregex_iterator iter(text.data(), text.data() + text.length(), lineBreakRegex);
304 std::cregex_iterator end;
307 while (iter != end) {
308 lengths.emplace_back(iter->position() - lineStart);
309 lineStart = iter->position() + iter->length();
313 if (includeExtraTextAsLine && (
long) text.length() > lineStart) {
314 lengths.emplace_back(text.length() - lineStart);
333 template <
typename ... T,
template <
typename ...>
class StringT>
334 static std::vector<size_t>
lineLengths(
const StringT<char, T ...> & text,
bool includeExtraTextAsLine =
true) {
335 return lineLengths(std::string_view{text}, Impl<0>::defaultLineBreakRegex, includeExtraTextAsLine);
351 static std::vector<size_t>
lineLengths(
const char * text,
bool includeExtraTextAsLine =
true) {
352 return lineLengths(std::string_view{text}, Impl<0>::defaultLineBreakRegex, includeExtraTextAsLine);
362 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename SubstrT>
363 static size_t lastIndexOf(
const StringT<CharT, T ...> & str,
const SubstrT & substring) {
364 return std::basic_string_view<CharT>{str}.rfind(std::basic_string_view<CharT>{substring});
372 template <
typename CharT,
typename SubstrT>
373 static size_t lastIndexOf(
const CharT * str,
const SubstrT & substring) {
374 return std::basic_string_view<CharT>{str}.rfind(std::basic_string_view<CharT>{substring});
388 while (offset < (int32_t) str.length()) {
411 static std::string
toUpper(
const std::string_view & s) {
412 std::string destination = std::string(s);
416 while (getOffset < (
int) s.length()) {
424 if ((
size_t) setOffset + charByteCount > destination.length()) {
425 destination.resize((
size_t) setOffset + charByteCount);
432 if ((
size_t) setOffset < destination.length()) {
433 destination.resize((
size_t) setOffset);
442 static std::u32string
toUpper(
const std::u32string_view & s) {
443 std::u32string destination = std::u32string(s);
445 for (char32_t & m : destination) {
457 static std::string
toLower(
const std::string_view & s) {
458 std::string destination = std::string(s);
462 while (getOffset < (
int) s.length()) {
470 if ((
size_t) setOffset + charByteCount > destination.length()) {
471 destination.resize((
size_t) setOffset + charByteCount);
478 if ((
size_t) setOffset < destination.length()) {
479 destination.resize((
size_t) setOffset);
488 static std::u32string
toLower(
const std::u32string_view & s) {
489 std::u32string destination = std::u32string{s};
491 for (char32_t & m : destination) {
507 static void append(std::string & str,
char c,
size_t count) {
508 const size_t start = str.length();
509 const size_t end = str.length() + count;
512 for (
size_t m = start; m < end; m++) {
524 static void append(std::string & str, char32_t c,
size_t count) {
526 int offset = (int) str.length();
527 const size_t end = str.length() + count * charByteCount;
530 for (
size_t m = 0; m < count; m++) {
542 static void append(std::u32string & str, char32_t c,
size_t count) {
543 const size_t start = str.length();
544 const size_t end = str.length() + count;
547 for (
size_t m = start; m < end; m++) {
562 static std::string
append(
const std::string_view & str,
char c,
size_t count) {
563 std::string ret{str};
576 static std::string
append(
const std::string & str, char32_t c,
size_t count) {
577 std::string ret{str};
590 static std::u32string
append(
const std::u32string & str, char32_t c,
size_t count) {
591 std::u32string ret{str};
603 static std::string
padLeft(
const std::string_view & str,
unsigned int width,
char c =
' ') {
606 if (width <= count) {
607 return std::string{str};
611 append(ret, c, width - count);
612 ret.append(std::string(str.data(), str.length()));
621 static std::string
padLeft(
const std::string_view & str,
unsigned int width, char32_t c) {
624 if (width <= count) {
625 return std::string{str};
629 append(ret, c, width - count);
630 ret.append(std::string(str.data(), str.length()));
639 static std::u32string
padLeft(
const std::u32string_view & str,
unsigned int width, char32_t c = U
' ') {
640 if (width <= str.length()) {
641 return std::u32string{str};
645 append(ret, c, width - str.length());
646 ret.append(std::u32string(str.data(), str.length()));
657 static std::string
padRight(
const std::string_view & str,
unsigned int width,
char c =
' ') {
660 if (width <= count) {
661 return std::string{str};
664 std::string ret = std::string{str};
665 append(ret, c, width - count);
674 static std::string
padRight(
const std::string_view & str,
unsigned int width, char32_t c) {
677 if (width <= count) {
678 return std::string(str);
681 std::string ret = std::string{str};
682 append(ret, c, width - count);
691 static std::u32string
padRight(
const std::u32string_view & str,
unsigned int width, char32_t c = U
' ') {
692 if (width <= str.length()) {
693 return std::u32string(str);
696 std::u32string ret = std::u32string{str};
697 append(ret, c, width - str.length());
706 static std::string_view
trim(
const std::string_view & input) {
708 int startPosition = offset;
711 startPosition = offset;
714 offset = (int) input.length();
715 int endPosition = offset;
718 endPosition = offset;
721 if (endPosition <= startPosition) {
722 return std::string_view(input.data(), 0);
725 return std::string_view(input.data() + (size_t) startPosition, (
size_t) (endPosition - startPosition));
731 static std::u32string_view
trim(
const std::u32string_view & input) {
732 size_t startPosition = 0;
738 size_t endPosition = input.length();
744 if (endPosition <= startPosition) {
745 return std::u32string_view(input.data(), 0);
748 return std::u32string_view(input.data() + startPosition, endPosition - startPosition);
756 static std::string_view
trimLeft(
const std::string_view & input) {
758 int startPosition = offset;
761 startPosition = offset;
764 return std::string_view(input.data() + startPosition, input.length() - startPosition);
770 static std::u32string_view
trimLeft(
const std::u32string_view & input) {
771 size_t startPosition = 0;
777 return std::u32string_view(input.data() + startPosition, input.length() - startPosition);
785 static std::string_view
trimRight(
const std::string_view & input) {
786 auto offset = (int) input.length();
787 int endPosition = offset;
790 endPosition = offset;
793 if (endPosition <= 0) {
794 return std::string_view(input.data(), 0);
797 return std::string_view(input.data(), (size_t) endPosition);
803 static std::u32string_view
trimRight(
const std::u32string_view & input) {
804 size_t endPosition = input.length();
810 if (endPosition <= 0) {
811 return std::u32string_view(input.data(), 0);
814 return std::u32string_view(input.data(), (size_t) endPosition);
827 static std::string
simplify(
const std::string_view & input) {
828 static const std::regex conflater(
"[\t ]+");
829 auto trimmed =
trim(input);
838 template <
typename CharT,
840 template <
typename ...>
class StringT,
842 typename ReplacementT>
843 static std::basic_string<CharT>
844 replaceAll(
const StringT<CharT, T ...> & input,
const MatchT & match,
const ReplacementT & replacement) {
846 std::basic_string_view<CharT>{input}
847 , std::basic_string_view<CharT>{match}
848 , std::basic_string_view<CharT>{replacement}
855 template <
typename CharT,
858 template <
typename ...>
class StringT,
860 typename ReplacementT>
861 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
862 replaceAll(
const StringT<CharT, T ...> & input,
const MatchT & match,
const ReplacementT & replacement) {
864 std::basic_string_view<CharT>{input}
865 , std::basic_string_view<CharT>{match}
866 , std::basic_string_view<CharT>{replacement}
873 template <
typename CharT,
typename AllocatorT,
typename MatchT,
typename ReplacementT>
874 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
replaceAll(
const CharT * input,
875 const MatchT & match,
876 const ReplacementT & replacement) {
878 std::basic_string_view<CharT>{input}
879 , std::basic_string_view<CharT>{match}
880 , std::basic_string_view<CharT>{replacement}
887 template <
typename CharT,
typename AllocatorT>
888 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
890 std::basic_string_view<CharT> match,
891 std::basic_string_view<CharT> replacement,
892 size_t * count =
nullptr) {
893 std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> ret(input);
894 auto m = std::string(match.data(), match.length());
895 auto r = std::string(replacement.data(), replacement.length());
896 Balau::Util::Impl::replaceAllImpl(ret, m, r, count);
903 template <
typename CharT>
904 static std::basic_string<CharT>
replaceAll(std::basic_string_view<CharT> input,
905 std::basic_string_view<CharT> match,
906 std::basic_string_view<CharT> replacement,
907 size_t * count =
nullptr) {
908 std::basic_string<CharT> ret(input);
909 auto m = std::string(match.data(), match.length());
910 auto r = std::string(replacement.data(), replacement.length());
911 Balau::Util::Impl::replaceAllImpl(ret, m, r, count);
919 std::string_view match,
920 std::string_view replacement,
921 size_t * count =
nullptr) {
922 std::string ret(input);
923 auto m = std::string(match.data(), match.length());
924 auto r = std::string(replacement.data(), replacement.length());
925 Balau::Util::Impl::replaceAllImpl(ret, m, r, count);
933 std::u32string_view match,
934 std::u32string_view replacement,
935 size_t * count =
nullptr) {
936 std::u32string ret(input);
937 auto m = std::u32string(match.data(), match.length());
938 auto r = std::u32string(replacement.data(), replacement.length());
939 Balau::Util::Impl::replaceAllImpl(ret, m, r, count);
948 template <
typename ReplacementT>
949 static std::string
replaceAll(
const char * input,
const std::regex & regex,
const ReplacementT & replacement) {
950 return replaceAll(std::string_view{input}, regex, replacement);
958 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename ReplacementT>
959 static std::string
replaceAll(
const StringT<CharT, T ...> & input,
960 const std::regex & regex,
961 const ReplacementT & replacement) {
962 std::ostringstream stream;
964 auto begin = std::cregex_iterator(Strings::begin(input), Strings::end(input), regex);
965 auto end = std::cregex_iterator();
968 return std::string{input};
973 for (std::cregex_iterator m = begin; m != end; m++) {
975 stream << match.prefix();
976 stream << replacement;
979 stream << match.suffix();
993 template <
typename AllocatorT,
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename P1,
typename ... P>
994 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
join(StringT<CharT, T ...> delimiter,
const P1 & p1,
const P & ... p) {
1005 template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename P1,
typename ... P>
1006 static std::basic_string<CharT>
join(StringT<CharT, T ...> delimiter,
const P1 & p1,
const P & ... p) {
1007 return (::
ToString<CharT, std::allocator<CharT>>()(p1) + ... + (delimiter + ::
ToString<CharT, std::allocator<CharT>>()(p)));
1017 template <
typename AllocatorT,
typename CharT,
typename P1,
typename ... P>
1018 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
join(
const CharT * delimiter,
const P1 & p1,
const P & ... p) {
1029 template <
typename CharT,
typename P1,
typename ... P>
1030 static std::basic_string<CharT>
join(
const CharT * delimiter,
const P1 & p1,
const P & ... p) {
1031 return (::
ToString<CharT, std::allocator<CharT>>()(p1) + ... + (delimiter + ::
ToString<CharT, std::allocator<CharT>>()(p)));
1044 template <
typename AllocatorT,
typename CharT,
typename ... T,
template <
typename ...>
class C>
1045 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1047 return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1060 template <
typename CharT,
typename ... T,
template <
typename ...>
class C>
static std::basic_string<CharT>
1062 return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1075 template <
typename AllocatorT,
typename CharT,
typename ... T,
template <
typename ...>
class C>
1076 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1077 joinContainer(
const std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> & delimiter,
const C<T ...> & container) {
1078 return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1091 template <
typename CharT,
typename ... T,
template <
typename ...>
class C>
1092 static std::basic_string<CharT>
joinContainer(
const std::basic_string<CharT> & delimiter,
const C<T ...> & container) {
1093 return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1102 template <
typename AllocatorT,
typename CharT,
typename ... T,
template <
typename ...>
class C>
1103 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
joinContainer(std::basic_string_view<CharT> delimiter,
const C<T ...> & container) {
1104 std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> builder;
1105 std::basic_string_view<CharT> d;
1107 for (
const auto & e : container) {
1108 builder.append(std::basic_string<CharT>(d.data(), d.length()));
1109 builder.append(::
ToString<CharT, std::allocator<CharT>>()(e));
1122 template <
typename CharT,
typename ... T,
template <
typename ...>
class C>
1123 static std::basic_string<CharT>
joinContainer(std::basic_string_view<CharT> delimiter,
const C<T ...> & container) {
1124 std::basic_string<CharT> builder;
1125 std::basic_string_view<CharT> d;
1127 for (
const auto & e : container) {
1128 builder.append(std::basic_string<CharT>(d.data(), d.length()));
1129 builder.append(::
ToString<CharT, std::allocator<CharT>>()(e));
1147 template <
typename AllocatorT,
1150 template <
typename ...>
class C,
1152 template <
typename ...>
class PrefixT,
1154 template <
typename ...>
class SuffixT>
1155 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1156 prefixSuffixJoin(
const C<T ...> & container,
const PrefixT<CharT, U ...> & prefix,
const SuffixT<CharT, V ...> & suffix) {
1157 std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> builder;
1159 for (
const auto & e : container) {
1175 template <
typename CharT,
1177 template <
typename ...>
class C,
1179 template <
typename ...>
class PrefixT,
1181 template <
typename ...>
class SuffixT>
1183 const PrefixT<CharT, U ...> & prefix,
1184 const SuffixT<CharT, V ...> & suffix) {
1185 return prefixSuffixJoin<std::allocator<CharT>>(container, prefix, suffix);
1197 template <
typename AllocatorT,
typename CharT,
typename ... T,
template <
typename ...>
class C>
1198 static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1200 std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> builder;
1202 for (
const auto & e : container) {
1204 std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>{prefix}
1222 template <
typename CharT,
typename ... T,
template <
typename ...>
class C>
1223 static std::basic_string<CharT>
prefixSuffixJoin(
const C<T ...> & container,
const CharT * prefix,
const CharT * suffix) {
1224 return prefixSuffixJoin<std::allocator<CharT>>(container, prefix, suffix);
1240 static std::vector<std::string_view>
split(
const std::string_view & input,
1241 const std::regex & delimiter,
1242 bool returnDelimiters =
false,
1243 bool compress =
true) {
1244 std::vector<std::string_view> elements;
1245 auto begin = std::cregex_iterator(input.begin(), input.end(), delimiter);
1246 auto end = std::cregex_iterator();
1249 if (!input.empty()) {
1250 elements.emplace_back(input.data(), input.length());
1256 long currentStart = 0;
1258 for (
auto i = begin; i != end; ++i) {
1259 std::cmatch match = *i;
1261 const auto pos = match.position(0);
1262 const auto len = match.length(0);
1264 if (pos > currentStart || !compress) {
1265 elements.emplace_back(input.data() + currentStart, pos - currentStart);
1268 currentStart = pos + len;
1270 if (returnDelimiters) {
1271 elements.emplace_back(input.data() + pos, len);
1277 if (j == end && (currentStart < (
long) input.length() || !compress)) {
1278 elements.emplace_back(input.data() + currentStart, input.length() - currentStart);
1292 static std::vector<std::string_view>
split(
const std::string_view & input,
1293 const std::string_view & delimiter,
1294 bool compress =
true) {
1295 return splitImpl(input, delimiter, compress);
1305 static std::vector<std::u32string_view>
split(
const std::u32string_view & input,
1306 const std::u32string_view & delimiter,
1307 bool compress =
true) {
1308 return splitImpl(input, delimiter, compress);
1324 static std::vector<std::string_view>
splitAndTrim(
const std::string_view & input,
1325 const std::regex & delimiter,
1326 bool returnDelimiters =
false,
1327 bool compress =
true) {
1328 auto elements =
split(input, delimiter, returnDelimiters, compress);
1330 for (
auto & element : elements) {
1331 element =
trim(element);
1344 static std::vector<std::string_view>
splitAndTrim(
const std::string_view & input,
1345 const std::string_view & delimiter,
1346 bool compress =
true) {
1347 auto elements =
split(input, delimiter, compress);
1349 for (
auto & element : elements) {
1350 element =
trim(element);
1363 static std::vector<std::u32string_view>
splitAndTrim(
const std::u32string_view & input,
1364 const std::u32string_view & delimiter,
1365 bool compress =
true) {
1366 auto elements =
split(input, delimiter, compress);
1368 for (
auto & element : elements) {
1369 element =
trim(element);
1381 template <
typename CharT,
typename ... T,
template <
typename ...>
class ContainerT>
1382 static ContainerT<std::basic_string<CharT>>
toStringContainer(
const ContainerT<std::basic_string_view<CharT>, T ...> & input) {
1383 ContainerT<std::basic_string<CharT>> ret;
1384 std::transform(input.begin(), input.end(), std::back_inserter(ret), [] (
auto s) {
return std::string(s); });
1394 private:
template <
typename CharT>
1395 static std::vector<std::basic_string_view<CharT>> splitImpl(std::basic_string_view<CharT> input,
1396 std::basic_string_view<CharT> delimiter,
1397 bool compress =
true) {
1398 std::vector<std::basic_string_view<CharT>> elements;
1399 const size_t delimiterLength = Balau::Util::Impl::length(delimiter);
1401 if (Balau::Util::Impl::length(delimiter) == 0) {
1402 elements.emplace_back(input.data(), input.length());
1406 std::string builder;
1407 size_t previousIndex = 0;
1409 for (
size_t currentIndex = 0; currentIndex < input.length(); ++currentIndex) {
1410 if (input[currentIndex] == delimiter[0]) {
1411 if (delimiterFound(input, currentIndex, delimiter)) {
1412 if (previousIndex != currentIndex || !compress) {
1413 elements.emplace_back(input.data() + previousIndex, currentIndex - previousIndex);
1416 currentIndex += delimiterLength - 1;
1417 previousIndex = currentIndex + 1;
1423 if (previousIndex != input.length() || !compress) {
1424 elements.emplace_back(input.data() + previousIndex, input.length() - previousIndex);
1431 private:
template <
typename CharT,
typename ... T,
template <
typename ...>
class StringT,
typename DelimiterT>
1432 static bool delimiterFound(
const StringT<CharT, T ...> & input,
size_t currentIndex,
const DelimiterT & delimiter) {
1433 size_t inputIndex = currentIndex;
1434 size_t delimiterIndex = 0;
1435 const size_t delimiterLength = Balau::Util::Impl::length(delimiter);
1437 while (inputIndex < input.length() && delimiterIndex < delimiterLength) {
1438 if (input[inputIndex] != delimiter[delimiterIndex]) {
1446 return delimiterIndex == delimiterLength;
1449 private:
template <
typename CharT,
typename AllocatorT>
static auto begin(
const std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> & str) {
1453 private:
template <
typename CharT>
static auto begin(
const CharT * str) {
1457 private:
template <
typename CharT>
static auto begin(std::basic_string_view<CharT> str) {
1461 private:
template <
typename CharT,
typename AllocatorT>
static auto end(
const std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> & str) {
1462 return str.data() + str.length();
1465 private:
template <
typename CharT>
static auto end(
const CharT * str) {
1466 return str + Balau::Util::Impl::length(str);
1469 private:
template <
typename CharT>
static auto end(std::basic_string_view<CharT> str) {
1470 return str.data() + str.length();
1473 private:
template <
int>
struct Impl {
1474 static const std::regex defaultLineBreakRegex;
1478 template <
int Unused>
const std::regex Strings::Impl<Unused>::defaultLineBreakRegex = std::regex(
"\n\r|\r\n|\n|\r");
1482 #endif // COM_BORA_SOFTWARE__BALAU_UTIL__STRINGS static std::string padLeft(const std::string_view &str, unsigned int width, char c=' ')
Left pad the supplied UTF-8 string up to the specified width in code points.
Definition: Strings.hpp:603
static size_t codePointCount(const std::u32string_view &str)
Count the number of code points in the supplied UTF-32 string.
Definition: Strings.hpp:401
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > joinContainer(const CharT *delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1046
static std::string replaceAll(std::string_view input, std::string_view match, std::string_view replacement, size_t *count=nullptr)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:918
static char32_t toUpper(char32_t c)
Convert the supplied code point to uppercase.
Definition: Character.hpp:303
static std::basic_string< CharT > join(StringT< CharT, T ... > delimiter, const P1 &p1, const P &... p)
Call to-string on each of the objects and join the resulting strings together with the delimiter...
Definition: Strings.hpp:1006
static std::vector< size_t > lineLengths(const StringT< char, T ... > &text, bool includeExtraTextAsLine=true)
Given the supplied multi-line text string, determine the length of each line in bytes.
Definition: Strings.hpp:334
static size_t occurrences(const std::string &str, const std::regex ®ex)
Count the number of non-overlapping occurrences of the supplied regular expression.
Definition: Strings.hpp:233
static std::u32string_view trimLeft(const std::u32string_view &input)
Trim whitespace from the beginning of the supplied UTF-32 string.
Definition: Strings.hpp:770
Pre-defined universal to-string functions.
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > replaceAll(const StringT< CharT, T ... > &input, const MatchT &match, const ReplacementT &replacement)
Replace all occurrences of the specified string with the supplied replacement (specified allocator ve...
Definition: Strings.hpp:862
static std::string prefixSuffixJoin(const C< T ... > &container, const PrefixT< CharT, U ... > &prefix, const SuffixT< CharT, V ... > &suffix)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1182
static bool endsWith(const std::u32string_view &str, const char32_t suffix)
Does the UTF-32 string end with the specified code point?
Definition: Strings.hpp:164
static ContainerT< std::basic_string< CharT > > toStringContainer(const ContainerT< std::basic_string_view< CharT >, T ... > &input)
Convert the container of string views to a container of strings.
Definition: Strings.hpp:1382
static std::u32string toUpper(const std::u32string_view &s)
Convert the supplied UTF-32 string to uppercase.
Definition: Strings.hpp:442
static char32_t toLower(char32_t c)
Convert the supplied code point to lowercase.
Definition: Character.hpp:310
static bool endsWith(const std::string_view &str, const char suffix)
Does the UTF-8 string end with the specified ascii char?
Definition: Strings.hpp:150
static std::string append(const std::string &str, char32_t c, size_t count)
Returns the supplied UTF-8 string with count times the supplied code point appended to it...
Definition: Strings.hpp:576
static std::string padRight(const std::string_view &str, unsigned int width, char c=' ')
Right pad the supplied UTF-8 string up to the specified width in code points.
Definition: Strings.hpp:657
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > replaceAll(const CharT *input, const MatchT &match, const ReplacementT &replacement)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:874
static std::string replaceAll(const char *input, const std::regex ®ex, const ReplacementT &replacement)
Replace all occurrences of the regular expression in the input string with the replacement string...
Definition: Strings.hpp:949
static std::vector< size_t > lineLengths(const StringT< char, T ... > &text, const std::regex &lineBreakRegex, bool includeExtraTextAsLine=true)
Determine the lengths of the lines in bytes, given the line break regular expression.
Definition: Strings.hpp:298
static std::string padLeft(const std::string_view &str, unsigned int width, char32_t c)
Left pad the supplied UTF-8 string up to the specified width in code points.
Definition: Strings.hpp:621
static size_t occurrences(const StringT< CharT, T ... > &str, const SubstrT &substring)
How many non-overlapping occurrences of the second string are found in the first string?
Definition: Strings.hpp:216
static std::vector< std::string_view > split(const std::string_view &input, const std::regex &delimiter, bool returnDelimiters=false, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter regular expression...
Definition: Strings.hpp:1240
static bool contains(const StringT< CharT, T ... > &str, const SubstrT &substring)
Does the first string contain the second string?
Definition: Strings.hpp:174
static bool startsWith(const CharT *str, CharT prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:70
static bool contains(const StringT< CharT, T ... > &str, const CharT &c)
Does the string contain the ascii char (UTF-8) / UTF-16 char (UTF-16) / code point (UTF-32)...
Definition: Strings.hpp:190
static std::string replaceAll(const StringT< CharT, T ... > &input, const std::regex ®ex, const ReplacementT &replacement)
Replace all occurrences of the regular expression in the input string with the replacement string...
Definition: Strings.hpp:959
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > prefixSuffixJoin(const C< T ... > &container, const PrefixT< CharT, U ... > &prefix, const SuffixT< CharT, V ... > &suffix)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1156
static size_t lastIndexOf(const CharT *str, const SubstrT &substring)
Get the character (UTF-8) / code point (UTF-32) position of the last index of the specified sub-strin...
Definition: Strings.hpp:373
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > replaceAll(std::basic_string_view< CharT > input, std::basic_string_view< CharT > match, std::basic_string_view< CharT > replacement, size_t *count=nullptr)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:889
static std::basic_string< CharT > replaceAll(const StringT< CharT, T ... > &input, const MatchT &match, const ReplacementT &replacement)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:844
static char32_t getNextUtf8(const std::string_view &text, int &offset)
Get the next code point from the UTF-8 string view.
Definition: Character.hpp:179
static std::string_view trimRight(const std::string_view &input)
Trim whitespace from the end of the supplied UTF-8 string.
Definition: Strings.hpp:785
static std::string padRight(const std::string_view &str, unsigned int width, char32_t c)
Right pad the supplied UTF-8 string up to the specified width in code points.
Definition: Strings.hpp:674
static std::string_view trimLeft(const std::string_view &input)
Trim whitespace from the beginning of the supplied UTF-8 string.
Definition: Strings.hpp:756
static void advanceUtf8(const std::string_view &text, int &offset)
Advance the supplied offset from one code point boundary to the next one.
Definition: Character.hpp:248
static std::string toUpper(const std::string_view &s)
Convert the supplied UTF-8 string to uppercase.
Definition: Strings.hpp:411
static std::basic_string< CharT > joinContainer(const CharT *delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1061
static size_t occurrences(const std::string_view &str, const std::regex ®ex)
Count the number of non-overlapping occurrences of the supplied regular expression.
Definition: Strings.hpp:251
static bool endsWith(const std::basic_string_view< CharT > &str, const std::basic_string_view< CharT > &suffix)
Does the first string end with the specified suffix?
Definition: Strings.hpp:136
static std::string append(const std::string_view &str, char c, size_t count)
Returns the supplied UTF-8 string with count times the supplied ascii character appended to it...
Definition: Strings.hpp:562
static bool endsWith(const char32_t *str, const char32_t suffix)
Does the UTF-32 string end with the specified ascii char?
Definition: Strings.hpp:157
static std::vector< std::string_view > split(const std::string_view &input, const std::string_view &delimiter, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter.
Definition: Strings.hpp:1292
static std::u32string_view trim(const std::u32string_view &input)
Trim whitespace from the beginning and end of the supplied UTF-32 string.
Definition: Strings.hpp:731
static bool equalsIgnoreCase(const CharT *lhs, const SubstrT &rhs)
Ignoring case, is the first string equal to the second string?
Definition: Strings.hpp:282
static bool contains(const CharT *str, const SubstrT &substring)
Does the first string contain the second string?
Definition: Strings.hpp:182
static std::basic_string< CharT > joinContainer(std::basic_string_view< CharT > delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1123
static size_t codePointCount(const std::string_view &str)
Count the number of code points in the supplied UTF-8 string.
Definition: Strings.hpp:384
static std::string simplify(const std::string_view &input)
Simplify whitespace (conflate blanks) from the supplied UTF-8 string.
Definition: Strings.hpp:827
static std::basic_string< CharT > joinContainer(const std::basic_string< CharT > &delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1092
static std::vector< std::string_view > splitAndTrim(const std::string_view &input, const std::regex &delimiter, bool returnDelimiters=false, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter regular expression and s...
Definition: Strings.hpp:1324
static bool startsWith(const StringT< CharT, T ... > &str, const PrefixT &prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:46
static std::string_view trim(const std::string_view &input)
Trim whitespace from the beginning and end of the supplied UTF-8 string.
Definition: Strings.hpp:706
static char32_t getPreviousUtf8(const std::string_view &text, int &offset)
Get the previous code point from the UTF-8 string view.
Definition: Character.hpp:215
static size_t utf8ByteCount(char32_t c)
Returns the number of bytes that the character occupies when UTF-8 encoded.
Definition: Character.hpp:162
static size_t occurrences(const char *str, const std::regex ®ex)
Count the number of non-overlapping occurrences of the supplied regular expression.
Definition: Strings.hpp:242
static std::vector< std::string_view > splitAndTrim(const std::string_view &input, const std::string_view &delimiter, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter and subsequently trim th...
Definition: Strings.hpp:1344
Utilities for unicode characters and code points.
static size_t lastIndexOf(const StringT< CharT, T ... > &str, const SubstrT &substring)
Get the character (UTF-8) / code point (UTF-32) position of the last index of the specified sub-strin...
Definition: Strings.hpp:363
static std::u32string replaceAll(std::u32string_view input, std::u32string_view match, std::u32string_view replacement, size_t *count=nullptr)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:932
static std::u32string toLower(const std::u32string_view &s)
Convert the supplied UTF-32 string to lowercase.
Definition: Strings.hpp:488
static void append(std::u32string &str, char32_t c, size_t count)
Appends count times the supplied code point to the supplied UTF-32 string (in place version)...
Definition: Strings.hpp:542
static bool startsWith(const StringT< CharT, T ... > &str, CharT prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:54
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > joinContainer(const std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > &delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1077
static bool startsWith(const CharT *str, const PrefixT &prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:62
static bool startsWith(const std::basic_string_view< CharT > &str, CharT prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:87
static void append(std::string &str, char32_t c, size_t count)
Appends count times the supplied code point to the supplied UTF-8 string (in place version)...
Definition: Strings.hpp:524
static bool isSpace(char32_t c)
Is the specified code point a space character (excluding CR / LF).
Definition: Character.hpp:99
static bool matches(const std::string &str, const std::regex &re)
Does the string match the specified regular expression?
Definition: Strings.hpp:109
static std::u32string padRight(const std::u32string_view &str, unsigned int width, char32_t c=U' ')
Right pad the supplied UTF-32 string up to the specified width in code points.
Definition: Strings.hpp:691
static bool endsWith(const char *str, const char suffix)
Does the UTF-8 string end with the specified ascii char?
Definition: Strings.hpp:143
static std::vector< size_t > lineLengths(const char *text, bool includeExtraTextAsLine=true)
Given the supplied multi-line text string, determine the length of each line in bytes.
Definition: Strings.hpp:351
static std::string toLower(const std::string_view &s)
Convert the supplied UTF-8 string to lowercase.
Definition: Strings.hpp:457
static bool endsWith(const StringT< CharT, T ... > &str, const SuffixT &suffix)
Does the string end with the specified suffix?
Definition: Strings.hpp:120
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > joinContainer(std::basic_string_view< CharT > delimiter, const C< T ... > &container)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1103
static bool startsWith(const std::basic_string_view< CharT > &str, const std::basic_string_view< CharT > &prefix)
Does the string start with the specified prefix?
Definition: Strings.hpp:78
Utilities for strings.
Definition: Strings.hpp:39
static std::u32string append(const std::u32string &str, char32_t c, size_t count)
Returns the supplied UTF-32 string with count times the supplied code point appended to it...
Definition: Strings.hpp:590
static void setUtf8AndAdvanceOffset(std::string &destination, int &offset, char32_t c)
Write a code point into the supplied UTF-8 string.
Definition: Character.hpp:329
static bool equalsIgnoreCase(const StringT< CharT, T ... > &lhs, const SubstrT &rhs)
Ignoring case, is the first string equal to the second string?
Definition: Strings.hpp:272
static bool contains(const CharT *str, const CharT &c)
Does the string contain the ascii char (UTF-8) / UTF-16 char (UTF-16) / code point (UTF-32)...
Definition: Strings.hpp:198
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > join(StringT< CharT, T ... > delimiter, const P1 &p1, const P &... p)
Call to-string on each of the objects and join the resulting strings together with the delimiter...
Definition: Strings.hpp:994
static std::basic_string< CharT > prefixSuffixJoin(const C< T ... > &container, const CharT *prefix, const CharT *suffix)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1223
static bool startsWithRegex(const std::string &str, const std::regex &prefix)
Does the string start with the specified regular expression?
Definition: Strings.hpp:94
static std::u32string_view trimRight(const std::u32string_view &input)
Trim whitespace from the end of the supplied UTF-32 string.
Definition: Strings.hpp:803
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > join(const CharT *delimiter, const P1 &p1, const P &... p)
Call to-string on each of the objects and join the resulting strings together with the delimiter...
Definition: Strings.hpp:1018
static void append(std::string &str, char c, size_t count)
Appends count times the supplied ascii character to the supplied UTF-8 string (in place version)...
Definition: Strings.hpp:507
static std::u32string padLeft(const std::u32string_view &str, unsigned int width, char32_t c=U' ')
Left pad the supplied UTF-32 string up to the specified width in code points.
Definition: Strings.hpp:639
static std::vector< std::u32string_view > splitAndTrim(const std::u32string_view &input, const std::u32string_view &delimiter, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter and subsequently trim th...
Definition: Strings.hpp:1363
static std::basic_string< CharT > replaceAll(std::basic_string_view< CharT > input, std::basic_string_view< CharT > match, std::basic_string_view< CharT > replacement, size_t *count=nullptr)
Replace all occurrences of the specified string with the supplied replacement.
Definition: Strings.hpp:904
Template class based to-string function for use in template classes.
Definition: ToStringA.hpp:1278
static size_t occurrences(const CharT *str, const SubstrT &substring)
How many non-overlapping occurrences of the second string are found in the first string?
Definition: Strings.hpp:208
static std::basic_string< CharT, std::char_traits< CharT >, AllocatorT > prefixSuffixJoin(const C< T ... > &container, const CharT *prefix, const CharT *suffix)
Call to-string on each of the objects in the container and join the resulting strings together with t...
Definition: Strings.hpp:1199
static std::basic_string< CharT > join(const CharT *delimiter, const P1 &p1, const P &... p)
Call to-string on each of the objects and join the resulting strings together with the delimiter...
Definition: Strings.hpp:1030
static std::vector< std::u32string_view > split(const std::u32string_view &input, const std::u32string_view &delimiter, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter.
Definition: Strings.hpp:1305
static bool endsWith(const CharT *str, const SuffixT &suffix)
Does the string end with the specified suffix?
Definition: Strings.hpp:128