A port of the irrlicht XML parser library.
irrString.h@0:41a49a73580c, 2010-11-17 (annotated)
- Committer:
- hlipka
- Date:
- Wed Nov 17 20:19:41 2010 +0000
- Revision:
- 0:41a49a73580c
initial version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hlipka | 0:41a49a73580c | 1 | // Copyright (C) 2002-2005 Nikolaus Gebhardt |
hlipka | 0:41a49a73580c | 2 | // This file is part of the "Irrlicht Engine" and the "irrXML" project. |
hlipka | 0:41a49a73580c | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h |
hlipka | 0:41a49a73580c | 4 | |
hlipka | 0:41a49a73580c | 5 | #ifndef __IRR_STRING_H_INCLUDED__ |
hlipka | 0:41a49a73580c | 6 | #define __IRR_STRING_H_INCLUDED__ |
hlipka | 0:41a49a73580c | 7 | |
hlipka | 0:41a49a73580c | 8 | #include "irrTypes.h" |
hlipka | 0:41a49a73580c | 9 | |
hlipka | 0:41a49a73580c | 10 | namespace irr |
hlipka | 0:41a49a73580c | 11 | { |
hlipka | 0:41a49a73580c | 12 | namespace core |
hlipka | 0:41a49a73580c | 13 | { |
hlipka | 0:41a49a73580c | 14 | |
hlipka | 0:41a49a73580c | 15 | //! Very simple string class with some useful features. |
hlipka | 0:41a49a73580c | 16 | /** string<c8> and string<wchar_t> work both with unicode AND ascii, |
hlipka | 0:41a49a73580c | 17 | so you can assign unicode to string<c8> and ascii to string<wchar_t> |
hlipka | 0:41a49a73580c | 18 | (and the other way round) if your ever would want to. |
hlipka | 0:41a49a73580c | 19 | Note that the conversation between both is not done using an encoding. |
hlipka | 0:41a49a73580c | 20 | |
hlipka | 0:41a49a73580c | 21 | Known bugs: |
hlipka | 0:41a49a73580c | 22 | Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the |
hlipka | 0:41a49a73580c | 23 | methods make_upper, make_lower and equals_ignore_case. |
hlipka | 0:41a49a73580c | 24 | */ |
hlipka | 0:41a49a73580c | 25 | template <class T> |
hlipka | 0:41a49a73580c | 26 | class string |
hlipka | 0:41a49a73580c | 27 | { |
hlipka | 0:41a49a73580c | 28 | public: |
hlipka | 0:41a49a73580c | 29 | |
hlipka | 0:41a49a73580c | 30 | //! Default constructor |
hlipka | 0:41a49a73580c | 31 | string() |
hlipka | 0:41a49a73580c | 32 | : allocated(1), used(1), array(0) |
hlipka | 0:41a49a73580c | 33 | { |
hlipka | 0:41a49a73580c | 34 | array = new T[1]; |
hlipka | 0:41a49a73580c | 35 | array[0] = 0x0; |
hlipka | 0:41a49a73580c | 36 | } |
hlipka | 0:41a49a73580c | 37 | |
hlipka | 0:41a49a73580c | 38 | |
hlipka | 0:41a49a73580c | 39 | |
hlipka | 0:41a49a73580c | 40 | //! Constructor |
hlipka | 0:41a49a73580c | 41 | string(const string<T>& other) |
hlipka | 0:41a49a73580c | 42 | : allocated(0), used(0), array(0) |
hlipka | 0:41a49a73580c | 43 | { |
hlipka | 0:41a49a73580c | 44 | *this = other; |
hlipka | 0:41a49a73580c | 45 | } |
hlipka | 0:41a49a73580c | 46 | |
hlipka | 0:41a49a73580c | 47 | |
hlipka | 0:41a49a73580c | 48 | //! Constructs a string from an int |
hlipka | 0:41a49a73580c | 49 | string(int number) |
hlipka | 0:41a49a73580c | 50 | : allocated(0), used(0), array(0) |
hlipka | 0:41a49a73580c | 51 | { |
hlipka | 0:41a49a73580c | 52 | // store if negative and make positive |
hlipka | 0:41a49a73580c | 53 | |
hlipka | 0:41a49a73580c | 54 | bool negative = false; |
hlipka | 0:41a49a73580c | 55 | if (number < 0) |
hlipka | 0:41a49a73580c | 56 | { |
hlipka | 0:41a49a73580c | 57 | number *= -1; |
hlipka | 0:41a49a73580c | 58 | negative = true; |
hlipka | 0:41a49a73580c | 59 | } |
hlipka | 0:41a49a73580c | 60 | |
hlipka | 0:41a49a73580c | 61 | // temporary buffer for 16 numbers |
hlipka | 0:41a49a73580c | 62 | |
hlipka | 0:41a49a73580c | 63 | c8 tmpbuf[16]; |
hlipka | 0:41a49a73580c | 64 | tmpbuf[15] = 0; |
hlipka | 0:41a49a73580c | 65 | s32 idx = 15; |
hlipka | 0:41a49a73580c | 66 | |
hlipka | 0:41a49a73580c | 67 | // special case '0' |
hlipka | 0:41a49a73580c | 68 | |
hlipka | 0:41a49a73580c | 69 | if (!number) |
hlipka | 0:41a49a73580c | 70 | { |
hlipka | 0:41a49a73580c | 71 | tmpbuf[14] = '0'; |
hlipka | 0:41a49a73580c | 72 | *this = &tmpbuf[14]; |
hlipka | 0:41a49a73580c | 73 | return; |
hlipka | 0:41a49a73580c | 74 | } |
hlipka | 0:41a49a73580c | 75 | |
hlipka | 0:41a49a73580c | 76 | // add numbers |
hlipka | 0:41a49a73580c | 77 | |
hlipka | 0:41a49a73580c | 78 | while(number && idx) |
hlipka | 0:41a49a73580c | 79 | { |
hlipka | 0:41a49a73580c | 80 | idx--; |
hlipka | 0:41a49a73580c | 81 | tmpbuf[idx] = (c8)('0' + (number % 10)); |
hlipka | 0:41a49a73580c | 82 | number = number / 10; |
hlipka | 0:41a49a73580c | 83 | } |
hlipka | 0:41a49a73580c | 84 | |
hlipka | 0:41a49a73580c | 85 | // add sign |
hlipka | 0:41a49a73580c | 86 | |
hlipka | 0:41a49a73580c | 87 | if (negative) |
hlipka | 0:41a49a73580c | 88 | { |
hlipka | 0:41a49a73580c | 89 | idx--; |
hlipka | 0:41a49a73580c | 90 | tmpbuf[idx] = '-'; |
hlipka | 0:41a49a73580c | 91 | } |
hlipka | 0:41a49a73580c | 92 | |
hlipka | 0:41a49a73580c | 93 | *this = &tmpbuf[idx]; |
hlipka | 0:41a49a73580c | 94 | } |
hlipka | 0:41a49a73580c | 95 | |
hlipka | 0:41a49a73580c | 96 | |
hlipka | 0:41a49a73580c | 97 | |
hlipka | 0:41a49a73580c | 98 | //! Constructor for copying a string from a pointer with a given lenght |
hlipka | 0:41a49a73580c | 99 | template <class B> |
hlipka | 0:41a49a73580c | 100 | string(const B* c, s32 lenght) |
hlipka | 0:41a49a73580c | 101 | : allocated(0), used(0), array(0) |
hlipka | 0:41a49a73580c | 102 | { |
hlipka | 0:41a49a73580c | 103 | if (!c) |
hlipka | 0:41a49a73580c | 104 | return; |
hlipka | 0:41a49a73580c | 105 | |
hlipka | 0:41a49a73580c | 106 | allocated = used = lenght+1; |
hlipka | 0:41a49a73580c | 107 | array = new T[used]; |
hlipka | 0:41a49a73580c | 108 | |
hlipka | 0:41a49a73580c | 109 | for (s32 l = 0; l<lenght; ++l) |
hlipka | 0:41a49a73580c | 110 | array[l] = (T)c[l]; |
hlipka | 0:41a49a73580c | 111 | |
hlipka | 0:41a49a73580c | 112 | array[lenght] = 0; |
hlipka | 0:41a49a73580c | 113 | } |
hlipka | 0:41a49a73580c | 114 | |
hlipka | 0:41a49a73580c | 115 | |
hlipka | 0:41a49a73580c | 116 | |
hlipka | 0:41a49a73580c | 117 | //! Constructor for unicode and ascii strings |
hlipka | 0:41a49a73580c | 118 | template <class B> |
hlipka | 0:41a49a73580c | 119 | string(const B* c) |
hlipka | 0:41a49a73580c | 120 | : allocated(0), used(0), array(0) |
hlipka | 0:41a49a73580c | 121 | { |
hlipka | 0:41a49a73580c | 122 | *this = c; |
hlipka | 0:41a49a73580c | 123 | } |
hlipka | 0:41a49a73580c | 124 | |
hlipka | 0:41a49a73580c | 125 | |
hlipka | 0:41a49a73580c | 126 | |
hlipka | 0:41a49a73580c | 127 | //! destructor |
hlipka | 0:41a49a73580c | 128 | ~string() |
hlipka | 0:41a49a73580c | 129 | { |
hlipka | 0:41a49a73580c | 130 | delete [] array; |
hlipka | 0:41a49a73580c | 131 | } |
hlipka | 0:41a49a73580c | 132 | |
hlipka | 0:41a49a73580c | 133 | |
hlipka | 0:41a49a73580c | 134 | |
hlipka | 0:41a49a73580c | 135 | //! Assignment operator |
hlipka | 0:41a49a73580c | 136 | string<T>& operator=(const string<T>& other) |
hlipka | 0:41a49a73580c | 137 | { |
hlipka | 0:41a49a73580c | 138 | if (this == &other) |
hlipka | 0:41a49a73580c | 139 | return *this; |
hlipka | 0:41a49a73580c | 140 | |
hlipka | 0:41a49a73580c | 141 | delete [] array; |
hlipka | 0:41a49a73580c | 142 | allocated = used = other.size()+1; |
hlipka | 0:41a49a73580c | 143 | array = new T[used]; |
hlipka | 0:41a49a73580c | 144 | |
hlipka | 0:41a49a73580c | 145 | const T* p = other.c_str(); |
hlipka | 0:41a49a73580c | 146 | for (s32 i=0; i<used; ++i, ++p) |
hlipka | 0:41a49a73580c | 147 | array[i] = *p; |
hlipka | 0:41a49a73580c | 148 | |
hlipka | 0:41a49a73580c | 149 | return *this; |
hlipka | 0:41a49a73580c | 150 | } |
hlipka | 0:41a49a73580c | 151 | |
hlipka | 0:41a49a73580c | 152 | |
hlipka | 0:41a49a73580c | 153 | |
hlipka | 0:41a49a73580c | 154 | //! Assignment operator for strings, ascii and unicode |
hlipka | 0:41a49a73580c | 155 | template <class B> |
hlipka | 0:41a49a73580c | 156 | string<T>& operator=(const B* c) |
hlipka | 0:41a49a73580c | 157 | { |
hlipka | 0:41a49a73580c | 158 | if (!c) |
hlipka | 0:41a49a73580c | 159 | { |
hlipka | 0:41a49a73580c | 160 | if (!array) |
hlipka | 0:41a49a73580c | 161 | { |
hlipka | 0:41a49a73580c | 162 | array = new T[1]; |
hlipka | 0:41a49a73580c | 163 | allocated = 1; |
hlipka | 0:41a49a73580c | 164 | used = 1; |
hlipka | 0:41a49a73580c | 165 | } |
hlipka | 0:41a49a73580c | 166 | array[0] = 0x0; |
hlipka | 0:41a49a73580c | 167 | return *this; |
hlipka | 0:41a49a73580c | 168 | } |
hlipka | 0:41a49a73580c | 169 | |
hlipka | 0:41a49a73580c | 170 | if ((void*)c == (void*)array) |
hlipka | 0:41a49a73580c | 171 | return *this; |
hlipka | 0:41a49a73580c | 172 | |
hlipka | 0:41a49a73580c | 173 | s32 len = 0; |
hlipka | 0:41a49a73580c | 174 | const B* p = c; |
hlipka | 0:41a49a73580c | 175 | while(*p) |
hlipka | 0:41a49a73580c | 176 | { |
hlipka | 0:41a49a73580c | 177 | ++len; |
hlipka | 0:41a49a73580c | 178 | ++p; |
hlipka | 0:41a49a73580c | 179 | } |
hlipka | 0:41a49a73580c | 180 | |
hlipka | 0:41a49a73580c | 181 | // we'll take the old string for a while, because the new string could be |
hlipka | 0:41a49a73580c | 182 | // a part of the current string. |
hlipka | 0:41a49a73580c | 183 | T* oldArray = array; |
hlipka | 0:41a49a73580c | 184 | |
hlipka | 0:41a49a73580c | 185 | allocated = used = len+1; |
hlipka | 0:41a49a73580c | 186 | array = new T[used]; |
hlipka | 0:41a49a73580c | 187 | |
hlipka | 0:41a49a73580c | 188 | for (s32 l = 0; l<len+1; ++l) |
hlipka | 0:41a49a73580c | 189 | array[l] = (T)c[l]; |
hlipka | 0:41a49a73580c | 190 | |
hlipka | 0:41a49a73580c | 191 | delete [] oldArray; |
hlipka | 0:41a49a73580c | 192 | return *this; |
hlipka | 0:41a49a73580c | 193 | } |
hlipka | 0:41a49a73580c | 194 | |
hlipka | 0:41a49a73580c | 195 | //! Add operator for other strings |
hlipka | 0:41a49a73580c | 196 | string<T> operator+(const string<T>& other) |
hlipka | 0:41a49a73580c | 197 | { |
hlipka | 0:41a49a73580c | 198 | string<T> str(*this); |
hlipka | 0:41a49a73580c | 199 | str.append(other); |
hlipka | 0:41a49a73580c | 200 | |
hlipka | 0:41a49a73580c | 201 | return str; |
hlipka | 0:41a49a73580c | 202 | } |
hlipka | 0:41a49a73580c | 203 | |
hlipka | 0:41a49a73580c | 204 | //! Add operator for strings, ascii and unicode |
hlipka | 0:41a49a73580c | 205 | template <class B> |
hlipka | 0:41a49a73580c | 206 | string<T> operator+(const B* c) |
hlipka | 0:41a49a73580c | 207 | { |
hlipka | 0:41a49a73580c | 208 | string<T> str(*this); |
hlipka | 0:41a49a73580c | 209 | str.append(c); |
hlipka | 0:41a49a73580c | 210 | |
hlipka | 0:41a49a73580c | 211 | return str; |
hlipka | 0:41a49a73580c | 212 | } |
hlipka | 0:41a49a73580c | 213 | |
hlipka | 0:41a49a73580c | 214 | |
hlipka | 0:41a49a73580c | 215 | |
hlipka | 0:41a49a73580c | 216 | //! Direct access operator |
hlipka | 0:41a49a73580c | 217 | T& operator [](const s32 index) const |
hlipka | 0:41a49a73580c | 218 | { |
hlipka | 0:41a49a73580c | 219 | _IRR_DEBUG_BREAK_IF(index>=used) // bad index |
hlipka | 0:41a49a73580c | 220 | |
hlipka | 0:41a49a73580c | 221 | return array[index]; |
hlipka | 0:41a49a73580c | 222 | } |
hlipka | 0:41a49a73580c | 223 | |
hlipka | 0:41a49a73580c | 224 | |
hlipka | 0:41a49a73580c | 225 | //! Comparison operator |
hlipka | 0:41a49a73580c | 226 | bool operator ==(const T* str) const |
hlipka | 0:41a49a73580c | 227 | { |
hlipka | 0:41a49a73580c | 228 | int i; |
hlipka | 0:41a49a73580c | 229 | for(i=0; array[i] && str[i]; ++i) |
hlipka | 0:41a49a73580c | 230 | if (array[i] != str[i]) |
hlipka | 0:41a49a73580c | 231 | return false; |
hlipka | 0:41a49a73580c | 232 | |
hlipka | 0:41a49a73580c | 233 | return !array[i] && !str[i]; |
hlipka | 0:41a49a73580c | 234 | } |
hlipka | 0:41a49a73580c | 235 | |
hlipka | 0:41a49a73580c | 236 | |
hlipka | 0:41a49a73580c | 237 | |
hlipka | 0:41a49a73580c | 238 | //! Comparison operator |
hlipka | 0:41a49a73580c | 239 | bool operator ==(const string<T>& other) const |
hlipka | 0:41a49a73580c | 240 | { |
hlipka | 0:41a49a73580c | 241 | for(s32 i=0; array[i] && other.array[i]; ++i) |
hlipka | 0:41a49a73580c | 242 | if (array[i] != other.array[i]) |
hlipka | 0:41a49a73580c | 243 | return false; |
hlipka | 0:41a49a73580c | 244 | |
hlipka | 0:41a49a73580c | 245 | return used == other.used; |
hlipka | 0:41a49a73580c | 246 | } |
hlipka | 0:41a49a73580c | 247 | |
hlipka | 0:41a49a73580c | 248 | |
hlipka | 0:41a49a73580c | 249 | |
hlipka | 0:41a49a73580c | 250 | //! Is smaller operator |
hlipka | 0:41a49a73580c | 251 | bool operator <(const string<T>& other) const |
hlipka | 0:41a49a73580c | 252 | { |
hlipka | 0:41a49a73580c | 253 | for(s32 i=0; array[i] && other.array[i]; ++i) |
hlipka | 0:41a49a73580c | 254 | if (array[i] != other.array[i]) |
hlipka | 0:41a49a73580c | 255 | return (array[i] < other.array[i]); |
hlipka | 0:41a49a73580c | 256 | |
hlipka | 0:41a49a73580c | 257 | return used < other.used; |
hlipka | 0:41a49a73580c | 258 | } |
hlipka | 0:41a49a73580c | 259 | |
hlipka | 0:41a49a73580c | 260 | |
hlipka | 0:41a49a73580c | 261 | |
hlipka | 0:41a49a73580c | 262 | //! Equals not operator |
hlipka | 0:41a49a73580c | 263 | bool operator !=(const string<T>& other) const |
hlipka | 0:41a49a73580c | 264 | { |
hlipka | 0:41a49a73580c | 265 | return !(*this == other); |
hlipka | 0:41a49a73580c | 266 | } |
hlipka | 0:41a49a73580c | 267 | |
hlipka | 0:41a49a73580c | 268 | |
hlipka | 0:41a49a73580c | 269 | |
hlipka | 0:41a49a73580c | 270 | //! Returns length of string |
hlipka | 0:41a49a73580c | 271 | /** \return Returns length of the string in characters. */ |
hlipka | 0:41a49a73580c | 272 | s32 size() const |
hlipka | 0:41a49a73580c | 273 | { |
hlipka | 0:41a49a73580c | 274 | return used-1; |
hlipka | 0:41a49a73580c | 275 | } |
hlipka | 0:41a49a73580c | 276 | |
hlipka | 0:41a49a73580c | 277 | |
hlipka | 0:41a49a73580c | 278 | |
hlipka | 0:41a49a73580c | 279 | //! Returns character string |
hlipka | 0:41a49a73580c | 280 | /** \return Returns pointer to C-style zero terminated string. */ |
hlipka | 0:41a49a73580c | 281 | const T* c_str() const |
hlipka | 0:41a49a73580c | 282 | { |
hlipka | 0:41a49a73580c | 283 | return array; |
hlipka | 0:41a49a73580c | 284 | } |
hlipka | 0:41a49a73580c | 285 | |
hlipka | 0:41a49a73580c | 286 | |
hlipka | 0:41a49a73580c | 287 | |
hlipka | 0:41a49a73580c | 288 | //! Makes the string lower case. |
hlipka | 0:41a49a73580c | 289 | void make_lower() |
hlipka | 0:41a49a73580c | 290 | { |
hlipka | 0:41a49a73580c | 291 | const T A = (T)'A'; |
hlipka | 0:41a49a73580c | 292 | const T Z = (T)'Z'; |
hlipka | 0:41a49a73580c | 293 | const T diff = (T)'a' - A; |
hlipka | 0:41a49a73580c | 294 | |
hlipka | 0:41a49a73580c | 295 | for (s32 i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 296 | { |
hlipka | 0:41a49a73580c | 297 | if (array[i]>=A && array[i]<=Z) |
hlipka | 0:41a49a73580c | 298 | array[i] += diff; |
hlipka | 0:41a49a73580c | 299 | } |
hlipka | 0:41a49a73580c | 300 | } |
hlipka | 0:41a49a73580c | 301 | |
hlipka | 0:41a49a73580c | 302 | |
hlipka | 0:41a49a73580c | 303 | |
hlipka | 0:41a49a73580c | 304 | //! Makes the string upper case. |
hlipka | 0:41a49a73580c | 305 | void make_upper() |
hlipka | 0:41a49a73580c | 306 | { |
hlipka | 0:41a49a73580c | 307 | const T a = (T)'a'; |
hlipka | 0:41a49a73580c | 308 | const T z = (T)'z'; |
hlipka | 0:41a49a73580c | 309 | const T diff = (T)'A' - a; |
hlipka | 0:41a49a73580c | 310 | |
hlipka | 0:41a49a73580c | 311 | for (s32 i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 312 | { |
hlipka | 0:41a49a73580c | 313 | if (array[i]>=a && array[i]<=z) |
hlipka | 0:41a49a73580c | 314 | array[i] += diff; |
hlipka | 0:41a49a73580c | 315 | } |
hlipka | 0:41a49a73580c | 316 | } |
hlipka | 0:41a49a73580c | 317 | |
hlipka | 0:41a49a73580c | 318 | |
hlipka | 0:41a49a73580c | 319 | |
hlipka | 0:41a49a73580c | 320 | //! Compares the string ignoring case. |
hlipka | 0:41a49a73580c | 321 | /** \param other: Other string to compare. |
hlipka | 0:41a49a73580c | 322 | \return Returns true if the string are equal ignoring case. */ |
hlipka | 0:41a49a73580c | 323 | bool equals_ignore_case(const string<T>& other) const |
hlipka | 0:41a49a73580c | 324 | { |
hlipka | 0:41a49a73580c | 325 | for(s32 i=0; array[i] && other[i]; ++i) |
hlipka | 0:41a49a73580c | 326 | if (toLower(array[i]) != toLower(other[i])) |
hlipka | 0:41a49a73580c | 327 | return false; |
hlipka | 0:41a49a73580c | 328 | |
hlipka | 0:41a49a73580c | 329 | return used == other.used; |
hlipka | 0:41a49a73580c | 330 | } |
hlipka | 0:41a49a73580c | 331 | |
hlipka | 0:41a49a73580c | 332 | |
hlipka | 0:41a49a73580c | 333 | //! compares the first n characters of the strings |
hlipka | 0:41a49a73580c | 334 | bool equalsn(const string<T>& other, int len) |
hlipka | 0:41a49a73580c | 335 | { |
hlipka | 0:41a49a73580c | 336 | int i; |
hlipka | 0:41a49a73580c | 337 | for(i=0; array[i] && other[i] && i < len; ++i) |
hlipka | 0:41a49a73580c | 338 | if (array[i] != other[i]) |
hlipka | 0:41a49a73580c | 339 | return false; |
hlipka | 0:41a49a73580c | 340 | |
hlipka | 0:41a49a73580c | 341 | // if one (or both) of the strings was smaller then they |
hlipka | 0:41a49a73580c | 342 | // are only equal if they have the same lenght |
hlipka | 0:41a49a73580c | 343 | return (i == len) || (used == other.used); |
hlipka | 0:41a49a73580c | 344 | } |
hlipka | 0:41a49a73580c | 345 | |
hlipka | 0:41a49a73580c | 346 | |
hlipka | 0:41a49a73580c | 347 | //! compares the first n characters of the strings |
hlipka | 0:41a49a73580c | 348 | bool equalsn(const T* str, int len) |
hlipka | 0:41a49a73580c | 349 | { |
hlipka | 0:41a49a73580c | 350 | int i; |
hlipka | 0:41a49a73580c | 351 | for(i=0; array[i] && str[i] && i < len; ++i) |
hlipka | 0:41a49a73580c | 352 | if (array[i] != str[i]) |
hlipka | 0:41a49a73580c | 353 | return false; |
hlipka | 0:41a49a73580c | 354 | |
hlipka | 0:41a49a73580c | 355 | // if one (or both) of the strings was smaller then they |
hlipka | 0:41a49a73580c | 356 | // are only equal if they have the same lenght |
hlipka | 0:41a49a73580c | 357 | return (i == len) || (array[i] == 0 && str[i] == 0); |
hlipka | 0:41a49a73580c | 358 | } |
hlipka | 0:41a49a73580c | 359 | |
hlipka | 0:41a49a73580c | 360 | |
hlipka | 0:41a49a73580c | 361 | //! Appends a character to this string |
hlipka | 0:41a49a73580c | 362 | /** \param character: Character to append. */ |
hlipka | 0:41a49a73580c | 363 | void append(T character) |
hlipka | 0:41a49a73580c | 364 | { |
hlipka | 0:41a49a73580c | 365 | if (used + 1 > allocated) |
hlipka | 0:41a49a73580c | 366 | reallocate((s32)used + 1); |
hlipka | 0:41a49a73580c | 367 | |
hlipka | 0:41a49a73580c | 368 | used += 1; |
hlipka | 0:41a49a73580c | 369 | |
hlipka | 0:41a49a73580c | 370 | array[used-2] = character; |
hlipka | 0:41a49a73580c | 371 | array[used-1] = 0; |
hlipka | 0:41a49a73580c | 372 | } |
hlipka | 0:41a49a73580c | 373 | |
hlipka | 0:41a49a73580c | 374 | //! Appends a string to this string |
hlipka | 0:41a49a73580c | 375 | /** \param other: String to append. */ |
hlipka | 0:41a49a73580c | 376 | void append(const string<T>& other) |
hlipka | 0:41a49a73580c | 377 | { |
hlipka | 0:41a49a73580c | 378 | --used; |
hlipka | 0:41a49a73580c | 379 | |
hlipka | 0:41a49a73580c | 380 | s32 len = other.size(); |
hlipka | 0:41a49a73580c | 381 | |
hlipka | 0:41a49a73580c | 382 | if (used + len + 1 > allocated) |
hlipka | 0:41a49a73580c | 383 | reallocate((s32)used + (s32)len + 1); |
hlipka | 0:41a49a73580c | 384 | |
hlipka | 0:41a49a73580c | 385 | for (s32 l=0; l<len+1; ++l) |
hlipka | 0:41a49a73580c | 386 | array[l+used] = other[l]; |
hlipka | 0:41a49a73580c | 387 | |
hlipka | 0:41a49a73580c | 388 | used = used + len + 1; |
hlipka | 0:41a49a73580c | 389 | } |
hlipka | 0:41a49a73580c | 390 | |
hlipka | 0:41a49a73580c | 391 | |
hlipka | 0:41a49a73580c | 392 | //! Appends a string of the length l to this string. |
hlipka | 0:41a49a73580c | 393 | /** \param other: other String to append to this string. |
hlipka | 0:41a49a73580c | 394 | \param length: How much characters of the other string to add to this one. */ |
hlipka | 0:41a49a73580c | 395 | void append(const string<T>& other, s32 length) |
hlipka | 0:41a49a73580c | 396 | { |
hlipka | 0:41a49a73580c | 397 | s32 len = other.size(); |
hlipka | 0:41a49a73580c | 398 | |
hlipka | 0:41a49a73580c | 399 | if (len < length) |
hlipka | 0:41a49a73580c | 400 | { |
hlipka | 0:41a49a73580c | 401 | append(other); |
hlipka | 0:41a49a73580c | 402 | return; |
hlipka | 0:41a49a73580c | 403 | } |
hlipka | 0:41a49a73580c | 404 | |
hlipka | 0:41a49a73580c | 405 | len = length; |
hlipka | 0:41a49a73580c | 406 | --used; |
hlipka | 0:41a49a73580c | 407 | |
hlipka | 0:41a49a73580c | 408 | if (used + len > allocated) |
hlipka | 0:41a49a73580c | 409 | reallocate((s32)used + (s32)len); |
hlipka | 0:41a49a73580c | 410 | |
hlipka | 0:41a49a73580c | 411 | for (s32 l=0; l<len; ++l) |
hlipka | 0:41a49a73580c | 412 | array[l+used] = other[l]; |
hlipka | 0:41a49a73580c | 413 | |
hlipka | 0:41a49a73580c | 414 | used = used + len; |
hlipka | 0:41a49a73580c | 415 | } |
hlipka | 0:41a49a73580c | 416 | |
hlipka | 0:41a49a73580c | 417 | |
hlipka | 0:41a49a73580c | 418 | //! Reserves some memory. |
hlipka | 0:41a49a73580c | 419 | /** \param count: Amount of characters to reserve. */ |
hlipka | 0:41a49a73580c | 420 | void reserve(s32 count) |
hlipka | 0:41a49a73580c | 421 | { |
hlipka | 0:41a49a73580c | 422 | if (count < allocated) |
hlipka | 0:41a49a73580c | 423 | return; |
hlipka | 0:41a49a73580c | 424 | |
hlipka | 0:41a49a73580c | 425 | reallocate(count); |
hlipka | 0:41a49a73580c | 426 | } |
hlipka | 0:41a49a73580c | 427 | |
hlipka | 0:41a49a73580c | 428 | |
hlipka | 0:41a49a73580c | 429 | //! finds first occurrence of character in string |
hlipka | 0:41a49a73580c | 430 | /** \param c: Character to search for. |
hlipka | 0:41a49a73580c | 431 | \return Returns position where the character has been found, |
hlipka | 0:41a49a73580c | 432 | or -1 if not found. */ |
hlipka | 0:41a49a73580c | 433 | s32 findFirst(T c) const |
hlipka | 0:41a49a73580c | 434 | { |
hlipka | 0:41a49a73580c | 435 | for (s32 i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 436 | if (array[i] == c) |
hlipka | 0:41a49a73580c | 437 | return i; |
hlipka | 0:41a49a73580c | 438 | |
hlipka | 0:41a49a73580c | 439 | return -1; |
hlipka | 0:41a49a73580c | 440 | } |
hlipka | 0:41a49a73580c | 441 | |
hlipka | 0:41a49a73580c | 442 | //! finds first occurrence of a character of a list in string |
hlipka | 0:41a49a73580c | 443 | /** \param c: List of strings to find. For example if the method |
hlipka | 0:41a49a73580c | 444 | should find the first occurance of 'a' or 'b', this parameter should be "ab". |
hlipka | 0:41a49a73580c | 445 | \param count: Amount of characters in the list. Ususally, |
hlipka | 0:41a49a73580c | 446 | this should be strlen(ofParameter1) |
hlipka | 0:41a49a73580c | 447 | \return Returns position where one of the character has been found, |
hlipka | 0:41a49a73580c | 448 | or -1 if not found. */ |
hlipka | 0:41a49a73580c | 449 | s32 findFirstChar(T* c, int count) const |
hlipka | 0:41a49a73580c | 450 | { |
hlipka | 0:41a49a73580c | 451 | for (s32 i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 452 | for (int j=0; j<count; ++j) |
hlipka | 0:41a49a73580c | 453 | if (array[i] == c[j]) |
hlipka | 0:41a49a73580c | 454 | return i; |
hlipka | 0:41a49a73580c | 455 | |
hlipka | 0:41a49a73580c | 456 | return -1; |
hlipka | 0:41a49a73580c | 457 | } |
hlipka | 0:41a49a73580c | 458 | |
hlipka | 0:41a49a73580c | 459 | |
hlipka | 0:41a49a73580c | 460 | //! Finds first position of a character not in a given list. |
hlipka | 0:41a49a73580c | 461 | /** \param c: List of characters not to find. For example if the method |
hlipka | 0:41a49a73580c | 462 | should find the first occurance of a character not 'a' or 'b', this parameter should be "ab". |
hlipka | 0:41a49a73580c | 463 | \param count: Amount of characters in the list. Ususally, |
hlipka | 0:41a49a73580c | 464 | this should be strlen(ofParameter1) |
hlipka | 0:41a49a73580c | 465 | \return Returns position where the character has been found, |
hlipka | 0:41a49a73580c | 466 | or -1 if not found. */ |
hlipka | 0:41a49a73580c | 467 | template <class B> |
hlipka | 0:41a49a73580c | 468 | s32 findFirstCharNotInList(B* c, int count) const |
hlipka | 0:41a49a73580c | 469 | { |
hlipka | 0:41a49a73580c | 470 | for (int i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 471 | { |
hlipka | 0:41a49a73580c | 472 | int j; |
hlipka | 0:41a49a73580c | 473 | for (j=0; j<count; ++j) |
hlipka | 0:41a49a73580c | 474 | if (array[i] == c[j]) |
hlipka | 0:41a49a73580c | 475 | break; |
hlipka | 0:41a49a73580c | 476 | |
hlipka | 0:41a49a73580c | 477 | if (j==count) |
hlipka | 0:41a49a73580c | 478 | return i; |
hlipka | 0:41a49a73580c | 479 | } |
hlipka | 0:41a49a73580c | 480 | |
hlipka | 0:41a49a73580c | 481 | return -1; |
hlipka | 0:41a49a73580c | 482 | } |
hlipka | 0:41a49a73580c | 483 | |
hlipka | 0:41a49a73580c | 484 | //! Finds last position of a character not in a given list. |
hlipka | 0:41a49a73580c | 485 | /** \param c: List of characters not to find. For example if the method |
hlipka | 0:41a49a73580c | 486 | should find the first occurance of a character not 'a' or 'b', this parameter should be "ab". |
hlipka | 0:41a49a73580c | 487 | \param count: Amount of characters in the list. Ususally, |
hlipka | 0:41a49a73580c | 488 | this should be strlen(ofParameter1) |
hlipka | 0:41a49a73580c | 489 | \return Returns position where the character has been found, |
hlipka | 0:41a49a73580c | 490 | or -1 if not found. */ |
hlipka | 0:41a49a73580c | 491 | template <class B> |
hlipka | 0:41a49a73580c | 492 | s32 findLastCharNotInList(B* c, int count) const |
hlipka | 0:41a49a73580c | 493 | { |
hlipka | 0:41a49a73580c | 494 | for (int i=used-2; i>=0; --i) |
hlipka | 0:41a49a73580c | 495 | { |
hlipka | 0:41a49a73580c | 496 | int j; |
hlipka | 0:41a49a73580c | 497 | for (j=0; j<count; ++j) |
hlipka | 0:41a49a73580c | 498 | if (array[i] == c[j]) |
hlipka | 0:41a49a73580c | 499 | break; |
hlipka | 0:41a49a73580c | 500 | |
hlipka | 0:41a49a73580c | 501 | if (j==count) |
hlipka | 0:41a49a73580c | 502 | return i; |
hlipka | 0:41a49a73580c | 503 | } |
hlipka | 0:41a49a73580c | 504 | |
hlipka | 0:41a49a73580c | 505 | return -1; |
hlipka | 0:41a49a73580c | 506 | } |
hlipka | 0:41a49a73580c | 507 | |
hlipka | 0:41a49a73580c | 508 | //! finds next occurrence of character in string |
hlipka | 0:41a49a73580c | 509 | /** \param c: Character to search for. |
hlipka | 0:41a49a73580c | 510 | \param startPos: Position in string to start searching. |
hlipka | 0:41a49a73580c | 511 | \return Returns position where the character has been found, |
hlipka | 0:41a49a73580c | 512 | or -1 if not found. */ |
hlipka | 0:41a49a73580c | 513 | s32 findNext(T c, s32 startPos) const |
hlipka | 0:41a49a73580c | 514 | { |
hlipka | 0:41a49a73580c | 515 | for (s32 i=startPos; i<used; ++i) |
hlipka | 0:41a49a73580c | 516 | if (array[i] == c) |
hlipka | 0:41a49a73580c | 517 | return i; |
hlipka | 0:41a49a73580c | 518 | |
hlipka | 0:41a49a73580c | 519 | return -1; |
hlipka | 0:41a49a73580c | 520 | } |
hlipka | 0:41a49a73580c | 521 | |
hlipka | 0:41a49a73580c | 522 | |
hlipka | 0:41a49a73580c | 523 | //! finds last occurrence of character in string |
hlipka | 0:41a49a73580c | 524 | //! \param c: Character to search for. |
hlipka | 0:41a49a73580c | 525 | //! \return Returns position where the character has been found, |
hlipka | 0:41a49a73580c | 526 | //! or -1 if not found. |
hlipka | 0:41a49a73580c | 527 | s32 findLast(T c) const |
hlipka | 0:41a49a73580c | 528 | { |
hlipka | 0:41a49a73580c | 529 | for (s32 i=used-1; i>=0; --i) |
hlipka | 0:41a49a73580c | 530 | if (array[i] == c) |
hlipka | 0:41a49a73580c | 531 | return i; |
hlipka | 0:41a49a73580c | 532 | |
hlipka | 0:41a49a73580c | 533 | return -1; |
hlipka | 0:41a49a73580c | 534 | } |
hlipka | 0:41a49a73580c | 535 | |
hlipka | 0:41a49a73580c | 536 | |
hlipka | 0:41a49a73580c | 537 | //! Returns a substring |
hlipka | 0:41a49a73580c | 538 | //! \param begin: Start of substring. |
hlipka | 0:41a49a73580c | 539 | //! \param length: Length of substring. |
hlipka | 0:41a49a73580c | 540 | string<T> subString(s32 begin, s32 length) |
hlipka | 0:41a49a73580c | 541 | { |
hlipka | 0:41a49a73580c | 542 | if (length <= 0) |
hlipka | 0:41a49a73580c | 543 | return string<T>(""); |
hlipka | 0:41a49a73580c | 544 | |
hlipka | 0:41a49a73580c | 545 | string<T> o; |
hlipka | 0:41a49a73580c | 546 | o.reserve(length+1); |
hlipka | 0:41a49a73580c | 547 | |
hlipka | 0:41a49a73580c | 548 | for (s32 i=0; i<length; ++i) |
hlipka | 0:41a49a73580c | 549 | o.array[i] = array[i+begin]; |
hlipka | 0:41a49a73580c | 550 | |
hlipka | 0:41a49a73580c | 551 | o.array[length] = 0; |
hlipka | 0:41a49a73580c | 552 | o.used = o.allocated; |
hlipka | 0:41a49a73580c | 553 | |
hlipka | 0:41a49a73580c | 554 | return o; |
hlipka | 0:41a49a73580c | 555 | } |
hlipka | 0:41a49a73580c | 556 | |
hlipka | 0:41a49a73580c | 557 | |
hlipka | 0:41a49a73580c | 558 | void operator += (T c) |
hlipka | 0:41a49a73580c | 559 | { |
hlipka | 0:41a49a73580c | 560 | append(c); |
hlipka | 0:41a49a73580c | 561 | } |
hlipka | 0:41a49a73580c | 562 | |
hlipka | 0:41a49a73580c | 563 | void operator += (const string<T>& other) |
hlipka | 0:41a49a73580c | 564 | { |
hlipka | 0:41a49a73580c | 565 | append(other); |
hlipka | 0:41a49a73580c | 566 | } |
hlipka | 0:41a49a73580c | 567 | |
hlipka | 0:41a49a73580c | 568 | void operator += (int i) |
hlipka | 0:41a49a73580c | 569 | { |
hlipka | 0:41a49a73580c | 570 | append(string<T>(i)); |
hlipka | 0:41a49a73580c | 571 | } |
hlipka | 0:41a49a73580c | 572 | |
hlipka | 0:41a49a73580c | 573 | //! replaces all characters of a special type with another one |
hlipka | 0:41a49a73580c | 574 | void replace(T toReplace, T replaceWith) |
hlipka | 0:41a49a73580c | 575 | { |
hlipka | 0:41a49a73580c | 576 | for (s32 i=0; i<used; ++i) |
hlipka | 0:41a49a73580c | 577 | if (array[i] == toReplace) |
hlipka | 0:41a49a73580c | 578 | array[i] = replaceWith; |
hlipka | 0:41a49a73580c | 579 | } |
hlipka | 0:41a49a73580c | 580 | |
hlipka | 0:41a49a73580c | 581 | //! trims the string. |
hlipka | 0:41a49a73580c | 582 | /** Removes whitespace from begin and end of the string. */ |
hlipka | 0:41a49a73580c | 583 | void trim() |
hlipka | 0:41a49a73580c | 584 | { |
hlipka | 0:41a49a73580c | 585 | const char whitespace[] = " \t\n"; |
hlipka | 0:41a49a73580c | 586 | const int whitespacecount = 3; |
hlipka | 0:41a49a73580c | 587 | |
hlipka | 0:41a49a73580c | 588 | // find start and end of real string without whitespace |
hlipka | 0:41a49a73580c | 589 | int begin = findFirstCharNotInList(whitespace, whitespacecount); |
hlipka | 0:41a49a73580c | 590 | if (begin == -1) |
hlipka | 0:41a49a73580c | 591 | return; |
hlipka | 0:41a49a73580c | 592 | |
hlipka | 0:41a49a73580c | 593 | int end = findLastCharNotInList(whitespace, whitespacecount); |
hlipka | 0:41a49a73580c | 594 | if (end == -1) |
hlipka | 0:41a49a73580c | 595 | return; |
hlipka | 0:41a49a73580c | 596 | |
hlipka | 0:41a49a73580c | 597 | *this = subString(begin, (end +1) - begin); |
hlipka | 0:41a49a73580c | 598 | } |
hlipka | 0:41a49a73580c | 599 | |
hlipka | 0:41a49a73580c | 600 | |
hlipka | 0:41a49a73580c | 601 | //! Erases a character from the string. May be slow, because all elements |
hlipka | 0:41a49a73580c | 602 | //! following after the erased element have to be copied. |
hlipka | 0:41a49a73580c | 603 | //! \param index: Index of element to be erased. |
hlipka | 0:41a49a73580c | 604 | void erase(int index) |
hlipka | 0:41a49a73580c | 605 | { |
hlipka | 0:41a49a73580c | 606 | _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation |
hlipka | 0:41a49a73580c | 607 | |
hlipka | 0:41a49a73580c | 608 | for (int i=index+1; i<used; ++i) |
hlipka | 0:41a49a73580c | 609 | array[i-1] = array[i]; |
hlipka | 0:41a49a73580c | 610 | |
hlipka | 0:41a49a73580c | 611 | --used; |
hlipka | 0:41a49a73580c | 612 | } |
hlipka | 0:41a49a73580c | 613 | |
hlipka | 0:41a49a73580c | 614 | |
hlipka | 0:41a49a73580c | 615 | |
hlipka | 0:41a49a73580c | 616 | private: |
hlipka | 0:41a49a73580c | 617 | |
hlipka | 0:41a49a73580c | 618 | //! Returns a character converted to lower case |
hlipka | 0:41a49a73580c | 619 | T toLower(const T& t) const |
hlipka | 0:41a49a73580c | 620 | { |
hlipka | 0:41a49a73580c | 621 | if (t>=(T)'A' && t<=(T)'Z') |
hlipka | 0:41a49a73580c | 622 | return t + ((T)'a' - (T)'A'); |
hlipka | 0:41a49a73580c | 623 | else |
hlipka | 0:41a49a73580c | 624 | return t; |
hlipka | 0:41a49a73580c | 625 | } |
hlipka | 0:41a49a73580c | 626 | |
hlipka | 0:41a49a73580c | 627 | //! Reallocate the array, make it bigger or smaler |
hlipka | 0:41a49a73580c | 628 | void reallocate(s32 new_size) |
hlipka | 0:41a49a73580c | 629 | { |
hlipka | 0:41a49a73580c | 630 | T* old_array = array; |
hlipka | 0:41a49a73580c | 631 | |
hlipka | 0:41a49a73580c | 632 | array = new T[new_size]; |
hlipka | 0:41a49a73580c | 633 | allocated = new_size; |
hlipka | 0:41a49a73580c | 634 | |
hlipka | 0:41a49a73580c | 635 | s32 amount = used < new_size ? used : new_size; |
hlipka | 0:41a49a73580c | 636 | for (s32 i=0; i<amount; ++i) |
hlipka | 0:41a49a73580c | 637 | array[i] = old_array[i]; |
hlipka | 0:41a49a73580c | 638 | |
hlipka | 0:41a49a73580c | 639 | if (allocated < used) |
hlipka | 0:41a49a73580c | 640 | used = allocated; |
hlipka | 0:41a49a73580c | 641 | |
hlipka | 0:41a49a73580c | 642 | delete [] old_array; |
hlipka | 0:41a49a73580c | 643 | } |
hlipka | 0:41a49a73580c | 644 | |
hlipka | 0:41a49a73580c | 645 | |
hlipka | 0:41a49a73580c | 646 | //--- member variables |
hlipka | 0:41a49a73580c | 647 | |
hlipka | 0:41a49a73580c | 648 | T* array; |
hlipka | 0:41a49a73580c | 649 | s32 allocated; |
hlipka | 0:41a49a73580c | 650 | s32 used; |
hlipka | 0:41a49a73580c | 651 | }; |
hlipka | 0:41a49a73580c | 652 | |
hlipka | 0:41a49a73580c | 653 | |
hlipka | 0:41a49a73580c | 654 | //! Typedef for character strings |
hlipka | 0:41a49a73580c | 655 | typedef string<irr::c8> stringc; |
hlipka | 0:41a49a73580c | 656 | |
hlipka | 0:41a49a73580c | 657 | //! Typedef for wide character strings |
hlipka | 0:41a49a73580c | 658 | typedef string<wchar_t> stringw; |
hlipka | 0:41a49a73580c | 659 | |
hlipka | 0:41a49a73580c | 660 | } // end namespace core |
hlipka | 0:41a49a73580c | 661 | } // end namespace irr |
hlipka | 0:41a49a73580c | 662 | |
hlipka | 0:41a49a73580c | 663 | #endif |