2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
// StringUtils.h
|
|
|
|
|
|
|
|
// Interfaces to various string helper functions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-17 10:33:09 -04:00
|
|
|
#pragma once
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2014-05-03 09:02:51 -04:00
|
|
|
#include <string>
|
2014-08-13 08:15:29 -04:00
|
|
|
#include <limits>
|
2014-05-03 09:02:51 -04:00
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
typedef std::string AString;
|
|
|
|
typedef std::vector<AString> AStringVector;
|
|
|
|
typedef std::list<AString> AStringList;
|
|
|
|
|
2015-11-11 04:32:42 -05:00
|
|
|
/** A string dictionary, used for key-value pairs. */
|
|
|
|
typedef std::map<AString, AString> AStringMap;
|
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-21 14:39:34 -05: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 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05: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 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Output the formatted text into string
|
|
|
|
Returns the formatted string by value. */
|
2014-03-14 09:11:49 -04:00
|
|
|
extern AString Printf(const char * format, ...) FORMATSTRING(1, 2);
|
2012-11-15 05:58:46 -05:00
|
|
|
|
2015-01-21 14:39:34 -05: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 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Split the string at any of the listed delimiters.
|
|
|
|
Return the splitted strings as a stringvector. */
|
2012-06-14 09:06:06 -04:00
|
|
|
extern AStringVector StringSplit(const AString & str, const AString & delim);
|
|
|
|
|
2015-03-10 23:14:17 -04: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);
|
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Split the string at any of the listed delimiters and trim each value.
|
|
|
|
Returns the splitted strings as a stringvector. */
|
2013-03-14 05:52:57 -04:00
|
|
|
extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim);
|
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Trims whitespace at both ends of the string.
|
|
|
|
Returns a trimmed copy of the original string. */
|
2013-07-07 10:42:07 -04:00
|
|
|
extern AString TrimString(const AString & str); // tolua_export
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** In-place string conversion to uppercase.
|
|
|
|
Returns the same string object. */
|
2014-08-04 05:16:19 -04:00
|
|
|
extern AString & InPlaceUppercase(AString & s);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** In-place string conversion to lowercase.
|
|
|
|
Returns the same string object. */
|
2014-08-04 05:16:19 -04:00
|
|
|
extern AString & InPlaceLowercase(AString & s);
|
|
|
|
|
|
|
|
/** Returns an upper-cased copy of the string */
|
|
|
|
extern AString StrToUpper(const AString & s);
|
2013-09-30 13:59:40 -04:00
|
|
|
|
2014-08-03 16:19:43 -04:00
|
|
|
/** Returns a lower-cased copy of the string */
|
|
|
|
extern AString StrToLower(const AString & s);
|
|
|
|
|
2015-01-21 14:39:34 -05: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 10:42:07 -04:00
|
|
|
extern int NoCaseCompare(const AString & s1, const AString & s2); // tolua_export
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1.length()]. */
|
2014-05-08 14:16:35 -04:00
|
|
|
extern size_t RateCompareString(const AString & s1, const AString & s2);
|
2012-08-22 19:05:12 -04:00
|
|
|
|
2015-05-09 05:16:56 -04:00
|
|
|
/** Replaces each occurence of iNeedle in iHayStack with iReplaceWith */
|
2013-07-07 10:42:07 -04:00
|
|
|
extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith); // tolua_export
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Converts a stream of BE shorts into UTF-8 string; returns a_UTF8. */
|
2014-05-08 14:16:35 -04:00
|
|
|
extern AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);
|
2012-08-17 06:18:07 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Converts a UTF-8 string into a UTF-16 BE string. */
|
2015-09-29 11:08:40 -04:00
|
|
|
extern std::u16string UTF8ToRawBEUTF16(const AString & a_String);
|
2012-08-28 17:59:49 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Creates a nicely formatted HEX dump of the given memory block.
|
|
|
|
Max a_BytesPerLine is 120. */
|
2014-04-04 04:42:17 -04:00
|
|
|
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Returns a copy of a_Message with all quotes and backslashes escaped by a backslash. */
|
2013-07-07 10:42:07 -04:00
|
|
|
extern AString EscapeString(const AString & a_Message); // tolua_export
|
|
|
|
|
2015-01-21 14:39:34 -05:00
|
|
|
/** Removes all control codes used by MC for colors and styles. */
|
2013-07-07 10:42:07 -04:00
|
|
|
extern AString StripColorCodes(const AString & a_Message); // tolua_export
|
2013-07-07 10:13:43 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** URL-Decodes the given string, replacing all "%HH" into the correct characters. Invalid % sequences are left intact */
|
2013-09-28 13:28:19 -04:00
|
|
|
extern AString URLDecode(const AString & a_String); // Cannot export to Lua automatically - would generated an extra return value
|
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Replaces all occurrences of char a_From inside a_String with char a_To. */
|
2013-09-28 13:28:19 -04: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 10:49:10 -04:00
|
|
|
/** Decodes a Base64-encoded string into the raw data */
|
2014-04-01 16:47:39 -04:00
|
|
|
extern AString Base64Decode(const AString & a_Base64String); // Exported manually due to embedded NULs and extra parameter
|
2013-10-04 14:28:30 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Encodes a string into Base64 */
|
2014-04-01 16:47:39 -04:00
|
|
|
extern AString Base64Encode(const AString & a_Input); // Exported manually due to embedded NULs and extra parameter
|
2014-01-07 06:36:36 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Reads two bytes from the specified memory location and interprets them as BigEndian short */
|
2014-01-02 11:33:18 -05:00
|
|
|
extern short GetBEShort(const char * a_Mem);
|
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Reads four bytes from the specified memory location and interprets them as BigEndian int */
|
2014-01-02 11:33:18 -05:00
|
|
|
extern int GetBEInt(const char * a_Mem);
|
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Writes four bytes to the specified memory location so that they interpret as BigEndian int */
|
2014-01-02 11:33:18 -05:00
|
|
|
extern void SetBEInt(char * a_Mem, Int32 a_Value);
|
|
|
|
|
2014-09-17 03:38:06 -04: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 03:39:14 -05: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 04:32:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-24 03:39:14 -05:00
|
|
|
/** Parses any integer type. Checks bounds and returns errors out of band. */
|
2014-08-28 09:44:36 -04:00
|
|
|
template <class T>
|
2014-08-29 04:20:23 -04:00
|
|
|
bool StringToInteger(const AString & a_str, T & a_Num)
|
2014-08-13 08:03:56 -04:00
|
|
|
{
|
|
|
|
size_t i = 0;
|
2014-08-13 08:37:07 -04:00
|
|
|
bool positive = true;
|
2014-08-13 08:03:56 -04:00
|
|
|
T result = 0;
|
|
|
|
if (a_str[0] == '+')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
else if (a_str[0] == '-')
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
positive = false;
|
|
|
|
}
|
|
|
|
if (positive)
|
|
|
|
{
|
2014-08-28 09:58:48 -04:00
|
|
|
for (size_t size = a_str.size(); i < size; i++)
|
2014-08-13 08:03:56 -04:00
|
|
|
{
|
2014-08-28 18:42:33 -04:00
|
|
|
if ((a_str[i] < '0') || (a_str[i] > '9'))
|
2014-08-13 08:03:56 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (std::numeric_limits<T>::max() / 10 < result)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result *= 10;
|
2015-05-19 06:50:59 -04:00
|
|
|
T digit = static_cast<T>(a_str[i] - '0');
|
2014-08-13 08:03:56 -04:00
|
|
|
if (std::numeric_limits<T>::max() - digit < result)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result += digit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Fix FreeBSD/clang errors caused by -Werror
With FreeBSD/clang, -Werror combined with the configured warning flags yields
some fatal errors, specifically related to signed conversion, 64 to 32 bit
conversion, and tautological compares.
CONTRIBUTORS
Add myself to the contributor list
src/Generating/FinishGen.cpp
In cFinishGenPassiveMobs::GetRandomMob(), change the type of RandMob
from size_t to the difference_type of the ListOfSpawnables iterator
MobIter. Using size_t triggers a 64 bit to 32 bit conversion if the
difference_type of the iterator class is 64 bit
Also explicitly cast the noise expression to unsigned long so we don't
get a signed conversion warning from the modulo against
ListOfSpawnables.size()
src/OSSupport/StackTrace.cpp
FreeBSD 10 and above includes a non glibc implementation of benchmark()
for which size_t, not int, is the return type. To account for this and
prevent a signed conversion warning, abstract the type for numItems with
a macro btsize
src/StringUtils.h
In StringToInteger(), correct a tautological compare warning for
unsigned types with the template. If T is unsigned, comparing
std::numeric_limits<T>::min() to the unsigned result is always
false. That control can enter this branch in an evaluated template with
an unsigned type T may also permit a signed number to be parsed and
erroneously stripped of its signedness at runtime. To guard against this
and avoid the warning in the case that the number parsed from the string
is non-positive, return false and don't try to parse if T is unsigned
and control enters the non-positive branch
2015-05-30 04:23:57 -04:00
|
|
|
// Unsigned result cannot be signed!
|
|
|
|
if (!std::numeric_limits<T>::is_signed)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-08-28 09:58:48 -04:00
|
|
|
for (size_t size = a_str.size(); i < size; i++)
|
2014-08-13 08:03:56 -04:00
|
|
|
{
|
2014-08-28 18:42:33 -04:00
|
|
|
if ((a_str[i] < '0') || (a_str[i] > '9'))
|
2014-08-13 08:03:56 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (std::numeric_limits<T>::min() / 10 > result)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result *= 10;
|
2015-05-19 06:50:59 -04:00
|
|
|
T digit = static_cast<T>(a_str[i] - '0');
|
2014-08-13 08:03:56 -04:00
|
|
|
if (std::numeric_limits<T>::min() + digit > result)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result -= digit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a_Num = result;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-11 04:32:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Returns an integer from a key-value string map.
|
|
|
|
Returns a_Default if the key is not present or the value is not an int. */
|
|
|
|
template <typename T>
|
|
|
|
int GetStringMapInteger(const AStringMap & a_Map, const AString & a_Key, T a_Default)
|
|
|
|
{
|
|
|
|
// 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 09:06:06 -04:00
|
|
|
// If you have any other string helper functions, declare them here
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|