2012-06-14 13:06:06 +00:00
|
|
|
|
|
|
|
|
// StringUtils.h
|
|
|
|
|
|
|
|
|
|
// Interfaces to various string helper functions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-17 16:33:09 +02:00
|
|
|
#pragma once
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2014-05-03 06:02:51 -07:00
|
|
|
|
2012-06-14 13:06:06 +00:00
|
|
|
|
|
|
|
|
typedef std::string AString;
|
|
|
|
|
typedef std::vector<AString> AStringVector;
|
|
|
|
|
typedef std::list<AString> AStringList;
|
|
|
|
|
|
2015-11-11 10:32:42 +01:00
|
|
|
/** A string dictionary, used for key-value pairs. */
|
|
|
|
|
typedef std::map<AString, AString> AStringMap;
|
|
|
|
|
|
|
|
|
|
|
2012-06-14 13:06:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Add the formated string to the existing data in the string.
|
|
|
|
|
Returns a_Dst. */
|
|
|
|
|
extern AString & AppendVPrintf(AString & a_Dst, const char * format, va_list args) FORMATSTRING(2, 0);
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Output the formatted text into the string.
|
|
|
|
|
Returns a_Dst. */
|
|
|
|
|
extern AString & Printf (AString & a_Dst, const char * format, ...) FORMATSTRING(2, 3);
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Output the formatted text into string
|
|
|
|
|
Returns the formatted string by value. */
|
2014-03-14 06:11:49 -07:00
|
|
|
extern AString Printf(const char * format, ...) FORMATSTRING(1, 2);
|
2012-11-15 10:58:46 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Add the formatted string to the existing data in the string.
|
|
|
|
|
Returns a_Dst */
|
|
|
|
|
extern AString & AppendPrintf (AString & a_Dst, const char * format, ...) FORMATSTRING(2, 3);
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Split the string at any of the listed delimiters.
|
|
|
|
|
Return the splitted strings as a stringvector. */
|
2012-06-14 13:06:06 +00:00
|
|
|
extern AStringVector StringSplit(const AString & str, const AString & delim);
|
|
|
|
|
|
2015-03-11 04:14:17 +01:00
|
|
|
/** Split the string at any of the listed delimiters. Keeps quoted content together
|
|
|
|
|
Resolves issue #490
|
|
|
|
|
Return the splitted strings as a stringvector. */
|
|
|
|
|
extern AStringVector StringSplitWithQuotes(const AString & str, const AString & delim);
|
|
|
|
|
|
2017-08-18 11:29:54 +01:00
|
|
|
/** Join a list of strings with the given delimiter between entries. */
|
|
|
|
|
AString StringJoin(const AStringVector & a_Strings, const AString & a_Delimiter);
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Split the string at any of the listed delimiters and trim each value.
|
|
|
|
|
Returns the splitted strings as a stringvector. */
|
2013-03-14 09:52:57 +00:00
|
|
|
extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim);
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Trims whitespace at both ends of the string.
|
|
|
|
|
Returns a trimmed copy of the original string. */
|
2013-07-07 14:42:07 +00:00
|
|
|
extern AString TrimString(const AString & str); // tolua_export
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** In-place string conversion to uppercase.
|
|
|
|
|
Returns the same string object. */
|
2014-08-04 11:16:19 +02:00
|
|
|
extern AString & InPlaceUppercase(AString & s);
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** In-place string conversion to lowercase.
|
|
|
|
|
Returns the same string object. */
|
2014-08-04 11:16:19 +02:00
|
|
|
extern AString & InPlaceLowercase(AString & s);
|
|
|
|
|
|
|
|
|
|
/** Returns an upper-cased copy of the string */
|
|
|
|
|
extern AString StrToUpper(const AString & s);
|
2013-09-30 19:59:40 +02:00
|
|
|
|
2014-08-03 22:19:43 +02:00
|
|
|
/** Returns a lower-cased copy of the string */
|
|
|
|
|
extern AString StrToLower(const AString & s);
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Case-insensitive string comparison.
|
|
|
|
|
Returns 0 if the strings are the same, <0 if s1 < s2 and >0 if s1 > s2. */
|
2013-07-07 14:42:07 +00:00
|
|
|
extern int NoCaseCompare(const AString & s1, const AString & s2); // tolua_export
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1.length()]. */
|
2014-05-08 20:16:35 +02:00
|
|
|
extern size_t RateCompareString(const AString & s1, const AString & s2);
|
2012-08-22 23:05:12 +00:00
|
|
|
|
2015-05-09 11:16:56 +02:00
|
|
|
/** Replaces each occurence of iNeedle in iHayStack with iReplaceWith */
|
2013-07-07 14:42:07 +00:00
|
|
|
extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith); // tolua_export
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Converts a stream of BE shorts into UTF-8 string; returns a_UTF8. */
|
2014-05-08 20:16:35 +02:00
|
|
|
extern AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);
|
2012-08-17 10:18:07 +00:00
|
|
|
|
2016-12-25 18:29:21 +01:00
|
|
|
/** Converts a unicode character to its UTF8 representation. */
|
|
|
|
|
extern AString UnicodeCharToUtf8(unsigned a_UnicodeChar);
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Converts a UTF-8 string into a UTF-16 BE string. */
|
2015-09-29 16:08:40 +01:00
|
|
|
extern std::u16string UTF8ToRawBEUTF16(const AString & a_String);
|
2012-08-28 21:59:49 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Creates a nicely formatted HEX dump of the given memory block.
|
|
|
|
|
Max a_BytesPerLine is 120. */
|
2014-04-04 10:42:17 +02:00
|
|
|
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine);
|
2012-06-14 13:06:06 +00:00
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Returns a copy of a_Message with all quotes and backslashes escaped by a backslash. */
|
2013-07-07 14:42:07 +00:00
|
|
|
extern AString EscapeString(const AString & a_Message); // tolua_export
|
|
|
|
|
|
2015-01-21 20:39:34 +01:00
|
|
|
/** Removes all control codes used by MC for colors and styles. */
|
2013-07-07 14:42:07 +00:00
|
|
|
extern AString StripColorCodes(const AString & a_Message); // tolua_export
|
2013-07-07 14:13:43 +00:00
|
|
|
|
2016-12-25 18:29:21 +01:00
|
|
|
/** URL-Decodes the given string.
|
|
|
|
|
The first value specifies whether the decoding was successful.
|
|
|
|
|
The second value is the decoded string, if successful. */
|
|
|
|
|
extern std::pair<bool, AString> URLDecode(const AString & a_String); // Exported to Lua as cUrlParser::UrlDecode()
|
|
|
|
|
|
|
|
|
|
/** URL-encodes the given string. */
|
|
|
|
|
extern AString URLEncode(const AString & a_Text);
|
2013-09-28 19:28:19 +02:00
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Replaces all occurrences of char a_From inside a_String with char a_To. */
|
2013-09-28 19:28:19 +02:00
|
|
|
extern AString ReplaceAllCharOccurrences(const AString & a_String, char a_From, char a_To); // Needn't export to Lua, since Lua doesn't have chars anyway
|
|
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Decodes a Base64-encoded string into the raw data */
|
2014-04-01 22:47:39 +02:00
|
|
|
extern AString Base64Decode(const AString & a_Base64String); // Exported manually due to embedded NULs and extra parameter
|
2013-10-04 20:28:30 +02:00
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Encodes a string into Base64 */
|
2014-04-01 22:47:39 +02:00
|
|
|
extern AString Base64Encode(const AString & a_Input); // Exported manually due to embedded NULs and extra parameter
|
2014-01-07 12:36:36 +01:00
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Reads two bytes from the specified memory location and interprets them as BigEndian short */
|
2014-01-02 17:33:18 +01:00
|
|
|
extern short GetBEShort(const char * a_Mem);
|
2016-12-25 18:29:21 +01:00
|
|
|
|
|
|
|
|
/** Reads two bytes from the specified memory location and interprets them as BigEndian unsigned short */
|
|
|
|
|
extern unsigned short GetBEUShort(const char * a_Mem);
|
2014-01-02 17:33:18 +01:00
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Reads four bytes from the specified memory location and interprets them as BigEndian int */
|
2014-01-02 17:33:18 +01:00
|
|
|
extern int GetBEInt(const char * a_Mem);
|
|
|
|
|
|
2015-07-31 16:49:10 +02:00
|
|
|
/** Writes four bytes to the specified memory location so that they interpret as BigEndian int */
|
2014-01-02 17:33:18 +01:00
|
|
|
extern void SetBEInt(char * a_Mem, Int32 a_Value);
|
|
|
|
|
|
2014-09-17 09:38:06 +02:00
|
|
|
/** Splits a string that has embedded \0 characters, on those characters.
|
|
|
|
|
a_Output is first cleared and then each separate string is pushed back into a_Output.
|
|
|
|
|
Returns true if there are at least two strings in a_Output (there was at least one \0 separator). */
|
|
|
|
|
extern bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output);
|
|
|
|
|
|
2015-01-24 09:39:14 +01:00
|
|
|
/** Merges the two vectors of strings, removing duplicate entries from the second vector.
|
|
|
|
|
The resulting vector contains items from a_Strings1 first, then from a_Strings2.
|
|
|
|
|
The order of items doesn't change, only the duplicates are removed.
|
|
|
|
|
If a_Strings1 contains duplicates, the result will still contain those duplicates. */
|
|
|
|
|
extern AStringVector MergeStringVectors(const AStringVector & a_Strings1, const AStringVector & a_Strings2);
|
|
|
|
|
|
|
|
|
|
/** Concatenates the specified strings into a single string, separated by the specified separator. */
|
|
|
|
|
extern AString StringsConcat(const AStringVector & a_Strings, char a_Separator);
|
|
|
|
|
|
2015-11-11 10:32:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-24 09:39:14 +01:00
|
|
|
/** Parses any integer type. Checks bounds and returns errors out of band. */
|
2014-08-28 16:44:36 +03:00
|
|
|
template <class T>
|
2014-08-29 11:20:23 +03:00
|
|
|
bool StringToInteger(const AString & a_str, T & a_Num)
|
2014-08-13 13:03:56 +01:00
|
|
|
{
|
|
|
|
|
size_t i = 0;
|
2014-08-13 13:37:07 +01:00
|
|
|
bool positive = true;
|
2014-08-13 13:03:56 +01:00
|
|
|
T result = 0;
|
|
|
|
|
if (a_str[0] == '+')
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
else if (a_str[0] == '-')
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
positive = false;
|
|
|
|
|
}
|
|
|
|
|
if (positive)
|
|
|
|
|
{
|
2014-08-28 16:58:48 +03:00
|
|
|
for (size_t size = a_str.size(); i < size; i++)
|
2014-08-13 13:03:56 +01:00
|
|
|
{
|
2014-08-29 00:42:33 +02:00
|
|
|
if ((a_str[i] < '0') || (a_str[i] > '9'))
|
2014-08-13 13:03:56 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (std::numeric_limits<T>::max() / 10 < result)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
result *= 10;
|
2015-05-19 11:50:59 +01:00
|
|
|
T digit = static_cast<T>(a_str[i] - '0');
|
2014-08-13 13:03:56 +01:00
|
|
|
if (std::numeric_limits<T>::max() - digit < result)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
result += digit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-05-30 02:23:57 -06:00
|
|
|
// Unsigned result cannot be signed!
|
|
|
|
|
if (!std::numeric_limits<T>::is_signed)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-28 16:58:48 +03:00
|
|
|
for (size_t size = a_str.size(); i < size; i++)
|
2014-08-13 13:03:56 +01:00
|
|
|
{
|
2014-08-29 00:42:33 +02:00
|
|
|
if ((a_str[i] < '0') || (a_str[i] > '9'))
|
2014-08-13 13:03:56 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (std::numeric_limits<T>::min() / 10 > result)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
result *= 10;
|
2015-05-19 11:50:59 +01:00
|
|
|
T digit = static_cast<T>(a_str[i] - '0');
|
2014-08-13 13:03:56 +01:00
|
|
|
if (std::numeric_limits<T>::min() + digit > result)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
result -= digit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a_Num = result;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-11 10:32:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-13 16:50:35 +01:00
|
|
|
/** Returns a number (of any integer type T) from a key-value string map.
|
|
|
|
|
Returns a_Default if the key is not present or the value is not a number representable in type T. */
|
2015-11-11 10:32:42 +01:00
|
|
|
template <typename T>
|
2017-02-13 16:50:35 +01:00
|
|
|
T GetStringMapInteger(const AStringMap & a_Map, const AString & a_Key, T a_Default)
|
2015-11-11 10:32:42 +01:00
|
|
|
{
|
|
|
|
|
// Try to locate the key:
|
|
|
|
|
auto itr = a_Map.find(a_Key);
|
|
|
|
|
if (itr == a_Map.end())
|
|
|
|
|
{
|
|
|
|
|
return a_Default;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try to convert the value to a number:
|
|
|
|
|
T res = a_Default;
|
|
|
|
|
if (!StringToInteger<T>(itr->second, res))
|
|
|
|
|
{
|
|
|
|
|
return a_Default;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-14 13:06:06 +00:00
|
|
|
// If you have any other string helper functions, declare them here
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|