29 */ |
29 */ |
30 |
30 |
31 #include <cstring> |
31 #include <cstring> |
32 #include "main.h" |
32 #include "main.h" |
33 #include "mystring.h" |
33 #include "mystring.h" |
34 #include "md5.h" |
|
35 |
34 |
36 BEGIN_ZFC_NAMESPACE |
35 BEGIN_ZFC_NAMESPACE |
37 |
36 |
38 /*! |
37 /*! |
39 * \brief Compares this string with another. |
|
40 * \param other The string to compare with. |
|
41 * \returns -1 if this string is lexicographically less than \c other, |
|
42 * 0 if they are equal, or |
|
43 * 1 if this string is lexicographically greater than \c other. |
|
44 */ |
|
45 int String::compare (const String& other) const |
|
46 { |
|
47 return m_string.compare (other.stdString()); |
|
48 } |
|
49 |
|
50 /*! |
|
51 * \returns an upper-case version of this string. |
|
52 */ |
|
53 String String::toUpperCase() const |
|
54 { |
|
55 String result (m_string); |
|
56 |
|
57 for (char &ch : result) |
|
58 { |
|
59 if (islower(ch)) |
|
60 ch -= 'a' - 'A'; |
|
61 } |
|
62 |
|
63 return result; |
|
64 } |
|
65 |
|
66 /*! |
|
67 * \returns a lower-case version of this string. |
38 * \returns a lower-case version of this string. |
68 */ |
39 */ |
69 String String::toLowerCase() const |
40 std::string to_lowercase(const std::string& string) |
70 { |
41 { |
71 String result (m_string); |
42 String result = string; |
72 |
43 |
73 for (char &ch : result) |
44 for (char& ch : result) |
74 { |
45 { |
75 if (isupper(ch)) |
46 if (isupper(ch)) |
76 ch += 'a' - 'A'; |
47 ch += 'a' - 'A'; |
77 } |
48 } |
78 |
49 |
79 return result; |
50 return result; |
|
51 } |
|
52 |
|
53 /*! |
|
54 * \brief Joins the elements of this string list into one longer string. |
|
55 * \param delimeter The delimeter to place between the element strings. |
|
56 * \returns the catenated string. |
|
57 */ |
|
58 std::string join_string_list(const StringList& strings, const std::string& delimeter) |
|
59 { |
|
60 std::string result; |
|
61 |
|
62 for (const std::string &item : strings) |
|
63 { |
|
64 if (not result.empty()) |
|
65 result += delimeter; |
|
66 |
|
67 result += item; |
|
68 } |
|
69 |
|
70 return result; |
|
71 } |
|
72 |
|
73 /*! |
|
74 * \brief Modifies the given index so that if it is negative, it is translated into a positive index starting from the |
|
75 * end of the string. For example, an index of -1 will be modified to point to the last character in the string, |
|
76 * -2 to the second last, etc. |
|
77 * \param index Index to translate. |
|
78 */ |
|
79 inline void modifyIndex(const std::string& str, int& index) |
|
80 { |
|
81 if (index < 0) |
|
82 index = str.length() - index; |
|
83 } |
|
84 |
|
85 /*! |
|
86 * \param a Starting index of the range. |
|
87 * \param b Ending index of the range. |
|
88 * \returns a sub-string containing all characters from \c a to \c b, not including the character at \c b. |
|
89 */ |
|
90 std::string mid(const std::string& str, int rangeBegin, int rangeEnd) |
|
91 { |
|
92 modifyIndex(str, rangeBegin); |
|
93 modifyIndex(str, rangeEnd); |
|
94 rangeBegin = max(rangeBegin, 0); |
|
95 rangeEnd = min(rangeEnd, static_cast<signed>(str.length())); |
|
96 |
|
97 if (rangeEnd <= rangeBegin) |
|
98 return ""; |
|
99 else |
|
100 return str.substr(rangeBegin, rangeEnd - rangeBegin); |
|
101 } |
|
102 |
|
103 /*! |
|
104 * \param length Amount of characters to return. |
|
105 * \returns the \c length right-most characters of the string. |
|
106 */ |
|
107 std::string right(const std::string& str, int length) |
|
108 { |
|
109 if (length >= static_cast<signed>(str.length())) |
|
110 return str; |
|
111 else |
|
112 return std::string{str.data() + str.length() - length}; |
|
113 } |
|
114 |
|
115 /*! |
|
116 * \brief Formats this string using \c vsnprintf, using the provided arguments. |
|
117 * \param formatString Template string to use with formatting. |
|
118 * \param args Variadic arguments to use with formatting. |
|
119 */ |
|
120 std::string vsprintf(const char* formatString, va_list args) |
|
121 { |
|
122 std::string result; |
|
123 |
|
124 // Copy the argument list so that we have something to provide to vsnprintf in case we have to call it again. |
|
125 va_list argsCopy; |
|
126 va_copy(argsCopy, args); |
|
127 |
|
128 // First, attempt to format using a fixed-size buffer. |
|
129 static char buffer[1024]; |
|
130 size_t length = vsnprintf(buffer, sizeof buffer, formatString, args); |
|
131 |
|
132 if (length < sizeof buffer) |
|
133 { |
|
134 // vsnprintf succeeded in fitting the formatted string into the buffer, so we're done. |
|
135 result = buffer; |
|
136 } |
|
137 else |
|
138 { |
|
139 // vsnprintf needs more space, so we have to allocate a new buffer and try again. |
|
140 Vector<char> newBuffer(length + 1); |
|
141 vsnprintf(newBuffer.data(), length + 1, formatString, argsCopy); |
|
142 result = newBuffer.data(); |
|
143 } |
|
144 |
|
145 return result; |
|
146 } |
|
147 |
|
148 /*! |
|
149 * \brief Formats this string using \c printf -like syntax. |
|
150 * \param formatString Template string to use with formatting. |
|
151 * \param ... Variadic arguments to use with formatting. |
|
152 */ |
|
153 std::string __cdecl sprintf(const char* formatString, ...) |
|
154 { |
|
155 va_list args; |
|
156 va_start (args, formatString); |
|
157 std::string result = vsprintf(formatString, args); |
|
158 va_end (args); |
|
159 return result; |
|
160 } |
|
161 |
|
162 std::string remove_range(const std::string &string, int start, int end) |
|
163 { |
|
164 std::string result; |
|
165 result.reserve(string.length() - (end - start)); |
|
166 std::copy(string.begin(), string.begin() + start, std::back_inserter(result)); |
|
167 std::copy(string.begin() + end, string.end(), std::back_inserter(result)); |
|
168 return result; |
|
169 } |
|
170 |
|
171 |
|
172 /*! |
|
173 * \param other Sub-string to find from the beginning of this string. |
|
174 * \returns whether or not this string begins with the provided sub-string. |
|
175 */ |
|
176 bool starts_with(const std::string& str, const String& other) |
|
177 { |
|
178 if (str.length() < other.length()) |
|
179 return false; |
|
180 else |
|
181 return std::strncmp(str.data(), other.data(), other.length()) == 0; |
|
182 } |
|
183 |
|
184 /*! |
|
185 * \brief Replaces all instances of \c text with \c replacement. |
|
186 * \param text Text to replace away. |
|
187 * \param replacement Text to replace \c text with. |
|
188 */ |
|
189 void replace_all(std::string& str, const char* text, const char* replacement) |
|
190 { |
|
191 int position; |
|
192 while ((position = str.find(text)) != -1) |
|
193 { |
|
194 str.replace(position, std::strlen(text), replacement); |
|
195 } |
80 } |
196 } |
81 |
197 |
82 /*! |
198 /*! |
83 * \brief Splits this string using the provided delimeter. |
199 * \brief Splits this string using the provided delimeter. |
84 * \param delimeter Delimeter to use for splitting. |
200 * \param delimeter Delimeter to use for splitting. |
85 * \returns a string list containing the split strings. |
201 * \returns a string list containing the split strings. |
86 */ |
202 */ |
87 StringList String::split (char delimeter) const |
203 StringList split(const std::string& string, const String& delimeter) |
88 { |
|
89 String delimeterString; |
|
90 delimeterString += delimeter; |
|
91 return split (delimeterString); |
|
92 } |
|
93 |
|
94 /*! |
|
95 * \brief Splits this string using the provided delimeter. |
|
96 * \param delimeter Delimeter to use for splitting. |
|
97 * \returns a string list containing the split strings. |
|
98 */ |
|
99 StringList String::split (const String& delimeter) const |
|
100 { |
204 { |
101 StringList result; |
205 StringList result; |
102 int a = 0; |
206 int a = 0; |
103 int b; |
207 int b; |
104 |
208 |
105 // Find all separators and store the text left to them. |
209 // Find all separators and store the text left to them. |
106 while ((b = find (delimeter, a)) != -1) |
210 while ((b = string.find(delimeter, a)) != -1) |
107 { |
211 { |
108 String sub = mid (a, b); |
212 String sub = mid(string, a, b); |
109 |
213 |
110 if (sub.length() > 0) |
214 if (sub.length() > 0) |
111 result.push_back(sub); |
215 result.push_back(sub); |
112 |
216 |
113 a = b + delimeter.length(); |
217 a = b + delimeter.length(); |
114 } |
218 } |
115 |
219 |
116 // Add the string at the right of the last separator |
220 // Add the string at the right of the last separator |
117 if (a < (int) length()) |
221 if (a < static_cast<int>(string.length())) |
118 result.push_back(mid(a, length())); |
222 result.push_back(mid(string, a, string.length())); |
119 |
223 |
120 return result; |
224 return result; |
121 } |
|
122 |
|
123 /*! |
|
124 * \brief Replaces all instances of \c text with \c replacement. |
|
125 * \param text Text to replace away. |
|
126 * \param replacement Text to replace \c text with. |
|
127 */ |
|
128 void String::replace (const char* text, const char* replacement) |
|
129 { |
|
130 int position; |
|
131 |
|
132 while ((position = find (text)) != -1) |
|
133 m_string = m_string.replace (position, strlen (text), replacement); |
|
134 } |
|
135 |
|
136 /*! |
|
137 * \param character Character to count. |
|
138 * \returns the amount of \c character found in the string. |
|
139 */ |
|
140 int String::count (char character) const |
|
141 { |
|
142 int result = 0; |
|
143 |
|
144 for (char ch : *this) |
|
145 { |
|
146 if (ch == character) |
|
147 result++; |
|
148 } |
|
149 |
|
150 return result; |
|
151 } |
|
152 |
|
153 /*! |
|
154 * \param a Starting index of the range. |
|
155 * \param b Ending index of the range. |
|
156 * \returns a sub-string containing all characters from \c a to \c b, not including the character at \c b. |
|
157 */ |
|
158 String String::mid (int rangeBegin, int rangeEnd) const |
|
159 { |
|
160 modifyIndex(rangeBegin); |
|
161 modifyIndex(rangeEnd); |
|
162 rangeBegin = max(rangeBegin, 0); |
|
163 rangeEnd = min(rangeEnd, length()); |
|
164 |
|
165 if (rangeEnd <= rangeBegin) |
|
166 return ""; |
|
167 else |
|
168 return m_string.substr(rangeBegin, rangeEnd - rangeBegin); |
|
169 } |
|
170 |
|
171 /*! |
|
172 * \param length Amount of characters to return. |
|
173 * \returns the \c length right-most characters of the string. |
|
174 */ |
|
175 String String::right(int length) const |
|
176 { |
|
177 if (length >= this->length()) |
|
178 return *this; |
|
179 else |
|
180 return String(chars() + this->length() - length); |
|
181 } |
|
182 |
|
183 /*! |
|
184 * \brief Finds the first instance of a sub-string. |
|
185 * \param subString Sub-string to search within this string. |
|
186 * \param startingPosition Position to start looking for the sub-string from. |
|
187 * \returns the position the first instance of sub-string found, or -1 if not found. |
|
188 */ |
|
189 int String::find (const char* subString, int startingPosition) const |
|
190 { |
|
191 int position = m_string.find (subString, startingPosition); |
|
192 |
|
193 if (position == int (std::string::npos)) |
|
194 return -1; |
|
195 else |
|
196 return position; |
|
197 } |
|
198 |
|
199 /*! |
|
200 * \brief Finds the first instance of a character. |
|
201 * \param character Character to search within this string. |
|
202 * \param startingPosition Position to start looking for the character from. |
|
203 * \returns the position of the first instance of the provided character found, or -1 if not found. |
|
204 */ |
|
205 int String::find (char character, int startingPosition) const |
|
206 { |
|
207 int position = m_string.find (character, startingPosition); |
|
208 |
|
209 if (position == int (std::string::npos)) |
|
210 return -1; |
|
211 else |
|
212 return position; |
|
213 } |
|
214 |
|
215 /*! |
|
216 * \brief Finds the last instance of a sub-string. |
|
217 * \param subString Sub-string to search within this string. |
|
218 * \param startingPosition Position to start looking for the sub-string from. |
|
219 * \returns the position the last instance of sub-string found, or -1 if not found. |
|
220 */ |
|
221 int String::findLast (const char* subString, int startingPosition) const |
|
222 { |
|
223 modifyIndex(startingPosition); |
|
224 |
|
225 for (; startingPosition > 0; startingPosition--) |
|
226 { |
|
227 if (strncmp (chars() + startingPosition, subString, strlen (subString)) == 0) |
|
228 return startingPosition; |
|
229 } |
|
230 |
|
231 return -1; |
|
232 } |
225 } |
233 |
226 |
234 /*! |
227 /*! |
235 * \brief Converts this string to an integer. |
228 * \brief Converts this string to an integer. |
236 * \param ok An pointer to a boolean to store whether or not the conversion was successful. |
229 * \param ok An pointer to a boolean to store whether or not the conversion was successful. |
237 * If \c ok is \c NULL, the success state is not stored. |
230 * If \c ok is \c NULL, the success state is not stored. |
238 * \param base The base to interpret this string with. |
231 * \param base The base to interpret this string with. |
239 * \returns the resulting integer. |
232 * \returns the resulting integer. |
240 */ |
233 */ |
241 long String::toInt (bool* ok, int base) const |
234 std::optional<long> to_int(const char* str, int base) |
242 { |
235 { |
243 errno = 0; |
236 errno = 0; |
244 char* endPointer; |
237 char* endPointer; |
245 long result = strtol (chars(), &endPointer, base); |
238 long result = strtol(str, &endPointer, base); |
246 |
239 if (errno == 0 and *endPointer == '\0') |
247 if (ok != nullptr) |
240 { |
248 *ok = (errno == 0 and *endPointer == '\0'); |
241 return result; |
249 |
242 } |
250 return result; |
243 else |
251 } |
244 { |
252 |
245 return {}; |
253 /*! |
246 } |
254 * \brief Converts this string to a floating-point number. |
|
255 * \param ok An pointer to a boolean to store whether or not the conversion was successful. |
|
256 * If \c ok is \c NULL, the success state is not stored. |
|
257 * \returns the resulting floating-point number. |
|
258 */ |
|
259 float String::toFloat (bool* ok) const |
|
260 { |
|
261 return static_cast<float>(toDouble(ok)); |
|
262 } |
|
263 |
|
264 /*! |
|
265 * \brief Converts this string to a double-precision floating-point number. |
|
266 * \param ok An pointer to a boolean to store whether or not the conversion was successful. |
|
267 * If \c ok is \c NULL, the success state is not stored. |
|
268 * \returns the resulting floating-point number. |
|
269 */ |
|
270 double String::toDouble (bool* ok) const |
|
271 { |
|
272 errno = 0; |
|
273 char* endptr; |
|
274 double i = strtod (chars(), &endptr); |
|
275 |
|
276 if (ok != nullptr) |
|
277 *ok = (errno == 0 and *endptr == '\0'); |
|
278 |
|
279 return i; |
|
280 } |
|
281 |
|
282 /*! |
|
283 * \brief Catenates this string with another string. |
|
284 * \param text String to catenate to the end of this string. |
|
285 * \returns the resulting string. |
|
286 */ |
|
287 String String::operator+ (const String& text) const |
|
288 { |
|
289 String newString = *this; |
|
290 newString.append (text); |
|
291 return newString; |
|
292 } |
|
293 |
|
294 /*! |
|
295 * \brief Catenates this string with another string. |
|
296 * \param text String to catenate to the end of this string. |
|
297 * \returns the resulting string. |
|
298 */ |
|
299 String String::operator+ (const char* text) const |
|
300 { |
|
301 String newString = *this; |
|
302 newString.append (text); |
|
303 return newString; |
|
304 } |
|
305 |
|
306 /*! |
|
307 * \returns whether or not this string represents a number. |
|
308 */ |
|
309 bool String::isNumeric() const |
|
310 { |
|
311 char* endPointer; |
|
312 strtol (chars(), &endPointer, 10); |
|
313 return (endPointer != nullptr) and (*endPointer != '\0'); |
|
314 } |
|
315 |
|
316 /*! |
|
317 * \param other Sub-string to find from the end of this string. |
|
318 * \return whether or not this string ends with the provided sub-string. |
|
319 */ |
|
320 bool String::endsWith (const String& other) const |
|
321 { |
|
322 if (length() < other.length()) |
|
323 { |
|
324 return false; |
|
325 } |
|
326 else |
|
327 { |
|
328 const int offset = length() - other.length(); |
|
329 return strncmp (chars() + offset, other.chars(), other.length()) == 0; |
|
330 } |
|
331 } |
|
332 |
|
333 /*! |
|
334 * \param other Sub-string to find from the beginning of this string. |
|
335 * \returns whether or not this string begins with the provided sub-string. |
|
336 */ |
|
337 bool String::startsWith (const String& other) const |
|
338 { |
|
339 if (length() < other.length()) |
|
340 return false; |
|
341 else |
|
342 return strncmp (chars(), other.chars(), other.length()) == 0; |
|
343 } |
|
344 |
|
345 /*! |
|
346 * \brief Formats this string using \c printf -like syntax. |
|
347 * \param formatString Template string to use with formatting. |
|
348 * \param ... Variadic arguments to use with formatting. |
|
349 */ |
|
350 void __cdecl String::sprintf (const char* formatString, ...) |
|
351 { |
|
352 va_list args; |
|
353 va_start (args, formatString); |
|
354 this->vsprintf (formatString, args); |
|
355 va_end (args); |
|
356 } |
|
357 |
|
358 /*! |
|
359 * \brief Formats this string using \c vsnprintf, using the provided arguments. |
|
360 * \param formatString Template string to use with formatting. |
|
361 * \param args Variadic arguments to use with formatting. |
|
362 */ |
|
363 void String::vsprintf (const char* formatString, va_list args) |
|
364 { |
|
365 // Copy the argument list so that we have something to provide to vsnprintf in case we have to call it again. |
|
366 va_list argsCopy; |
|
367 va_copy(argsCopy, args); |
|
368 |
|
369 // First, attempt to format using a fixed-size buffer. |
|
370 static char buffer[1024]; |
|
371 size_t length = vsnprintf(buffer, sizeof buffer, formatString, args); |
|
372 |
|
373 if (length < sizeof buffer) |
|
374 { |
|
375 // vsnprintf succeeded in fitting the formatted string into the buffer, so we're done. |
|
376 m_string = buffer; |
|
377 } |
|
378 else |
|
379 { |
|
380 // vsnprintf needs more space, so we have to allocate a new buffer and try again. |
|
381 Vector<char> newBuffer(length + 1); |
|
382 vsnprintf(newBuffer.data(), length + 1, formatString, argsCopy); |
|
383 m_string = newBuffer.data(); |
|
384 } |
|
385 } |
|
386 |
|
387 /*! |
|
388 * \brief Joins the elements of this string list into one longer string. |
|
389 * \param delimeter The delimeter to place between the element strings. |
|
390 * \returns the catenated string. |
|
391 */ |
|
392 String join_string_list(const StringList& strings, const String& delimeter) |
|
393 { |
|
394 String result; |
|
395 |
|
396 for (const String &item : strings) |
|
397 { |
|
398 if (result.isEmpty() == false) |
|
399 result += delimeter; |
|
400 |
|
401 result += item; |
|
402 } |
|
403 |
|
404 return result; |
|
405 } |
|
406 |
|
407 /*! |
|
408 * \brief Tries to match this string against a mask pattern. In the pattern, '?' refers to one character, and '*' to |
|
409 * any number of characters. |
|
410 * \param pattern The masking pattern to use for matching. |
|
411 * \returns whether or not this string matches the provided pattern. |
|
412 */ |
|
413 bool String::maskAgainst (const String& pattern) const |
|
414 { |
|
415 // Elevate to uppercase for case-insensitive matching |
|
416 String pattern_upper = pattern.toUpperCase(); |
|
417 String this_upper = toUpperCase(); |
|
418 const char* maskstring = pattern_upper.chars(); |
|
419 const char* mptr = &maskstring[0]; |
|
420 |
|
421 for (const char* sptr = this_upper.chars(); *sptr != '\0'; sptr++) |
|
422 { |
|
423 if (*mptr == '?') |
|
424 { |
|
425 if (*(sptr + 1) == '\0') |
|
426 { |
|
427 // ? demands that there's a character here and there wasn't. |
|
428 // Therefore, mask matching fails |
|
429 return false; |
|
430 } |
|
431 } |
|
432 else if (*mptr == '*') |
|
433 { |
|
434 char end = *(++mptr); |
|
435 |
|
436 // If '*' is the final character of the message, all of the remaining |
|
437 // string matches against the '*'. We don't need to bother checking |
|
438 // the string any further. |
|
439 if (end == '\0') |
|
440 return true; |
|
441 |
|
442 // Skip to the end character |
|
443 while (*sptr != end and *sptr != '\0') |
|
444 sptr++; |
|
445 |
|
446 // String ended while the mask still had stuff |
|
447 if (*sptr == '\0') |
|
448 return false; |
|
449 } |
|
450 else if (*sptr != *mptr) |
|
451 return false; |
|
452 |
|
453 mptr++; |
|
454 } |
|
455 |
|
456 return true; |
|
457 } |
|
458 |
|
459 /*! |
|
460 * \brief Converts a short integer into a string. |
|
461 * \param value The value to convert. |
|
462 * \returns the resulting string. |
|
463 */ |
|
464 String String::fromNumber (short int value) |
|
465 { |
|
466 char buffer[32]; |
|
467 ::sprintf (buffer, "%d", value); |
|
468 return String (buffer); |
|
469 } |
|
470 |
|
471 /*! |
|
472 * \brief Converts an integer into a string. |
|
473 * \param value The value to convert. |
|
474 * \returns the resulting string. |
|
475 */ |
|
476 String String::fromNumber (int value) |
|
477 { |
|
478 char buffer[32]; |
|
479 ::sprintf (buffer, "%d", value); |
|
480 return String (buffer); |
|
481 } |
|
482 |
|
483 /*! |
|
484 * \brief Converts a long integer into a string. |
|
485 * \param value The value to convert. |
|
486 * \returns the resulting string. |
|
487 */ |
|
488 String String::fromNumber (long int value) |
|
489 { |
|
490 char buffer[32]; |
|
491 ::sprintf (buffer, "%ld", value); |
|
492 return String (buffer); |
|
493 } |
|
494 |
|
495 /*! |
|
496 * \brief Converts an unsigned short integer into a string. |
|
497 * \param value The value to convert. |
|
498 * \returns the resulting string. |
|
499 */ |
|
500 String String::fromNumber (unsigned short int value) |
|
501 { |
|
502 char buffer[32]; |
|
503 ::sprintf (buffer, "%u", value); |
|
504 return String (buffer); |
|
505 } |
|
506 |
|
507 /*! |
|
508 * \brief Converts an unsigned integer into a string. |
|
509 * \param value The value to convert. |
|
510 * \returns the resulting string. |
|
511 */ |
|
512 String String::fromNumber (unsigned int value) |
|
513 { |
|
514 char buffer[32]; |
|
515 ::sprintf (buffer, "%u", value); |
|
516 return String (buffer); |
|
517 } |
|
518 |
|
519 /*! |
|
520 * \brief Converts an unsigned long integer into a string. |
|
521 * \param value The value to convert. |
|
522 * \returns the resulting string. |
|
523 */ |
|
524 String String::fromNumber (unsigned long int value) |
|
525 { |
|
526 char buffer[32]; |
|
527 ::sprintf (buffer, "%lu", value); |
|
528 return String (buffer); |
|
529 } |
|
530 |
|
531 /*! |
|
532 * \brief Converts a double-precision floating point number into a string, using the "%f" format specifier. |
|
533 * \param value The value to convert. |
|
534 * \returns the resulting string. |
|
535 */ |
|
536 String String::fromNumber (double value) |
|
537 { |
|
538 char buffer[64]; |
|
539 ::sprintf (buffer, "%f", value); |
|
540 return String (buffer); |
|
541 } |
|
542 |
|
543 /*! |
|
544 * \brief Constructs a string from a vector of bytes. The bytes do not have to be null-terminated. |
|
545 * \param bytes Bytes to use for construction |
|
546 * \returns the resulting string. |
|
547 */ |
|
548 String String::fromBytes(const ByteArray& bytes) |
|
549 { |
|
550 return String(reinterpret_cast<const Vector<char>&>(bytes)); |
|
551 } |
|
552 |
|
553 /*! |
|
554 * \returns the MD5-checksum of this string. |
|
555 */ |
|
556 String String::md5() const |
|
557 { |
|
558 char checksum[33]; |
|
559 CalculateMD5 (reinterpret_cast<const unsigned char*> (chars()), length(), checksum); |
|
560 checksum[sizeof checksum - 1] = '\0'; |
|
561 return String (checksum); |
|
562 } |
247 } |
563 |
248 |
564 /*! |
249 /*! |
565 * \brief Removes leading and trailing whitespace from this string. Alternatively a custom filter can be used to strip |
250 * \brief Removes leading and trailing whitespace from this string. Alternatively a custom filter can be used to strip |
566 * something else than whitespace. |
251 * something else than whitespace. |
567 * \param filter The filtering function to use. |
252 * \param filter The filtering function to use. |
568 */ |
253 */ |
569 void String::normalize (int (*filter)(int)) |
254 void normalize(std::string& string, int (*filter)(int)) |
570 { |
255 { |
571 int a = 0; |
256 int a = 0; |
572 int b = length() - 1; |
257 int b = string.length() - 1; |
573 |
258 while ((*filter)(string[a]) and a != b) |
574 while ((*filter) (m_string[a]) and a != b) |
259 { |
575 ++a; |
260 ++a; |
576 |
261 } |
577 while ((*filter) (m_string[b]) and a != b) |
262 while ((*filter)(string[b]) and a != b) |
|
263 { |
578 --b; |
264 --b; |
579 |
265 } |
580 if (a == b) |
266 if (a == b) |
581 m_string = ""; |
267 { |
582 else if (a != 0 or b != length() - 1) |
268 string = ""; |
583 m_string = m_string.substr (a, b - a + 1); |
269 } |
584 } |
270 else if (a != 0 or b != static_cast<signed>(string.length() - 1)) |
585 |
271 { |
586 /*! |
272 string = string.substr (a, b - a + 1); |
587 * \returns a version of this string without leading or trailing whitespace. Alternatively a custom filter can be used |
273 } |
588 * to strip something else than whitespace. |
|
589 */ |
|
590 String String::normalized (int (*filter)(int)) const |
|
591 { |
|
592 String result = *this; |
|
593 result.normalize(filter); |
|
594 return result; |
|
595 } |
274 } |
596 |
275 |
597 END_ZFC_NAMESPACE |
276 END_ZFC_NAMESPACE |