Strings.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2008 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_UTIL__STRINGS
18 #define COM_BORA_SOFTWARE__BALAU_UTIL__STRINGS
19 
20 #include <Balau/Type/Character.hpp>
21 #include <Balau/Type/ToString.hpp>
22 #include <Balau/Util/Impl/StringsImpl.hpp>
23 
24 #include <boost/algorithm/string/classification.hpp>
25 #include <boost/algorithm/string/split.hpp>
26 
27 #include <regex>
28 
29 namespace Balau::Util {
30 
39 struct Strings final {
41 
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});
48  }
49 
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);
56  }
57 
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});
64  }
65 
69  template <typename CharT>
70  static bool startsWith(const CharT * str, CharT prefix) {
71  return startsWith(std::basic_string_view<CharT>{str}, prefix);
72  }
73 
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;
81  }
82 
86  template <typename CharT>
87  static bool startsWith(const std::basic_string_view<CharT> & str, CharT prefix) {
88  return str.find(prefix) == 0;
89  }
90 
94  static bool startsWithRegex(const std::string & str, const std::regex & prefix) {
95  std::smatch match;
96 
97  if (!std::regex_search(str, match, prefix)) {
98  return false;
99  }
100 
101  return match.position(0) == 0;
102  }
103 
105 
109  static bool matches(const std::string & str, const std::regex & re) {
110  std::smatch match;
111  return std::regex_match(str, match, re);
112  }
113 
115 
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});
122  }
123 
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});
130  }
131 
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();
138  }
139 
143  static bool endsWith(const char * str, const char suffix) {
144  return endsWith(std::string_view{str}, suffix);
145  }
146 
150  static bool endsWith(const std::string_view & str, const char suffix) {
151  return str.length() >= 1 && str[str.length() - 1] == suffix;
152  }
153 
157  static bool endsWith(const char32_t * str, const char32_t suffix) {
158  return endsWith(std::u32string_view{str}, suffix);
159  }
160 
164  static bool endsWith(const std::u32string_view & str, const char32_t suffix) {
165  return str.length() >= 1 && str[str.length() - 1] == suffix;
166  }
167 
169 
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;
176  }
177 
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);
184  }
185 
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;
192  }
193 
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;
200  }
201 
203 
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});
210  }
211 
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) {
217  size_t index = 0;
218  size_t count = 0;
219 
220  while ((index = str.find(substring, index)) != StringT<CharT, T ...>::npos) {
221  index += Balau::Util::Impl::length(substring);
222  ++count;
223  }
224 
225  return count;
226  }
227 
233  static size_t occurrences(const std::string & str, const std::regex & regex) {
234  return occurrences(std::string_view{str}, regex);
235  }
236 
242  static size_t occurrences(const char * str, const std::regex & regex) {
243  return occurrences(std::string_view{str}, regex);
244  }
245 
251  static size_t occurrences(const std::string_view & str, const std::regex & regex) {
252  size_t count = 0;
253  std::cregex_iterator iter(str.begin(), str.end(), regex);
254  std::cregex_iterator end;
255 
256  while (iter != end) {
257  ++count;
258  ++iter;
259  }
260 
261  return count;
262  }
263 
265 
271  template <typename CharT, typename ... T, template <typename ...> class StringT, typename SubstrT>
272  static bool equalsIgnoreCase(const StringT<CharT, T ...> & lhs, const SubstrT & rhs) {
273  return toLower(lhs) == toLower(rhs);
274  }
275 
281  template <typename CharT, typename SubstrT>
282  static bool equalsIgnoreCase(const CharT * lhs, const SubstrT & rhs) {
283  return toLower(std::basic_string_view<CharT>{lhs}) == toLower(std::basic_string_view<CharT>{rhs});
284  }
285 
287 
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;
302  // A character iterator is used here in order to allow different string types.
303  std::cregex_iterator iter(text.data(), text.data() + text.length(), lineBreakRegex);
304  std::cregex_iterator end;
305  long lineStart = 0;
306 
307  while (iter != end) {
308  lengths.emplace_back(iter->position() - lineStart);
309  lineStart = iter->position() + iter->length();
310  ++iter;
311  }
312 
313  if (includeExtraTextAsLine && (long) text.length() > lineStart) {
314  lengths.emplace_back(text.length() - lineStart);
315  }
316 
317  return lengths;
318  }
319 
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);
336  }
337 
351  static std::vector<size_t> lineLengths(const char * text, bool includeExtraTextAsLine = true) {
352  return lineLengths(std::string_view{text}, Impl<0>::defaultLineBreakRegex, includeExtraTextAsLine);
353  }
354 
356 
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});
365  }
366 
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});
375  }
376 
378 
384  static size_t codePointCount(const std::string_view & str) {
385  int offset = 0;
386  size_t codePointCount = 0;
387 
388  while (offset < (int32_t) str.length()) {
389  Character::advanceUtf8(str, offset);
390  ++codePointCount;
391  }
392 
393  return codePointCount;
394  }
395 
401  static size_t codePointCount(const std::u32string_view & str) {
402  return str.length();
403  }
404 
406 
411  static std::string toUpper(const std::string_view & s) {
412  std::string destination = std::string(s);
413  int getOffset = 0;
414  int setOffset = 0;
415 
416  while (getOffset < (int) s.length()) {
417  char32_t c = Character::getNextUtf8(s, getOffset);
418  char32_t upper = Character::toUpper(c);
419 
420  // Are all uppercase code points the same number of bytes as lowercase
421  // code points? The algorithm currently assumes not. If this is not the
422  // case, then this conditional code is not required.
423  const size_t charByteCount = Character::utf8ByteCount(upper);
424  if ((size_t) setOffset + charByteCount > destination.length()) {
425  destination.resize((size_t) setOffset + charByteCount);
426  }
427 
428  Character::setUtf8AndAdvanceOffset(destination, setOffset, upper);
429  }
430 
431  // Ditto.
432  if ((size_t) setOffset < destination.length()) {
433  destination.resize((size_t) setOffset);
434  }
435 
436  return destination;
437  }
438 
442  static std::u32string toUpper(const std::u32string_view & s) {
443  std::u32string destination = std::u32string(s);
444 
445  for (char32_t & m : destination) {
446  m = Character::toUpper(m);
447  }
448 
449  return destination;
450  }
451 
453 
457  static std::string toLower(const std::string_view & s) {
458  std::string destination = std::string(s);
459  int getOffset = 0;
460  int setOffset = 0;
461 
462  while (getOffset < (int) s.length()) {
463  char32_t c = Character::getNextUtf8(s, getOffset);
464  char32_t lower = Character::toLower(c);
465 
466  // Are all lowercase code points the same number of bytes as uppercase
467  // code points? The algorithm currently assumes not. If this is not the
468  // case, then this conditional code is not required.
469  const size_t charByteCount = Character::utf8ByteCount(lower);
470  if ((size_t) setOffset + charByteCount > destination.length()) {
471  destination.resize((size_t) setOffset + charByteCount);
472  }
473 
474  Character::setUtf8AndAdvanceOffset(destination, setOffset, lower);
475  }
476 
477  // Ditto.
478  if ((size_t) setOffset < destination.length()) {
479  destination.resize((size_t) setOffset);
480  }
481 
482  return destination;
483  }
484 
488  static std::u32string toLower(const std::u32string_view & s) {
489  std::u32string destination = std::u32string{s};
490 
491  for (char32_t & m : destination) {
492  m = Character::toLower(m);
493  }
494 
495  return destination;
496  }
497 
499 
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;
510  str.resize(end);
511 
512  for (size_t m = start; m < end; m++) {
513  str[m] = c;
514  }
515  }
516 
524  static void append(std::string & str, char32_t c, size_t count) {
525  const size_t charByteCount = Character::utf8ByteCount(c);
526  int offset = (int) str.length();
527  const size_t end = str.length() + count * charByteCount;
528  str.resize(end);
529 
530  for (size_t m = 0; m < count; m++) {
531  Character::setUtf8AndAdvanceOffset(str, offset, c);
532  }
533  }
534 
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;
545  str.resize(end);
546 
547  for (size_t m = start; m < end; m++) {
548  str[m] = c;
549  }
550  }
551 
553 
562  static std::string append(const std::string_view & str, char c, size_t count) {
563  std::string ret{str};
564  append(ret, c, count);
565  return ret;
566  }
567 
576  static std::string append(const std::string & str, char32_t c, size_t count) {
577  std::string ret{str};
578  append(ret, c, count);
579  return ret;
580  }
581 
590  static std::u32string append(const std::u32string & str, char32_t c, size_t count) {
591  std::u32string ret{str};
592  append(ret, c, count);
593  return ret;
594  }
595 
597 
603  static std::string padLeft(const std::string_view & str, unsigned int width, char c = ' ') {
604  const size_t count = codePointCount(str);
605 
606  if (width <= count) {
607  return std::string{str};
608  }
609 
610  std::string ret;
611  append(ret, c, width - count);
612  ret.append(std::string(str.data(), str.length()));
613  return ret;
614  }
615 
621  static std::string padLeft(const std::string_view & str, unsigned int width, char32_t c) {
622  const size_t count = codePointCount(str);
623 
624  if (width <= count) {
625  return std::string{str};
626  }
627 
628  std::string ret;
629  append(ret, c, width - count);
630  ret.append(std::string(str.data(), str.length()));
631  return ret;
632  }
633 
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};
642  }
643 
644  std::u32string ret;
645  append(ret, c, width - str.length());
646  ret.append(std::u32string(str.data(), str.length()));
647  return ret;
648  }
649 
651 
657  static std::string padRight(const std::string_view & str, unsigned int width, char c = ' ') {
658  const size_t count = codePointCount(str);
659 
660  if (width <= count) {
661  return std::string{str};
662  }
663 
664  std::string ret = std::string{str};
665  append(ret, c, width - count);
666  return ret;
667  }
668 
674  static std::string padRight(const std::string_view & str, unsigned int width, char32_t c) {
675  const size_t count = codePointCount(str);
676 
677  if (width <= count) {
678  return std::string(str);
679  }
680 
681  std::string ret = std::string{str};
682  append(ret, c, width - count);
683  return ret;
684  }
685 
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);
694  }
695 
696  std::u32string ret = std::u32string{str};
697  append(ret, c, width - str.length());
698  return ret;
699  }
700 
702 
706  static std::string_view trim(const std::string_view & input) {
707  int offset = 0;
708  int startPosition = offset;
709 
710  while (offset < (int) input.length() && Character::isSpace(Character::getNextUtf8(input, offset))) {
711  startPosition = offset;
712  }
713 
714  offset = (int) input.length();
715  int endPosition = offset;
716 
717  while (endPosition > 0 && Character::isSpace(Character::getPreviousUtf8(input, offset))) {
718  endPosition = offset;
719  }
720 
721  if (endPosition <= startPosition) {
722  return std::string_view(input.data(), 0);
723  }
724 
725  return std::string_view(input.data() + (size_t) startPosition, (size_t) (endPosition - startPosition));
726  }
727 
731  static std::u32string_view trim(const std::u32string_view & input) {
732  size_t startPosition = 0;
733 
734  while (startPosition < input.length() && Character::isSpace(input[startPosition])) {
735  ++startPosition;
736  }
737 
738  size_t endPosition = input.length();
739 
740  while (endPosition > 0 && Character::isSpace(input[endPosition - 1])) {
741  --endPosition;
742  }
743 
744  if (endPosition <= startPosition) {
745  return std::u32string_view(input.data(), 0);
746  }
747 
748  return std::u32string_view(input.data() + startPosition, endPosition - startPosition);
749  }
750 
752 
756  static std::string_view trimLeft(const std::string_view & input) {
757  int offset = 0;
758  int startPosition = offset;
759 
760  while (offset < (int) input.length() && Character::isSpace(Character::getNextUtf8(input, offset))) {
761  startPosition = offset;
762  }
763 
764  return std::string_view(input.data() + startPosition, input.length() - startPosition);
765  }
766 
770  static std::u32string_view trimLeft(const std::u32string_view & input) {
771  size_t startPosition = 0;
772 
773  while (startPosition < input.length() && Character::isSpace(input[startPosition])) {
774  ++startPosition;
775  }
776 
777  return std::u32string_view(input.data() + startPosition, input.length() - startPosition);
778  }
779 
781 
785  static std::string_view trimRight(const std::string_view & input) {
786  auto offset = (int) input.length();
787  int endPosition = offset;
788 
789  while (endPosition > 0 && Character::isSpace(Character::getPreviousUtf8(input, offset))) {
790  endPosition = offset;
791  }
792 
793  if (endPosition <= 0) {
794  return std::string_view(input.data(), 0);
795  }
796 
797  return std::string_view(input.data(), (size_t) endPosition);
798  }
799 
803  static std::u32string_view trimRight(const std::u32string_view & input) {
804  size_t endPosition = input.length();
805 
806  while (endPosition > 0 && Character::isSpace(input[endPosition - 1])) {
807  --endPosition;
808  }
809 
810  if (endPosition <= 0) {
811  return std::u32string_view(input.data(), 0);
812  }
813 
814  return std::u32string_view(input.data(), (size_t) endPosition);
815  }
816 
818 
827  static std::string simplify(const std::string_view & input) {
828  static const std::regex conflater("[\t ]+");
829  auto trimmed = trim(input);
830  return replaceAll(trimmed, conflater, " ");
831  }
832 
834 
838  template <typename CharT,
839  typename ... T,
840  template <typename ...> class StringT,
841  typename MatchT,
842  typename ReplacementT>
843  static std::basic_string<CharT>
844  replaceAll(const StringT<CharT, T ...> & input, const MatchT & match, const ReplacementT & replacement) {
845  return replaceAll(
846  std::basic_string_view<CharT>{input}
847  , std::basic_string_view<CharT>{match}
848  , std::basic_string_view<CharT>{replacement}
849  );
850  }
851 
855  template <typename CharT,
856  typename AllocatorT,
857  typename ... T,
858  template <typename ...> class StringT,
859  typename MatchT,
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) {
863  return replaceAll(
864  std::basic_string_view<CharT>{input}
865  , std::basic_string_view<CharT>{match}
866  , std::basic_string_view<CharT>{replacement}
867  );
868  }
869 
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) {
877  return replaceAll(
878  std::basic_string_view<CharT>{input}
879  , std::basic_string_view<CharT>{match}
880  , std::basic_string_view<CharT>{replacement}
881  );
882  }
883 
887  template <typename CharT, typename AllocatorT>
888  static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
889  replaceAll(std::basic_string_view<CharT> input,
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);
897  return ret;
898  }
899 
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);
912  return ret;
913  }
914 
918  static std::string replaceAll(std::string_view input,
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);
926  return ret;
927  }
928 
932  static std::u32string replaceAll(std::u32string_view input,
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);
940  return ret;
941  }
942 
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);
951  }
952 
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;
963 
964  auto begin = std::cregex_iterator(Strings::begin(input), Strings::end(input), regex);
965  auto end = std::cregex_iterator();
966 
967  if (begin == end) {
968  return std::string{input};
969  }
970 
971  std::cmatch match;
972 
973  for (std::cregex_iterator m = begin; m != end; m++) {
974  match = *m;
975  stream << match.prefix();
976  stream << replacement;
977  }
978 
979  stream << match.suffix();
980 
981  return stream.str();
982  }
983 
985 
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) {
995  return (::ToString<CharT, AllocatorT>()(p1) + ... + (delimiter + ::ToString<CharT, AllocatorT>()(p)));
996  }
997 
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)));
1008  }
1009 
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) {
1019  return (::ToString<CharT, AllocatorT>()(p1) + ... + (delimiter + ::ToString<CharT, AllocatorT>()(p)));
1020  }
1021 
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)));
1032  }
1033 
1044  template <typename AllocatorT, typename CharT, typename ... T, template <typename ...> class C>
1045  static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1046  joinContainer(const CharT * delimiter, const C<T ...> & container) {
1047  return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1048  }
1049 
1060  template <typename CharT, typename ... T, template <typename ...> class C> static std::basic_string<CharT>
1061  joinContainer(const CharT * delimiter, const C<T ...> & container) {
1062  return joinContainer(std::basic_string_view<CharT>(delimiter), container);
1063  }
1064 
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);
1079  }
1080 
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);
1094  }
1095 
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;
1106 
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));
1110  d = delimiter;
1111  }
1112 
1113  return builder;
1114  }
1115 
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;
1126 
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));
1130  d = delimiter;
1131  }
1132 
1133  return builder;
1134  }
1135 
1137 
1147  template <typename AllocatorT,
1148  typename CharT,
1149  typename ... T,
1150  template <typename ...> class C,
1151  typename ... U,
1152  template <typename ...> class PrefixT,
1153  typename ... V,
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;
1158 
1159  for (const auto & e : container) {
1160  builder.append(prefix + ::ToString<CharT, AllocatorT>()(e) + suffix);
1161  }
1162 
1163  return builder;
1164  }
1165 
1175  template <typename CharT,
1176  typename ... T,
1177  template <typename ...> class C,
1178  typename ... U,
1179  template <typename ...> class PrefixT,
1180  typename ... V,
1181  template <typename ...> class SuffixT>
1182  static std::string prefixSuffixJoin(const C<T ...> & container,
1183  const PrefixT<CharT, U ...> & prefix,
1184  const SuffixT<CharT, V ...> & suffix) {
1185  return prefixSuffixJoin<std::allocator<CharT>>(container, prefix, suffix);
1186  }
1187 
1197  template <typename AllocatorT, typename CharT, typename ... T, template <typename ...> class C>
1198  static std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>
1199  prefixSuffixJoin(const C<T ...> & container, const CharT * prefix, const CharT * suffix) {
1200  std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> builder;
1201 
1202  for (const auto & e : container) {
1203  builder.append(
1204  std::basic_string<CharT, std::char_traits<CharT>, AllocatorT>{prefix}
1206  + suffix
1207  );
1208  }
1209 
1210  return builder;
1211  }
1212 
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);
1225  }
1226 
1228 
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();
1247 
1248  if (begin == end) {
1249  if (!input.empty()) {
1250  elements.emplace_back(input.data(), input.length());
1251  }
1252 
1253  return elements;
1254  }
1255 
1256  long currentStart = 0;
1257 
1258  for (auto i = begin; i != end; ++i) {
1259  std::cmatch match = *i;
1260 
1261  const auto pos = match.position(0);
1262  const auto len = match.length(0);
1263 
1264  if (pos > currentStart || !compress) {
1265  elements.emplace_back(input.data() + currentStart, pos - currentStart);
1266  }
1267 
1268  currentStart = pos + len;
1269 
1270  if (returnDelimiters) {
1271  elements.emplace_back(input.data() + pos, len);
1272  }
1273 
1274  auto j = i;
1275  ++j;
1276 
1277  if (j == end && (currentStart < (long) input.length() || !compress)) {
1278  elements.emplace_back(input.data() + currentStart, input.length() - currentStart);
1279  }
1280  }
1281 
1282  return elements;
1283  }
1284 
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);
1296  }
1297 
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);
1309  }
1310 
1312 
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);
1329 
1330  for (auto & element : elements) {
1331  element = trim(element);
1332  }
1333 
1334  return elements;
1335  }
1336 
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);
1348 
1349  for (auto & element : elements) {
1350  element = trim(element);
1351  }
1352 
1353  return elements;
1354  }
1355 
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);
1367 
1368  for (auto & element : elements) {
1369  element = trim(element);
1370  }
1371 
1372  return elements;
1373  }
1374 
1376 
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); });
1385  return ret;
1386  }
1387 
1389 
1390  Strings() = delete;
1391  Strings(const Strings &) = delete;
1392  Strings & operator = (const Strings &) = delete;
1393 
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);
1400 
1401  if (Balau::Util::Impl::length(delimiter) == 0) {
1402  elements.emplace_back(input.data(), input.length());
1403  return elements;
1404  }
1405 
1406  std::string builder;
1407  size_t previousIndex = 0;
1408 
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);
1414  }
1415 
1416  currentIndex += delimiterLength - 1;
1417  previousIndex = currentIndex + 1;
1418  }
1419  }
1420  }
1421 
1422  // TODO finish
1423  if (previousIndex != input.length() || !compress) {
1424  elements.emplace_back(input.data() + previousIndex, input.length() - previousIndex);
1425  }
1426 
1427  return elements;
1428  }
1429 
1430  // Used in splitImpl method.
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);
1436 
1437  while (inputIndex < input.length() && delimiterIndex < delimiterLength) {
1438  if (input[inputIndex] != delimiter[delimiterIndex]) {
1439  return false;
1440  }
1441 
1442  ++inputIndex;
1443  ++delimiterIndex;
1444  }
1445 
1446  return delimiterIndex == delimiterLength;
1447  }
1448 
1449  private: template <typename CharT, typename AllocatorT> static auto begin(const std::basic_string<CharT, std::char_traits<CharT>, AllocatorT> & str) {
1450  return str.data();
1451  }
1452 
1453  private: template <typename CharT> static auto begin(const CharT * str) {
1454  return str;
1455  }
1456 
1457  private: template <typename CharT> static auto begin(std::basic_string_view<CharT> str) {
1458  return str.data();
1459  }
1460 
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();
1463  }
1464 
1465  private: template <typename CharT> static auto end(const CharT * str) {
1466  return str + Balau::Util::Impl::length(str);
1467  }
1468 
1469  private: template <typename CharT> static auto end(std::basic_string_view<CharT> str) {
1470  return str.data() + str.length();
1471  }
1472 
1473  private: template <int> struct Impl {
1474  static const std::regex defaultLineBreakRegex;
1475  };
1476 };
1477 
1478 template <int Unused> const std::regex Strings::Impl<Unused>::defaultLineBreakRegex = std::regex("\n\r|\r\n|\n|\r");
1479 
1480 } // namespace Balau::Util
1481 
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 &regex)
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
Utility functions.
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 &regex, 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 &regex, 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 &regex)
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 &regex)
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