summaryrefslogtreecommitdiffstats
path: root/src/StringUtils.h
blob: efb6a8566cf0ed15ef97da9f52608bc118335b65 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

// StringUtils.h

// Interfaces to various string helper functions




#pragma once

typedef std::string AString;
typedef std::vector<AString> AStringVector;
typedef std::list<AString>   AStringList;

/** A string dictionary, used for key-value pairs. */
typedef std::map<AString, AString> AStringMap;





/** Split the string at any of the listed delimiters.
Return the splitted strings as a stringvector. */
extern AStringVector StringSplit(const AString & str, const AString & delim);

/** 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);

/** Join a list of strings with the given delimiter between entries. */
AString StringJoin(const AStringVector & a_Strings, const AString & a_Delimiter);

/** Split the string at any of the listed delimiters and trim each value.
Returns the splitted strings as a stringvector. */
extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim);

/** Trims whitespace at both ends of the string.
Returns a trimmed copy of the original string. */
extern AString TrimString(const AString & str);  // tolua_export

/** In-place string conversion to uppercase.
Returns the same string object. */
extern AString & InPlaceUppercase(AString & s);

/** In-place string conversion to lowercase.
Returns the same string object. */
extern AString & InPlaceLowercase(AString & s);

/** Returns an upper-cased copy of the string */
extern AString StrToUpper(const AString & s);

/** Returns a lower-cased copy of the string */
extern AString StrToLower(const AString & s);

/** Case-insensitive string comparison.
Returns 0 if the strings are the same, <0 if s1 < s2 and >0 if s1 > s2. */
extern int NoCaseCompare(const AString & s1, const AString & s2);  // tolua_export

/** Case-insensitive string comparison that returns a rating of equal-ness between [0 - s1.length()]. */
extern size_t RateCompareString(const AString & s1, const AString & s2);

/** Replaces each occurence of iNeedle in iHayStack with iReplaceWith */
extern void ReplaceString(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith);  // tolua_export

/** Replaces each occurence of iNeedle in iHayStack with iReplaceWith, after URL-encoding iReplaceWith */
extern void ReplaceURL(AString & iHayStack, const AString & iNeedle, const AString & iReplaceWith);

/** Converts a stream of BE shorts into UTF-8 string; returns a_UTF8. */
extern AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UTF8);

/** Converts a unicode character to its UTF8 representation. */
extern AString UnicodeCharToUtf8(unsigned a_UnicodeChar);

/** Converts a UTF-8 string into a UTF-16 BE string. */
extern std::u16string UTF8ToRawBEUTF16(const AString & a_String);

/** Creates a nicely formatted HEX dump of the given memory block. */
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, size_t a_Size, size_t a_BytesPerLine);

/** Returns a copy of a_Message with all quotes and backslashes escaped by a backslash. */
extern AString EscapeString(const AString & a_Message);  // tolua_export

/** Removes all control codes used by MC for colors and styles. */
extern AString StripColorCodes(const AString & a_Message);  // tolua_export

/** 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);

/** Replaces all occurrences of char a_From inside a_String with char a_To. */
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

/** Decodes a Base64-encoded string into the raw data */
extern AString Base64Decode(const AString & a_Base64String);  // Exported manually due to embedded NULs and extra parameter

/** Encodes a string into Base64 */
extern AString Base64Encode(const AString & a_Input);  // Exported manually due to embedded NULs and extra parameter

/** Reads two bytes from the specified memory location and interprets them as BigEndian short */
extern short GetBEShort(const std::byte * a_Mem);

/** Reads two bytes from the specified memory location and interprets them as BigEndian unsigned short */
extern unsigned short GetBEUShort(const char * a_Mem);

/** Reads four bytes from the specified memory location and interprets them as BigEndian int */
extern int GetBEInt(const std::byte * a_Mem);

/** Writes four bytes to the specified memory location so that they interpret as BigEndian int */
extern void SetBEInt(std::byte * a_Mem, Int32 a_Value);

/** 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);

/** 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 character.
Use StringJoin() if you need multiple separator characters. */
extern AString StringsConcat(const AStringVector & a_Strings, char a_Separator);

/** Converts a string into a float. Returns false if the conversion fails. */
extern bool StringToFloat(const AString & a_String, float & a_Num);

/** Returns true if only whitespace characters are present in the string */
bool IsOnlyWhitespace(const AString & a_String);





/** Parses any integer type. Checks bounds and returns errors out of band. */
template <class T>
bool StringToInteger(const AString & a_str, T & a_Num)
{
	size_t i = 0;
	bool positive = true;
	T result = 0;
	if (a_str[0] == '+')
	{
		i++;
	}
	else if (a_str[0] == '-')
	{
		i++;
		positive = false;
	}
	if (positive)
	{
		for (size_t size = a_str.size(); i < size; i++)
		{
			if ((a_str[i] < '0') || (a_str[i] > '9'))
			{
				return false;
			}
			if (std::numeric_limits<T>::max() / 10 < result)
			{
				return false;
			}
			result *= 10;
			T digit = static_cast<T>(a_str[i] - '0');
			if (std::numeric_limits<T>::max() - digit < result)
			{
				return false;
			}
			result += digit;
		}
	}
	else
	{
		// Unsigned result cannot be signed!
		if (!std::numeric_limits<T>::is_signed)
		{
			return false;
		}

		for (size_t size = a_str.size(); i < size; i++)
		{
			if ((a_str[i] < '0') || (a_str[i] > '9'))
			{
				return false;
			}
			if (std::numeric_limits<T>::min() / 10 > result)
			{
				return false;
			}
			result *= 10;
			T digit = static_cast<T>(a_str[i] - '0');
			if (std::numeric_limits<T>::min() + digit > result)
			{
				return false;
			}
			result -= digit;
		}
	}
	a_Num = result;
	return true;
}





/** 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. */
template <typename T>
T 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;
}





// If you have any other string helper functions, declare them here