30 #include "Main.h" |
30 #include "Main.h" |
31 #include "String.h" |
31 #include "String.h" |
32 |
32 |
33 // ============================================================================= |
33 // ============================================================================= |
34 // |
34 // |
35 int String::Compare (const String& other) const |
35 int String::compare (const String& other) const |
36 { |
36 { |
37 return mString.compare (other.STDString()); |
37 return m_string.compare (other.stdString()); |
38 } |
38 } |
39 |
39 |
40 // ============================================================================= |
40 // ============================================================================= |
41 // |
41 // |
42 void String::Trim (int n) |
42 void String::trim (int n) |
43 { |
43 { |
44 if (n > 0) |
44 if (n > 0) |
45 mString = Mid (0, Length() - n).STDString(); |
45 m_string = mid (0, length() - n).stdString(); |
46 else |
46 else |
47 mString = Mid (n, -1).STDString(); |
47 m_string = mid (n, -1).stdString(); |
48 } |
48 } |
49 |
49 |
50 // ============================================================================= |
50 // ============================================================================= |
51 // |
51 // |
52 String String::Strip (const List< char >& unwanted) |
52 String String::strip (const List< char >& unwanted) |
53 { |
53 { |
54 String copy (mString); |
54 String copy (m_string); |
55 |
55 |
56 for (char c : unwanted) |
56 for (char c : unwanted) |
57 for (int i = 0; i < copy.Length(); ++i) |
57 for (int i = 0; i < copy.length(); ++i) |
58 if (copy[i] == c) |
58 if (copy[i] == c) |
59 copy.RemoveAt (i); |
59 copy.removeAt (i); |
60 |
60 |
61 /* |
61 /* |
62 int pos = 0; |
62 int pos = 0; |
63 while ((pos = copy.First (c)) != -1) |
63 while ((pos = copy.First (c)) != -1) |
64 copy.RemoveAt (pos--); |
64 copy.RemoveAt (pos--); |
67 return copy; |
67 return copy; |
68 } |
68 } |
69 |
69 |
70 // ============================================================================= |
70 // ============================================================================= |
71 // |
71 // |
72 String String::ToUppercase() const |
72 String String::toUppercase() const |
73 { |
73 { |
74 String newstr = mString; |
74 String newstr = m_string; |
75 |
75 |
76 for (char& c : newstr) |
76 for (char& c : newstr) |
77 if (c >= 'a' && c <= 'z') |
77 if (c >= 'a' && c <= 'z') |
78 c -= 'a' - 'A'; |
78 c -= 'a' - 'A'; |
79 |
79 |
80 return newstr; |
80 return newstr; |
81 } |
81 } |
82 |
82 |
83 // ============================================================================= |
83 // ============================================================================= |
84 // |
84 // |
85 String String::ToLowercase() const |
85 String String::toLowercase() const |
86 { |
86 { |
87 String newstr = mString; |
87 String newstr = m_string; |
88 |
88 |
89 for (char & c : newstr) |
89 for (char & c : newstr) |
90 if (c >= 'A' && c <= 'Z') |
90 if (c >= 'A' && c <= 'Z') |
91 c += 'a' - 'A'; |
91 c += 'a' - 'A'; |
92 |
92 |
93 return newstr; |
93 return newstr; |
94 } |
94 } |
95 |
95 |
96 // ============================================================================= |
96 // ============================================================================= |
97 // |
97 // |
98 StringList String::Split (char del) const |
98 StringList String::split (char del) const |
99 { |
99 { |
100 String delimstr; |
100 String delimstr; |
101 delimstr += del; |
101 delimstr += del; |
102 return Split (delimstr); |
102 return split (delimstr); |
103 } |
103 } |
104 |
104 |
105 // ============================================================================= |
105 // ============================================================================= |
106 // |
106 // |
107 StringList String::Split (String del) const |
107 StringList String::split (const String& del) const |
108 { |
108 { |
109 StringList res; |
109 StringList res; |
110 long a = 0; |
110 long a = 0; |
111 |
111 |
112 // Find all separators and store the text left to them. |
112 // Find all separators and store the text left to them. |
113 for (;;) |
113 for (;;) |
114 { |
114 { |
115 long b = FirstIndexOf (del, a); |
115 long b = firstIndexOf (del, a); |
116 |
116 |
117 if (b == -1) |
117 if (b == -1) |
118 break; |
118 break; |
119 |
119 |
120 String sub = Mid (a, b); |
120 String sub = mid (a, b); |
121 |
121 |
122 if (sub.Length() > 0) |
122 if (sub.length() > 0) |
123 res.Append (Mid (a, b)); |
123 res.append (mid (a, b)); |
124 |
124 |
125 a = b + del.Length(); |
125 a = b + del.length(); |
126 } |
126 } |
127 |
127 |
128 // Add the string at the right of the last separator |
128 // Add the string at the right of the last separator |
129 if (a < (int) Length()) |
129 if (a < (int) length()) |
130 res.Append (Mid (a, Length())); |
130 res.append (mid (a, length())); |
131 |
131 |
132 return res; |
132 return res; |
133 } |
133 } |
134 |
134 |
135 // ============================================================================= |
135 // ============================================================================= |
136 // |
136 // |
137 void String::Replace (const char* a, const char* b) |
137 void String::replace (const char* a, const char* b) |
138 { |
138 { |
139 long pos; |
139 long pos; |
140 |
140 |
141 while ( (pos = FirstIndexOf (a)) != -1) |
141 while ((pos = firstIndexOf (a)) != -1) |
142 mString = mString.replace (pos, strlen (a), b); |
142 m_string = m_string.replace (pos, strlen (a), b); |
143 } |
143 } |
144 |
144 |
145 // ============================================================================= |
145 // ============================================================================= |
146 // |
146 // |
147 int String::Count (char needle) const |
147 int String::count (char needle) const |
148 { |
148 { |
149 int needles = 0; |
149 int needles = 0; |
150 |
150 |
151 for (const char & c : mString) |
151 for (const char & c : m_string) |
152 if (c == needle) |
152 if (c == needle) |
153 needles++; |
153 needles++; |
154 |
154 |
155 return needles; |
155 return needles; |
156 } |
156 } |
157 |
157 |
158 // ============================================================================= |
158 // ============================================================================= |
159 // |
159 // |
160 String String::Mid (long a, long b) const |
160 String String::mid (long a, long b) const |
161 { |
161 { |
162 if (b == -1) |
162 if (b == -1) |
163 b = Length(); |
163 b = length(); |
164 |
164 |
165 if (b == a) |
165 if (b == a) |
166 return ""; |
166 return ""; |
167 |
167 |
168 if (b < a) |
168 if (b < a) |
172 a = b; |
172 a = b; |
173 b = c; |
173 b = c; |
174 } |
174 } |
175 |
175 |
176 char* newstr = new char[b - a + 1]; |
176 char* newstr = new char[b - a + 1]; |
177 strncpy (newstr, mString.c_str() + a, b - a); |
177 strncpy (newstr, m_string.c_str() + a, b - a); |
178 newstr[b - a] = '\0'; |
178 newstr[b - a] = '\0'; |
179 |
179 |
180 String other (newstr); |
180 String other (newstr); |
181 delete[] newstr; |
181 delete[] newstr; |
182 return other; |
182 return other; |
183 } |
183 } |
184 |
184 |
185 // ============================================================================= |
185 // ============================================================================= |
186 // |
186 // |
187 int String::WordPosition (int n) const |
187 int String::wordPosition (int n) const |
188 { |
188 { |
189 int count = 0; |
189 int count = 0; |
190 |
190 |
191 for (int i = 0; i < Length(); ++i) |
191 for (int i = 0; i < length(); ++i) |
192 { |
192 { |
193 if (mString[i] != ' ') |
193 if (m_string[i] != ' ') |
194 continue; |
194 continue; |
195 |
195 |
196 if (++count < n) |
196 if (++count < n) |
197 continue; |
197 continue; |
198 |
198 |
202 return -1; |
202 return -1; |
203 } |
203 } |
204 |
204 |
205 // ============================================================================= |
205 // ============================================================================= |
206 // |
206 // |
207 int String::FirstIndexOf (const char* c, int a) const |
207 int String::firstIndexOf (const char* c, int a) const |
208 { |
208 { |
209 for (; a < Length(); a++) |
209 for (; a < length(); a++) |
210 if (mString[a] == c[0] && strncmp (mString.c_str() + a, c, strlen (c)) == 0) |
210 if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0) |
211 return a; |
211 return a; |
212 |
212 |
213 return -1; |
213 return -1; |
214 } |
214 } |
215 |
215 |
216 // ============================================================================= |
216 // ============================================================================= |
217 // |
217 // |
218 int String::LastIndexOf (const char* c, int a) const |
218 int String::lastIndexOf (const char* c, int a) const |
219 { |
219 { |
220 if (a == -1 || a >= Length()) |
220 if (a == -1 || a >= length()) |
221 a = Length() - 1; |
221 a = length() - 1; |
222 |
222 |
223 for (; a > 0; a--) |
223 for (; a > 0; a--) |
224 if (mString[a] == c[0] && strncmp (mString.c_str() + a, c, strlen (c)) == 0) |
224 if (m_string[a] == c[0] && strncmp (m_string.c_str() + a, c, strlen (c)) == 0) |
225 return a; |
225 return a; |
226 |
226 |
227 return -1; |
227 return -1; |
228 } |
228 } |
229 |
229 |
230 // ============================================================================= |
230 // ============================================================================= |
231 // |
231 // |
232 void String::Dump() const |
232 void String::dump() const |
233 { |
233 { |
234 Print ("`%1`:\n", CString()); |
234 print ("`%1`:\n", chars()); |
235 int i = 0; |
235 int i = 0; |
236 |
236 |
237 for (char u : mString) |
237 for (char u : m_string) |
238 Print ("\t%1. [%d2] `%3`\n", i++, u, String (u)); |
238 print ("\t%1. [%d2] `%3`\n", i++, u, String (u)); |
239 } |
239 } |
240 |
240 |
241 // ============================================================================= |
241 // ============================================================================= |
242 // |
242 // |
243 long String::ToLong (bool* ok, int base) const |
243 long String::toLong (bool* ok, int base) const |
244 { |
244 { |
245 errno = 0; |
245 errno = 0; |
246 char* endptr; |
246 char* endptr; |
247 long i = strtol (mString.c_str(), &endptr, base); |
247 long i = strtol (m_string.c_str(), &endptr, base); |
248 |
248 |
249 if (ok) |
249 if (ok) |
250 *ok = (errno == 0 && *endptr == '\0'); |
250 *ok = (errno == 0 && *endptr == '\0'); |
251 |
251 |
252 return i; |
252 return i; |
253 } |
253 } |
254 |
254 |
255 // ============================================================================= |
255 // ============================================================================= |
256 // |
256 // |
257 float String::ToFloat (bool* ok) const |
257 float String::toFloat (bool* ok) const |
258 { |
258 { |
259 errno = 0; |
259 errno = 0; |
260 char* endptr; |
260 char* endptr; |
261 float i = strtof (mString.c_str(), &endptr); |
261 float i = strtof (m_string.c_str(), &endptr); |
262 |
262 |
263 if (ok) |
263 if (ok) |
264 *ok = (errno == 0 && *endptr == '\0'); |
264 *ok = (errno == 0 && *endptr == '\0'); |
265 |
265 |
266 return i; |
266 return i; |
267 } |
267 } |
268 |
268 |
269 // ============================================================================= |
269 // ============================================================================= |
270 // |
270 // |
271 double String::ToDouble (bool* ok) const |
271 double String::toDouble (bool* ok) const |
272 { |
272 { |
273 errno = 0; |
273 errno = 0; |
274 char* endptr; |
274 char* endptr; |
275 double i = strtod (mString.c_str(), &endptr); |
275 double i = strtod (m_string.c_str(), &endptr); |
276 |
276 |
277 if (ok) |
277 if (ok) |
278 *ok = (errno == 0 && *endptr == '\0'); |
278 *ok = (errno == 0 && *endptr == '\0'); |
279 |
279 |
280 return i; |
280 return i; |
283 // ============================================================================= |
283 // ============================================================================= |
284 // |
284 // |
285 String String::operator+ (const String& data) const |
285 String String::operator+ (const String& data) const |
286 { |
286 { |
287 String newString = *this; |
287 String newString = *this; |
288 newString.Append (data); |
288 newString.append (data); |
289 return newString; |
289 return newString; |
290 } |
290 } |
291 |
291 |
292 // ============================================================================= |
292 // ============================================================================= |
293 // |
293 // |
294 String String::operator+ (const char* data) const |
294 String String::operator+ (const char* data) const |
295 { |
295 { |
296 String newstr = *this; |
296 String newstr = *this; |
297 newstr.Append (data); |
297 newstr.append (data); |
298 return newstr; |
298 return newstr; |
299 } |
299 } |
300 |
300 |
301 // ============================================================================= |
301 // ============================================================================= |
302 // |
302 // |
303 bool String::IsNumeric() const |
303 bool String::isNumeric() const |
304 { |
304 { |
305 bool gotDot = false; |
305 bool gotDot = false; |
306 |
306 |
307 for (const char & c : mString) |
307 for (const char & c : m_string) |
308 { |
308 { |
309 // Allow leading hyphen for negatives |
309 // Allow leading hyphen for negatives |
310 if (&c == &mString[0] && c == '-') |
310 if (&c == &m_string[0] && c == '-') |
311 continue; |
311 continue; |
312 |
312 |
313 // Check for decimal point |
313 // Check for decimal point |
314 if (!gotDot && c == '.') |
314 if (!gotDot && c == '.') |
315 { |
315 { |
328 return true; |
328 return true; |
329 } |
329 } |
330 |
330 |
331 // ============================================================================= |
331 // ============================================================================= |
332 // |
332 // |
333 bool String::EndsWith (const String& other) |
333 bool String::endsWith (const String& other) |
334 { |
334 { |
335 if (Length() < other.Length()) |
335 if (length() < other.length()) |
336 return false; |
336 return false; |
337 |
337 |
338 const int ofs = Length() - other.Length(); |
338 const int ofs = length() - other.length(); |
339 return strncmp (CString() + ofs, other.CString(), other.Length()) == 0; |
339 return strncmp (chars() + ofs, other.chars(), other.length()) == 0; |
340 } |
340 } |
341 |
341 |
342 // ============================================================================= |
342 // ============================================================================= |
343 // |
343 // |
344 bool String::StartsWith (const String& other) |
344 bool String::startsWith (const String& other) |
345 { |
345 { |
346 if (Length() < other.Length()) |
346 if (length() < other.length()) |
347 return false; |
347 return false; |
348 |
348 |
349 return strncmp (CString(), other.CString(), other.Length()) == 0; |
349 return strncmp (chars(), other.chars(), other.length()) == 0; |
350 } |
350 } |
351 |
351 |
352 // ============================================================================= |
352 // ============================================================================= |
353 // |
353 // |
354 void String::SPrintf (const char* fmtstr, ...) |
354 void String::sprintf (const char* fmtstr, ...) |
355 { |
355 { |
356 char* buf; |
356 char* buf; |
357 int bufsize = 256; |
357 int bufsize = 256; |
358 va_list va; |
358 va_list va; |
359 va_start (va, fmtstr); |
359 va_start (va, fmtstr); |
361 do |
361 do |
362 buf = new char[bufsize]; |
362 buf = new char[bufsize]; |
363 while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize); |
363 while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize); |
364 |
364 |
365 va_end (va); |
365 va_end (va); |
366 mString = buf; |
366 m_string = buf; |
367 delete[] buf; |
367 delete[] buf; |
368 } |
368 } |
369 |
369 |
370 // ============================================================================= |
370 // ============================================================================= |
371 // |
371 // |
372 String StringList::Join (const String& delim) |
372 String StringList::join (const String& delim) |
373 { |
373 { |
374 String result; |
374 String result; |
375 |
375 |
376 for (const String& it : GetDeque()) |
376 for (const String& it : deque()) |
377 { |
377 { |
378 if (result.IsEmpty() == false) |
378 if (result.isEmpty() == false) |
379 result += delim; |
379 result += delim; |
380 |
380 |
381 result += it; |
381 result += it; |
382 } |
382 } |
383 |
383 |
384 return result; |
384 return result; |
385 } |
385 } |
386 |
386 |
387 // ============================================================================= |
387 // ============================================================================= |
388 // |
388 // |
389 bool String::MaskAgainst (const String& pattern) const |
389 bool String::maskAgainst (const String& pattern) const |
390 { |
390 { |
391 // Elevate to uppercase for case-insensitive matching |
391 // Elevate to uppercase for case-insensitive matching |
392 String pattern_upper = pattern.ToUppercase(); |
392 String pattern_upper = pattern.toUppercase(); |
393 String this_upper = ToUppercase(); |
393 String this_upper = toUppercase(); |
394 const char* maskstring = pattern_upper.CString(); |
394 const char* maskstring = pattern_upper.chars(); |
395 const char* mptr = &maskstring[0]; |
395 const char* mptr = &maskstring[0]; |
396 |
396 |
397 for (const char* sptr = this_upper.CString(); *sptr != '\0'; sptr++) |
397 for (const char* sptr = this_upper.chars(); *sptr != '\0'; sptr++) |
398 { |
398 { |
399 if (*mptr == '?') |
399 if (*mptr == '?') |
400 { |
400 { |
401 if (*(sptr + 1) == '\0') |
401 if (*(sptr + 1) == '\0') |
402 { |
402 { |
432 return true; |
432 return true; |
433 } |
433 } |
434 |
434 |
435 // ============================================================================= |
435 // ============================================================================= |
436 // |
436 // |
437 String String::FromNumber (int a) |
437 String String::fromNumber (int a) |
438 { |
438 { |
439 char buf[32]; |
439 char buf[32]; |
440 sprintf (buf, "%d", a); |
440 ::sprintf (buf, "%d", a); |
441 return String (buf); |
441 return String (buf); |
442 } |
442 } |
443 |
443 |
444 // ============================================================================= |
444 // ============================================================================= |
445 // |
445 // |
446 String String::FromNumber (long a) |
446 String String::fromNumber (long a) |
447 { |
447 { |
448 char buf[32]; |
448 char buf[32]; |
449 sprintf (buf, "%ld", a); |
449 ::sprintf (buf, "%ld", a); |
450 return String (buf); |
450 return String (buf); |
451 } |
451 } |