diff options
Diffstat (limited to 'libraries/irrlicht-1.8/include/irrString.h')
-rw-r--r-- | libraries/irrlicht-1.8/include/irrString.h | 2736 |
1 files changed, 1368 insertions, 1368 deletions
diff --git a/libraries/irrlicht-1.8/include/irrString.h b/libraries/irrlicht-1.8/include/irrString.h index 43557cd..752ea1a 100644 --- a/libraries/irrlicht-1.8/include/irrString.h +++ b/libraries/irrlicht-1.8/include/irrString.h | |||
@@ -1,1368 +1,1368 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine" and the "irrXML" project. | 2 | // This file is part of the "Irrlicht Engine" and the "irrXML" project. |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h |
4 | 4 | ||
5 | #ifndef __IRR_STRING_H_INCLUDED__ | 5 | #ifndef __IRR_STRING_H_INCLUDED__ |
6 | #define __IRR_STRING_H_INCLUDED__ | 6 | #define __IRR_STRING_H_INCLUDED__ |
7 | 7 | ||
8 | #include "irrTypes.h" | 8 | #include "irrTypes.h" |
9 | #include "irrAllocator.h" | 9 | #include "irrAllocator.h" |
10 | #include "irrMath.h" | 10 | #include "irrMath.h" |
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | #include <string.h> | 12 | #include <string.h> |
13 | #include <stdlib.h> | 13 | #include <stdlib.h> |
14 | 14 | ||
15 | namespace irr | 15 | namespace irr |
16 | { | 16 | { |
17 | namespace core | 17 | namespace core |
18 | { | 18 | { |
19 | 19 | ||
20 | //! Very simple string class with some useful features. | 20 | //! Very simple string class with some useful features. |
21 | /** string<c8> and string<wchar_t> both accept Unicode AND ASCII/Latin-1, | 21 | /** string<c8> and string<wchar_t> both accept Unicode AND ASCII/Latin-1, |
22 | so you can assign Unicode to string<c8> and ASCII/Latin-1 to string<wchar_t> | 22 | so you can assign Unicode to string<c8> and ASCII/Latin-1 to string<wchar_t> |
23 | (and the other way round) if you want to. | 23 | (and the other way round) if you want to. |
24 | 24 | ||
25 | However, note that the conversation between both is not done using any encoding. | 25 | However, note that the conversation between both is not done using any encoding. |
26 | This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and | 26 | This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and |
27 | are simply expanded to the equivalent wchar_t, while Unicode/wchar_t | 27 | are simply expanded to the equivalent wchar_t, while Unicode/wchar_t |
28 | characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all | 28 | characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all |
29 | other information in the wchar_t. | 29 | other information in the wchar_t. |
30 | */ | 30 | */ |
31 | 31 | ||
32 | enum eLocaleID | 32 | enum eLocaleID |
33 | { | 33 | { |
34 | IRR_LOCALE_ANSI = 0, | 34 | IRR_LOCALE_ANSI = 0, |
35 | IRR_LOCALE_GERMAN = 1 | 35 | IRR_LOCALE_GERMAN = 1 |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static eLocaleID locale_current = IRR_LOCALE_ANSI; | 38 | static eLocaleID locale_current = IRR_LOCALE_ANSI; |
39 | static inline void locale_set ( eLocaleID id ) | 39 | static inline void locale_set ( eLocaleID id ) |
40 | { | 40 | { |
41 | locale_current = id; | 41 | locale_current = id; |
42 | } | 42 | } |
43 | 43 | ||
44 | //! Returns a character converted to lower case | 44 | //! Returns a character converted to lower case |
45 | static inline u32 locale_lower ( u32 x ) | 45 | static inline u32 locale_lower ( u32 x ) |
46 | { | 46 | { |
47 | switch ( locale_current ) | 47 | switch ( locale_current ) |
48 | { | 48 | { |
49 | case IRR_LOCALE_GERMAN: | 49 | case IRR_LOCALE_GERMAN: |
50 | case IRR_LOCALE_ANSI: | 50 | case IRR_LOCALE_ANSI: |
51 | break; | 51 | break; |
52 | } | 52 | } |
53 | // ansi | 53 | // ansi |
54 | return x >= 'A' && x <= 'Z' ? x + 0x20 : x; | 54 | return x >= 'A' && x <= 'Z' ? x + 0x20 : x; |
55 | } | 55 | } |
56 | 56 | ||
57 | //! Returns a character converted to upper case | 57 | //! Returns a character converted to upper case |
58 | static inline u32 locale_upper ( u32 x ) | 58 | static inline u32 locale_upper ( u32 x ) |
59 | { | 59 | { |
60 | switch ( locale_current ) | 60 | switch ( locale_current ) |
61 | { | 61 | { |
62 | case IRR_LOCALE_GERMAN: | 62 | case IRR_LOCALE_GERMAN: |
63 | case IRR_LOCALE_ANSI: | 63 | case IRR_LOCALE_ANSI: |
64 | break; | 64 | break; |
65 | } | 65 | } |
66 | 66 | ||
67 | // ansi | 67 | // ansi |
68 | return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; | 68 | return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; |
69 | } | 69 | } |
70 | 70 | ||
71 | 71 | ||
72 | template <typename T, typename TAlloc = irrAllocator<T> > | 72 | template <typename T, typename TAlloc = irrAllocator<T> > |
73 | class string | 73 | class string |
74 | { | 74 | { |
75 | public: | 75 | public: |
76 | 76 | ||
77 | typedef T char_type; | 77 | typedef T char_type; |
78 | 78 | ||
79 | //! Default constructor | 79 | //! Default constructor |
80 | string() | 80 | string() |
81 | : array(0), allocated(1), used(1) | 81 | : array(0), allocated(1), used(1) |
82 | { | 82 | { |
83 | array = allocator.allocate(1); // new T[1]; | 83 | array = allocator.allocate(1); // new T[1]; |
84 | array[0] = 0; | 84 | array[0] = 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | 87 | ||
88 | //! Constructor | 88 | //! Constructor |
89 | string(const string<T,TAlloc>& other) | 89 | string(const string<T,TAlloc>& other) |
90 | : array(0), allocated(0), used(0) | 90 | : array(0), allocated(0), used(0) |
91 | { | 91 | { |
92 | *this = other; | 92 | *this = other; |
93 | } | 93 | } |
94 | 94 | ||
95 | //! Constructor from other string types | 95 | //! Constructor from other string types |
96 | template <class B, class A> | 96 | template <class B, class A> |
97 | string(const string<B, A>& other) | 97 | string(const string<B, A>& other) |
98 | : array(0), allocated(0), used(0) | 98 | : array(0), allocated(0), used(0) |
99 | { | 99 | { |
100 | *this = other; | 100 | *this = other; |
101 | } | 101 | } |
102 | 102 | ||
103 | 103 | ||
104 | //! Constructs a string from a float | 104 | //! Constructs a string from a float |
105 | explicit string(const double number) | 105 | explicit string(const double number) |
106 | : array(0), allocated(0), used(0) | 106 | : array(0), allocated(0), used(0) |
107 | { | 107 | { |
108 | c8 tmpbuf[255]; | 108 | c8 tmpbuf[255]; |
109 | snprintf(tmpbuf, 255, "%0.6f", number); | 109 | snprintf(tmpbuf, 255, "%0.6f", number); |
110 | *this = tmpbuf; | 110 | *this = tmpbuf; |
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
114 | //! Constructs a string from an int | 114 | //! Constructs a string from an int |
115 | explicit string(int number) | 115 | explicit string(int number) |
116 | : array(0), allocated(0), used(0) | 116 | : array(0), allocated(0), used(0) |
117 | { | 117 | { |
118 | // store if negative and make positive | 118 | // store if negative and make positive |
119 | 119 | ||
120 | bool negative = false; | 120 | bool negative = false; |
121 | if (number < 0) | 121 | if (number < 0) |
122 | { | 122 | { |
123 | number *= -1; | 123 | number *= -1; |
124 | negative = true; | 124 | negative = true; |
125 | } | 125 | } |
126 | 126 | ||
127 | // temporary buffer for 16 numbers | 127 | // temporary buffer for 16 numbers |
128 | 128 | ||
129 | c8 tmpbuf[16]={0}; | 129 | c8 tmpbuf[16]={0}; |
130 | u32 idx = 15; | 130 | u32 idx = 15; |
131 | 131 | ||
132 | // special case '0' | 132 | // special case '0' |
133 | 133 | ||
134 | if (!number) | 134 | if (!number) |
135 | { | 135 | { |
136 | tmpbuf[14] = '0'; | 136 | tmpbuf[14] = '0'; |
137 | *this = &tmpbuf[14]; | 137 | *this = &tmpbuf[14]; |
138 | return; | 138 | return; |
139 | } | 139 | } |
140 | 140 | ||
141 | // add numbers | 141 | // add numbers |
142 | 142 | ||
143 | while(number && idx) | 143 | while(number && idx) |
144 | { | 144 | { |
145 | --idx; | 145 | --idx; |
146 | tmpbuf[idx] = (c8)('0' + (number % 10)); | 146 | tmpbuf[idx] = (c8)('0' + (number % 10)); |
147 | number /= 10; | 147 | number /= 10; |
148 | } | 148 | } |
149 | 149 | ||
150 | // add sign | 150 | // add sign |
151 | 151 | ||
152 | if (negative) | 152 | if (negative) |
153 | { | 153 | { |
154 | --idx; | 154 | --idx; |
155 | tmpbuf[idx] = '-'; | 155 | tmpbuf[idx] = '-'; |
156 | } | 156 | } |
157 | 157 | ||
158 | *this = &tmpbuf[idx]; | 158 | *this = &tmpbuf[idx]; |
159 | } | 159 | } |
160 | 160 | ||
161 | 161 | ||
162 | //! Constructs a string from an unsigned int | 162 | //! Constructs a string from an unsigned int |
163 | explicit string(unsigned int number) | 163 | explicit string(unsigned int number) |
164 | : array(0), allocated(0), used(0) | 164 | : array(0), allocated(0), used(0) |
165 | { | 165 | { |
166 | // temporary buffer for 16 numbers | 166 | // temporary buffer for 16 numbers |
167 | 167 | ||
168 | c8 tmpbuf[16]={0}; | 168 | c8 tmpbuf[16]={0}; |
169 | u32 idx = 15; | 169 | u32 idx = 15; |
170 | 170 | ||
171 | // special case '0' | 171 | // special case '0' |
172 | 172 | ||
173 | if (!number) | 173 | if (!number) |
174 | { | 174 | { |
175 | tmpbuf[14] = '0'; | 175 | tmpbuf[14] = '0'; |
176 | *this = &tmpbuf[14]; | 176 | *this = &tmpbuf[14]; |
177 | return; | 177 | return; |
178 | } | 178 | } |
179 | 179 | ||
180 | // add numbers | 180 | // add numbers |
181 | 181 | ||
182 | while(number && idx) | 182 | while(number && idx) |
183 | { | 183 | { |
184 | --idx; | 184 | --idx; |
185 | tmpbuf[idx] = (c8)('0' + (number % 10)); | 185 | tmpbuf[idx] = (c8)('0' + (number % 10)); |
186 | number /= 10; | 186 | number /= 10; |
187 | } | 187 | } |
188 | 188 | ||
189 | *this = &tmpbuf[idx]; | 189 | *this = &tmpbuf[idx]; |
190 | } | 190 | } |
191 | 191 | ||
192 | 192 | ||
193 | //! Constructs a string from a long | 193 | //! Constructs a string from a long |
194 | explicit string(long number) | 194 | explicit string(long number) |
195 | : array(0), allocated(0), used(0) | 195 | : array(0), allocated(0), used(0) |
196 | { | 196 | { |
197 | // store if negative and make positive | 197 | // store if negative and make positive |
198 | 198 | ||
199 | bool negative = false; | 199 | bool negative = false; |
200 | if (number < 0) | 200 | if (number < 0) |
201 | { | 201 | { |
202 | number *= -1; | 202 | number *= -1; |
203 | negative = true; | 203 | negative = true; |
204 | } | 204 | } |
205 | 205 | ||
206 | // temporary buffer for 16 numbers | 206 | // temporary buffer for 16 numbers |
207 | 207 | ||
208 | c8 tmpbuf[16]={0}; | 208 | c8 tmpbuf[16]={0}; |
209 | u32 idx = 15; | 209 | u32 idx = 15; |
210 | 210 | ||
211 | // special case '0' | 211 | // special case '0' |
212 | 212 | ||
213 | if (!number) | 213 | if (!number) |
214 | { | 214 | { |
215 | tmpbuf[14] = '0'; | 215 | tmpbuf[14] = '0'; |
216 | *this = &tmpbuf[14]; | 216 | *this = &tmpbuf[14]; |
217 | return; | 217 | return; |
218 | } | 218 | } |
219 | 219 | ||
220 | // add numbers | 220 | // add numbers |
221 | 221 | ||
222 | while(number && idx) | 222 | while(number && idx) |
223 | { | 223 | { |
224 | --idx; | 224 | --idx; |
225 | tmpbuf[idx] = (c8)('0' + (number % 10)); | 225 | tmpbuf[idx] = (c8)('0' + (number % 10)); |
226 | number /= 10; | 226 | number /= 10; |
227 | } | 227 | } |
228 | 228 | ||
229 | // add sign | 229 | // add sign |
230 | 230 | ||
231 | if (negative) | 231 | if (negative) |
232 | { | 232 | { |
233 | --idx; | 233 | --idx; |
234 | tmpbuf[idx] = '-'; | 234 | tmpbuf[idx] = '-'; |
235 | } | 235 | } |
236 | 236 | ||
237 | *this = &tmpbuf[idx]; | 237 | *this = &tmpbuf[idx]; |
238 | } | 238 | } |
239 | 239 | ||
240 | 240 | ||
241 | //! Constructs a string from an unsigned long | 241 | //! Constructs a string from an unsigned long |
242 | explicit string(unsigned long number) | 242 | explicit string(unsigned long number) |
243 | : array(0), allocated(0), used(0) | 243 | : array(0), allocated(0), used(0) |
244 | { | 244 | { |
245 | // temporary buffer for 16 numbers | 245 | // temporary buffer for 16 numbers |
246 | 246 | ||
247 | c8 tmpbuf[16]={0}; | 247 | c8 tmpbuf[16]={0}; |
248 | u32 idx = 15; | 248 | u32 idx = 15; |
249 | 249 | ||
250 | // special case '0' | 250 | // special case '0' |
251 | 251 | ||
252 | if (!number) | 252 | if (!number) |
253 | { | 253 | { |
254 | tmpbuf[14] = '0'; | 254 | tmpbuf[14] = '0'; |
255 | *this = &tmpbuf[14]; | 255 | *this = &tmpbuf[14]; |
256 | return; | 256 | return; |
257 | } | 257 | } |
258 | 258 | ||
259 | // add numbers | 259 | // add numbers |
260 | 260 | ||
261 | while(number && idx) | 261 | while(number && idx) |
262 | { | 262 | { |
263 | --idx; | 263 | --idx; |
264 | tmpbuf[idx] = (c8)('0' + (number % 10)); | 264 | tmpbuf[idx] = (c8)('0' + (number % 10)); |
265 | number /= 10; | 265 | number /= 10; |
266 | } | 266 | } |
267 | 267 | ||
268 | *this = &tmpbuf[idx]; | 268 | *this = &tmpbuf[idx]; |
269 | } | 269 | } |
270 | 270 | ||
271 | 271 | ||
272 | //! Constructor for copying a string from a pointer with a given length | 272 | //! Constructor for copying a string from a pointer with a given length |
273 | template <class B> | 273 | template <class B> |
274 | string(const B* const c, u32 length) | 274 | string(const B* const c, u32 length) |
275 | : array(0), allocated(0), used(0) | 275 | : array(0), allocated(0), used(0) |
276 | { | 276 | { |
277 | if (!c) | 277 | if (!c) |
278 | { | 278 | { |
279 | // correctly init the string to an empty one | 279 | // correctly init the string to an empty one |
280 | *this=""; | 280 | *this=""; |
281 | return; | 281 | return; |
282 | } | 282 | } |
283 | 283 | ||
284 | allocated = used = length+1; | 284 | allocated = used = length+1; |
285 | array = allocator.allocate(used); // new T[used]; | 285 | array = allocator.allocate(used); // new T[used]; |
286 | 286 | ||
287 | for (u32 l = 0; l<length; ++l) | 287 | for (u32 l = 0; l<length; ++l) |
288 | array[l] = (T)c[l]; | 288 | array[l] = (T)c[l]; |
289 | 289 | ||
290 | array[length] = 0; | 290 | array[length] = 0; |
291 | } | 291 | } |
292 | 292 | ||
293 | 293 | ||
294 | //! Constructor for unicode and ascii strings | 294 | //! Constructor for unicode and ascii strings |
295 | template <class B> | 295 | template <class B> |
296 | string(const B* const c) | 296 | string(const B* const c) |
297 | : array(0), allocated(0), used(0) | 297 | : array(0), allocated(0), used(0) |
298 | { | 298 | { |
299 | *this = c; | 299 | *this = c; |
300 | } | 300 | } |
301 | 301 | ||
302 | 302 | ||
303 | //! Destructor | 303 | //! Destructor |
304 | ~string() | 304 | ~string() |
305 | { | 305 | { |
306 | allocator.deallocate(array); // delete [] array; | 306 | allocator.deallocate(array); // delete [] array; |
307 | } | 307 | } |
308 | 308 | ||
309 | 309 | ||
310 | //! Assignment operator | 310 | //! Assignment operator |
311 | string<T,TAlloc>& operator=(const string<T,TAlloc>& other) | 311 | string<T,TAlloc>& operator=(const string<T,TAlloc>& other) |
312 | { | 312 | { |
313 | if (this == &other) | 313 | if (this == &other) |
314 | return *this; | 314 | return *this; |
315 | 315 | ||
316 | used = other.size()+1; | 316 | used = other.size()+1; |
317 | if (used>allocated) | 317 | if (used>allocated) |
318 | { | 318 | { |
319 | allocator.deallocate(array); // delete [] array; | 319 | allocator.deallocate(array); // delete [] array; |
320 | allocated = used; | 320 | allocated = used; |
321 | array = allocator.allocate(used); //new T[used]; | 321 | array = allocator.allocate(used); //new T[used]; |
322 | } | 322 | } |
323 | 323 | ||
324 | const T* p = other.c_str(); | 324 | const T* p = other.c_str(); |
325 | for (u32 i=0; i<used; ++i, ++p) | 325 | for (u32 i=0; i<used; ++i, ++p) |
326 | array[i] = *p; | 326 | array[i] = *p; |
327 | 327 | ||
328 | return *this; | 328 | return *this; |
329 | } | 329 | } |
330 | 330 | ||
331 | //! Assignment operator for other string types | 331 | //! Assignment operator for other string types |
332 | template <class B, class A> | 332 | template <class B, class A> |
333 | string<T,TAlloc>& operator=(const string<B,A>& other) | 333 | string<T,TAlloc>& operator=(const string<B,A>& other) |
334 | { | 334 | { |
335 | *this = other.c_str(); | 335 | *this = other.c_str(); |
336 | return *this; | 336 | return *this; |
337 | } | 337 | } |
338 | 338 | ||
339 | 339 | ||
340 | //! Assignment operator for strings, ascii and unicode | 340 | //! Assignment operator for strings, ascii and unicode |
341 | template <class B> | 341 | template <class B> |
342 | string<T,TAlloc>& operator=(const B* const c) | 342 | string<T,TAlloc>& operator=(const B* const c) |
343 | { | 343 | { |
344 | if (!c) | 344 | if (!c) |
345 | { | 345 | { |
346 | if (!array) | 346 | if (!array) |
347 | { | 347 | { |
348 | array = allocator.allocate(1); //new T[1]; | 348 | array = allocator.allocate(1); //new T[1]; |
349 | allocated = 1; | 349 | allocated = 1; |
350 | } | 350 | } |
351 | used = 1; | 351 | used = 1; |
352 | array[0] = 0x0; | 352 | array[0] = 0x0; |
353 | return *this; | 353 | return *this; |
354 | } | 354 | } |
355 | 355 | ||
356 | if ((void*)c == (void*)array) | 356 | if ((void*)c == (void*)array) |
357 | return *this; | 357 | return *this; |
358 | 358 | ||
359 | u32 len = 0; | 359 | u32 len = 0; |
360 | const B* p = c; | 360 | const B* p = c; |
361 | do | 361 | do |
362 | { | 362 | { |
363 | ++len; | 363 | ++len; |
364 | } while(*p++); | 364 | } while(*p++); |
365 | 365 | ||
366 | // we'll keep the old string for a while, because the new | 366 | // we'll keep the old string for a while, because the new |
367 | // string could be a part of the current string. | 367 | // string could be a part of the current string. |
368 | T* oldArray = array; | 368 | T* oldArray = array; |
369 | 369 | ||
370 | used = len; | 370 | used = len; |
371 | if (used>allocated) | 371 | if (used>allocated) |
372 | { | 372 | { |
373 | allocated = used; | 373 | allocated = used; |
374 | array = allocator.allocate(used); //new T[used]; | 374 | array = allocator.allocate(used); //new T[used]; |
375 | } | 375 | } |
376 | 376 | ||
377 | for (u32 l = 0; l<len; ++l) | 377 | for (u32 l = 0; l<len; ++l) |
378 | array[l] = (T)c[l]; | 378 | array[l] = (T)c[l]; |
379 | 379 | ||
380 | if (oldArray != array) | 380 | if (oldArray != array) |
381 | allocator.deallocate(oldArray); // delete [] oldArray; | 381 | allocator.deallocate(oldArray); // delete [] oldArray; |
382 | 382 | ||
383 | return *this; | 383 | return *this; |
384 | } | 384 | } |
385 | 385 | ||
386 | 386 | ||
387 | //! Append operator for other strings | 387 | //! Append operator for other strings |
388 | string<T,TAlloc> operator+(const string<T,TAlloc>& other) const | 388 | string<T,TAlloc> operator+(const string<T,TAlloc>& other) const |
389 | { | 389 | { |
390 | string<T,TAlloc> str(*this); | 390 | string<T,TAlloc> str(*this); |
391 | str.append(other); | 391 | str.append(other); |
392 | 392 | ||
393 | return str; | 393 | return str; |
394 | } | 394 | } |
395 | 395 | ||
396 | 396 | ||
397 | //! Append operator for strings, ascii and unicode | 397 | //! Append operator for strings, ascii and unicode |
398 | template <class B> | 398 | template <class B> |
399 | string<T,TAlloc> operator+(const B* const c) const | 399 | string<T,TAlloc> operator+(const B* const c) const |
400 | { | 400 | { |
401 | string<T,TAlloc> str(*this); | 401 | string<T,TAlloc> str(*this); |
402 | str.append(c); | 402 | str.append(c); |
403 | 403 | ||
404 | return str; | 404 | return str; |
405 | } | 405 | } |
406 | 406 | ||
407 | 407 | ||
408 | //! Direct access operator | 408 | //! Direct access operator |
409 | T& operator [](const u32 index) | 409 | T& operator [](const u32 index) |
410 | { | 410 | { |
411 | _IRR_DEBUG_BREAK_IF(index>=used) // bad index | 411 | _IRR_DEBUG_BREAK_IF(index>=used) // bad index |
412 | return array[index]; | 412 | return array[index]; |
413 | } | 413 | } |
414 | 414 | ||
415 | 415 | ||
416 | //! Direct access operator | 416 | //! Direct access operator |
417 | const T& operator [](const u32 index) const | 417 | const T& operator [](const u32 index) const |
418 | { | 418 | { |
419 | _IRR_DEBUG_BREAK_IF(index>=used) // bad index | 419 | _IRR_DEBUG_BREAK_IF(index>=used) // bad index |
420 | return array[index]; | 420 | return array[index]; |
421 | } | 421 | } |
422 | 422 | ||
423 | 423 | ||
424 | //! Equality operator | 424 | //! Equality operator |
425 | bool operator==(const T* const str) const | 425 | bool operator==(const T* const str) const |
426 | { | 426 | { |
427 | if (!str) | 427 | if (!str) |
428 | return false; | 428 | return false; |
429 | 429 | ||
430 | u32 i; | 430 | u32 i; |
431 | for (i=0; array[i] && str[i]; ++i) | 431 | for (i=0; array[i] && str[i]; ++i) |
432 | if (array[i] != str[i]) | 432 | if (array[i] != str[i]) |
433 | return false; | 433 | return false; |
434 | 434 | ||
435 | return (!array[i] && !str[i]); | 435 | return (!array[i] && !str[i]); |
436 | } | 436 | } |
437 | 437 | ||
438 | 438 | ||
439 | //! Equality operator | 439 | //! Equality operator |
440 | bool operator==(const string<T,TAlloc>& other) const | 440 | bool operator==(const string<T,TAlloc>& other) const |
441 | { | 441 | { |
442 | for (u32 i=0; array[i] && other.array[i]; ++i) | 442 | for (u32 i=0; array[i] && other.array[i]; ++i) |
443 | if (array[i] != other.array[i]) | 443 | if (array[i] != other.array[i]) |
444 | return false; | 444 | return false; |
445 | 445 | ||
446 | return used == other.used; | 446 | return used == other.used; |
447 | } | 447 | } |
448 | 448 | ||
449 | 449 | ||
450 | //! Is smaller comparator | 450 | //! Is smaller comparator |
451 | bool operator<(const string<T,TAlloc>& other) const | 451 | bool operator<(const string<T,TAlloc>& other) const |
452 | { | 452 | { |
453 | for (u32 i=0; array[i] && other.array[i]; ++i) | 453 | for (u32 i=0; array[i] && other.array[i]; ++i) |
454 | { | 454 | { |
455 | const s32 diff = array[i] - other.array[i]; | 455 | const s32 diff = array[i] - other.array[i]; |
456 | if (diff) | 456 | if (diff) |
457 | return (diff < 0); | 457 | return (diff < 0); |
458 | } | 458 | } |
459 | 459 | ||
460 | return (used < other.used); | 460 | return (used < other.used); |
461 | } | 461 | } |
462 | 462 | ||
463 | 463 | ||
464 | //! Inequality operator | 464 | //! Inequality operator |
465 | bool operator!=(const T* const str) const | 465 | bool operator!=(const T* const str) const |
466 | { | 466 | { |
467 | return !(*this == str); | 467 | return !(*this == str); |
468 | } | 468 | } |
469 | 469 | ||
470 | 470 | ||
471 | //! Inequality operator | 471 | //! Inequality operator |
472 | bool operator!=(const string<T,TAlloc>& other) const | 472 | bool operator!=(const string<T,TAlloc>& other) const |
473 | { | 473 | { |
474 | return !(*this == other); | 474 | return !(*this == other); |
475 | } | 475 | } |
476 | 476 | ||
477 | 477 | ||
478 | //! Returns length of the string's content | 478 | //! Returns length of the string's content |
479 | /** \return Length of the string's content in characters, excluding | 479 | /** \return Length of the string's content in characters, excluding |
480 | the trailing NUL. */ | 480 | the trailing NUL. */ |
481 | u32 size() const | 481 | u32 size() const |
482 | { | 482 | { |
483 | return used-1; | 483 | return used-1; |
484 | } | 484 | } |
485 | 485 | ||
486 | //! Informs if the string is empty or not. | 486 | //! Informs if the string is empty or not. |
487 | //! \return True if the string is empty, false if not. | 487 | //! \return True if the string is empty, false if not. |
488 | bool empty() const | 488 | bool empty() const |
489 | { | 489 | { |
490 | return (size() == 0); | 490 | return (size() == 0); |
491 | } | 491 | } |
492 | 492 | ||
493 | //! Returns character string | 493 | //! Returns character string |
494 | /** \return pointer to C-style NUL terminated string. */ | 494 | /** \return pointer to C-style NUL terminated string. */ |
495 | const T* c_str() const | 495 | const T* c_str() const |
496 | { | 496 | { |
497 | return array; | 497 | return array; |
498 | } | 498 | } |
499 | 499 | ||
500 | 500 | ||
501 | //! Makes the string lower case. | 501 | //! Makes the string lower case. |
502 | string<T,TAlloc>& make_lower() | 502 | string<T,TAlloc>& make_lower() |
503 | { | 503 | { |
504 | for (u32 i=0; array[i]; ++i) | 504 | for (u32 i=0; array[i]; ++i) |
505 | array[i] = locale_lower ( array[i] ); | 505 | array[i] = locale_lower ( array[i] ); |
506 | return *this; | 506 | return *this; |
507 | } | 507 | } |
508 | 508 | ||
509 | 509 | ||
510 | //! Makes the string upper case. | 510 | //! Makes the string upper case. |
511 | string<T,TAlloc>& make_upper() | 511 | string<T,TAlloc>& make_upper() |
512 | { | 512 | { |
513 | for (u32 i=0; array[i]; ++i) | 513 | for (u32 i=0; array[i]; ++i) |
514 | array[i] = locale_upper ( array[i] ); | 514 | array[i] = locale_upper ( array[i] ); |
515 | return *this; | 515 | return *this; |
516 | } | 516 | } |
517 | 517 | ||
518 | 518 | ||
519 | //! Compares the strings ignoring case. | 519 | //! Compares the strings ignoring case. |
520 | /** \param other: Other string to compare. | 520 | /** \param other: Other string to compare. |
521 | \return True if the strings are equal ignoring case. */ | 521 | \return True if the strings are equal ignoring case. */ |
522 | bool equals_ignore_case(const string<T,TAlloc>& other) const | 522 | bool equals_ignore_case(const string<T,TAlloc>& other) const |
523 | { | 523 | { |
524 | for(u32 i=0; array[i] && other[i]; ++i) | 524 | for(u32 i=0; array[i] && other[i]; ++i) |
525 | if (locale_lower( array[i]) != locale_lower(other[i])) | 525 | if (locale_lower( array[i]) != locale_lower(other[i])) |
526 | return false; | 526 | return false; |
527 | 527 | ||
528 | return used == other.used; | 528 | return used == other.used; |
529 | } | 529 | } |
530 | 530 | ||
531 | //! Compares the strings ignoring case. | 531 | //! Compares the strings ignoring case. |
532 | /** \param other: Other string to compare. | 532 | /** \param other: Other string to compare. |
533 | \param sourcePos: where to start to compare in the string | 533 | \param sourcePos: where to start to compare in the string |
534 | \return True if the strings are equal ignoring case. */ | 534 | \return True if the strings are equal ignoring case. */ |
535 | bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const | 535 | bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const |
536 | { | 536 | { |
537 | if ( (u32) sourcePos >= used ) | 537 | if ( (u32) sourcePos >= used ) |
538 | return false; | 538 | return false; |
539 | 539 | ||
540 | u32 i; | 540 | u32 i; |
541 | for( i=0; array[sourcePos + i] && other[i]; ++i) | 541 | for( i=0; array[sourcePos + i] && other[i]; ++i) |
542 | if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) | 542 | if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) |
543 | return false; | 543 | return false; |
544 | 544 | ||
545 | return array[sourcePos + i] == 0 && other[i] == 0; | 545 | return array[sourcePos + i] == 0 && other[i] == 0; |
546 | } | 546 | } |
547 | 547 | ||
548 | 548 | ||
549 | //! Compares the strings ignoring case. | 549 | //! Compares the strings ignoring case. |
550 | /** \param other: Other string to compare. | 550 | /** \param other: Other string to compare. |
551 | \return True if this string is smaller ignoring case. */ | 551 | \return True if this string is smaller ignoring case. */ |
552 | bool lower_ignore_case(const string<T,TAlloc>& other) const | 552 | bool lower_ignore_case(const string<T,TAlloc>& other) const |
553 | { | 553 | { |
554 | for(u32 i=0; array[i] && other.array[i]; ++i) | 554 | for(u32 i=0; array[i] && other.array[i]; ++i) |
555 | { | 555 | { |
556 | s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); | 556 | s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); |
557 | if ( diff ) | 557 | if ( diff ) |
558 | return diff < 0; | 558 | return diff < 0; |
559 | } | 559 | } |
560 | 560 | ||
561 | return used < other.used; | 561 | return used < other.used; |
562 | } | 562 | } |
563 | 563 | ||
564 | 564 | ||
565 | //! compares the first n characters of the strings | 565 | //! compares the first n characters of the strings |
566 | /** \param other Other string to compare. | 566 | /** \param other Other string to compare. |
567 | \param n Number of characters to compare | 567 | \param n Number of characters to compare |
568 | \return True if the n first characters of both strings are equal. */ | 568 | \return True if the n first characters of both strings are equal. */ |
569 | bool equalsn(const string<T,TAlloc>& other, u32 n) const | 569 | bool equalsn(const string<T,TAlloc>& other, u32 n) const |
570 | { | 570 | { |
571 | u32 i; | 571 | u32 i; |
572 | for(i=0; array[i] && other[i] && i < n; ++i) | 572 | for(i=0; array[i] && other[i] && i < n; ++i) |
573 | if (array[i] != other[i]) | 573 | if (array[i] != other[i]) |
574 | return false; | 574 | return false; |
575 | 575 | ||
576 | // if one (or both) of the strings was smaller then they | 576 | // if one (or both) of the strings was smaller then they |
577 | // are only equal if they have the same length | 577 | // are only equal if they have the same length |
578 | return (i == n) || (used == other.used); | 578 | return (i == n) || (used == other.used); |
579 | } | 579 | } |
580 | 580 | ||
581 | 581 | ||
582 | //! compares the first n characters of the strings | 582 | //! compares the first n characters of the strings |
583 | /** \param str Other string to compare. | 583 | /** \param str Other string to compare. |
584 | \param n Number of characters to compare | 584 | \param n Number of characters to compare |
585 | \return True if the n first characters of both strings are equal. */ | 585 | \return True if the n first characters of both strings are equal. */ |
586 | bool equalsn(const T* const str, u32 n) const | 586 | bool equalsn(const T* const str, u32 n) const |
587 | { | 587 | { |
588 | if (!str) | 588 | if (!str) |
589 | return false; | 589 | return false; |
590 | u32 i; | 590 | u32 i; |
591 | for(i=0; array[i] && str[i] && i < n; ++i) | 591 | for(i=0; array[i] && str[i] && i < n; ++i) |
592 | if (array[i] != str[i]) | 592 | if (array[i] != str[i]) |
593 | return false; | 593 | return false; |
594 | 594 | ||
595 | // if one (or both) of the strings was smaller then they | 595 | // if one (or both) of the strings was smaller then they |
596 | // are only equal if they have the same length | 596 | // are only equal if they have the same length |
597 | return (i == n) || (array[i] == 0 && str[i] == 0); | 597 | return (i == n) || (array[i] == 0 && str[i] == 0); |
598 | } | 598 | } |
599 | 599 | ||
600 | 600 | ||
601 | //! Appends a character to this string | 601 | //! Appends a character to this string |
602 | /** \param character: Character to append. */ | 602 | /** \param character: Character to append. */ |
603 | string<T,TAlloc>& append(T character) | 603 | string<T,TAlloc>& append(T character) |
604 | { | 604 | { |
605 | if (used + 1 > allocated) | 605 | if (used + 1 > allocated) |
606 | reallocate(used + 1); | 606 | reallocate(used + 1); |
607 | 607 | ||
608 | ++used; | 608 | ++used; |
609 | 609 | ||
610 | array[used-2] = character; | 610 | array[used-2] = character; |
611 | array[used-1] = 0; | 611 | array[used-1] = 0; |
612 | 612 | ||
613 | return *this; | 613 | return *this; |
614 | } | 614 | } |
615 | 615 | ||
616 | 616 | ||
617 | //! Appends a char string to this string | 617 | //! Appends a char string to this string |
618 | /** \param other: Char string to append. */ | 618 | /** \param other: Char string to append. */ |
619 | /** \param length: The length of the string to append. */ | 619 | /** \param length: The length of the string to append. */ |
620 | string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff) | 620 | string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff) |
621 | { | 621 | { |
622 | if (!other) | 622 | if (!other) |
623 | return *this; | 623 | return *this; |
624 | 624 | ||
625 | u32 len = 0; | 625 | u32 len = 0; |
626 | const T* p = other; | 626 | const T* p = other; |
627 | while(*p) | 627 | while(*p) |
628 | { | 628 | { |
629 | ++len; | 629 | ++len; |
630 | ++p; | 630 | ++p; |
631 | } | 631 | } |
632 | if (len > length) | 632 | if (len > length) |
633 | len = length; | 633 | len = length; |
634 | 634 | ||
635 | if (used + len > allocated) | 635 | if (used + len > allocated) |
636 | reallocate(used + len); | 636 | reallocate(used + len); |
637 | 637 | ||
638 | --used; | 638 | --used; |
639 | ++len; | 639 | ++len; |
640 | 640 | ||
641 | for (u32 l=0; l<len; ++l) | 641 | for (u32 l=0; l<len; ++l) |
642 | array[l+used] = *(other+l); | 642 | array[l+used] = *(other+l); |
643 | 643 | ||
644 | used += len; | 644 | used += len; |
645 | 645 | ||
646 | return *this; | 646 | return *this; |
647 | } | 647 | } |
648 | 648 | ||
649 | 649 | ||
650 | //! Appends a string to this string | 650 | //! Appends a string to this string |
651 | /** \param other: String to append. */ | 651 | /** \param other: String to append. */ |
652 | string<T,TAlloc>& append(const string<T,TAlloc>& other) | 652 | string<T,TAlloc>& append(const string<T,TAlloc>& other) |
653 | { | 653 | { |
654 | if (other.size() == 0) | 654 | if (other.size() == 0) |
655 | return *this; | 655 | return *this; |
656 | 656 | ||
657 | --used; | 657 | --used; |
658 | u32 len = other.size()+1; | 658 | u32 len = other.size()+1; |
659 | 659 | ||
660 | if (used + len > allocated) | 660 | if (used + len > allocated) |
661 | reallocate(used + len); | 661 | reallocate(used + len); |
662 | 662 | ||
663 | for (u32 l=0; l<len; ++l) | 663 | for (u32 l=0; l<len; ++l) |
664 | array[used+l] = other[l]; | 664 | array[used+l] = other[l]; |
665 | 665 | ||
666 | used += len; | 666 | used += len; |
667 | 667 | ||
668 | return *this; | 668 | return *this; |
669 | } | 669 | } |
670 | 670 | ||
671 | 671 | ||
672 | //! Appends a string of the length l to this string. | 672 | //! Appends a string of the length l to this string. |
673 | /** \param other: other String to append to this string. | 673 | /** \param other: other String to append to this string. |
674 | \param length: How much characters of the other string to add to this one. */ | 674 | \param length: How much characters of the other string to add to this one. */ |
675 | string<T,TAlloc>& append(const string<T,TAlloc>& other, u32 length) | 675 | string<T,TAlloc>& append(const string<T,TAlloc>& other, u32 length) |
676 | { | 676 | { |
677 | if (other.size() == 0) | 677 | if (other.size() == 0) |
678 | return *this; | 678 | return *this; |
679 | 679 | ||
680 | if (other.size() < length) | 680 | if (other.size() < length) |
681 | { | 681 | { |
682 | append(other); | 682 | append(other); |
683 | return *this; | 683 | return *this; |
684 | } | 684 | } |
685 | 685 | ||
686 | if (used + length > allocated) | 686 | if (used + length > allocated) |
687 | reallocate(used + length); | 687 | reallocate(used + length); |
688 | 688 | ||
689 | --used; | 689 | --used; |
690 | 690 | ||
691 | for (u32 l=0; l<length; ++l) | 691 | for (u32 l=0; l<length; ++l) |
692 | array[l+used] = other[l]; | 692 | array[l+used] = other[l]; |
693 | used += length; | 693 | used += length; |
694 | 694 | ||
695 | // ensure proper termination | 695 | // ensure proper termination |
696 | array[used]=0; | 696 | array[used]=0; |
697 | ++used; | 697 | ++used; |
698 | 698 | ||
699 | return *this; | 699 | return *this; |
700 | } | 700 | } |
701 | 701 | ||
702 | 702 | ||
703 | //! Reserves some memory. | 703 | //! Reserves some memory. |
704 | /** \param count: Amount of characters to reserve. */ | 704 | /** \param count: Amount of characters to reserve. */ |
705 | void reserve(u32 count) | 705 | void reserve(u32 count) |
706 | { | 706 | { |
707 | if (count < allocated) | 707 | if (count < allocated) |
708 | return; | 708 | return; |
709 | 709 | ||
710 | reallocate(count); | 710 | reallocate(count); |
711 | } | 711 | } |
712 | 712 | ||
713 | 713 | ||
714 | //! finds first occurrence of character in string | 714 | //! finds first occurrence of character in string |
715 | /** \param c: Character to search for. | 715 | /** \param c: Character to search for. |
716 | \return Position where the character has been found, | 716 | \return Position where the character has been found, |
717 | or -1 if not found. */ | 717 | or -1 if not found. */ |
718 | s32 findFirst(T c) const | 718 | s32 findFirst(T c) const |
719 | { | 719 | { |
720 | for (u32 i=0; i<used-1; ++i) | 720 | for (u32 i=0; i<used-1; ++i) |
721 | if (array[i] == c) | 721 | if (array[i] == c) |
722 | return i; | 722 | return i; |
723 | 723 | ||
724 | return -1; | 724 | return -1; |
725 | } | 725 | } |
726 | 726 | ||
727 | //! finds first occurrence of a character of a list in string | 727 | //! finds first occurrence of a character of a list in string |
728 | /** \param c: List of characters to find. For example if the method | 728 | /** \param c: List of characters to find. For example if the method |
729 | should find the first occurrence of 'a' or 'b', this parameter should be "ab". | 729 | should find the first occurrence of 'a' or 'b', this parameter should be "ab". |
730 | \param count: Amount of characters in the list. Usually, | 730 | \param count: Amount of characters in the list. Usually, |
731 | this should be strlen(c) | 731 | this should be strlen(c) |
732 | \return Position where one of the characters has been found, | 732 | \return Position where one of the characters has been found, |
733 | or -1 if not found. */ | 733 | or -1 if not found. */ |
734 | s32 findFirstChar(const T* const c, u32 count=1) const | 734 | s32 findFirstChar(const T* const c, u32 count=1) const |
735 | { | 735 | { |
736 | if (!c || !count) | 736 | if (!c || !count) |
737 | return -1; | 737 | return -1; |
738 | 738 | ||
739 | for (u32 i=0; i<used-1; ++i) | 739 | for (u32 i=0; i<used-1; ++i) |
740 | for (u32 j=0; j<count; ++j) | 740 | for (u32 j=0; j<count; ++j) |
741 | if (array[i] == c[j]) | 741 | if (array[i] == c[j]) |
742 | return i; | 742 | return i; |
743 | 743 | ||
744 | return -1; | 744 | return -1; |
745 | } | 745 | } |
746 | 746 | ||
747 | 747 | ||
748 | //! Finds first position of a character not in a given list. | 748 | //! Finds first position of a character not in a given list. |
749 | /** \param c: List of characters not to find. For example if the method | 749 | /** \param c: List of characters not to find. For example if the method |
750 | should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". | 750 | should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". |
751 | \param count: Amount of characters in the list. Usually, | 751 | \param count: Amount of characters in the list. Usually, |
752 | this should be strlen(c) | 752 | this should be strlen(c) |
753 | \return Position where the character has been found, | 753 | \return Position where the character has been found, |
754 | or -1 if not found. */ | 754 | or -1 if not found. */ |
755 | template <class B> | 755 | template <class B> |
756 | s32 findFirstCharNotInList(const B* const c, u32 count=1) const | 756 | s32 findFirstCharNotInList(const B* const c, u32 count=1) const |
757 | { | 757 | { |
758 | if (!c || !count) | 758 | if (!c || !count) |
759 | return -1; | 759 | return -1; |
760 | 760 | ||
761 | for (u32 i=0; i<used-1; ++i) | 761 | for (u32 i=0; i<used-1; ++i) |
762 | { | 762 | { |
763 | u32 j; | 763 | u32 j; |
764 | for (j=0; j<count; ++j) | 764 | for (j=0; j<count; ++j) |
765 | if (array[i] == c[j]) | 765 | if (array[i] == c[j]) |
766 | break; | 766 | break; |
767 | 767 | ||
768 | if (j==count) | 768 | if (j==count) |
769 | return i; | 769 | return i; |
770 | } | 770 | } |
771 | 771 | ||
772 | return -1; | 772 | return -1; |
773 | } | 773 | } |
774 | 774 | ||
775 | //! Finds last position of a character not in a given list. | 775 | //! Finds last position of a character not in a given list. |
776 | /** \param c: List of characters not to find. For example if the method | 776 | /** \param c: List of characters not to find. For example if the method |
777 | should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". | 777 | should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". |
778 | \param count: Amount of characters in the list. Usually, | 778 | \param count: Amount of characters in the list. Usually, |
779 | this should be strlen(c) | 779 | this should be strlen(c) |
780 | \return Position where the character has been found, | 780 | \return Position where the character has been found, |
781 | or -1 if not found. */ | 781 | or -1 if not found. */ |
782 | template <class B> | 782 | template <class B> |
783 | s32 findLastCharNotInList(const B* const c, u32 count=1) const | 783 | s32 findLastCharNotInList(const B* const c, u32 count=1) const |
784 | { | 784 | { |
785 | if (!c || !count) | 785 | if (!c || !count) |
786 | return -1; | 786 | return -1; |
787 | 787 | ||
788 | for (s32 i=(s32)(used-2); i>=0; --i) | 788 | for (s32 i=(s32)(used-2); i>=0; --i) |
789 | { | 789 | { |
790 | u32 j; | 790 | u32 j; |
791 | for (j=0; j<count; ++j) | 791 | for (j=0; j<count; ++j) |
792 | if (array[i] == c[j]) | 792 | if (array[i] == c[j]) |
793 | break; | 793 | break; |
794 | 794 | ||
795 | if (j==count) | 795 | if (j==count) |
796 | return i; | 796 | return i; |
797 | } | 797 | } |
798 | 798 | ||
799 | return -1; | 799 | return -1; |
800 | } | 800 | } |
801 | 801 | ||
802 | //! finds next occurrence of character in string | 802 | //! finds next occurrence of character in string |
803 | /** \param c: Character to search for. | 803 | /** \param c: Character to search for. |
804 | \param startPos: Position in string to start searching. | 804 | \param startPos: Position in string to start searching. |
805 | \return Position where the character has been found, | 805 | \return Position where the character has been found, |
806 | or -1 if not found. */ | 806 | or -1 if not found. */ |
807 | s32 findNext(T c, u32 startPos) const | 807 | s32 findNext(T c, u32 startPos) const |
808 | { | 808 | { |
809 | for (u32 i=startPos; i<used-1; ++i) | 809 | for (u32 i=startPos; i<used-1; ++i) |
810 | if (array[i] == c) | 810 | if (array[i] == c) |
811 | return i; | 811 | return i; |
812 | 812 | ||
813 | return -1; | 813 | return -1; |
814 | } | 814 | } |
815 | 815 | ||
816 | 816 | ||
817 | //! finds last occurrence of character in string | 817 | //! finds last occurrence of character in string |
818 | /** \param c: Character to search for. | 818 | /** \param c: Character to search for. |
819 | \param start: start to search reverse ( default = -1, on end ) | 819 | \param start: start to search reverse ( default = -1, on end ) |
820 | \return Position where the character has been found, | 820 | \return Position where the character has been found, |
821 | or -1 if not found. */ | 821 | or -1 if not found. */ |
822 | s32 findLast(T c, s32 start = -1) const | 822 | s32 findLast(T c, s32 start = -1) const |
823 | { | 823 | { |
824 | start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 ); | 824 | start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 ); |
825 | for (s32 i=start; i>=0; --i) | 825 | for (s32 i=start; i>=0; --i) |
826 | if (array[i] == c) | 826 | if (array[i] == c) |
827 | return i; | 827 | return i; |
828 | 828 | ||
829 | return -1; | 829 | return -1; |
830 | } | 830 | } |
831 | 831 | ||
832 | //! finds last occurrence of a character of a list in string | 832 | //! finds last occurrence of a character of a list in string |
833 | /** \param c: List of strings to find. For example if the method | 833 | /** \param c: List of strings to find. For example if the method |
834 | should find the last occurrence of 'a' or 'b', this parameter should be "ab". | 834 | should find the last occurrence of 'a' or 'b', this parameter should be "ab". |
835 | \param count: Amount of characters in the list. Usually, | 835 | \param count: Amount of characters in the list. Usually, |
836 | this should be strlen(c) | 836 | this should be strlen(c) |
837 | \return Position where one of the characters has been found, | 837 | \return Position where one of the characters has been found, |
838 | or -1 if not found. */ | 838 | or -1 if not found. */ |
839 | s32 findLastChar(const T* const c, u32 count=1) const | 839 | s32 findLastChar(const T* const c, u32 count=1) const |
840 | { | 840 | { |
841 | if (!c || !count) | 841 | if (!c || !count) |
842 | return -1; | 842 | return -1; |
843 | 843 | ||
844 | for (s32 i=(s32)used-2; i>=0; --i) | 844 | for (s32 i=(s32)used-2; i>=0; --i) |
845 | for (u32 j=0; j<count; ++j) | 845 | for (u32 j=0; j<count; ++j) |
846 | if (array[i] == c[j]) | 846 | if (array[i] == c[j]) |
847 | return i; | 847 | return i; |
848 | 848 | ||
849 | return -1; | 849 | return -1; |
850 | } | 850 | } |
851 | 851 | ||
852 | 852 | ||
853 | //! finds another string in this string | 853 | //! finds another string in this string |
854 | /** \param str: Another string | 854 | /** \param str: Another string |
855 | \param start: Start position of the search | 855 | \param start: Start position of the search |
856 | \return Positions where the string has been found, | 856 | \return Positions where the string has been found, |
857 | or -1 if not found. */ | 857 | or -1 if not found. */ |
858 | template <class B> | 858 | template <class B> |
859 | s32 find(const B* const str, const u32 start = 0) const | 859 | s32 find(const B* const str, const u32 start = 0) const |
860 | { | 860 | { |
861 | if (str && *str) | 861 | if (str && *str) |
862 | { | 862 | { |
863 | u32 len = 0; | 863 | u32 len = 0; |
864 | 864 | ||
865 | while (str[len]) | 865 | while (str[len]) |
866 | ++len; | 866 | ++len; |
867 | 867 | ||
868 | if (len > used-1) | 868 | if (len > used-1) |
869 | return -1; | 869 | return -1; |
870 | 870 | ||
871 | for (u32 i=start; i<used-len; ++i) | 871 | for (u32 i=start; i<used-len; ++i) |
872 | { | 872 | { |
873 | u32 j=0; | 873 | u32 j=0; |
874 | 874 | ||
875 | while(str[j] && array[i+j] == str[j]) | 875 | while(str[j] && array[i+j] == str[j]) |
876 | ++j; | 876 | ++j; |
877 | 877 | ||
878 | if (!str[j]) | 878 | if (!str[j]) |
879 | return i; | 879 | return i; |
880 | } | 880 | } |
881 | } | 881 | } |
882 | 882 | ||
883 | return -1; | 883 | return -1; |
884 | } | 884 | } |
885 | 885 | ||
886 | 886 | ||
887 | //! Returns a substring | 887 | //! Returns a substring |
888 | /** \param begin Start of substring. | 888 | /** \param begin Start of substring. |
889 | \param length Length of substring. | 889 | \param length Length of substring. |
890 | \param make_lower copy only lower case */ | 890 | \param make_lower copy only lower case */ |
891 | string<T> subString(u32 begin, s32 length, bool make_lower = false ) const | 891 | string<T> subString(u32 begin, s32 length, bool make_lower = false ) const |
892 | { | 892 | { |
893 | // if start after string | 893 | // if start after string |
894 | // or no proper substring length | 894 | // or no proper substring length |
895 | if ((length <= 0) || (begin>=size())) | 895 | if ((length <= 0) || (begin>=size())) |
896 | return string<T>(""); | 896 | return string<T>(""); |
897 | // clamp length to maximal value | 897 | // clamp length to maximal value |
898 | if ((length+begin) > size()) | 898 | if ((length+begin) > size()) |
899 | length = size()-begin; | 899 | length = size()-begin; |
900 | 900 | ||
901 | string<T> o; | 901 | string<T> o; |
902 | o.reserve(length+1); | 902 | o.reserve(length+1); |
903 | 903 | ||
904 | s32 i; | 904 | s32 i; |
905 | if ( !make_lower ) | 905 | if ( !make_lower ) |
906 | { | 906 | { |
907 | for (i=0; i<length; ++i) | 907 | for (i=0; i<length; ++i) |
908 | o.array[i] = array[i+begin]; | 908 | o.array[i] = array[i+begin]; |
909 | } | 909 | } |
910 | else | 910 | else |
911 | { | 911 | { |
912 | for (i=0; i<length; ++i) | 912 | for (i=0; i<length; ++i) |
913 | o.array[i] = locale_lower ( array[i+begin] ); | 913 | o.array[i] = locale_lower ( array[i+begin] ); |
914 | } | 914 | } |
915 | 915 | ||
916 | o.array[length] = 0; | 916 | o.array[length] = 0; |
917 | o.used = length + 1; | 917 | o.used = length + 1; |
918 | 918 | ||
919 | return o; | 919 | return o; |
920 | } | 920 | } |
921 | 921 | ||
922 | 922 | ||
923 | //! Appends a character to this string | 923 | //! Appends a character to this string |
924 | /** \param c Character to append. */ | 924 | /** \param c Character to append. */ |
925 | string<T,TAlloc>& operator += (T c) | 925 | string<T,TAlloc>& operator += (T c) |
926 | { | 926 | { |
927 | append(c); | 927 | append(c); |
928 | return *this; | 928 | return *this; |
929 | } | 929 | } |
930 | 930 | ||
931 | 931 | ||
932 | //! Appends a char string to this string | 932 | //! Appends a char string to this string |
933 | /** \param c Char string to append. */ | 933 | /** \param c Char string to append. */ |
934 | string<T,TAlloc>& operator += (const T* const c) | 934 | string<T,TAlloc>& operator += (const T* const c) |
935 | { | 935 | { |
936 | append(c); | 936 | append(c); |
937 | return *this; | 937 | return *this; |
938 | } | 938 | } |
939 | 939 | ||
940 | 940 | ||
941 | //! Appends a string to this string | 941 | //! Appends a string to this string |
942 | /** \param other String to append. */ | 942 | /** \param other String to append. */ |
943 | string<T,TAlloc>& operator += (const string<T,TAlloc>& other) | 943 | string<T,TAlloc>& operator += (const string<T,TAlloc>& other) |
944 | { | 944 | { |
945 | append(other); | 945 | append(other); |
946 | return *this; | 946 | return *this; |
947 | } | 947 | } |
948 | 948 | ||
949 | 949 | ||
950 | //! Appends a string representation of a number to this string | 950 | //! Appends a string representation of a number to this string |
951 | /** \param i Number to append. */ | 951 | /** \param i Number to append. */ |
952 | string<T,TAlloc>& operator += (const int i) | 952 | string<T,TAlloc>& operator += (const int i) |
953 | { | 953 | { |
954 | append(string<T,TAlloc>(i)); | 954 | append(string<T,TAlloc>(i)); |
955 | return *this; | 955 | return *this; |
956 | } | 956 | } |
957 | 957 | ||
958 | 958 | ||
959 | //! Appends a string representation of a number to this string | 959 | //! Appends a string representation of a number to this string |
960 | /** \param i Number to append. */ | 960 | /** \param i Number to append. */ |
961 | string<T,TAlloc>& operator += (const unsigned int i) | 961 | string<T,TAlloc>& operator += (const unsigned int i) |
962 | { | 962 | { |
963 | append(string<T,TAlloc>(i)); | 963 | append(string<T,TAlloc>(i)); |
964 | return *this; | 964 | return *this; |
965 | } | 965 | } |
966 | 966 | ||
967 | 967 | ||
968 | //! Appends a string representation of a number to this string | 968 | //! Appends a string representation of a number to this string |
969 | /** \param i Number to append. */ | 969 | /** \param i Number to append. */ |
970 | string<T,TAlloc>& operator += (const long i) | 970 | string<T,TAlloc>& operator += (const long i) |
971 | { | 971 | { |
972 | append(string<T,TAlloc>(i)); | 972 | append(string<T,TAlloc>(i)); |
973 | return *this; | 973 | return *this; |
974 | } | 974 | } |
975 | 975 | ||
976 | 976 | ||
977 | //! Appends a string representation of a number to this string | 977 | //! Appends a string representation of a number to this string |
978 | /** \param i Number to append. */ | 978 | /** \param i Number to append. */ |
979 | string<T,TAlloc>& operator += (const unsigned long i) | 979 | string<T,TAlloc>& operator += (const unsigned long i) |
980 | { | 980 | { |
981 | append(string<T,TAlloc>(i)); | 981 | append(string<T,TAlloc>(i)); |
982 | return *this; | 982 | return *this; |
983 | } | 983 | } |
984 | 984 | ||
985 | 985 | ||
986 | //! Appends a string representation of a number to this string | 986 | //! Appends a string representation of a number to this string |
987 | /** \param i Number to append. */ | 987 | /** \param i Number to append. */ |
988 | string<T,TAlloc>& operator += (const double i) | 988 | string<T,TAlloc>& operator += (const double i) |
989 | { | 989 | { |
990 | append(string<T,TAlloc>(i)); | 990 | append(string<T,TAlloc>(i)); |
991 | return *this; | 991 | return *this; |
992 | } | 992 | } |
993 | 993 | ||
994 | 994 | ||
995 | //! Appends a string representation of a number to this string | 995 | //! Appends a string representation of a number to this string |
996 | /** \param i Number to append. */ | 996 | /** \param i Number to append. */ |
997 | string<T,TAlloc>& operator += (const float i) | 997 | string<T,TAlloc>& operator += (const float i) |
998 | { | 998 | { |
999 | append(string<T,TAlloc>(i)); | 999 | append(string<T,TAlloc>(i)); |
1000 | return *this; | 1000 | return *this; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | 1003 | ||
1004 | //! Replaces all characters of a special type with another one | 1004 | //! Replaces all characters of a special type with another one |
1005 | /** \param toReplace Character to replace. | 1005 | /** \param toReplace Character to replace. |
1006 | \param replaceWith Character replacing the old one. */ | 1006 | \param replaceWith Character replacing the old one. */ |
1007 | string<T,TAlloc>& replace(T toReplace, T replaceWith) | 1007 | string<T,TAlloc>& replace(T toReplace, T replaceWith) |
1008 | { | 1008 | { |
1009 | for (u32 i=0; i<used-1; ++i) | 1009 | for (u32 i=0; i<used-1; ++i) |
1010 | if (array[i] == toReplace) | 1010 | if (array[i] == toReplace) |
1011 | array[i] = replaceWith; | 1011 | array[i] = replaceWith; |
1012 | return *this; | 1012 | return *this; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | 1015 | ||
1016 | //! Replaces all instances of a string with another one. | 1016 | //! Replaces all instances of a string with another one. |
1017 | /** \param toReplace The string to replace. | 1017 | /** \param toReplace The string to replace. |
1018 | \param replaceWith The string replacing the old one. */ | 1018 | \param replaceWith The string replacing the old one. */ |
1019 | string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith) | 1019 | string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith) |
1020 | { | 1020 | { |
1021 | if (toReplace.size() == 0) | 1021 | if (toReplace.size() == 0) |
1022 | return *this; | 1022 | return *this; |
1023 | 1023 | ||
1024 | const T* other = toReplace.c_str(); | 1024 | const T* other = toReplace.c_str(); |
1025 | const T* replace = replaceWith.c_str(); | 1025 | const T* replace = replaceWith.c_str(); |
1026 | const u32 other_size = toReplace.size(); | 1026 | const u32 other_size = toReplace.size(); |
1027 | const u32 replace_size = replaceWith.size(); | 1027 | const u32 replace_size = replaceWith.size(); |
1028 | 1028 | ||
1029 | // Determine the delta. The algorithm will change depending on the delta. | 1029 | // Determine the delta. The algorithm will change depending on the delta. |
1030 | s32 delta = replace_size - other_size; | 1030 | s32 delta = replace_size - other_size; |
1031 | 1031 | ||
1032 | // A character for character replace. The string will not shrink or grow. | 1032 | // A character for character replace. The string will not shrink or grow. |
1033 | if (delta == 0) | 1033 | if (delta == 0) |
1034 | { | 1034 | { |
1035 | s32 pos = 0; | 1035 | s32 pos = 0; |
1036 | while ((pos = find(other, pos)) != -1) | 1036 | while ((pos = find(other, pos)) != -1) |
1037 | { | 1037 | { |
1038 | for (u32 i = 0; i < replace_size; ++i) | 1038 | for (u32 i = 0; i < replace_size; ++i) |
1039 | array[pos + i] = replace[i]; | 1039 | array[pos + i] = replace[i]; |
1040 | ++pos; | 1040 | ++pos; |
1041 | } | 1041 | } |
1042 | return *this; | 1042 | return *this; |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | // We are going to be removing some characters. The string will shrink. | 1045 | // We are going to be removing some characters. The string will shrink. |
1046 | if (delta < 0) | 1046 | if (delta < 0) |
1047 | { | 1047 | { |
1048 | u32 i = 0; | 1048 | u32 i = 0; |
1049 | for (u32 pos = 0; pos < used; ++i, ++pos) | 1049 | for (u32 pos = 0; pos < used; ++i, ++pos) |
1050 | { | 1050 | { |
1051 | // Is this potentially a match? | 1051 | // Is this potentially a match? |
1052 | if (array[pos] == *other) | 1052 | if (array[pos] == *other) |
1053 | { | 1053 | { |
1054 | // Check to see if we have a match. | 1054 | // Check to see if we have a match. |
1055 | u32 j; | 1055 | u32 j; |
1056 | for (j = 0; j < other_size; ++j) | 1056 | for (j = 0; j < other_size; ++j) |
1057 | { | 1057 | { |
1058 | if (array[pos + j] != other[j]) | 1058 | if (array[pos + j] != other[j]) |
1059 | break; | 1059 | break; |
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | // If we have a match, replace characters. | 1062 | // If we have a match, replace characters. |
1063 | if (j == other_size) | 1063 | if (j == other_size) |
1064 | { | 1064 | { |
1065 | for (j = 0; j < replace_size; ++j) | 1065 | for (j = 0; j < replace_size; ++j) |
1066 | array[i + j] = replace[j]; | 1066 | array[i + j] = replace[j]; |
1067 | i += replace_size - 1; | 1067 | i += replace_size - 1; |
1068 | pos += other_size - 1; | 1068 | pos += other_size - 1; |
1069 | continue; | 1069 | continue; |
1070 | } | 1070 | } |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | // No match found, just copy characters. | 1073 | // No match found, just copy characters. |
1074 | array[i] = array[pos]; | 1074 | array[i] = array[pos]; |
1075 | } | 1075 | } |
1076 | array[i-1] = 0; | 1076 | array[i-1] = 0; |
1077 | used = i; | 1077 | used = i; |
1078 | 1078 | ||
1079 | return *this; | 1079 | return *this; |
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | // We are going to be adding characters, so the string size will increase. | 1082 | // We are going to be adding characters, so the string size will increase. |
1083 | // Count the number of times toReplace exists in the string so we can allocate the new size. | 1083 | // Count the number of times toReplace exists in the string so we can allocate the new size. |
1084 | u32 find_count = 0; | 1084 | u32 find_count = 0; |
1085 | s32 pos = 0; | 1085 | s32 pos = 0; |
1086 | while ((pos = find(other, pos)) != -1) | 1086 | while ((pos = find(other, pos)) != -1) |
1087 | { | 1087 | { |
1088 | ++find_count; | 1088 | ++find_count; |
1089 | ++pos; | 1089 | ++pos; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | // Re-allocate the string now, if needed. | 1092 | // Re-allocate the string now, if needed. |
1093 | u32 len = delta * find_count; | 1093 | u32 len = delta * find_count; |
1094 | if (used + len > allocated) | 1094 | if (used + len > allocated) |
1095 | reallocate(used + len); | 1095 | reallocate(used + len); |
1096 | 1096 | ||
1097 | // Start replacing. | 1097 | // Start replacing. |
1098 | pos = 0; | 1098 | pos = 0; |
1099 | while ((pos = find(other, pos)) != -1) | 1099 | while ((pos = find(other, pos)) != -1) |
1100 | { | 1100 | { |
1101 | T* start = array + pos + other_size - 1; | 1101 | T* start = array + pos + other_size - 1; |
1102 | T* ptr = array + used - 1; | 1102 | T* ptr = array + used - 1; |
1103 | T* end = array + delta + used -1; | 1103 | T* end = array + delta + used -1; |
1104 | 1104 | ||
1105 | // Shift characters to make room for the string. | 1105 | // Shift characters to make room for the string. |
1106 | while (ptr != start) | 1106 | while (ptr != start) |
1107 | { | 1107 | { |
1108 | *end = *ptr; | 1108 | *end = *ptr; |
1109 | --ptr; | 1109 | --ptr; |
1110 | --end; | 1110 | --end; |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | // Add the new string now. | 1113 | // Add the new string now. |
1114 | for (u32 i = 0; i < replace_size; ++i) | 1114 | for (u32 i = 0; i < replace_size; ++i) |
1115 | array[pos + i] = replace[i]; | 1115 | array[pos + i] = replace[i]; |
1116 | 1116 | ||
1117 | pos += replace_size; | 1117 | pos += replace_size; |
1118 | used += delta; | 1118 | used += delta; |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | return *this; | 1121 | return *this; |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | 1124 | ||
1125 | //! Removes characters from a string. | 1125 | //! Removes characters from a string. |
1126 | /** \param c: Character to remove. */ | 1126 | /** \param c: Character to remove. */ |
1127 | string<T,TAlloc>& remove(T c) | 1127 | string<T,TAlloc>& remove(T c) |
1128 | { | 1128 | { |
1129 | u32 pos = 0; | 1129 | u32 pos = 0; |
1130 | u32 found = 0; | 1130 | u32 found = 0; |
1131 | for (u32 i=0; i<used-1; ++i) | 1131 | for (u32 i=0; i<used-1; ++i) |
1132 | { | 1132 | { |
1133 | if (array[i] == c) | 1133 | if (array[i] == c) |
1134 | { | 1134 | { |
1135 | ++found; | 1135 | ++found; |
1136 | continue; | 1136 | continue; |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | array[pos++] = array[i]; | 1139 | array[pos++] = array[i]; |
1140 | } | 1140 | } |
1141 | used -= found; | 1141 | used -= found; |
1142 | array[used-1] = 0; | 1142 | array[used-1] = 0; |
1143 | return *this; | 1143 | return *this; |
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | 1146 | ||
1147 | //! Removes a string from the string. | 1147 | //! Removes a string from the string. |
1148 | /** \param toRemove: String to remove. */ | 1148 | /** \param toRemove: String to remove. */ |
1149 | string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove) | 1149 | string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove) |
1150 | { | 1150 | { |
1151 | u32 size = toRemove.size(); | 1151 | u32 size = toRemove.size(); |
1152 | if ( size == 0 ) | 1152 | if ( size == 0 ) |
1153 | return *this; | 1153 | return *this; |
1154 | u32 pos = 0; | 1154 | u32 pos = 0; |
1155 | u32 found = 0; | 1155 | u32 found = 0; |
1156 | for (u32 i=0; i<used-1; ++i) | 1156 | for (u32 i=0; i<used-1; ++i) |
1157 | { | 1157 | { |
1158 | u32 j = 0; | 1158 | u32 j = 0; |
1159 | while (j < size) | 1159 | while (j < size) |
1160 | { | 1160 | { |
1161 | if (array[i + j] != toRemove[j]) | 1161 | if (array[i + j] != toRemove[j]) |
1162 | break; | 1162 | break; |
1163 | ++j; | 1163 | ++j; |
1164 | } | 1164 | } |
1165 | if (j == size) | 1165 | if (j == size) |
1166 | { | 1166 | { |
1167 | found += size; | 1167 | found += size; |
1168 | i += size - 1; | 1168 | i += size - 1; |
1169 | continue; | 1169 | continue; |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | array[pos++] = array[i]; | 1172 | array[pos++] = array[i]; |
1173 | } | 1173 | } |
1174 | used -= found; | 1174 | used -= found; |
1175 | array[used-1] = 0; | 1175 | array[used-1] = 0; |
1176 | return *this; | 1176 | return *this; |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | 1179 | ||
1180 | //! Removes characters from a string. | 1180 | //! Removes characters from a string. |
1181 | /** \param characters: Characters to remove. */ | 1181 | /** \param characters: Characters to remove. */ |
1182 | string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters) | 1182 | string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters) |
1183 | { | 1183 | { |
1184 | if (characters.size() == 0) | 1184 | if (characters.size() == 0) |
1185 | return *this; | 1185 | return *this; |
1186 | 1186 | ||
1187 | u32 pos = 0; | 1187 | u32 pos = 0; |
1188 | u32 found = 0; | 1188 | u32 found = 0; |
1189 | for (u32 i=0; i<used-1; ++i) | 1189 | for (u32 i=0; i<used-1; ++i) |
1190 | { | 1190 | { |
1191 | // Don't use characters.findFirst as it finds the \0, | 1191 | // Don't use characters.findFirst as it finds the \0, |
1192 | // causing used to become incorrect. | 1192 | // causing used to become incorrect. |
1193 | bool docontinue = false; | 1193 | bool docontinue = false; |
1194 | for (u32 j=0; j<characters.size(); ++j) | 1194 | for (u32 j=0; j<characters.size(); ++j) |
1195 | { | 1195 | { |
1196 | if (characters[j] == array[i]) | 1196 | if (characters[j] == array[i]) |
1197 | { | 1197 | { |
1198 | ++found; | 1198 | ++found; |
1199 | docontinue = true; | 1199 | docontinue = true; |
1200 | break; | 1200 | break; |
1201 | } | 1201 | } |
1202 | } | 1202 | } |
1203 | if (docontinue) | 1203 | if (docontinue) |
1204 | continue; | 1204 | continue; |
1205 | 1205 | ||
1206 | array[pos++] = array[i]; | 1206 | array[pos++] = array[i]; |
1207 | } | 1207 | } |
1208 | used -= found; | 1208 | used -= found; |
1209 | array[used-1] = 0; | 1209 | array[used-1] = 0; |
1210 | 1210 | ||
1211 | return *this; | 1211 | return *this; |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | 1214 | ||
1215 | //! Trims the string. | 1215 | //! Trims the string. |
1216 | /** Removes the specified characters (by default, Latin-1 whitespace) | 1216 | /** Removes the specified characters (by default, Latin-1 whitespace) |
1217 | from the begining and the end of the string. */ | 1217 | from the begining and the end of the string. */ |
1218 | string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r") | 1218 | string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r") |
1219 | { | 1219 | { |
1220 | // find start and end of the substring without the specified characters | 1220 | // find start and end of the substring without the specified characters |
1221 | const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); | 1221 | const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); |
1222 | if (begin == -1) | 1222 | if (begin == -1) |
1223 | return (*this=""); | 1223 | return (*this=""); |
1224 | 1224 | ||
1225 | const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); | 1225 | const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); |
1226 | 1226 | ||
1227 | return (*this = subString(begin, (end +1) - begin)); | 1227 | return (*this = subString(begin, (end +1) - begin)); |
1228 | } | 1228 | } |
1229 | 1229 | ||
1230 | 1230 | ||
1231 | //! Erases a character from the string. | 1231 | //! Erases a character from the string. |
1232 | /** May be slow, because all elements | 1232 | /** May be slow, because all elements |
1233 | following after the erased element have to be copied. | 1233 | following after the erased element have to be copied. |
1234 | \param index: Index of element to be erased. */ | 1234 | \param index: Index of element to be erased. */ |
1235 | string<T,TAlloc>& erase(u32 index) | 1235 | string<T,TAlloc>& erase(u32 index) |
1236 | { | 1236 | { |
1237 | _IRR_DEBUG_BREAK_IF(index>=used) // access violation | 1237 | _IRR_DEBUG_BREAK_IF(index>=used) // access violation |
1238 | 1238 | ||
1239 | for (u32 i=index+1; i<used; ++i) | 1239 | for (u32 i=index+1; i<used; ++i) |
1240 | array[i-1] = array[i]; | 1240 | array[i-1] = array[i]; |
1241 | 1241 | ||
1242 | --used; | 1242 | --used; |
1243 | return *this; | 1243 | return *this; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | //! verify the existing string. | 1246 | //! verify the existing string. |
1247 | string<T,TAlloc>& validate() | 1247 | string<T,TAlloc>& validate() |
1248 | { | 1248 | { |
1249 | // terminate on existing null | 1249 | // terminate on existing null |
1250 | for (u32 i=0; i<allocated; ++i) | 1250 | for (u32 i=0; i<allocated; ++i) |
1251 | { | 1251 | { |
1252 | if (array[i] == 0) | 1252 | if (array[i] == 0) |
1253 | { | 1253 | { |
1254 | used = i + 1; | 1254 | used = i + 1; |
1255 | return *this; | 1255 | return *this; |
1256 | } | 1256 | } |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | // terminate | 1259 | // terminate |
1260 | if ( allocated > 0 ) | 1260 | if ( allocated > 0 ) |
1261 | { | 1261 | { |
1262 | used = allocated; | 1262 | used = allocated; |
1263 | array[used-1] = 0; | 1263 | array[used-1] = 0; |
1264 | } | 1264 | } |
1265 | else | 1265 | else |
1266 | { | 1266 | { |
1267 | used = 0; | 1267 | used = 0; |
1268 | } | 1268 | } |
1269 | 1269 | ||
1270 | return *this; | 1270 | return *this; |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | //! gets the last char of a string or null | 1273 | //! gets the last char of a string or null |
1274 | T lastChar() const | 1274 | T lastChar() const |
1275 | { | 1275 | { |
1276 | return used > 1 ? array[used-2] : 0; | 1276 | return used > 1 ? array[used-2] : 0; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | //! split string into parts. | 1279 | //! split string into parts. |
1280 | /** This method will split a string at certain delimiter characters | 1280 | /** This method will split a string at certain delimiter characters |
1281 | into the container passed in as reference. The type of the container | 1281 | into the container passed in as reference. The type of the container |
1282 | has to be given as template parameter. It must provide a push_back and | 1282 | has to be given as template parameter. It must provide a push_back and |
1283 | a size method. | 1283 | a size method. |
1284 | \param ret The result container | 1284 | \param ret The result container |
1285 | \param c C-style string of delimiter characters | 1285 | \param c C-style string of delimiter characters |
1286 | \param count Number of delimiter characters | 1286 | \param count Number of delimiter characters |
1287 | \param ignoreEmptyTokens Flag to avoid empty substrings in the result | 1287 | \param ignoreEmptyTokens Flag to avoid empty substrings in the result |
1288 | container. If two delimiters occur without a character in between, an | 1288 | container. If two delimiters occur without a character in between, an |
1289 | empty substring would be placed in the result. If this flag is set, | 1289 | empty substring would be placed in the result. If this flag is set, |
1290 | only non-empty strings are stored. | 1290 | only non-empty strings are stored. |
1291 | \param keepSeparators Flag which allows to add the separator to the | 1291 | \param keepSeparators Flag which allows to add the separator to the |
1292 | result string. If this flag is true, the concatenation of the | 1292 | result string. If this flag is true, the concatenation of the |
1293 | substrings results in the original string. Otherwise, only the | 1293 | substrings results in the original string. Otherwise, only the |
1294 | characters between the delimiters are returned. | 1294 | characters between the delimiters are returned. |
1295 | \return The number of resulting substrings | 1295 | \return The number of resulting substrings |
1296 | */ | 1296 | */ |
1297 | template<class container> | 1297 | template<class container> |
1298 | u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const | 1298 | u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const |
1299 | { | 1299 | { |
1300 | if (!c) | 1300 | if (!c) |
1301 | return 0; | 1301 | return 0; |
1302 | 1302 | ||
1303 | const u32 oldSize=ret.size(); | 1303 | const u32 oldSize=ret.size(); |
1304 | u32 lastpos = 0; | 1304 | u32 lastpos = 0; |
1305 | bool lastWasSeparator = false; | 1305 | bool lastWasSeparator = false; |
1306 | for (u32 i=0; i<used; ++i) | 1306 | for (u32 i=0; i<used; ++i) |
1307 | { | 1307 | { |
1308 | bool foundSeparator = false; | 1308 | bool foundSeparator = false; |
1309 | for (u32 j=0; j<count; ++j) | 1309 | for (u32 j=0; j<count; ++j) |
1310 | { | 1310 | { |
1311 | if (array[i] == c[j]) | 1311 | if (array[i] == c[j]) |
1312 | { | 1312 | { |
1313 | if ((!ignoreEmptyTokens || i - lastpos != 0) && | 1313 | if ((!ignoreEmptyTokens || i - lastpos != 0) && |
1314 | !lastWasSeparator) | 1314 | !lastWasSeparator) |
1315 | ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos)); | 1315 | ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos)); |
1316 | foundSeparator = true; | 1316 | foundSeparator = true; |
1317 | lastpos = (keepSeparators ? i : i + 1); | 1317 | lastpos = (keepSeparators ? i : i + 1); |
1318 | break; | 1318 | break; |
1319 | } | 1319 | } |
1320 | } | 1320 | } |
1321 | lastWasSeparator = foundSeparator; | 1321 | lastWasSeparator = foundSeparator; |
1322 | } | 1322 | } |
1323 | if ((used - 1) > lastpos) | 1323 | if ((used - 1) > lastpos) |
1324 | ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos)); | 1324 | ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos)); |
1325 | return ret.size()-oldSize; | 1325 | return ret.size()-oldSize; |
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | private: | 1328 | private: |
1329 | 1329 | ||
1330 | //! Reallocate the array, make it bigger or smaller | 1330 | //! Reallocate the array, make it bigger or smaller |
1331 | void reallocate(u32 new_size) | 1331 | void reallocate(u32 new_size) |
1332 | { | 1332 | { |
1333 | T* old_array = array; | 1333 | T* old_array = array; |
1334 | 1334 | ||
1335 | array = allocator.allocate(new_size); //new T[new_size]; | 1335 | array = allocator.allocate(new_size); //new T[new_size]; |
1336 | allocated = new_size; | 1336 | allocated = new_size; |
1337 | 1337 | ||
1338 | u32 amount = used < new_size ? used : new_size; | 1338 | u32 amount = used < new_size ? used : new_size; |
1339 | for (u32 i=0; i<amount; ++i) | 1339 | for (u32 i=0; i<amount; ++i) |
1340 | array[i] = old_array[i]; | 1340 | array[i] = old_array[i]; |
1341 | 1341 | ||
1342 | if (allocated < used) | 1342 | if (allocated < used) |
1343 | used = allocated; | 1343 | used = allocated; |
1344 | 1344 | ||
1345 | allocator.deallocate(old_array); // delete [] old_array; | 1345 | allocator.deallocate(old_array); // delete [] old_array; |
1346 | } | 1346 | } |
1347 | 1347 | ||
1348 | //--- member variables | 1348 | //--- member variables |
1349 | 1349 | ||
1350 | T* array; | 1350 | T* array; |
1351 | u32 allocated; | 1351 | u32 allocated; |
1352 | u32 used; | 1352 | u32 used; |
1353 | TAlloc allocator; | 1353 | TAlloc allocator; |
1354 | }; | 1354 | }; |
1355 | 1355 | ||
1356 | 1356 | ||
1357 | //! Typedef for character strings | 1357 | //! Typedef for character strings |
1358 | typedef string<c8> stringc; | 1358 | typedef string<c8> stringc; |
1359 | 1359 | ||
1360 | //! Typedef for wide character strings | 1360 | //! Typedef for wide character strings |
1361 | typedef string<wchar_t> stringw; | 1361 | typedef string<wchar_t> stringw; |
1362 | 1362 | ||
1363 | 1363 | ||
1364 | } // end namespace core | 1364 | } // end namespace core |
1365 | } // end namespace irr | 1365 | } // end namespace irr |
1366 | 1366 | ||
1367 | #endif | 1367 | #endif |
1368 | 1368 | ||