C++ Utilities 5.27.0
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 <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
50#ifndef CPP_UTILITIES_NO_ICONV
52 const char *fromCharset, const char *toCharset, const char *inputBuffer, std::size_t inputBufferSize, float outputBufferSizeFactor = 1.0f);
53CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize);
54CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
55CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize);
56CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
57CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize);
58CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize);
59#endif
60
61#ifdef PLATFORM_WINDOWS
62using WideStringData = std::pair<std::unique_ptr<wchar_t[]>, int>;
63CPP_UTILITIES_EXPORT std::wstring convertMultiByteToWide(std::error_code &ec, std::string_view inputBuffer);
64CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuffer, int inputBufferSize = -1);
65CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer);
66CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1);
67CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const std::string &inputBuffer);
68#endif
69
70CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0');
71
73namespace Detail {
74#ifdef CPP_UTILITIES_USE_RANGES
75template <class Container>
76using ContainerValueType = typename std::conditional_t<std::ranges::range<Container>,
77 std::iterator_traits<std::remove_cvref_t<std::ranges::iterator_t<Container>>>, Container>::value_type;
78#else
79template <class Container> using ContainerValueType = typename Container::value_type;
80#endif
81template <class Container> using DefaultReturnTypeForContainer = ContainerValueType<Container>;
82template <class Container> using StringParamForContainer = std::basic_string_view<typename ContainerValueType<Container>::value_type>;
83} // namespace Detail
85
100template <class Container = std::initializer_list<std::string>, class ReturnType = Detail::DefaultReturnTypeForContainer<Container>>
101ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer<Container> delimiter = Detail::StringParamForContainer<Container>(),
102 bool omitEmpty = false, Detail::StringParamForContainer<Container> leftClosure = Detail::StringParamForContainer<Container>(),
103 Detail::StringParamForContainer<Container> rightClosure = Detail::StringParamForContainer<Container>())
104{
105 ReturnType res;
106 if (!strings.size()) {
107 return res;
108 }
109 std::size_t entries = 0, size = 0;
110 for (const auto &str : strings) {
111 if (omitEmpty && str.empty()) {
112 continue;
113 }
114 size += str.size();
115 ++entries;
116 }
117 if (!entries) {
118 return res;
119 }
120 size += (entries * leftClosure.size()) + (entries * rightClosure.size()) + ((entries - 1) * delimiter.size());
121 res.reserve(size);
122 for (const auto &str : strings) {
123 if (omitEmpty && str.empty()) {
124 continue;
125 }
126 if (!res.empty()) {
127 res.append(delimiter);
128 }
129 res.append(leftClosure);
130 res.append(str);
131 res.append(rightClosure);
132 }
133 return res;
134}
135
139template <class Container = std::initializer_list<std::string>> inline auto toMultiline(const Container &arrayOfLines)
140{
141 return joinStrings(arrayOfLines, "\n", false);
142}
143
147enum class EmptyPartsTreat {
148 Keep,
149 Omit,
150 Merge
151};
152
162template <class Container = std::list<std::string>>
163Container splitString(Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter,
164 EmptyPartsTreat emptyPartsRole = EmptyPartsTreat::Keep, int maxParts = -1)
165{
166 --maxParts;
167 Container res;
168 typename Container::value_type *last = nullptr;
169 bool merge = false;
170 typename Container::value_type::size_type i = 0, end = string.size();
171 for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
172 delimPos = string.find(delimiter, i);
173 if (!merge && maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
174 if (delimPos == i && emptyPartsRole == EmptyPartsTreat::Merge) {
175 if (last) {
176 merge = true;
177 continue;
178 }
179 }
180 delimPos = Container::value_type::npos;
181 }
182 if (delimPos == Container::value_type::npos) {
183 delimPos = string.size();
184 }
185 if (emptyPartsRole == EmptyPartsTreat::Keep || i != delimPos) {
186 if (merge) {
187 last->append(delimiter);
188 last->append(string, i, delimPos - i);
189 merge = false;
190 } else {
191 last = &res.emplace_back(string, i, delimPos - i);
192 }
193 } else if (emptyPartsRole == EmptyPartsTreat::Merge) {
194 if (last) {
195 merge = true;
196 }
197 }
198 }
199 if (i == end && emptyPartsRole == EmptyPartsTreat::Keep) {
200 res.emplace_back();
201 }
202 return res;
203}
204
214template <class Container = std::list<std::string>>
216 Detail::StringParamForContainer<Container> string, Detail::StringParamForContainer<Container> delimiter, int maxParts = -1)
217{
218 --maxParts;
219 Container res;
220 typename Container::value_type::size_type i = 0, end = string.size();
221 for (typename Container::value_type::size_type delimPos; i < end; i = delimPos + delimiter.size()) {
222 delimPos = string.find(delimiter, i);
223 if (maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
224 delimPos = Container::value_type::npos;
225 }
226 if (delimPos == Container::value_type::npos) {
227 delimPos = string.size();
228 }
229#if __cplusplus >= 201709
230 if constexpr (requires { res.emplace_back(string); }) {
231#endif
232 res.emplace_back(string.data() + i, delimPos - i);
233#if __cplusplus >= 201709
234 } else {
235 res.emplace(string.data() + i, delimPos - i);
236 }
237#endif
238 }
239 if (i == end) {
240#if __cplusplus >= 201709
241 if constexpr (requires { res.emplace_back(); }) {
242#endif
243 res.emplace_back();
244#if __cplusplus >= 201709
245 } else {
246 res.emplace();
247 }
248#endif
249 }
250 return res;
251}
252
256template <class Container = std::vector<std::string>> inline auto toArrayOfLines(const std::string &multilineString)
257{
258 return splitString<Container>(multilineString, "\n", EmptyPartsTreat::Keep);
259}
260
264template <typename StringType> bool startsWith(const StringType &str, const StringType &phrase)
265{
266 if (str.size() < phrase.size()) {
267 return false;
268 }
269 for (auto stri = str.cbegin(), strend = str.cend(), phrasei = phrase.cbegin(), phraseend = phrase.cend();; ++stri, ++phrasei) {
270 if (phrasei == phraseend) {
271 return true;
272 } else if (stri == strend) {
273 return false;
274 } else if (*stri != *phrasei) {
275 return false;
276 }
277 }
278 return false;
279}
280
284template <typename StringType> bool startsWith(const StringType &str, const typename StringType::value_type *phrase)
285{
286 for (auto stri = str.cbegin(), strend = str.cend();; ++stri, ++phrase) {
287 if (!*phrase) {
288 return true;
289 } else if (stri == strend) {
290 return false;
291 } else if (*stri != *phrase) {
292 return false;
293 }
294 }
295 return false;
296}
297
301template <typename StringType> bool endsWith(const StringType &str, const StringType &phrase)
302{
303 if (str.size() < phrase.size()) {
304 return false;
305 }
306 for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phrase.size()), strend = str.cend(), phrasei = phrase.cbegin();
307 stri != strend; ++stri, ++phrasei) {
308 if (*stri != *phrasei) {
309 return false;
310 }
311 }
312 return true;
313}
314
318template <typename StringType> bool endsWith(const StringType &str, const typename StringType::value_type *phrase)
319{
320 const auto phraseSize = std::strlen(phrase);
321 if (str.size() < phraseSize) {
322 return false;
323 }
324 for (auto stri = str.cend() - static_cast<typename StringType::difference_type>(phraseSize), strend = str.cend(); stri != strend;
325 ++stri, ++phrase) {
326 if (*stri != *phrase) {
327 return false;
328 }
329 }
330 return true;
331}
332
337template <typename StringType> bool containsSubstrings(const StringType &str, std::initializer_list<StringType> substrings)
338{
339 typename StringType::size_type currentPos = 0;
340 for (const auto &substr : substrings) {
341 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
342 return false;
343 }
344 currentPos += substr.size();
345 }
346 return true;
347}
348
353template <typename StringType>
354bool containsSubstrings(const StringType &str, std::initializer_list<const typename StringType::value_type *> substrings)
355{
356 typename StringType::size_type currentPos = 0;
357 for (const auto *substr : substrings) {
358 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
359 return false;
360 }
361 currentPos += std::strlen(substr);
362 }
363 return true;
364}
365
369template <typename StringType1, typename StringType2, typename StringType3>
370void findAndReplace(StringType1 &str, const StringType2 &find, const StringType3 &replace)
371{
372 for (typename StringType1::size_type i = 0; (i = str.find(find, i)) != StringType1::npos; i += replace.size()) {
373 str.replace(i, find.size(), replace);
374 }
375}
376
380template <typename StringType>
381inline void findAndReplace(StringType &str, const typename StringType::value_type *find, const typename StringType::value_type *replace)
382{
384 str, std::basic_string_view<typename StringType::value_type>(find), std::basic_string_view<typename StringType::value_type>(replace));
385}
386
390template <typename StringType1, typename StringType2>
391inline void findAndReplace(StringType1 &str, const StringType2 &find, const typename StringType1::value_type *replace)
392{
393 findAndReplace(str, find, std::basic_string_view<typename StringType1::value_type>(replace));
394}
395
399template <typename StringType1, typename StringType2>
400inline void findAndReplace(StringType1 &str, const typename StringType1::value_type *find, const StringType2 &replace)
401{
402 findAndReplace(str, std::basic_string_view<typename StringType1::value_type>(find), replace);
403}
404
411template <typename CharType> constexpr CharType digitToChar(CharType digit)
412{
413 return digit <= 9 ? (digit + '0') : (digit + 'A' - 10);
414}
415
422template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
423 CppUtilities::Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
424StringType numberToString(IntegralType number, BaseType base = 10)
425{
426 auto resSize = std::size_t();
427 auto n = number;
428 do {
429 n /= static_cast<IntegralType>(base), ++resSize;
430 } while (n);
431 auto res = StringType(resSize, typename StringType::value_type());
432 auto resIter = res.end();
433 do {
434 *(--resIter)
435 = digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % static_cast<IntegralType>(base)));
436 number /= static_cast<IntegralType>(base);
437 } while (number);
438 return res;
439}
440
447template <typename IntegralType, class StringType = std::string, typename BaseType = IntegralType,
448 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
449StringType numberToString(IntegralType number, BaseType base = 10)
450{
451 const auto negative = number < 0;
452 auto resSize = std::size_t();
453 if (negative) {
454 number = -number, resSize = 1;
455 }
456 auto n = number;
457 do {
458 n /= static_cast<IntegralType>(base), ++resSize;
459 } while (n);
460 auto res = StringType(resSize, typename StringType::value_type());
461 auto resIter = res.end();
462 do {
463 *(--resIter)
464 = digitToChar<typename StringType::value_type>(static_cast<typename StringType::value_type>(number % static_cast<IntegralType>(base)));
465 number /= static_cast<IntegralType>(base);
466 } while (number);
467 if (negative) {
468 *(--resIter) = '-';
469 }
470 return res;
471}
472
481template <typename FloatingType, class StringType = std::string, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
482StringType numberToString(FloatingType number, int base = 10)
483{
484 std::basic_stringstream<typename StringType::value_type> ss;
485 ss << std::setbase(base) << number;
486 return ss.str();
487}
488
493template <typename CharType> CharType charToDigit(CharType character, CharType base)
494{
495 auto res = base;
496 if (character >= '0' && character <= '9') {
497 res = character - '0';
498 } else if (character >= 'a' && character <= 'z') {
499 res = character - 'a' + 10;
500 } else if (character >= 'A' && character <= 'Z') {
501 res = character - 'A' + 10;
502 }
503 if (res < base) {
504 return res;
505 }
506 constexpr auto msgBegin = std::string_view("The character \"");
507 constexpr auto msgEnd = std::string_view("\" is no valid digit.");
508 auto errorMsg = std::string();
509 errorMsg.reserve(msgBegin.size() + msgEnd.size() + 2);
510 errorMsg += msgBegin;
511 errorMsg += character >= ' ' && character <= '~' ? static_cast<std::string::value_type>(character) : '?';
512 errorMsg += msgEnd;
513 throw ConversionException(std::move(errorMsg));
514}
515
517namespace Detail {
518template <typename IntegralType, typename CharType, typename BaseType = IntegralType>
519void raiseAndAdd(IntegralType &result, BaseType base, CharType character)
520{
521 if (character == ' ') {
522 return;
523 }
524#ifdef __GNUC__ // overflow detection only supported on GCC and Clang
525 if (__builtin_mul_overflow(result, base, &result)
526 || __builtin_add_overflow(result, charToDigit(character, static_cast<CharType>(base)), &result)) {
527 throw ConversionException("Number exceeds limit.");
528 }
529#else
530 result *= static_cast<IntegralType>(base);
531 result += static_cast<IntegralType>(charToDigit<CharType>(character, static_cast<CharType>(base)));
532#endif
533}
534} // namespace Detail
536
544template <typename IntegralType, class CharType, typename BaseType = IntegralType,
545 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
546IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
547{
548 IntegralType result = 0;
549 for (const CharType *end = string + size; string != end; ++string) {
550 Detail::raiseAndAdd(result, base, *string);
551 }
552 return result;
553}
554
562template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
563 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
564IntegralType bufferToNumber(const CharType *string, std::size_t size, BaseType base = 10)
565{
566 if (!size) {
567 return 0;
568 }
569 const CharType *end = string + size;
570 for (; string != end && *string == ' '; ++string)
571 ;
572 if (string == end) {
573 return 0;
574 }
575 const bool negative = (*string == '-');
576 if (negative) {
577 ++string;
578 }
579 IntegralType result = 0;
580 for (; string != end; ++string) {
581 Detail::raiseAndAdd(result, base, *string);
582 }
583 return negative ? -result : result;
584}
585
593template <typename IntegralType, class StringType, typename BaseType = IntegralType,
595IntegralType stringToNumber(const StringType &string, BaseType base = 10)
596{
597 return bufferToNumber<IntegralType, typename StringType::value_type, BaseType>(string.data(), string.size(), base);
598}
599
609template <typename FloatingType, class StringViewType,
610 Traits::EnableIf<std::is_floating_point<FloatingType>, Traits::IsSpecializationOf<StringViewType, std::basic_string_view>> * = nullptr>
611FloatingType stringToNumber(StringViewType stringView, int base = 10)
612{
613 std::basic_stringstream<typename StringViewType::value_type> ss;
614 ss << std::setbase(base) << stringView;
615 FloatingType result;
616 if ((ss >> result) && ss.eof()) {
617 return result;
618 }
619 std::string errorMsg;
620 errorMsg.reserve(48 + stringView.size());
621 errorMsg += "The string \"";
622 errorMsg += stringView;
623 errorMsg += "\" is no valid floating point number.";
624 throw ConversionException(errorMsg);
625}
626
636template <typename FloatingType, class StringType,
639FloatingType stringToNumber(const StringType &string, int base = 10)
640{
641 using StringViewType = std::basic_string_view<typename StringType::value_type>;
642 return stringToNumber<FloatingType, StringViewType>(StringViewType(string.data(), string.size()), base);
643}
644
652template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
653 Traits::EnableIf<std::is_integral<IntegralType>, std::is_unsigned<IntegralType>> * = nullptr>
654IntegralType stringToNumber(const CharType *string, BaseType base = 10)
655{
656 IntegralType result = 0;
657 for (; *string; ++string) {
658 Detail::raiseAndAdd(result, base, *string);
659 }
660 return result;
661}
662
672template <typename FloatingType, class CharType, Traits::EnableIf<std::is_floating_point<FloatingType>> * = nullptr>
673FloatingType stringToNumber(const CharType *string, int base = 10)
674{
676}
677
685template <typename IntegralType, typename CharType, typename BaseType = IntegralType,
686 Traits::EnableIf<std::is_integral<IntegralType>, std::is_signed<IntegralType>> * = nullptr>
687IntegralType stringToNumber(const CharType *string, IntegralType base = 10)
688{
689 if (!*string) {
690 return 0;
691 }
692 for (; *string && *string == ' '; ++string)
693 ;
694 if (!*string) {
695 return 0;
696 }
697 const bool negative = (*string == '-');
698 if (negative) {
699 ++string;
700 }
701 IntegralType result = 0;
702 for (; *string; ++string) {
703 Detail::raiseAndAdd(result, base, *string);
704 }
705 return negative ? -result : result;
706}
707
717template <typename T> std::string interpretIntegerAsString(T integer, int startOffset = 0)
718{
719 char buffer[sizeof(T)];
720 BE::getBytes(integer, buffer);
721 return std::string(buffer + startOffset, sizeof(T) - static_cast<std::size_t>(startOffset));
722}
723
724CPP_UTILITIES_EXPORT std::string dataSizeToString(std::uint64_t sizeInByte, bool includeByte = false);
725CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits = false);
726CPP_UTILITIES_EXPORT std::string encodeBase64(const std::uint8_t *data, std::uint32_t dataSize);
727CPP_UTILITIES_EXPORT std::pair<std::unique_ptr<std::uint8_t[]>, std::uint32_t> decodeBase64(const char *encodedStr, const std::uint32_t strSize);
728} // namespace CppUtilities
729
730#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 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.
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.
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...
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