1 #ifndef CONVERSION_UTILITIES_STRINGCONVERSION_H 2 #define CONVERSION_UTILITIES_STRINGCONVERSION_H 7 #include "../misc/traits.h" 11 #include <initializer_list> 31 std::free(stringData);
38 using StringData = std::pair<std::unique_ptr<char[], StringDataDeleter>, std::size_t>;
42 const char *fromCharset,
const char *toCharset,
const char *inputBuffer, std::size_t inputBufferSize,
float outputBufferSizeFactor = 1.0f);
50 #ifdef PLATFORM_WINDOWS 51 using WideStringData = std::pair<std::unique_ptr<wchar_t[]>,
int>;
52 CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(
const char *inputBuffer,
int inputBufferSize = -1);
71 template <
class Container = std::initializer_list<std::
string>>
72 typename Container::value_type
joinStrings(
const Container &strings,
73 const typename Container::value_type &delimiter =
typename Container::value_type(),
bool omitEmpty =
false,
74 const typename Container::value_type &leftClosure =
typename Container::value_type(),
75 const typename Container::value_type &rightClosure =
typename Container::value_type())
77 typename Container::value_type res;
78 if (!strings.size()) {
81 std::size_t entries = 0, size = 0;
82 for (
const auto &str : strings) {
83 if (omitEmpty && str.empty()) {
92 size += (entries * leftClosure.size()) + (entries * rightClosure.size()) + ((entries - 1) * delimiter.size());
94 for (
const auto &str : strings) {
95 if (omitEmpty && str.empty()) {
99 res.append(delimiter);
101 res.append(leftClosure);
103 res.append(rightClosure);
111 template <
class Container = std::initializer_list<std::
string>>
inline std::vector<std::string>
toMultiline(
const Container &arrayOfLines)
134 template <
class Container = std::list<std::
string>>
135 Container
splitString(
const typename Container::value_type &
string,
const typename Container::value_type &delimiter,
141 for (
typename Container::value_type::size_type
i = 0, end =
string.size(), delimPos;
i < end;
i = delimPos + delimiter.size()) {
142 delimPos =
string.find(delimiter,
i);
143 if (!merge && maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
150 delimPos = Container::value_type::npos;
152 if (delimPos == Container::value_type::npos) {
153 delimPos =
string.size();
157 res.back().append(delimiter);
158 res.back().append(
string.substr(
i, delimPos -
i));
161 res.emplace_back(
string.substr(
i, delimPos -
i));
181 template <
class Container = std::list<std::
string>>
182 Container
splitStringSimple(
const typename Container::value_type &
string,
const typename Container::value_type &delimiter,
int maxParts = -1)
186 for (
typename Container::value_type::size_type
i = 0, end =
string.size(), delimPos;
i < end;
i = delimPos + delimiter.size()) {
187 delimPos =
string.find(delimiter,
i);
188 if (maxParts >= 0 && res.size() == static_cast<typename Container::value_type::size_type>(maxParts)) {
189 delimPos = Container::value_type::npos;
191 if (delimPos == Container::value_type::npos) {
192 delimPos =
string.size();
194 res.emplace_back(
string.substr(
i, delimPos -
i));
202 template <
class Container = std::vector<std::
string>>
inline std::vector<std::string>
toArrayOfLines(
const std::string &multilineString)
210 template <
typename StringType>
bool startsWith(
const StringType &str,
const StringType &phrase)
212 if (str.size() < phrase.size()) {
215 for (
auto stri = str.cbegin(), strend = str.cend(), phrasei = phrase.cbegin(), phraseend = phrase.cend(); stri != strend; ++stri, ++phrasei) {
216 if (phrasei == phraseend) {
218 }
else if (*stri != *phrasei) {
228 template <
typename StringType>
bool startsWith(
const StringType &str,
const typename StringType::value_type *phrase)
230 for (
auto stri = str.cbegin(), strend = str.cend(); stri != strend; ++stri, ++phrase) {
233 }
else if (*stri != *phrase) {
244 template <
typename StringType>
bool containsSubstrings(
const StringType &str, std::initializer_list<StringType> substrings)
246 typename StringType::size_type currentPos = 0;
247 for (
const auto &substr : substrings) {
248 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
251 currentPos += substr.size();
260 template <
typename StringType>
261 bool containsSubstrings(
const StringType &str, std::initializer_list<const typename StringType::value_type *> substrings)
263 typename StringType::size_type currentPos = 0;
264 for (
const auto *substr : substrings) {
265 if ((currentPos = str.find(substr, currentPos)) == StringType::npos) {
268 currentPos += std::strlen(substr);
276 template <
typename StringType>
void findAndReplace(StringType &str,
const StringType &find,
const StringType &replace)
278 for (
typename StringType::size_type
i = 0; (
i = str.find(find,
i)) != StringType::npos;
i += replace.size()) {
279 str.replace(
i, find.size(), replace);
289 template <
typename CharType> constexpr CharType
digitToChar(CharType digit)
291 return digit <= 9 ? (digit +
'0') : (digit +
'A' - 10);
300 template <
typename IntegralType,
class StringType = std::string,
302 StringType
numberToString(IntegralType number,
typename StringType::value_type base = 10)
304 std::size_t resSize = 0;
305 for (
auto n = number; n; n /= base, ++resSize)
308 res.reserve(resSize);
310 res.insert(res.begin(), digitToChar<typename StringType::value_type>(number % base));
322 template <
typename IntegralType,
class StringType = std::string,
324 StringType
numberToString(IntegralType number,
typename StringType::value_type base = 10)
326 const bool negative = number < 0;
329 number = -number, resSize = 1;
333 for (
auto n = number; n; n /= base, ++resSize)
336 res.reserve(resSize);
338 res.insert(res.begin(), digitToChar<typename StringType::value_type>(number % base));
342 res.insert(res.begin(),
'-');
355 template <
typename FloatingType,
class StringType = std::
string, Traits::EnableIf<std::is_
floating_po
int<FloatingType>> * =
nullptr>
356 StringType
numberToString(FloatingType number,
typename StringType::value_type base = 10)
358 std::basic_stringstream<typename StringType::value_type> ss;
359 ss << std::setbase(base) << number;
368 template <
typename CharType> CharType
charToDigit(CharType character, CharType base)
371 if (character >=
'0' && character <=
'9') {
372 res = character -
'0';
373 }
else if (character >=
'a' && character <=
'z') {
374 res = character -
'a' + 10;
375 }
else if (character >=
'A' && character <=
'Z') {
376 res = character -
'A' + 10;
381 std::string errorMsg;
382 errorMsg.reserve(36);
383 errorMsg +=
"The character \"";
384 errorMsg += character;
385 errorMsg +=
"\" is no valid digit.";
397 template <
typename IntegralType,
typename StringType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
unsigned<IntegralType>> * =
nullptr>
398 IntegralType
stringToNumber(
const StringType &
string,
typename StringType::value_type base = 10)
400 IntegralType result = 0;
401 for (
const auto &c :
string) {
406 result += charToDigit<typename StringType::value_type>(c, base);
419 template <
typename IntegralType,
class StringType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
signed<IntegralType>> * =
nullptr>
420 IntegralType
stringToNumber(
const StringType &
string,
typename StringType::value_type base = 10)
422 auto i =
string.begin();
423 auto end =
string.end();
424 for (;
i != end && *
i ==
' '; ++
i)
429 const bool negative = (*
i ==
'-');
433 IntegralType result = 0;
434 for (;
i != end; ++
i) {
439 result += charToDigit<typename StringType::value_type>(*
i, base);
441 return negative ? -result : result;
454 template <
typename FloatingType,
class StringType, Traits::EnableIf<std::is_
floating_po
int<FloatingType>> * =
nullptr>
455 FloatingType
stringToNumber(
const StringType &
string,
typename StringType::value_type base = 10)
457 std::basic_stringstream<typename StringType::value_type> ss;
458 ss << std::setbase(base) << string;
460 if ((ss >> result) && ss.eof()) {
463 std::string errorMsg;
464 errorMsg.reserve(42 +
string.size());
465 errorMsg +=
"The string \"";
467 errorMsg +=
"\" is no valid floating number.";
479 template <
typename IntegralType,
class CharType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
unsigned<IntegralType>> * =
nullptr>
482 IntegralType result = 0;
483 for (; *string; ++string) {
484 if (*
string ==
' ') {
488 result += charToDigit<CharType>(*
string, base);
503 template <
typename FloatingType,
class CharType, Traits::EnableIf<std::is_
floating_po
int<FloatingType>> * =
nullptr>
506 std::basic_stringstream<CharType> ss;
507 ss << std::setbase(base) << string;
509 if ((ss >> result) && ss.eof()) {
512 std::string errorMsg;
513 errorMsg.reserve(42 + std::char_traits<CharType>::length(
string));
514 errorMsg +=
"The string \"";
516 errorMsg +=
"\" is no valid floating number.";
527 template <
typename IntegralType,
class CharType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
unsigned<IntegralType>> * =
nullptr>
528 IntegralType
bufferToNumber(
const CharType *
string, std::size_t size,
unsigned char base = 10)
530 IntegralType result = 0;
531 for (
const CharType *end =
string + size;
string != end; ++string) {
532 if (*
string ==
' ') {
536 result += charToDigit<CharType>(*
string, base);
548 template <
typename IntegralType,
class CharType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
signed<IntegralType>> * =
nullptr>
549 IntegralType
stringToNumber(
const CharType *
string,
unsigned char base = 10)
554 for (; *
string && *
string ==
' '; ++string)
559 const bool negative = (*
string ==
'-');
563 IntegralType result = 0;
564 for (; *string; ++string) {
565 if (*
string ==
' ') {
569 result += charToDigit<CharType>(*
string, base);
571 return negative ? -result : result;
581 template <
typename IntegralType,
class CharType, Traits::EnableIf<std::is_
integral<IntegralType>, std::is_
signed<IntegralType>> * =
nullptr>
582 IntegralType
bufferToNumber(
const CharType *
string, std::size_t size,
unsigned char base = 10)
587 const CharType *end =
string + size;
588 for (;
string != end && *
string ==
' '; ++string)
593 const bool negative = (*
string ==
'-');
597 IntegralType result = 0;
598 for (;
string != end; ++string) {
599 if (*
string ==
' ') {
603 result += charToDigit<CharType>(*
string, base);
605 return negative ? -result : result;
619 char buffer[
sizeof(T)];
621 return std::string(buffer + startOffset,
sizeof(T) - startOffset);
630 #endif // CONVERSION_UTILITIES_STRINGCONVERSION_H CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16LE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (little-endian).
bool startsWith(const StringType &str, const StringType &phrase)
Returns whether str starts with phrase.
void operator()(char *stringData)
Deletes the specified stringData with std::free(), because the memory has been allocated using std::m...
CPP_UTILITIES_EXPORT std::string encodeBase64(const byte *data, uint32 dataSize)
Encodes the specified data to Base64.
std::pair< std::unique_ptr< char[], StringDataDeleter >, std::size_t > StringData
Type used to return string encoding conversion result.
IntegralType stringToNumber(const StringType &string, typename StringType::value_type base=10)
Converts the given string to an unsigned number assuming string uses the specified base.
Container splitStringSimple(const typename Container::value_type &string, const typename Container::value_type &delimiter, int maxParts=-1)
Splits the given string (which might also be a string view) at the specified delimiter.
#define CPP_UTILITIES_EXPORT
bool containsSubstrings(const StringType &str, std::initializer_list< StringType > substrings)
Returns whether str contains the specified substrings.
The ConversionException class is thrown by the various conversion functions of this library when a co...
std::vector< std::string > toArrayOfLines(const std::string &multilineString)
Converts the specified multilineString to an array of lines.
CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (big-endian) string to UTF-8.
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...
StringType numberToString(IntegralType number, typename StringType::value_type base=10)
Converts the given number to its equivalent string representation using the specified base.
std::uint64_t uint64
unsigned 64-bit integer
The StringDataDeleter struct deletes the data of a StringData instance.
typename std::enable_if< All< Condition... >::value, Detail::Enabler >::type EnableIf
Shortcut for std::enable_if to omit ::value and ::type.
std::string interpretIntegerAsString(T integer, int startOffset=0)
Interprets the given integer at the specified position as std::string using the specified byte order.
CPP_UTILITIES_EXPORT StringData convertUtf8ToUtf16BE(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to UTF-16 (big-endian).
EmptyPartsTreat
Specifies the role of empty parts when splitting strings.
CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-8 string to Latin-1.
void findAndReplace(StringType &str, const StringType &find, const StringType &replace)
Replaces all occurences of find with relpace in the specified str.
Contains several functions providing conversions between different data types.
std::uint32_t uint32
unsigned 32-bit integer
IntegralType bufferToNumber(const CharType *string, std::size_t size, unsigned char base=10)
Converts the given string of size characters to an unsigned numeric value using the specified base.
CPP_UTILITIES_EXPORT StringData convertUtf16LEToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified UTF-16 (little-endian) string to UTF-8.
CharType charToDigit(CharType character, CharType base)
Returns number/digit of the specified character representation using the specified base.
Container::value_type joinStrings(const Container &strings, const typename Container::value_type &delimiter=typename Container::value_type(), bool omitEmpty=false, const typename Container::value_type &leftClosure=typename Container::value_type(), const typename Container::value_type &rightClosure=typename Container::value_type())
Joins the given strings using the specified delimiter.
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.
CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize)
Converts the specified Latin-1 string to UTF-8.
std::vector< std::string > toMultiline(const Container &arrayOfLines)
Converts the specified arrayOfLines to a multiline string.
Container splitString(const typename Container::value_type &string, const typename Container::value_type &delimiter, EmptyPartsTreat emptyPartsRole=EmptyPartsTreat::Keep, int maxParts=-1)
Splits the given string at the specified delimiter.
CPP_UTILITIES_EXPORT std::string dataSizeToString(uint64 sizeInByte, bool includeByte=false)
Converts the specified data size in byte to its equivalent std::string representation.
CPP_UTILITIES_EXPORT std::pair< std::unique_ptr< byte[]>, uint32 > decodeBase64(const char *encodedStr, const uint32 strSize)
Decodes the specified Base64 encoded string.
constexpr CharType digitToChar(CharType digit)
Returns the character representation of the specified digit.
CPP_UTILITIES_EXPORT std::string bitrateToString(double speedInKbitsPerSecond, bool useByteInsteadOfBits=false)
Converts the specified bitrate in kbit/s to its equivalent std::string representation.
CPP_UTILITIES_EXPORT void getBytes(int16 value, char *outputbuffer)
Stores the specified 16-bit signed integer value at a specified position in a char array.