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