vrshoot

view libs/assimp/irrXML/irrString.h @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 // Copyright (C) 2002-2005 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
5 #ifndef __IRR_STRING_H_INCLUDED__
6 #define __IRR_STRING_H_INCLUDED__
8 #include "irrTypes.h"
10 namespace irr
11 {
12 namespace core
13 {
15 //! Very simple string class with some useful features.
16 /** string<c8> and string<wchar_t> work both with unicode AND ascii,
17 so you can assign unicode to string<c8> and ascii to string<wchar_t>
18 (and the other way round) if your ever would want to.
19 Note that the conversation between both is not done using an encoding.
21 Known bugs:
22 Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the
23 methods make_upper, make_lower and equals_ignore_case.
24 */
25 template <class T>
26 class string
27 {
28 public:
30 //! Default constructor
31 string()
32 : array(0), allocated(1), used(1)
33 {
34 array = new T[1];
35 array[0] = 0x0;
36 }
40 //! Constructor
41 string(const string<T>& other)
42 : array(0), allocated(0), used(0)
43 {
44 *this = other;
45 }
48 //! Constructs a string from an int
49 string(int number)
50 : array(0), allocated(0), used(0)
51 {
52 // store if negative and make positive
54 bool negative = false;
55 if (number < 0)
56 {
57 number *= -1;
58 negative = true;
59 }
61 // temporary buffer for 16 numbers
63 c8 tmpbuf[16];
64 tmpbuf[15] = 0;
65 s32 idx = 15;
67 // special case '0'
69 if (!number)
70 {
71 tmpbuf[14] = '0';
72 *this = &tmpbuf[14];
73 return;
74 }
76 // add numbers
78 while(number && idx)
79 {
80 idx--;
81 tmpbuf[idx] = (c8)('0' + (number % 10));
82 number = number / 10;
83 }
85 // add sign
87 if (negative)
88 {
89 idx--;
90 tmpbuf[idx] = '-';
91 }
93 *this = &tmpbuf[idx];
94 }
98 //! Constructor for copying a string from a pointer with a given lenght
99 template <class B>
100 string(const B* c, s32 lenght)
101 : array(0), allocated(0), used(0)
102 {
103 if (!c)
104 return;
106 allocated = used = lenght+1;
107 array = new T[used];
109 for (s32 l = 0; l<lenght; ++l)
110 array[l] = (T)c[l];
112 array[lenght] = 0;
113 }
117 //! Constructor for unicode and ascii strings
118 template <class B>
119 string(const B* c)
120 : array(0),allocated(0), used(0)
121 {
122 *this = c;
123 }
127 //! destructor
128 ~string()
129 {
130 delete [] array;
131 }
135 //! Assignment operator
136 string<T>& operator=(const string<T>& other)
137 {
138 if (this == &other)
139 return *this;
141 delete [] array;
142 allocated = used = other.size()+1;
143 array = new T[used];
145 const T* p = other.c_str();
146 for (s32 i=0; i<used; ++i, ++p)
147 array[i] = *p;
149 return *this;
150 }
154 //! Assignment operator for strings, ascii and unicode
155 template <class B>
156 string<T>& operator=(const B* c)
157 {
158 if (!c)
159 {
160 if (!array)
161 {
162 array = new T[1];
163 allocated = 1;
164 used = 1;
165 }
166 array[0] = 0x0;
167 return *this;
168 }
170 if ((void*)c == (void*)array)
171 return *this;
173 s32 len = 0;
174 const B* p = c;
175 while(*p)
176 {
177 ++len;
178 ++p;
179 }
181 // we'll take the old string for a while, because the new string could be
182 // a part of the current string.
183 T* oldArray = array;
185 allocated = used = len+1;
186 array = new T[used];
188 for (s32 l = 0; l<len+1; ++l)
189 array[l] = (T)c[l];
191 delete [] oldArray;
192 return *this;
193 }
195 //! Add operator for other strings
196 string<T> operator+(const string<T>& other)
197 {
198 string<T> str(*this);
199 str.append(other);
201 return str;
202 }
204 //! Add operator for strings, ascii and unicode
205 template <class B>
206 string<T> operator+(const B* c)
207 {
208 string<T> str(*this);
209 str.append(c);
211 return str;
212 }
216 //! Direct access operator
217 T& operator [](const s32 index) const
218 {
219 _IRR_DEBUG_BREAK_IF(index>=used) // bad index
221 return array[index];
222 }
225 //! Comparison operator
226 bool operator ==(const T* str) const
227 {
228 int i;
229 for(i=0; array[i] && str[i]; ++i)
230 if (array[i] != str[i])
231 return false;
233 return !array[i] && !str[i];
234 }
238 //! Comparison operator
239 bool operator ==(const string<T>& other) const
240 {
241 for(s32 i=0; array[i] && other.array[i]; ++i)
242 if (array[i] != other.array[i])
243 return false;
245 return used == other.used;
246 }
250 //! Is smaller operator
251 bool operator <(const string<T>& other) const
252 {
253 for(s32 i=0; array[i] && other.array[i]; ++i)
254 if (array[i] != other.array[i])
255 return (array[i] < other.array[i]);
257 return used < other.used;
258 }
262 //! Equals not operator
263 bool operator !=(const string<T>& other) const
264 {
265 return !(*this == other);
266 }
270 //! Returns length of string
271 /** \return Returns length of the string in characters. */
272 s32 size() const
273 {
274 return used-1;
275 }
279 //! Returns character string
280 /** \return Returns pointer to C-style zero terminated string. */
281 const T* c_str() const
282 {
283 return array;
284 }
288 //! Makes the string lower case.
289 void make_lower()
290 {
291 const T A = (T)'A';
292 const T Z = (T)'Z';
293 const T diff = (T)'a' - A;
295 for (s32 i=0; i<used; ++i)
296 {
297 if (array[i]>=A && array[i]<=Z)
298 array[i] += diff;
299 }
300 }
304 //! Makes the string upper case.
305 void make_upper()
306 {
307 const T a = (T)'a';
308 const T z = (T)'z';
309 const T diff = (T)'A' - a;
311 for (s32 i=0; i<used; ++i)
312 {
313 if (array[i]>=a && array[i]<=z)
314 array[i] += diff;
315 }
316 }
320 //! Compares the string ignoring case.
321 /** \param other: Other string to compare.
322 \return Returns true if the string are equal ignoring case. */
323 bool equals_ignore_case(const string<T>& other) const
324 {
325 for(s32 i=0; array[i] && other[i]; ++i)
326 if (toLower(array[i]) != toLower(other[i]))
327 return false;
329 return used == other.used;
330 }
333 //! compares the first n characters of the strings
334 bool equalsn(const string<T>& other, int len)
335 {
336 int i;
337 for(i=0; array[i] && other[i] && i < len; ++i)
338 if (array[i] != other[i])
339 return false;
341 // if one (or both) of the strings was smaller then they
342 // are only equal if they have the same lenght
343 return (i == len) || (used == other.used);
344 }
347 //! compares the first n characters of the strings
348 bool equalsn(const T* str, int len)
349 {
350 int i;
351 for(i=0; array[i] && str[i] && i < len; ++i)
352 if (array[i] != str[i])
353 return false;
355 // if one (or both) of the strings was smaller then they
356 // are only equal if they have the same lenght
357 return (i == len) || (array[i] == 0 && str[i] == 0);
358 }
361 //! Appends a character to this string
362 /** \param character: Character to append. */
363 void append(T character)
364 {
365 if (used + 1 > allocated)
366 reallocate((s32)used + 1);
368 used += 1;
370 array[used-2] = character;
371 array[used-1] = 0;
372 }
374 //! Appends a string to this string
375 /** \param other: String to append. */
376 void append(const string<T>& other)
377 {
378 --used;
380 s32 len = other.size();
382 if (used + len + 1 > allocated)
383 reallocate((s32)used + (s32)len + 1);
385 for (s32 l=0; l<len+1; ++l)
386 array[l+used] = other[l];
388 used = used + len + 1;
389 }
392 //! Appends a string of the length l to this string.
393 /** \param other: other String to append to this string.
394 \param length: How much characters of the other string to add to this one. */
395 void append(const string<T>& other, s32 length)
396 {
397 s32 len = other.size();
399 if (len < length)
400 {
401 append(other);
402 return;
403 }
405 len = length;
406 --used;
408 if (used + len > allocated)
409 reallocate((s32)used + (s32)len);
411 for (s32 l=0; l<len; ++l)
412 array[l+used] = other[l];
414 used = used + len;
415 }
418 //! Reserves some memory.
419 /** \param count: Amount of characters to reserve. */
420 void reserve(s32 count)
421 {
422 if (count < allocated)
423 return;
425 reallocate(count);
426 }
429 //! finds first occurrence of character in string
430 /** \param c: Character to search for.
431 \return Returns position where the character has been found,
432 or -1 if not found. */
433 s32 findFirst(T c) const
434 {
435 for (s32 i=0; i<used; ++i)
436 if (array[i] == c)
437 return i;
439 return -1;
440 }
442 //! finds first occurrence of a character of a list in string
443 /** \param c: List of strings to find. For example if the method
444 should find the first occurance of 'a' or 'b', this parameter should be "ab".
445 \param count: Amount of characters in the list. Ususally,
446 this should be strlen(ofParameter1)
447 \return Returns position where one of the character has been found,
448 or -1 if not found. */
449 s32 findFirstChar(T* c, int count) const
450 {
451 for (s32 i=0; i<used; ++i)
452 for (int j=0; j<count; ++j)
453 if (array[i] == c[j])
454 return i;
456 return -1;
457 }
460 //! Finds first position of a character not in a given list.
461 /** \param c: List of characters not to find. For example if the method
462 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
463 \param count: Amount of characters in the list. Ususally,
464 this should be strlen(ofParameter1)
465 \return Returns position where the character has been found,
466 or -1 if not found. */
467 template <class B>
468 s32 findFirstCharNotInList(B* c, int count) const
469 {
470 for (int i=0; i<used; ++i)
471 {
472 int j;
473 for (j=0; j<count; ++j)
474 if (array[i] == c[j])
475 break;
477 if (j==count)
478 return i;
479 }
481 return -1;
482 }
484 //! Finds last position of a character not in a given list.
485 /** \param c: List of characters not to find. For example if the method
486 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
487 \param count: Amount of characters in the list. Ususally,
488 this should be strlen(ofParameter1)
489 \return Returns position where the character has been found,
490 or -1 if not found. */
491 template <class B>
492 s32 findLastCharNotInList(B* c, int count) const
493 {
494 for (int i=used-2; i>=0; --i)
495 {
496 int j;
497 for (j=0; j<count; ++j)
498 if (array[i] == c[j])
499 break;
501 if (j==count)
502 return i;
503 }
505 return -1;
506 }
508 //! finds next occurrence of character in string
509 /** \param c: Character to search for.
510 \param startPos: Position in string to start searching.
511 \return Returns position where the character has been found,
512 or -1 if not found. */
513 s32 findNext(T c, s32 startPos) const
514 {
515 for (s32 i=startPos; i<used; ++i)
516 if (array[i] == c)
517 return i;
519 return -1;
520 }
523 //! finds last occurrence of character in string
524 //! \param c: Character to search for.
525 //! \return Returns position where the character has been found,
526 //! or -1 if not found.
527 s32 findLast(T c) const
528 {
529 for (s32 i=used-1; i>=0; --i)
530 if (array[i] == c)
531 return i;
533 return -1;
534 }
537 //! Returns a substring
538 //! \param begin: Start of substring.
539 //! \param length: Length of substring.
540 string<T> subString(s32 begin, s32 length)
541 {
542 if (length <= 0)
543 return string<T>("");
545 string<T> o;
546 o.reserve(length+1);
548 for (s32 i=0; i<length; ++i)
549 o.array[i] = array[i+begin];
551 o.array[length] = 0;
552 o.used = o.allocated;
554 return o;
555 }
558 void operator += (T c)
559 {
560 append(c);
561 }
563 void operator += (const string<T>& other)
564 {
565 append(other);
566 }
568 void operator += (int i)
569 {
570 append(string<T>(i));
571 }
573 //! replaces all characters of a special type with another one
574 void replace(T toReplace, T replaceWith)
575 {
576 for (s32 i=0; i<used; ++i)
577 if (array[i] == toReplace)
578 array[i] = replaceWith;
579 }
581 //! trims the string.
582 /** Removes whitespace from begin and end of the string. */
583 void trim()
584 {
585 const char whitespace[] = " \t\n";
586 const int whitespacecount = 3;
588 // find start and end of real string without whitespace
589 int begin = findFirstCharNotInList(whitespace, whitespacecount);
590 if (begin == -1)
591 return;
593 int end = findLastCharNotInList(whitespace, whitespacecount);
594 if (end == -1)
595 return;
597 *this = subString(begin, (end +1) - begin);
598 }
601 //! Erases a character from the string. May be slow, because all elements
602 //! following after the erased element have to be copied.
603 //! \param index: Index of element to be erased.
604 void erase(int index)
605 {
606 _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
608 for (int i=index+1; i<used; ++i)
609 array[i-1] = array[i];
611 --used;
612 }
616 private:
618 //! Returns a character converted to lower case
619 T toLower(const T& t) const
620 {
621 if (t>=(T)'A' && t<=(T)'Z')
622 return t + ((T)'a' - (T)'A');
623 else
624 return t;
625 }
627 //! Reallocate the array, make it bigger or smaler
628 void reallocate(s32 new_size)
629 {
630 T* old_array = array;
632 array = new T[new_size];
633 allocated = new_size;
635 s32 amount = used < new_size ? used : new_size;
636 for (s32 i=0; i<amount; ++i)
637 array[i] = old_array[i];
639 if (allocated < used)
640 used = allocated;
642 delete [] old_array;
643 }
646 //--- member variables
648 T* array;
649 s32 allocated;
650 s32 used;
651 };
654 //! Typedef for character strings
655 typedef string<irr::c8> stringc;
657 //! Typedef for wide character strings
658 typedef string<wchar_t> stringw;
660 } // end namespace core
661 } // end namespace irr
663 #endif