C++ Utilities  5.10.5
Useful C++ classes and routines such as argument parser, IO and conversion utilities
stringconversion.h
Go to the documentation of this file.
1 #ifndef CONVERSION_UTILITIES_STRINGCONVERSION_H
2 #define CONVERSION_UTILITIES_STRINGCONVERSION_H
3 
4 #include "./binaryconversion.h"
6 
7 #include "../misc/traits.h"
8 
9 #include <cstdlib>
10 #include <cstring>
11 #include <initializer_list>
12 #include <iomanip>
13 #include <list>
14 #include <memory>
15 #include <sstream>
16 #include <string>
17 #include <string_view>
18 #include <system_error>
19 #include <vector>
20 
21 #if __cplusplus >= 201709 && !defined(REFLECTIVE_RAPIDJSON_GENERATOR)
22 #ifndef CPP_UTILITIES_USE_RANGES
23 #define CPP_UTILITIES_USE_RANGES
24 #endif
25 #include <ranges>
26 #endif
27 
28 namespace CppUtilities {
29 
38  void operator()(char *stringData)
39  {
40  std::free(stringData);
41  }
42 };
43 
47 using StringData = std::pair<std::unique_ptr<char[], StringDataDeleter>, std::size_t>;
48 //using StringData = std::pair<std::unique_ptr<char>, std::size_t>; // might work too
49 
51  const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor = 1.0f);
52 CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize);
53 CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
54 CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize);
55 CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
56 CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
57 CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize);
58 
59 #ifdef PLATFORM_WINDOWS
60 using WideStringData = std::pair<std::unique_ptr<wchar_t[]>, int>;
61 CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuffer, int inputBufferSize = -1);
62 CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer);
63 CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1);
64 CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const std::string &inputBuffer);
65 #endif
66 
67 CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0');
68 
70 namespace Detail {
71 #ifdef CPP_UTILITIES_USE_RANGES
72 template <class Container>
73 using ContainerValueType = typename std::conditional_t<std::ranges::range<Container>,
74  std::iterator_traits<std::remove_cvref_t<std::ranges::iterator_t<Container>>>, Container>::value_type;
75 #else
76 template <class Container> using ContainerValueType = typename Container::value_type;
77 #endif
78 template <class Container> using DefaultReturnTypeForContainer = ContainerValueType<Container>;
79 template <class Container> using StringParamForContainer = std::basic_string_view<typename ContainerValueType<Container>::value_type>;
80 } // namespace Detail
82 
97 template <class Container = std::initializer_list<std::string>, class ReturnType = Detail::DefaultReturnTypeForContainer<Container>>
98 ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer<Container> delimiter = Detail::StringParamForContainer<Container>(),
99  bool omitEmpty = false, Detail::StringParamForContainer<Container> leftClosure = Detail::StringParamForContainer<Container>(),
100  Detail::StringParamForContainer<Container> rightClosure = Detail::StringParamForContainer<Container>())
101 {
102  ReturnType res;
103  if (!strings.size()) {
104  return res;
105  }
106  std::size_t entries = 0, size = 0;
107  for (const auto &str : strings) {
108  if (omitEmpty && str.empty()) {
109  continue;
110  }
111  size += str.size();
112  ++entries;
113  }
114  if (!entries) {
115  return res;
116  }
117  size += (entries * leftClosure.size()) + (entries * rightClosure.size()) + ((entries - 1) * delimiter.size());
118  res.reserve(size);
119  for (const auto &str : strings) {
120  if (omitEmpty && str.empty()) {
121  continue;
122  }
123  if (!res.empty()) {
124  res.append(delimiter);
125  }
126  res.append(leftClosure);
127  res.append(str);
128  res.append(rightClosure);
129  }
130  return res;
131 }
132 
136 template <class Container = std::initializer_list<std::string>> inline auto toMultiline(const Container &arrayOfLines)
137 {
138  return joinStrings(arrayOfLines, "\n", false);
139 }
140 
144 enum class EmptyPartsTreat {
145  Keep,
146  Omit,
147  Merge
148 };
149 
159 template <class Container = std::list<std::string>>
160 Container splitString(Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter,
161  EmptyPartsTreat emptyPartsRole = EmptyPartsTreat::Keep, int maxParts = -1)
162 {
163  --maxParts;
164  Container res;
165  typename Container::value_type *last = nullptr;
166  bool merge = false;
167  typename Container::value_type::size_type i = 0, end = string.size();
168  for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
169  delimPos = string.find(delimiter, i);
170  if (!merge && maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
171  if (delimPos == i && emptyPartsRole == EmptyPartsTreat::Merge) {
172  if (last) {
173  merge = true;
174  continue;
175  }
176  }
177  delimPos = Container::value_type::npos;
178  }
179  if (delimPos == Container::value_type::npos) {
180  delimPos = string.size();
181  }
182  if (emptyPartsRole == EmptyPartsTreat::Keep || i != delimPos) {
183  if (merge) {
184  last->append(delimiter);
185  last->append(string, i, delimPos - i);
186  merge = false;
187  } else {
188  last = &res.emplace_back(string, i, delimPos - i);
189  }
190  } else if (emptyPartsRole == EmptyPartsTreat::Merge) {
191  if (last) {
192  merge = true;
193  }
194  }
195  }
196  if (i == end && emptyPartsRole == EmptyPartsTreat::Keep) {
197  res.emplace_back();
198  }
199  return res;
200 }
201 
211 template <class Container = std::list<std::string>>
213  Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter, int maxParts = -1)
214 {
215  --maxParts;
216  Container res;
217  typename Container::value_type::size_type i = 0, end = string.size();
218  for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
219  delimPos = string.find(delimiter, i);
220  if (maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
221  delimPos = Container::value_type::npos;
222  }
223  if (delimPos == Container::value_type::npos) {
224  delimPos = string.size();
225  }
226 #if __cplusplus >= 201709
227  if constexpr (requires { res.emplace_back(string); }) {
228 #endif
229  res.emplace_back(string.data() + i, delimPos - i);
230 #if __cplusplus >= 201709
231  } else {
232  res.emplace(string.data() + i, delimPos - i);
233  }
234 #endif
235  }
236  if (i == end) {
237 #if __cplusplus >= 201709
238  if constexpr (requires { res.emplace_back(); }) {
239 #endif
240  res.emplace_back();
241 #if __cplusplus >= 201709
242  } else {
243  res.emplace();
244  }
245 #endif
246  }
247  return res;
248 }
249 
253 template <class Container = std::vector<std::string>> inline auto toArrayOfLines(const std::string &multilineString)
254 {
255  return splitString<Container>(multilineString, "\n", EmptyPartsTreat::Keep);
256 }
257 
261 template <typename StringType> bool startsWith(const StringType &str, const StringType &phrase)
262 {
263  if (str.size() < phrase.size()) {
264  return false;
265  }
266  for (auto stri = str.cbegin(), strend = str.cend(), phrasei = phrase.cbegin(), phraseend = phrase.cend();; ++stri, ++phrasei) {
267  if (phrasei == phraseend) {
268  return true;
269  } else if (stri == strend) {
270  return false;
271  } else if (*stri != *phrasei) {
272  return false;
273  }
274  }
275  return false;
276 }
277 
281 template <typename StringType> bool startsWith(const StringType &str, const typename StringType::value_type *phrase)
282 {
283  for (auto stri = str.cbegin(), strend = str.cend();; ++stri, ++phrase) {
284  if (!*phrase) {
285  return true;
286  } else if (stri == strend) {
287  return false;
288  } else if (*stri != *phrase) {
289  return false;
290  }
291  }
292  return false;
293 }
294 
298 template <typename StringType> bool endsWith(const StringType &str, const StringType &phrase)
299 {
300  if (str.size() < phrase.size()) {
301  return false;
302  }
303  for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phrase.size()), strend = str.cend(), phrasei = phrase.cbegin();
304  stri != strend; ++stri, ++phrasei) {
305  if (*stri != *phrasei) {
306  return false;
307  }
308  }
309  return true;
310 }
311 
315 template <typename StringType> bool endsWith(const StringType &str, const typename StringType::value_type *phrase)
316 {
317  const auto phraseSize = std::strlen(phrase);
318  if (str.size() < phraseSize) {
319  return false;
320  }
321  for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phraseSize), strend = str.cend(); stri != strend;
322  ++stri, ++phrase) {
323  if (*stri != *phrase) {
324  return false;
325  }
326  }
327  return true;
328 }
329 
334 template <typename StringType> bool containsSubstrings(const StringType &str, std::initializer_list<StringType> substrings)
335 {
336  typename StringType::size_type currentPos = 0;
337  for (const auto &substr : substrings) {
338  if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
339  return false;
340  }
341  currentPos += substr.size();
342  }
343  return true;
344 }
345 
350 template <typename StringType>
351 bool containsSubstrings(const StringType &str, std::initializer_list<const typename StringType::value_type *> substrings)
352 {
353  typename StringType::size_type currentPos = 0;
354  for (const auto *substr : substrings) {
355  if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
356  return false;
357  }
358  currentPos += std::strlen(substr);
359  }
360  return true;
361 }
362 
366 template <typename StringType1, typename StringType2, typename StringType3>
367 void findAndReplace(StringType1 &str, const StringType2 &find, const StringType3 &replace)
368 {
369  for (typename StringType1::size_type i = 0; (i = str.find(find, i)) != StringType1::npos; i += replace.size()) {
370  str.replace(i, find.size(), replace);
371  }
372 }
373 
377 template <typename StringType>
378 inline void findAndReplace(StringType &str, const typename StringType::value_type *find, const typename StringType::value_type *replace)
379 {
381  str, std::basic_string_view<typename StringType::value_type>(find), std::basic_string_view<typename StringType::value_type>(replace));
382 }
383 
387 template <typename StringType1, typename StringType2>
388 inline void findAndReplace(StringType1 &str, const StringType2 &find, const typename StringType1::value_type *replace)
389 {
390  findAndReplace(str, find, std::basic_string_view<typename StringType1::value_type>(replace));
391 }
392 
396 template <typename StringType1, typename StringType2>
397 inline void findAndReplace(StringType1 &str, const typename StringType1::value_type *find, const StringType2 &replace)
398 {
399  findAndReplace(str, std::basic_string_view<typename StringType1::value_type>(find), replace);
400 }
401 
408 template <typename CharType> constexpr CharType digitToChar(CharType digit)
409 {
410  return digit <= 9 ? (digit + '0') : (digit + 'A' - 10);
411 }
412 
419 template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
420  CppUtilities::Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
421 StringType numberToString(IntegralType number, BaseType base = 10)
422 {
423  std::size_t resSize = 0;
424  for (auto n = number; n; n /= static_cast<IntegralType>(base), ++resSize)
425  ;
426  StringType res;
427  res.reserve(resSize);
428  do {
429  res.insert(res.begin(), digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % base)));
430  number /= static_cast<IntegralType>(base);
431  } while (number);
432  return res;
433 }
434 
441 template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
442  Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
443 StringType numberToString(IntegralType number, BaseType base = 10)
444 {
445  const bool negative = number < 0;
446  std::size_t resSize;
447  if (negative) {
448  number = -number, resSize = 1;
449  } else {
450  resSize = 0;
451  }
452  for (auto n = number; n; n /= static_cast<IntegralType>(base), ++resSize)
453  ;
454  StringType res;
455  res.reserve(resSize);
456  do {
457  res.insert(res.begin(),
458  digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % static_cast<IntegralType>(base))));
459  number /= static_cast<IntegralType>(base);
460  } while (number);
461  if (negative) {
462  res.insert(res.begin(), '-');
463  }
464  return res;
465 }
466 
475 template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
476 StringType numberToString(FloatingType number, int base = 10)
477 {
478  std::basic_stringstream<typename StringType::value_type> ss;
479  ss << std::setbase(base) << number;
480  return ss.str();
481 }
482 
487 template <typename CharType> CharType charToDigit(CharType character, CharType base)
488 {
489  CharType res = base;
490  if (character >= '0' && character <= '9') {
491  res = character - '0';
492  } else if (character >= 'a' && character <= 'z') {
493  res = character - 'a' + 10;
494  } else if (character >= 'A' && character <= 'Z') {
495  res = character - 'A' + 10;
496  }
497  if (res < base) {
498  return res;
499  }
500  std::string errorMsg;
501  errorMsg.reserve(36);
502  errorMsg += "The character \"";
503  errorMsg += character >= ' ' && character <= '~' ? static_cast<std::string::value_type>(character) : '?';
504  errorMsg += "\" is no valid digit.";
505  throw ConversionException(std::move(errorMsg));
506 }
507 
509 namespace Detail {
510 template <typename IntegralType, typename CharType, typename BaseType = IntegralType>
511 void raiseAndAdd(IntegralType &result, BaseType base, CharType character)
512 {
513  if (character == ' ') {
514  return;
515  }
516 #ifdef __GNUC__ // overflow detection only supported on GCC and Clang
517  if (__builtin_mul_overflow(result, base, &result)
518  || __builtin_add_overflow(result, charToDigit(character, static_cast<CharType>(base)), &result)) {
519  throw ConversionException("Number exceeds limit.");
520  }
521 #else
522  result *= static_cast<IntegralType>(base);
523  result += static_cast<IntegralType>(charToDigit<CharType>(character, static_cast<CharType>(base)));
524 #endif
525 }
526 } // namespace Detail
528 
536 template <typename IntegralType, class CharType, typename BaseType = IntegralType,
537  Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
538 IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
539 {
540  IntegralType result = 0;
541  for (const CharType *end = string + size; string != end; ++string) {
542  Detail::raiseAndAdd(result, base, *string);
543  }
544  return result;
545 }
546 
554 template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
555  Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
556 IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
557 {
558  if (!size) {
559  return 0;
560  }
561  const CharType *end = string + size;
562  for (; string != end && *string == ' '; ++string)
563  ;
564  if (string == end) {
565  return 0;
566  }
567  const bool negative = (*string == '-');
568  if (negative) {
569  ++string;
570  }
571  IntegralType result = 0;
572  for (; string != end; ++string) {
573  Detail::raiseAndAdd(result, base, *string);
574  }
575  return negative ? -result : result;
576 }
577 
585 template <typename IntegralType, class StringType, typename BaseType = IntegralType,
586  Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>> * = nullptr>
587 IntegralType stringToNumber(const StringType &string, BaseType base = 10)
588 {
589  return bufferToNumber<IntegralType, typename StringType::value_type, BaseType>(string.data(), string.size(), base);
590 }
591 
601 template <typename FloatingType, class StringViewType,
602  Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::IsSpecializationOf<StringViewType, std::basic_string_view>> * = nullptr>
603 FloatingType stringToNumber(StringViewType stringView, int base = 10)
604 {
605  std::basic_stringstream<typename StringViewType::value_type> ss;
606  ss << std::setbase(base) << stringView;
607  FloatingType result;
608  if ((ss >> result) && ss.eof()) {
609  return result;
610  }
611  std::string errorMsg;
612  errorMsg.reserve(48 + stringView.size());
613  errorMsg += "The string \"";
614  errorMsg += stringView;
615  errorMsg += "\" is no valid floating point number.";
616  throw ConversionException(errorMsg);
617 }
618 
628 template <typename FloatingType, class StringType,
629  Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>,
630  Traits::Not<Traits::IsSpecializationOf<StringType, std::basic_string_view>>> * = nullptr>
631 FloatingType stringToNumber(const StringType &string, int base = 10)
632 {
633  using StringViewType = std::basic_string_view<typename StringType::value_type>;
634  return stringToNumber<FloatingType, StringViewType>(StringViewType(string.data(), string.size()), base);
635 }
636 
644 template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
645  Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
646 IntegralType stringToNumber(const CharType *string, BaseType base = 10)
647 {
648  IntegralType result = 0;
649  for (; *string; ++string) {
650  Detail::raiseAndAdd(result, base, *string);
651  }
652  return result;
653 }
654 
664 template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
665 FloatingType stringToNumber(const CharType *string, int base = 10)
666 {
667  return stringToNumber<FloatingType, std::basic_string_view<CharType>>(string, base);
668 }
669 
677 template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
678  Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
679 IntegralType stringToNumber(const CharType *string, IntegralType base = 10)
680 {
681  if (!*string) {
682  return 0;
683  }
684  for (; *string && *string == ' '; ++string)
685  ;
686  if (!*string) {
687  return 0;
688  }
689  const bool negative = (*string == '-');
690  if (negative) {
691  ++string;
692  }
693  IntegralType result = 0;
694  for (; *string; ++string) {
695  Detail::raiseAndAdd(result, base, *string);
696  }
697  return negative ? -result : result;
698 }
699 
709 template <typename T> std::string interpretIntegerAsString(T integer, int startOffset = 0)
710 {
711  char buffer[sizeof(T)];
712  BE::getBytes(integer, buffer);
713  return std::string(buffer + startOffset, sizeof(T) - static_cast<std::size_t>(startOffset));
714 }
715 
716 CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte = false);
717 CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false);
718 CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize);
719 CPP_UTILITIES_EXPORT std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t> decodeBase64(const char *encodedStr, const std::uint32_t strSize);
720 } // namespace CppUtilities
721 
722 #endif // CONVERSION_UTILITIES_STRINGCONVERSION_H
The ConversionException class is thrown by the various conversion functions of this library when a co...
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
typename std::enable_if< All< Condition... >::value, Detail::Enabler >::type EnableIf
Shortcut for std::enable_if to omit ::value and ::type.
Definition: traits.h:51
Contains all utilities provides by the c++utilities library.
void findAndReplace(StringType1 &str, const StringType2 &find, const StringType3 &replace)
Replaces all occurrences of find with relpace in the specified str.
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (big-endian).
CPP_UTILITIES_EXPORT StringData convertString(const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor=1.0f)
Converts the specified string from one character set to another.
StringType numberToString(IntegralType number, BaseType base=10)
Converts the given number to its equivalent string representation using the specified base.
CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified Latin-1 string to UTF-8.
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
EmptyPartsTreat
Specifies the role of empty parts when splitting strings.
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< std::uint8_t[]>, std::uint32_t > decodeBase64(const char *encodedStr, const std::uint32_t strSize)
Decodes the specified Base64 encoded string.
ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer< Container > delimiter=Detail::StringParamForContainer< Container >(), bool omitEmpty=false, Detail::StringParamForContainer< Container > leftClosure=Detail::StringParamForContainer< Container >(), Detail::StringParamForContainer< Container > rightClosure=Detail::StringParamForContainer< Container >())
Joins the given strings using the specified delimiter.
bool startsWith(const StringType &str, const StringType &phrase)
Returns whether str starts with phrase.
IntegralType stringToNumber(const StringType &string, BaseType base=10)
Converts the given string to an unsigned/signed number assuming string uses the specified base.
CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar='\0')
Truncates all characters after the first occurrence of the specified terminationChar and the terminat...
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
constexpr CharType digitToChar(CharType digit)
Returns the character representation of the specified digit.
Container splitStringSimple(Detail::StringParamForContainer< Container > string, Detail::StringParamForContainer< Container > delimiter, int maxParts=-1)
Splits the given string (which might also be a string view) at the specified delimiter.
auto toArrayOfLines(const std::string &multilineString)
Converts the specified multilineString to an array of lines.
bool containsSubstrings(const StringType &str, std::initializer_list< StringType > substrings)
Returns whether str contains the specified substrings.
CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to Latin-1.
std::string interpretIntegerAsString(T integer, int startOffset=0)
Interprets the given integer at the specified position as std::string using the specified byte order.
bool endsWith(const StringType &str, const StringType &phrase)
Returns whether str ends with phrase.
auto toMultiline(const Container &arrayOfLines)
Converts the specified arrayOfLines to a multiline string.
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (little-endian).
CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits=false)
Converts the specified bitrate in kbit/s to its equivalent std::string representation.
CharType charToDigit(CharType character, CharType base)
Returns number/digit of the specified character representation using the specified base.
CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize)
Encodes the specified data to Base64.
CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte=false)
Converts the specified data size in byte to its equivalent std::string representation.
IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base=10)
Converts the given string of size characters to an unsigned numeric value using the specified base.
Container splitString(Detail::StringParamForContainer< Container > string, Detail::StringParamForContainer< Container > delimiter, EmptyPartsTreat emptyPartsRole=EmptyPartsTreat::Keep, int maxParts=-1)
Splits the given string at the specified delimiter.
The StringDataDeleter struct deletes the data of a StringData instance.
void operator()(char *stringData)
Deletes the specified stringData with std::free(), because the memory has been allocated using std::m...
constexpr int i