C++ Utilities 5.13.0
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
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
28namespace CppUtilities {
29
38 void operator()(char *stringData)
39 {
40 std::free(stringData);
41 }
42};
43
47using 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);
52CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize);
53CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
54CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize);
55CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
56CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
57CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize);
58
59#ifdef PLATFORM_WINDOWS
60using WideStringData = std::pair<std::unique_ptr<wchar_t[]>, int>;
61CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuffer, int inputBufferSize = -1);
62CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer);
63CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1);
64CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const std::string &inputBuffer);
65#endif
66
67CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0');
68
70namespace Detail {
71#ifdef CPP_UTILITIES_USE_RANGES
72template <class Container>
73using 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
76template <class Container> using ContainerValueType = typename Container::value_type;
77#endif
78template <class Container> using DefaultReturnTypeForContainer = ContainerValueType<Container>;
79template <class Container> using StringParamForContainer = std::basic_string_view<typename ContainerValueType<Container>::value_type>;
80} // namespace Detail
82
97template <class Container = std::initializer_list<std::string>, class ReturnType = Detail::DefaultReturnTypeForContainer<Container>>
98ReturnType 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
136template <class Container = std::initializer_list<std::string>> inline auto toMultiline(const Container &arrayOfLines)
137{
138 return joinStrings(arrayOfLines, "\n", false);
139}
140
144enum class EmptyPartsTreat {
145 Keep,
146 Omit,
147 Merge
148};
149
159template <class Container = std::list<std::string>>
160Container 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
211template <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
253template <class Container = std::vector<std::string>> inline auto toArrayOfLines(const std::string &multilineString)
254{
255 return splitString<Container>(multilineString, "\n", EmptyPartsTreat::Keep);
256}
257
261template <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
281template <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
298template <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
315template <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
334template <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
350template <typename StringType>
351bool 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
366template <typename StringType1, typename StringType2, typename StringType3>
367void 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
377template <typename StringType>
378inline 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
387template <typename StringType1, typename StringType2>
388inline 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
396template <typename StringType1, typename StringType2>
397inline 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
408template <typename CharType> constexpr CharType digitToChar(CharType digit)
409{
410 return digit <= 9 ? (digit + '0') : (digit + 'A' - 10);
411}
412
419template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
420 CppUtilities::Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
421StringType 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
441template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
442 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
443StringType 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
475template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
476StringType 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
487template <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
509namespace Detail {
510template <typename IntegralType, typename CharType, typename BaseType = IntegralType>
511void 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
536template <typename IntegralType, class CharType, typename BaseType = IntegralType,
537 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
538IntegralType 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
554template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
555 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
556IntegralType 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
585template <typename IntegralType, class StringType, typename BaseType = IntegralType,
586 Traits::EnableIf<std::is_integral<IntegralType>, Traits::Not<std::is_scalar<std::decay_t<StringType>>>> * = nullptr>
587IntegralType stringToNumber(const StringType &string, BaseType base = 10)
588{
589 return bufferToNumber<IntegralType, typename StringType::value_type, BaseType>(string.data(), string.size(), base);
590}
591
601template <typename FloatingType, class StringViewType,
602 Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::IsSpecializationOf<StringViewType, std::basic_string_view>> * = nullptr>
603FloatingType 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
628template <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>
631FloatingType 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
644template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
645 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
646IntegralType 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
664template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
665FloatingType stringToNumber(const CharType *string, int base = 10)
666{
667 return stringToNumber<FloatingType, std::basic_string_view<CharType>>(string, base);
668}
669
677template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
678 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
679IntegralType 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
709template <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
716CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte = false);
717CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false);
718CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize);
719CPP_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