C++ Utilities 5.31.1
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Loading...
Searching...
No Matches
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 <vector>
19
20#ifdef PLATFORM_WINDOWS
21#include <system_error>
22#endif
23
24// configure use of ranges and concepts
25#if __cplusplus >= 201709
26#include <version>
27#endif
28#if __cplusplus >= 201709 && defined(__cpp_lib_ranges) && !defined(REFLECTIVE_RAPIDJSON_GENERATOR)
29#ifndef CPP_UTILITIES_USE_RANGES
30#define CPP_UTILITIES_USE_RANGES
31#endif
32#include <ranges>
33#endif
34#if __cplusplus >= 201709 && defined(__cpp_concepts)
35#ifndef CPP_UTILITIES_USE_REQUIRES
36#define CPP_UTILITIES_USE_REQUIRES
37#endif
38#endif
39
40namespace CppUtilities {
41
42// clang-format off
50 void operator()(char *stringData){ std::free(stringData); }
51};
52// clang-format on
53
57using StringData = std::pair<std::unique_ptr<char[], StringDataDeleter>, std::size_t>;
58//using StringData = std::pair<std::unique_ptr<char>, std::size_t>; // might work too
59
60#ifndef CPP_UTILITIES_NO_ICONV
62 const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor = 1.0f);
63CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize);
64CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
65CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize);
66CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
67CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
68CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize);
69#endif
70
71#ifdef PLATFORM_WINDOWS
72using WideStringData = std::pair<std::unique_ptr<wchar_t[]>, int>;
73CPP_UTILITIES_EXPORT std::wstring convertMultiByteToWide(std::error_code &ec, std::string_view inputBuffer);
74CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuffer, int inputBufferSize = -1);
75CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer);
76CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1);
77CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const std::string &inputBuffer);
78#endif
79
80CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0');
81
83namespace Detail {
84#ifdef CPP_UTILITIES_USE_RANGES
85template <class Container>
86using ContainerValueType = typename std::conditional_t<std::ranges::range<Container>,
87 std::iterator_traits<std::remove_cvref_t<std::ranges::iterator_t<Container>>>, Container>::value_type;
88#else
89template <class Container> using ContainerValueType = typename Container::value_type;
90#endif
91template <class Container> using DefaultReturnTypeForContainer = ContainerValueType<Container>;
92template <class Container> using StringParamForContainer = std::basic_string_view<typename ContainerValueType<Container>::value_type>;
93} // namespace Detail
95
110template <class Container = std::initializer_list<std::string>, class ReturnType = Detail::DefaultReturnTypeForContainer<Container>>
111ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer<Container> delimiter = Detail::StringParamForContainer<Container>(),
112 bool omitEmpty = false, Detail::StringParamForContainer<Container> leftClosure = Detail::StringParamForContainer<Container>(),
113 Detail::StringParamForContainer<Container> rightClosure = Detail::StringParamForContainer<Container>())
114{
115 ReturnType res;
116 if (!strings.size()) {
117 return res;
118 }
119 std::size_t entries = 0, size = 0;
120 for (const auto &str : strings) {
121 if (omitEmpty && str.empty()) {
122 continue;
123 }
124 size += str.size();
125 ++entries;
126 }
127 if (!entries) {
128 return res;
129 }
130 size += (entries * leftClosure.size()) + (entries * rightClosure.size()) + ((entries - 1) * delimiter.size());
131 res.reserve(size);
132 for (const auto &str : strings) {
133 if (omitEmpty && str.empty()) {
134 continue;
135 }
136 if (!res.empty()) {
137 res.append(delimiter);
138 }
139 res.append(leftClosure);
140 res.append(str);
141 res.append(rightClosure);
142 }
143 return res;
144}
145
149template <class Container = std::initializer_list<std::string>> inline auto toMultiline(const Container &arrayOfLines)
150{
151 return joinStrings(arrayOfLines, "\n", false);
152}
153
162
172template <class Container = std::list<std::string>>
173Container splitString(Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter,
174 EmptyPartsTreat emptyPartsRole = EmptyPartsTreat::Keep, int maxParts = -1)
175{
176 --maxParts;
177 Container res;
178 typename Container::value_type *last = nullptr;
179 bool merge = false;
180 typename Container::value_type::size_type i = 0, end = string.size();
181 for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
182 delimPos = string.find(delimiter, i);
183 if (!merge && maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
184 if (delimPos == i && emptyPartsRole == EmptyPartsTreat::Merge) {
185 if (last) {
186 merge = true;
187 continue;
188 }
189 }
190 delimPos = Container::value_type::npos;
191 }
192 if (delimPos == Container::value_type::npos) {
193 delimPos = string.size();
194 }
195 if (emptyPartsRole == EmptyPartsTreat::Keep || i != delimPos) {
196 if (merge) {
197 last->append(delimiter);
198 last->append(string, i, delimPos - i);
199 merge = false;
200 } else {
201 last = &res.emplace_back(string, i, delimPos - i);
202 }
203 } else if (emptyPartsRole == EmptyPartsTreat::Merge) {
204 if (last) {
205 merge = true;
206 }
207 }
208 }
209 if (i == end && emptyPartsRole == EmptyPartsTreat::Keep) {
210 res.emplace_back();
211 }
212 return res;
213}
214
224template <class Container = std::list<std::string>>
226 Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter, int maxParts = -1)
227{
228 --maxParts;
229 Container res;
230 typename Container::value_type::size_type i = 0, end = string.size();
231 for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
232 delimPos = string.find(delimiter, i);
233 if (maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
234 delimPos = Container::value_type::npos;
235 }
236 if (delimPos == Container::value_type::npos) {
237 delimPos = string.size();
238 }
239#ifdef CPP_UTILITIES_USE_REQUIRES
240 if constexpr (requires { res.emplace_back(string); }) {
241#endif
242 res.emplace_back(string.data() + i, delimPos - i);
243#ifdef CPP_UTILITIES_USE_REQUIRES
244 } else {
245 res.emplace(string.data() + i, delimPos - i);
246 }
247#endif
248 }
249 if (i == end) {
250#ifdef CPP_UTILITIES_USE_REQUIRES
251 if constexpr (requires { res.emplace_back(); }) {
252#endif
253 res.emplace_back();
254#ifdef CPP_UTILITIES_USE_REQUIRES
255 } else {
256 res.emplace();
257 }
258#endif
259 }
260 return res;
261}
262
266template <class Container = std::vector<std::string>> inline auto toArrayOfLines(const std::string &multilineString)
267{
268 return splitString<Container>(multilineString, "\n", EmptyPartsTreat::Keep);
269}
270
274template <typename StringType> bool startsWith(const StringType &str, const StringType &phrase)
275{
276 if (str.size() < phrase.size()) {
277 return false;
278 }
279 for (auto stri = str.cbegin(), strend = str.cend(), phrasei = phrase.cbegin(), phraseend = phrase.cend();; ++stri, ++phrasei) {
280 if (phrasei == phraseend) {
281 return true;
282 } else if (stri == strend) {
283 return false;
284 } else if (*stri != *phrasei) {
285 return false;
286 }
287 }
288 return false;
289}
290
294template <typename StringType> bool startsWith(const StringType &str, const typename StringType::value_type *phrase)
295{
296 for (auto stri = str.cbegin(), strend = str.cend();; ++stri, ++phrase) {
297 if (!*phrase) {
298 return true;
299 } else if (stri == strend) {
300 return false;
301 } else if (*stri != *phrase) {
302 return false;
303 }
304 }
305 return false;
306}
307
311template <typename StringType> bool endsWith(const StringType &str, const StringType &phrase)
312{
313 if (str.size() < phrase.size()) {
314 return false;
315 }
316 for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phrase.size()), strend = str.cend(), phrasei = phrase.cbegin();
317 stri != strend; ++stri, ++phrasei) {
318 if (*stri != *phrasei) {
319 return false;
320 }
321 }
322 return true;
323}
324
328template <typename StringType> bool endsWith(const StringType &str, const typename StringType::value_type *phrase)
329{
330 const auto phraseSize = std::strlen(phrase);
331 if (str.size() < phraseSize) {
332 return false;
333 }
334 for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phraseSize), strend = str.cend(); stri != strend;
335 ++stri, ++phrase) {
336 if (*stri != *phrase) {
337 return false;
338 }
339 }
340 return true;
341}
342
347template <typename StringType> bool containsSubstrings(const StringType &str, std::initializer_list<StringType> substrings)
348{
349 typename StringType::size_type currentPos = 0;
350 for (const auto &substr : substrings) {
351 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
352 return false;
353 }
354 currentPos += substr.size();
355 }
356 return true;
357}
358
363template <typename StringType>
364bool containsSubstrings(const StringType &str, std::initializer_list<const typename StringType::value_type *> substrings)
365{
366 typename StringType::size_type currentPos = 0;
367 for (const auto *substr : substrings) {
368 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
369 return false;
370 }
371 currentPos += std::strlen(substr);
372 }
373 return true;
374}
375
379template <typename StringType1, typename StringType2, typename StringType3>
380void findAndReplace(StringType1 &str, const StringType2 &find, const StringType3 &replace)
381{
382 for (typename StringType1::size_type i = 0; (i = str.find(find, i)) != StringType1::npos; i += replace.size()) {
383 str.replace(i, find.size(), replace);
384 }
385}
386
390template <typename StringType>
391inline void findAndReplace(StringType &str, const typename StringType::value_type *find, const typename StringType::value_type *replace)
392{
394 str, std::basic_string_view<typename StringType::value_type>(find), std::basic_string_view<typename StringType::value_type>(replace));
395}
396
400template <typename StringType1, typename StringType2>
401inline void findAndReplace(StringType1 &str, const StringType2 &find, const typename StringType1::value_type *replace)
402{
403 findAndReplace(str, find, std::basic_string_view<typename StringType1::value_type>(replace));
404}
405
409template <typename StringType1, typename StringType2>
410inline void findAndReplace(StringType1 &str, const typename StringType1::value_type *find, const StringType2 &replace)
411{
412 findAndReplace(str, std::basic_string_view<typename StringType1::value_type>(find), replace);
413}
414
421template <typename CharType> constexpr CharType digitToChar(CharType digit)
422{
423 return digit <= 9 ? (digit + '0') : (digit + 'A' - 10);
424}
425
432template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
433 CppUtilities::Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
434StringType numberToString(IntegralType number, BaseType base = 10)
435{
436 auto resSize = std::size_t();
437 auto n = number;
438 do {
439 n /= static_cast<IntegralType>(base), ++resSize;
440 } while (n);
441 auto res = StringType(resSize, typename StringType::value_type());
442 auto resIter = res.end();
443 do {
444 *(--resIter)
445 = digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % static_cast<IntegralType>(base)));
446 number /= static_cast<IntegralType>(base);
447 } while (number);
448 return res;
449}
450
457template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
458 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
459StringType numberToString(IntegralType number, BaseType base = 10)
460{
461 const auto negative = number < 0;
462 auto resSize = std::size_t();
463 if (negative) {
464 number = -number, resSize = 1;
465 }
466 auto n = number;
467 do {
468 n /= static_cast<IntegralType>(base), ++resSize;
469 } while (n);
470 auto res = StringType(resSize, typename StringType::value_type());
471 auto resIter = res.end();
472 do {
473 *(--resIter)
474 = digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % static_cast<IntegralType>(base)));
475 number /= static_cast<IntegralType>(base);
476 } while (number);
477 if (negative) {
478 *(--resIter) = '-';
479 }
480 return res;
481}
482
491template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
492StringType numberToString(FloatingType number, int base = 10)
493{
494 std::basic_stringstream<typename StringType::value_type> ss;
495 ss << std::setbase(base) << number;
496 return ss.str();
497}
498
503template <typename CharType> CharType charToDigit(CharType character, CharType base)
504{
505 auto res = base;
506 if (character >= '0' && character <= '9') {
507 res = character - '0';
508 } else if (character >= 'a' && character <= 'z') {
509 res = character - 'a' + 10;
510 } else if (character >= 'A' && character <= 'Z') {
511 res = character - 'A' + 10;
512 }
513 if (res < base) {
514 return res;
515 }
516 constexpr auto msgBegin = std::string_view("The character \"");
517 constexpr auto msgEnd = std::string_view("\" is no valid digit.");
518 auto errorMsg = std::string();
519 errorMsg.reserve(msgBegin.size() + msgEnd.size() + 2);
520 errorMsg += msgBegin;
521 errorMsg += character >= ' ' && character <= '~' ? static_cast<std::string::value_type>(character) : '?';
522 errorMsg += msgEnd;
523 throw ConversionException(std::move(errorMsg));
524}
525
527namespace Detail {
528template <typename IntegralType, typename CharType, typename BaseType = IntegralType>
529void raiseAndAdd(IntegralType &result, BaseType base, CharType character)
530{
531 if (character == ' ') {
532 return;
533 }
534#ifdef __GNUC__ // overflow detection only supported on GCC and Clang
535 if (__builtin_mul_overflow(result, base, &result)
536 || __builtin_add_overflow(result, charToDigit(character, static_cast<CharType>(base)), &result)) {
537 throw ConversionException("Number exceeds limit.");
538 }
539#else
540 result *= static_cast<IntegralType>(base);
541 result += static_cast<IntegralType>(charToDigit<CharType>(character, static_cast<CharType>(base)));
542#endif
543}
544} // namespace Detail
546
554template <typename IntegralType, class CharType, typename BaseType = IntegralType,
555 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
556IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
557{
558 IntegralType result = 0;
559 for (const CharType *end = string + size; string != end; ++string) {
560 Detail::raiseAndAdd(result, base, *string);
561 }
562 return result;
563}
564
572template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
573 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
574IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
575{
576 if (!size) {
577 return 0;
578 }
579 const CharType *end = string + size;
580 for (; string != end && *string == ' '; ++string)
581 ;
582 if (string == end) {
583 return 0;
584 }
585 const bool negative = (*string == '-');
586 if (negative) {
587 ++string;
588 }
589 IntegralType result = 0;
590 for (; string != end; ++string) {
591 Detail::raiseAndAdd(result, base, *string);
592 }
593 return negative ? -result : result;
594}
595
603template <typename IntegralType, class StringType, typename BaseType = IntegralType,
605IntegralType stringToNumber(const StringType &string, BaseType base = 10)
606{
607 return bufferToNumber<IntegralType, typename StringType::value_type, BaseType>(string.data(), string.size(), base);
608}
609
619template <typename FloatingType, class StringViewType,
620 Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::IsSpecializationOf<StringViewType, std::basic_string_view>> * = nullptr>
621FloatingType stringToNumber(StringViewType stringView, int base = 10)
622{
623 std::basic_stringstream<typename StringViewType::value_type> ss;
624 ss << std::setbase(base) << stringView;
625 FloatingType result;
626 if ((ss >> result) && ss.eof()) {
627 return result;
628 }
629 std::string errorMsg;
630 errorMsg.reserve(48 + stringView.size());
631 errorMsg += "The string \"";
632 errorMsg += stringView;
633 errorMsg += "\" is no valid floating point number.";
634 throw ConversionException(errorMsg);
635}
636
646template <typename FloatingType, class StringType,
649FloatingType stringToNumber(const StringType &string, int base = 10)
650{
651 using StringViewType = std::basic_string_view<typename StringType::value_type>;
652 return stringToNumber<FloatingType, StringViewType>(StringViewType(string.data(), string.size()), base);
653}
654
662template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
663 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
664IntegralType stringToNumber(const CharType *string, BaseType base = 10)
665{
666 IntegralType result = 0;
667 for (; *string; ++string) {
668 Detail::raiseAndAdd(result, base, *string);
669 }
670 return result;
671}
672
682template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
683FloatingType stringToNumber(const CharType *string, int base = 10)
684{
686}
687
695template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
696 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
697IntegralType stringToNumber(const CharType *string, IntegralType base = 10)
698{
699 if (!*string) {
700 return 0;
701 }
702 for (; *string && *string == ' '; ++string)
703 ;
704 if (!*string) {
705 return 0;
706 }
707 const bool negative = (*string == '-');
708 if (negative) {
709 ++string;
710 }
711 IntegralType result = 0;
712 for (; *string; ++string) {
713 Detail::raiseAndAdd(result, base, *string);
714 }
715 return negative ? -result : result;
716}
717
727template <typename T> std::string interpretIntegerAsString(T integer, int startOffset = 0)
728{
729 char buffer[sizeof(T)];
730 BE::getBytes(integer, buffer);
731 return std::string(buffer + startOffset, sizeof(T) - static_cast<std::size_t>(startOffset));
732}
733
734CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte = false);
735CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false);
736CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize);
737CPP_UTILITIES_EXPORT std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t> decodeBase64(const char *encodedStr, const std::uint32_t strSize);
738} // namespace CppUtilities
739
740#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.
Definition global.h:14
CPP_UTILITIES_EXPORT void getBytes(T value, char *outputbuffer)
Stores the specified (unsigned) integer value in a char array.
Bool<!T::value > Not
Negates the specified value.
Definition traits.h:26
typename std::enable_if< All< Condition... >::value, Detail::Enabler >::type EnableIf
Shortcut for std::enable_if to omit value and type.
Definition traits.h:44
Contains all utilities provided 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.
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
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.
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...
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.
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.
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