8 #include "fmt/printf.h"
12 #pragma comment(lib, "ws2_32.lib")
60 while ((cutAt = str.find_first_of(delim, Prev)) != str.npos)
62 results.push_back(str.substr(Prev, cutAt - Prev));
65 if (Prev < str.length())
67 results.push_back(str.substr(Prev));
82 size_t cutAtQuote = 0;
84 while ((cutAt = str.find_first_of(delim, Prev)) != str.npos)
93 AString current = str.substr(Prev, cutAt - Prev);
94 if ((current.front() ==
'"') || (current.front() ==
'\''))
97 cutAtQuote = str.find_first_of(current.front(), Prev);
98 if (cutAtQuote != str.npos)
100 current = str.substr(Prev, cutAtQuote - Prev);
101 cutAt = cutAtQuote + 1;
105 results.push_back(std::move(current));
109 if (Prev < str.length())
111 AString current = str.substr(Prev);
115 (current.length() >= 2) &&
116 ((current.front() ==
'"') || (current.front() ==
'\'')) &&
117 (current.front() == current.back())
120 current = current.substr(1, current.length() - 2);
123 results.push_back(current);
135 if (a_Strings.empty())
141 const auto DelimSize = a_Delimeter.size();
142 size_t ResultSize = a_Strings[0].size();
143 std::for_each(a_Strings.begin() + 1, a_Strings.end(),
146 ResultSize += DelimSize;
147 ResultSize += a_String.size();
153 Result.reserve(ResultSize);
154 Result.append(a_Strings[0]);
155 std::for_each(a_Strings.begin() + 1, a_Strings.end(),
158 Result += a_Delimeter;
174 while ((cutAt = str.find_first_of(delim, Prev)) != str.npos)
176 results.push_back(
TrimString(str.substr(Prev, cutAt - Prev)));
179 if (Prev < str.length())
181 results.push_back(
TrimString(str.substr(Prev)));
192 size_t len = str.length();
196 if (
static_cast<unsigned char>(str[start]) > 32)
210 if (
static_cast<unsigned char>(str[end]) > 32)
217 return str.substr(start, end - start + 1);
226 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
236 std::transform(s.begin(), s.end(), s.begin(), ::toupper);
247 res.resize(s.size());
248 std::transform(s.begin(), s.end(), res.begin(), ::tolower);
259 res.resize(s.size());
260 std::transform(s.begin(), s.end(), res.begin(), ::toupper);
271 return _stricmp(s1.c_str(), s2.c_str());
273 return strcasecmp(s1.c_str(), s2.c_str());
283 size_t MatchedLetters = 0;
284 size_t s1Length = s1.length();
286 if (s1Length > s2.length())
292 for (
size_t i = 0; i < s1Length; i++)
294 char c1 =
static_cast<char>(toupper(s1[i]));
295 char c2 =
static_cast<char>(toupper(s2[i]));
305 return MatchedLetters;
320 size_t pos1 = iHayStack.find(iNeedle);
321 while (pos1 != AString::npos)
323 iHayStack.replace( pos1, iNeedle.size(), iReplaceWith);
324 pos1 = iHayStack.find(iNeedle, pos1 + iReplaceWith.size());
334 auto ReplaceWith =
URLEncode(iReplaceWith);
345 a_UTF8.reserve(3 * a_NumShorts / 2);
346 for (
size_t i = 0; i < a_NumShorts; i++)
359 if (a_UnicodeChar < 0x80)
361 return AString{
static_cast<char>(a_UnicodeChar)};
363 else if (a_UnicodeChar < 0x800)
367 static_cast<char>(192 + a_UnicodeChar / 64),
368 static_cast<char>(128 + a_UnicodeChar % 64),
371 else if (a_UnicodeChar - 0xd800 < 0x800)
376 else if (a_UnicodeChar < 0x10000)
380 static_cast<char>(224 + a_UnicodeChar / 4096),
381 static_cast<char>(128 + (a_UnicodeChar / 64) % 64),
382 static_cast<char>(128 + a_UnicodeChar % 64)
385 else if (a_UnicodeChar < 0x110000)
389 static_cast<char>(240 + a_UnicodeChar / 262144),
390 static_cast<char>(128 + (a_UnicodeChar / 4096) % 64),
391 static_cast<char>(128 + (a_UnicodeChar / 64) % 64),
392 static_cast<char>(128 + a_UnicodeChar % 64),
407 #pragma GCC diagnostic push
408 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
440 #define UNI_MAX_BMP 0x0000FFFF
441 #define UNI_MAX_UTF16 0x0010FFFF
442 #define UNI_SUR_HIGH_START 0xD800
443 #define UNI_SUR_LOW_START 0xDC00
444 #define UNI_SUR_LOW_END 0xDFFF
452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
453 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
454 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
459 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
468 0x00000000UL, 0x00003080UL, 0x000E2080UL,
469 0x03C82080UL, 0xFA082080UL, 0x82082080UL
479 const unsigned char * srcptr = source + length;
482 default:
return false;
484 case 4:
if (((a = (*--srcptr)) < 0x80) || (a > 0xbf))
return false;
485 case 3:
if (((a = (*--srcptr)) < 0x80) || (a > 0xbf))
return false;
488 if ((a = (*--srcptr)) > 0xbf)
495 case 0xe0:
if (a < 0xa0)
return false;
break;
496 case 0xed:
if (a > 0x9f)
return false;
break;
497 case 0xf0:
if (a < 0x90)
return false;
break;
498 case 0xf4:
if (a > 0x8f)
return false;
break;
499 default:
if (a < 0x80)
return false;
502 case 1:
if ((*source >= 0x80) && (*source < 0xc2))
return false;
504 return (*source <= 0xf4);
513 std::u16string UTF16;
514 UTF16.reserve(a_UTF8.size() * 2);
516 const unsigned char * source =
reinterpret_cast<const unsigned char *
>(a_UTF8.data());
517 const unsigned char * sourceEnd = source + a_UTF8.size();
518 const int halfShift = 10;
519 const unsigned int halfBase = 0x0010000UL;
520 const unsigned int halfMask = 0x3ffUL;
522 while (source < sourceEnd)
526 if (source + extraBytesToRead >= sourceEnd)
537 switch (extraBytesToRead)
539 case 5: ch += *source++; ch <<= 6;
540 case 4: ch += *source++; ch <<= 6;
541 case 3: ch += *source++; ch <<= 6;
542 case 2: ch += *source++; ch <<= 6;
543 case 1: ch += *source++; ch <<= 6;
544 case 0: ch += *source++;
556 unsigned short v = htons(
static_cast<unsigned short>(ch));
557 UTF16.push_back(
static_cast<char16_t
>(v));
562 unsigned short v = htons(
' ');
563 UTF16.push_back(
static_cast<char16_t
>(v));
571 UTF16.push_back(
static_cast<char16_t
>(v1));
572 UTF16.push_back(
static_cast<char16_t
>(v2));
603 #pragma GCC diagnostic pop
610 #define HEX(x) static_cast<char>((x) > 9 ? (x) + 'A' - 10 : (x) + '0')
618 fmt::memory_buffer Output;
622 fmt::memory_buffer Hex, Chars;
627 const size_t NumLines = a_Size / a_BytesPerLine + (a_Size % a_BytesPerLine != 0);
628 const size_t CharsPerLine = 14 + 4 * a_BytesPerLine;
629 Output.reserve(NumLines * CharsPerLine);
632 for (
size_t i = 0; i < a_Size; i += a_BytesPerLine)
634 size_t k = std::min(a_Size - i, a_BytesPerLine);
635 for (
size_t j = 0; j < k; j++)
637 Byte c = (
static_cast<const Byte *
>(a_Data))[i + j];
638 Hex.push_back(
HEX(c >> 4));
639 Hex.push_back(
HEX(c & 0xf));
641 Chars.push_back((c >=
' ') ?
static_cast<char>(c) :
'.');
645 auto HexStr = fmt::string_view(Hex.data(), Hex.size());
646 auto CharsStr = fmt::string_view(Chars.data(), Chars.size());
648 Output,
"{0:08x}: {1:{2}} {3}\n",
649 i, HexStr, a_BytesPerLine * 3, CharsStr
655 a_Out.append(Output.data(), Output.size());
666 size_t len = a_Message.size();
668 EscapedMsg.reserve(len);
669 for (
size_t i = 0; i < len; i++)
671 char ch = a_Message[i];
680 EscapedMsg.append(a_Message, last, i - last);
682 EscapedMsg.push_back(
'\\');
683 EscapedMsg.push_back(ch);
691 EscapedMsg.append(a_Message, last, len - last);
706 idx = res.find(
"\xc2\xa7", idx);
707 if (idx == AString::npos)
722 auto len = a_Text.size();
724 for (
size_t i = 0; i < len; i++)
726 if (a_Text[i] ==
'+')
731 if (a_Text[i] !=
'%')
733 res.push_back(a_Text[i]);
739 return std::make_pair(
false,
AString());
741 if ((a_Text[i + 1] ==
'u') || (a_Text[i + 1] ==
'U'))
746 return std::make_pair(
false,
AString());
748 if (a_Text[i + 2] !=
'0')
750 return std::make_pair(
false,
AString());
752 unsigned v1 =
HexToDec(a_Text[i + 3]);
753 unsigned v2 =
HexToDec(a_Text[i + 4]);
754 unsigned v3 =
HexToDec(a_Text[i + 5]);
755 unsigned v4 =
HexToDec(a_Text[i + 6]);
756 if ((v1 == 0xff) || (v2 == 0xff) || (v4 == 0xff) || (v3 == 0xff))
759 return std::make_pair(
false,
AString());
769 return std::make_pair(
false,
AString());
773 if ((v1 == 0xff) || (v2 == 0xff))
776 return std::make_pair(
false,
AString());
778 res.push_back(
static_cast<char>((v1 << 4) | v2));
782 return std::make_pair(
true, res);
792 auto len = a_Text.size();
794 static const char HEX[] =
"0123456789ABCDEF";
795 for (
size_t i = 0; i < len; ++i)
797 if (isalnum(a_Text[i]))
799 res.push_back(a_Text[i]);
801 else if (a_Text[i] ==
' ')
808 res.push_back(
HEX[
static_cast<unsigned char>(a_Text[i]) >> 4]);
809 res.push_back(
HEX[
static_cast<unsigned char>(a_Text[i]) & 0x0f]);
822 std::replace(res.begin(), res.end(), a_From, a_To);
833 if ((c >=
'A') && (c <=
'Z'))
837 if ((c >=
'a') && (c <=
'z'))
841 if ((c >=
'0') && (c <=
'9'))
867 size_t i, len = a_Base64String.size();
870 res.resize((len * 4) / 3 + 5, 0);
871 for (o = 0, i = 0; i < len; i++)
878 case 0: res[o >> 3] |= (c << 2);
break;
879 case 6: res[o >> 3] |= (c >> 4); res[(o >> 3) + 1] |= (c << 4);
break;
880 case 4: res[o >> 3] |= (c >> 2); res[(o >> 3) + 1] |= (c << 6);
break;
881 case 2: res[o >> 3] |= c;
break;
902 static const char BASE64[64] =
904 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
905 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
906 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
907 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
911 output.resize(((a_Input.size() + 2) / 3) * 4);
913 size_t output_index = 0;
914 size_t size_full24 = (a_Input.size() / 3) * 3;
916 for (
size_t i = 0; i < size_full24; i += 3)
918 output[output_index++] = BASE64[
static_cast<unsigned char>(a_Input[i]) >> 2];
919 output[output_index++] = BASE64[(
static_cast<unsigned char>(a_Input[i]) << 4 |
static_cast<unsigned char>(a_Input[i + 1]) >> 4) & 63];
920 output[output_index++] = BASE64[(
static_cast<unsigned char>(a_Input[i + 1]) << 2 |
static_cast<unsigned char>(a_Input[i + 2]) >> 6) & 63];
921 output[output_index++] = BASE64[
static_cast<unsigned char>(a_Input[i + 2]) & 63];
924 if (size_full24 < a_Input.size())
926 output[output_index++] = BASE64[
static_cast<unsigned char>(a_Input[size_full24]) >> 2];
927 if (size_full24 + 1 == a_Input.size())
929 output[output_index++] = BASE64[(
static_cast<unsigned char>(a_Input[size_full24]) << 4) & 63];
930 output[output_index++] =
'=';
934 output[output_index++] = BASE64[(
static_cast<unsigned char>(a_Input[size_full24]) << 4 |
static_cast<unsigned char>(a_Input[size_full24 + 1]) >> 4) & 63];
935 output[output_index++] = BASE64[(
static_cast<unsigned char>(a_Input[size_full24 + 1]) << 2) & 63];
938 output[output_index++] =
'=';
940 ASSERT(output_index == output.size());
951 return static_cast<short>(
952 (
static_cast<short>(a_Mem[0]) << 8) |
953 static_cast<short>(a_Mem[1])
963 const Byte * Bytes =
reinterpret_cast<const Byte *
>(a_Mem);
964 return static_cast<unsigned short>((Bytes[0] << 8) | Bytes[1]);
974 (
static_cast<int>(a_Mem[0]) << 24) |
975 (
static_cast<int>(a_Mem[1]) << 16) |
976 (
static_cast<int>(a_Mem[2]) << 8) |
977 static_cast<int>(a_Mem[3])
987 a_Mem[0] = std::byte(a_Value >> 24);
988 a_Mem[1] = std::byte((a_Value >> 16) & 0xff);
989 a_Mem[2] = std::byte((a_Value >> 8) & 0xff);
990 a_Mem[3] = std::byte(a_Value & 0xff);
1000 size_t size = a_Strings.size();
1003 for (
size_t i = 0; i < size; i++)
1005 if (a_Strings[i] == 0)
1007 a_Output.push_back(a_Strings.substr(start, i - start));
1014 a_Output.push_back(a_Strings.substr(start, size - start));
1031 for (
const auto & item : a_Strings2)
1033 if (std::find(res.begin(), res.end(), item) == res.end())
1035 res.push_back(item);
1049 if (a_Strings.empty())
1056 res.append(a_Strings[0]);
1057 for (
auto itr = a_Strings.cbegin() + 1, end = a_Strings.cend(); itr != end; ++itr)
1059 res.push_back(a_Separator);
1072 a_Num = strtof(a_String.c_str(), &err);
1082 return std::all_of(a_String.cbegin(), a_String.cend(), isspace);
std::pair< bool, AString > URLDecode(const AString &a_Text)
URL-Decodes the given string.
short GetBEShort(const std::byte *const a_Mem)
Reads two bytes from the specified memory location and interprets them as BigEndian short.
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
static bool isLegalUTF8(const unsigned char *source, int length)
AString & InPlaceLowercase(AString &s)
In-place string conversion to lowercase.
AString TrimString(const AString &str)
Trims whitespace at both ends of the string.
#define UNI_SUR_LOW_START
static const unsigned int offsetsFromUTF8[6]
AString & RawBEToUTF8(const char *a_RawData, size_t a_NumShorts, AString &a_UTF8)
Converts a stream of BE shorts into UTF-8 string; returns a_UTF8.
AString URLEncode(const AString &a_Text)
URL-encodes the given string.
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
int GetBEInt(const std::byte *const a_Mem)
Reads four bytes from the specified memory location and interprets them as BigEndian int.
AString & InPlaceUppercase(AString &s)
In-place string conversion to uppercase.
AString EscapeString(const AString &a_Message)
Returns a copy of a_Message with all quotes and backslashes escaped by a backslash.
AString ReplaceAllCharOccurrences(const AString &a_String, char a_From, char a_To)
Replaces all occurrences of char a_From inside a_String with char a_To.
#define UNI_SUR_HIGH_START
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
bool SplitZeroTerminatedStrings(const AString &a_Strings, AStringVector &a_Output)
Splits a string that has embedded \0 characters, on those characters.
AString Base64Decode(const AString &a_Base64String)
Decodes a Base64-encoded string into the raw data.
void SetBEInt(std::byte *a_Mem, Int32 a_Value)
Writes four bytes to the specified memory location so that they interpret as BigEndian int.
void ReplaceString(AString &iHayStack, const AString &iNeedle, const AString &iReplaceWith)
Replaces each occurence of iNeedle in iHayStack with iReplaceWith.
static int UnBase64(char c)
Converts one Hex character in a Base64 encoding into the data value.
AString StripColorCodes(const AString &a_Message)
Removes all control codes used by MC for colors and styles.
AString & CreateHexDump(AString &a_Out, const void *a_Data, size_t a_Size, size_t a_BytesPerLine)
format binary data this way: 00001234: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 1234567890abcd...
AStringVector StringSplitWithQuotes(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
AString StringsConcat(const AStringVector &a_Strings, char a_Separator)
Concatenates the specified strings into a single string, separated by the specified separator charact...
int NoCaseCompare(const AString &s1, const AString &s2)
Case-insensitive string comparison.
void ReplaceURL(AString &iHayStack, const AString &iNeedle, const AString &iReplaceWith)
Replaces each occurence of iNeedle in iHayStack with iReplaceWith, after URL-encoding iReplaceWith.
static unsigned char HexToDec(char a_HexChar)
Returns the value of the single hex digit.
AStringVector MergeStringVectors(const AStringVector &a_Strings1, const AStringVector &a_Strings2)
Merges the two vectors of strings, removing duplicate entries from the second vector.
AString StrToUpper(const AString &s)
Returns an upper-cased copy of the string.
AString UnicodeCharToUtf8(unsigned a_UnicodeChar)
Converts a unicode character to its UTF8 representation.
AString StringJoin(const AStringVector &a_Strings, const AString &a_Delimeter)
Join a list of strings with the given delimiter between entries.
size_t RateCompareString(const AString &s1, const AString &s2)
Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1....
bool StringToFloat(const AString &a_String, float &a_Num)
Converts a string into a float.
bool IsOnlyWhitespace(const AString &a_String)
Returns true if only whitespace characters are present in the string.
AString Base64Encode(const AString &a_Input)
Encodes a string into Base64.
std::u16string UTF8ToRawBEUTF16(const AString &a_UTF8)
Converts a UTF-8 string into a UTF-16 BE string.
static const Byte trailingBytesForUTF8[256]
unsigned short GetBEUShort(const char *a_Mem)
Reads two bytes from the specified memory location and interprets them as BigEndian unsigned short.
std::vector< AString > AStringVector