Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Common/String.h |
michael@0 | 2 | |
michael@0 | 3 | #ifndef __COMMON_STRING_H |
michael@0 | 4 | #define __COMMON_STRING_H |
michael@0 | 5 | |
michael@0 | 6 | #include <string.h> |
michael@0 | 7 | // #include <wchar.h> |
michael@0 | 8 | |
michael@0 | 9 | #include "Vector.h" |
michael@0 | 10 | |
michael@0 | 11 | #ifdef _WIN32 |
michael@0 | 12 | #include "MyWindows.h" |
michael@0 | 13 | #endif |
michael@0 | 14 | |
michael@0 | 15 | static const char *kTrimDefaultCharSet = " \n\t"; |
michael@0 | 16 | |
michael@0 | 17 | template <class T> |
michael@0 | 18 | inline int MyStringLen(const T *s) |
michael@0 | 19 | { |
michael@0 | 20 | int i; |
michael@0 | 21 | for (i = 0; s[i] != '\0'; i++); |
michael@0 | 22 | return i; |
michael@0 | 23 | } |
michael@0 | 24 | |
michael@0 | 25 | template <class T> |
michael@0 | 26 | inline T * MyStringCopy(T *dest, const T *src) |
michael@0 | 27 | { |
michael@0 | 28 | T *destStart = dest; |
michael@0 | 29 | while((*dest++ = *src++) != 0); |
michael@0 | 30 | return destStart; |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) |
michael@0 | 34 | { return (p + 1); } |
michael@0 | 35 | inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) |
michael@0 | 36 | { return (p + 1); } |
michael@0 | 37 | inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) |
michael@0 | 38 | { return (p - 1); } |
michael@0 | 39 | inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) |
michael@0 | 40 | { return (p - 1); } |
michael@0 | 41 | |
michael@0 | 42 | #ifdef _WIN32 |
michael@0 | 43 | |
michael@0 | 44 | inline char* MyStringGetNextCharPointer(char *p) |
michael@0 | 45 | { return CharNextA(p); } |
michael@0 | 46 | inline const char* MyStringGetNextCharPointer(const char *p) |
michael@0 | 47 | { return CharNextA(p); } |
michael@0 | 48 | |
michael@0 | 49 | inline char* MyStringGetPrevCharPointer(char *base, char *p) |
michael@0 | 50 | { return CharPrevA(base, p); } |
michael@0 | 51 | inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) |
michael@0 | 52 | { return CharPrevA(base, p); } |
michael@0 | 53 | |
michael@0 | 54 | inline char MyCharUpper(char c) |
michael@0 | 55 | { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } |
michael@0 | 56 | #ifdef _UNICODE |
michael@0 | 57 | inline wchar_t MyCharUpper(wchar_t c) |
michael@0 | 58 | { return (wchar_t)CharUpperW((LPWSTR)c); } |
michael@0 | 59 | #else |
michael@0 | 60 | wchar_t MyCharUpper(wchar_t c); |
michael@0 | 61 | #endif |
michael@0 | 62 | |
michael@0 | 63 | inline char MyCharLower(char c) |
michael@0 | 64 | { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } |
michael@0 | 65 | #ifdef _UNICODE |
michael@0 | 66 | inline wchar_t MyCharLower(wchar_t c) |
michael@0 | 67 | { return (wchar_t)CharLowerW((LPWSTR)c); } |
michael@0 | 68 | #else |
michael@0 | 69 | wchar_t MyCharLower(wchar_t c); |
michael@0 | 70 | #endif |
michael@0 | 71 | |
michael@0 | 72 | inline char * MyStringUpper(char *s) { return CharUpperA(s); } |
michael@0 | 73 | #ifdef _UNICODE |
michael@0 | 74 | inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } |
michael@0 | 75 | #else |
michael@0 | 76 | wchar_t * MyStringUpper(wchar_t *s); |
michael@0 | 77 | #endif |
michael@0 | 78 | |
michael@0 | 79 | inline char * MyStringLower(char *s) { return CharLowerA(s); } |
michael@0 | 80 | #ifdef _UNICODE |
michael@0 | 81 | inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } |
michael@0 | 82 | #else |
michael@0 | 83 | wchar_t * MyStringLower(wchar_t *s); |
michael@0 | 84 | #endif |
michael@0 | 85 | |
michael@0 | 86 | #else // Standard-C |
michael@0 | 87 | wchar_t MyCharUpper(wchar_t c); |
michael@0 | 88 | #endif |
michael@0 | 89 | |
michael@0 | 90 | ////////////////////////////////////// |
michael@0 | 91 | // Compare |
michael@0 | 92 | |
michael@0 | 93 | /* |
michael@0 | 94 | #ifndef _WIN32_WCE |
michael@0 | 95 | int MyStringCollate(const char *s1, const char *s2); |
michael@0 | 96 | int MyStringCollateNoCase(const char *s1, const char *s2); |
michael@0 | 97 | #endif |
michael@0 | 98 | int MyStringCollate(const wchar_t *s1, const wchar_t *s2); |
michael@0 | 99 | int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); |
michael@0 | 100 | */ |
michael@0 | 101 | |
michael@0 | 102 | int MyStringCompare(const char *s1, const char *s2); |
michael@0 | 103 | int MyStringCompare(const wchar_t *s1, const wchar_t *s2); |
michael@0 | 104 | |
michael@0 | 105 | #ifdef _WIN32 |
michael@0 | 106 | int MyStringCompareNoCase(const char *s1, const char *s2); |
michael@0 | 107 | #endif |
michael@0 | 108 | |
michael@0 | 109 | int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); |
michael@0 | 110 | |
michael@0 | 111 | template <class T> |
michael@0 | 112 | class CStringBase |
michael@0 | 113 | { |
michael@0 | 114 | void TrimLeftWithCharSet(const CStringBase &charSet) |
michael@0 | 115 | { |
michael@0 | 116 | const T *p = _chars; |
michael@0 | 117 | while (charSet.Find(*p) >= 0 && (*p != 0)) |
michael@0 | 118 | p = GetNextCharPointer(p); |
michael@0 | 119 | Delete(0, (int)(p - _chars)); |
michael@0 | 120 | } |
michael@0 | 121 | void TrimRightWithCharSet(const CStringBase &charSet) |
michael@0 | 122 | { |
michael@0 | 123 | const T *p = _chars; |
michael@0 | 124 | const T *pLast = NULL; |
michael@0 | 125 | while (*p != 0) |
michael@0 | 126 | { |
michael@0 | 127 | if (charSet.Find(*p) >= 0) |
michael@0 | 128 | { |
michael@0 | 129 | if (pLast == NULL) |
michael@0 | 130 | pLast = p; |
michael@0 | 131 | } |
michael@0 | 132 | else |
michael@0 | 133 | pLast = NULL; |
michael@0 | 134 | p = GetNextCharPointer(p); |
michael@0 | 135 | } |
michael@0 | 136 | if(pLast != NULL) |
michael@0 | 137 | { |
michael@0 | 138 | int i = (int)(pLast - _chars); |
michael@0 | 139 | Delete(i, _length - i); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | } |
michael@0 | 143 | void MoveItems(int destIndex, int srcIndex) |
michael@0 | 144 | { |
michael@0 | 145 | memmove(_chars + destIndex, _chars + srcIndex, |
michael@0 | 146 | sizeof(T) * (_length - srcIndex + 1)); |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | void InsertSpace(int &index, int size) |
michael@0 | 150 | { |
michael@0 | 151 | CorrectIndex(index); |
michael@0 | 152 | GrowLength(size); |
michael@0 | 153 | MoveItems(index + size, index); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | static T *GetNextCharPointer(T *p) |
michael@0 | 157 | { return MyStringGetNextCharPointer(p); } |
michael@0 | 158 | static const T *GetNextCharPointer(const T *p) |
michael@0 | 159 | { return MyStringGetNextCharPointer(p); } |
michael@0 | 160 | static T *GetPrevCharPointer(T *base, T *p) |
michael@0 | 161 | { return MyStringGetPrevCharPointer(base, p); } |
michael@0 | 162 | static const T *GetPrevCharPointer(const T *base, const T *p) |
michael@0 | 163 | { return MyStringGetPrevCharPointer(base, p); } |
michael@0 | 164 | protected: |
michael@0 | 165 | T *_chars; |
michael@0 | 166 | int _length; |
michael@0 | 167 | int _capacity; |
michael@0 | 168 | |
michael@0 | 169 | void SetCapacity(int newCapacity) |
michael@0 | 170 | { |
michael@0 | 171 | int realCapacity = newCapacity + 1; |
michael@0 | 172 | if(realCapacity == _capacity) |
michael@0 | 173 | return; |
michael@0 | 174 | /* |
michael@0 | 175 | const int kMaxStringSize = 0x20000000; |
michael@0 | 176 | #ifndef _WIN32_WCE |
michael@0 | 177 | if(newCapacity > kMaxStringSize || newCapacity < _length) |
michael@0 | 178 | throw 1052337; |
michael@0 | 179 | #endif |
michael@0 | 180 | */ |
michael@0 | 181 | T *newBuffer = new T[realCapacity]; |
michael@0 | 182 | if(_capacity > 0) |
michael@0 | 183 | { |
michael@0 | 184 | for (int i = 0; i < (_length + 1); i++) |
michael@0 | 185 | newBuffer[i] = _chars[i]; |
michael@0 | 186 | delete []_chars; |
michael@0 | 187 | _chars = newBuffer; |
michael@0 | 188 | } |
michael@0 | 189 | else |
michael@0 | 190 | { |
michael@0 | 191 | _chars = newBuffer; |
michael@0 | 192 | _chars[0] = 0; |
michael@0 | 193 | } |
michael@0 | 194 | _capacity = realCapacity; |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | void GrowLength(int n) |
michael@0 | 198 | { |
michael@0 | 199 | int freeSize = _capacity - _length - 1; |
michael@0 | 200 | if (n <= freeSize) |
michael@0 | 201 | return; |
michael@0 | 202 | int delta; |
michael@0 | 203 | if (_capacity > 64) |
michael@0 | 204 | delta = _capacity / 2; |
michael@0 | 205 | else if (_capacity > 8) |
michael@0 | 206 | delta = 16; |
michael@0 | 207 | else |
michael@0 | 208 | delta = 4; |
michael@0 | 209 | if (freeSize + delta < n) |
michael@0 | 210 | delta = n - freeSize; |
michael@0 | 211 | SetCapacity(_capacity + delta); |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | void CorrectIndex(int &index) const |
michael@0 | 215 | { |
michael@0 | 216 | if (index > _length) |
michael@0 | 217 | index = _length; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | public: |
michael@0 | 221 | CStringBase(): _chars(0), _length(0), _capacity(0) |
michael@0 | 222 | { SetCapacity(16 - 1); } |
michael@0 | 223 | CStringBase(T c): _chars(0), _length(0), _capacity(0) |
michael@0 | 224 | { |
michael@0 | 225 | SetCapacity(1); |
michael@0 | 226 | _chars[0] = c; |
michael@0 | 227 | _chars[1] = 0; |
michael@0 | 228 | _length = 1; |
michael@0 | 229 | } |
michael@0 | 230 | CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) |
michael@0 | 231 | { |
michael@0 | 232 | int length = MyStringLen(chars); |
michael@0 | 233 | SetCapacity(length); |
michael@0 | 234 | MyStringCopy(_chars, chars); // can be optimized by memove() |
michael@0 | 235 | _length = length; |
michael@0 | 236 | } |
michael@0 | 237 | CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) |
michael@0 | 238 | { |
michael@0 | 239 | SetCapacity(s._length); |
michael@0 | 240 | MyStringCopy(_chars, s._chars); |
michael@0 | 241 | _length = s._length; |
michael@0 | 242 | } |
michael@0 | 243 | ~CStringBase() { delete []_chars; } |
michael@0 | 244 | |
michael@0 | 245 | operator const T*() const { return _chars;} |
michael@0 | 246 | |
michael@0 | 247 | // The minimum size of the character buffer in characters. |
michael@0 | 248 | // This value does not include space for a null terminator. |
michael@0 | 249 | T* GetBuffer(int minBufLength) |
michael@0 | 250 | { |
michael@0 | 251 | if(minBufLength >= _capacity) |
michael@0 | 252 | SetCapacity(minBufLength + 1); |
michael@0 | 253 | return _chars; |
michael@0 | 254 | } |
michael@0 | 255 | void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } |
michael@0 | 256 | void ReleaseBuffer(int newLength) |
michael@0 | 257 | { |
michael@0 | 258 | /* |
michael@0 | 259 | #ifndef _WIN32_WCE |
michael@0 | 260 | if(newLength >= _capacity) |
michael@0 | 261 | throw 282217; |
michael@0 | 262 | #endif |
michael@0 | 263 | */ |
michael@0 | 264 | _chars[newLength] = 0; |
michael@0 | 265 | _length = newLength; |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | CStringBase& operator=(T c) |
michael@0 | 269 | { |
michael@0 | 270 | Empty(); |
michael@0 | 271 | SetCapacity(1); |
michael@0 | 272 | _chars[0] = c; |
michael@0 | 273 | _chars[1] = 0; |
michael@0 | 274 | _length = 1; |
michael@0 | 275 | return *this; |
michael@0 | 276 | } |
michael@0 | 277 | CStringBase& operator=(const T *chars) |
michael@0 | 278 | { |
michael@0 | 279 | Empty(); |
michael@0 | 280 | int length = MyStringLen(chars); |
michael@0 | 281 | SetCapacity(length); |
michael@0 | 282 | MyStringCopy(_chars, chars); |
michael@0 | 283 | _length = length; |
michael@0 | 284 | return *this; |
michael@0 | 285 | } |
michael@0 | 286 | CStringBase& operator=(const CStringBase& s) |
michael@0 | 287 | { |
michael@0 | 288 | if(&s == this) |
michael@0 | 289 | return *this; |
michael@0 | 290 | Empty(); |
michael@0 | 291 | SetCapacity(s._length); |
michael@0 | 292 | MyStringCopy(_chars, s._chars); |
michael@0 | 293 | _length = s._length; |
michael@0 | 294 | return *this; |
michael@0 | 295 | } |
michael@0 | 296 | |
michael@0 | 297 | CStringBase& operator+=(T c) |
michael@0 | 298 | { |
michael@0 | 299 | GrowLength(1); |
michael@0 | 300 | _chars[_length] = c; |
michael@0 | 301 | _chars[++_length] = 0; |
michael@0 | 302 | return *this; |
michael@0 | 303 | } |
michael@0 | 304 | CStringBase& operator+=(const T *s) |
michael@0 | 305 | { |
michael@0 | 306 | int len = MyStringLen(s); |
michael@0 | 307 | GrowLength(len); |
michael@0 | 308 | MyStringCopy(_chars + _length, s); |
michael@0 | 309 | _length += len; |
michael@0 | 310 | return *this; |
michael@0 | 311 | } |
michael@0 | 312 | CStringBase& operator+=(const CStringBase &s) |
michael@0 | 313 | { |
michael@0 | 314 | GrowLength(s._length); |
michael@0 | 315 | MyStringCopy(_chars + _length, s._chars); |
michael@0 | 316 | _length += s._length; |
michael@0 | 317 | return *this; |
michael@0 | 318 | } |
michael@0 | 319 | void Empty() |
michael@0 | 320 | { |
michael@0 | 321 | _length = 0; |
michael@0 | 322 | _chars[0] = 0; |
michael@0 | 323 | } |
michael@0 | 324 | int Length() const { return _length; } |
michael@0 | 325 | bool IsEmpty() const { return (_length == 0); } |
michael@0 | 326 | |
michael@0 | 327 | CStringBase Mid(int startIndex) const |
michael@0 | 328 | { return Mid(startIndex, _length - startIndex); } |
michael@0 | 329 | CStringBase Mid(int startIndex, int count ) const |
michael@0 | 330 | { |
michael@0 | 331 | if (startIndex + count > _length) |
michael@0 | 332 | count = _length - startIndex; |
michael@0 | 333 | |
michael@0 | 334 | if (startIndex == 0 && startIndex + count == _length) |
michael@0 | 335 | return *this; |
michael@0 | 336 | |
michael@0 | 337 | CStringBase<T> result; |
michael@0 | 338 | result.SetCapacity(count); |
michael@0 | 339 | // MyStringNCopy(result._chars, _chars + startIndex, count); |
michael@0 | 340 | for (int i = 0; i < count; i++) |
michael@0 | 341 | result._chars[i] = _chars[startIndex + i]; |
michael@0 | 342 | result._chars[count] = 0; |
michael@0 | 343 | result._length = count; |
michael@0 | 344 | return result; |
michael@0 | 345 | } |
michael@0 | 346 | CStringBase Left(int count) const |
michael@0 | 347 | { return Mid(0, count); } |
michael@0 | 348 | CStringBase Right(int count) const |
michael@0 | 349 | { |
michael@0 | 350 | if (count > _length) |
michael@0 | 351 | count = _length; |
michael@0 | 352 | return Mid(_length - count, count); |
michael@0 | 353 | } |
michael@0 | 354 | |
michael@0 | 355 | void MakeUpper() |
michael@0 | 356 | { MyStringUpper(_chars); } |
michael@0 | 357 | void MakeLower() |
michael@0 | 358 | { MyStringLower(_chars); } |
michael@0 | 359 | |
michael@0 | 360 | int Compare(const CStringBase& s) const |
michael@0 | 361 | { return MyStringCompare(_chars, s._chars); } |
michael@0 | 362 | |
michael@0 | 363 | int CompareNoCase(const CStringBase& s) const |
michael@0 | 364 | { return MyStringCompareNoCase(_chars, s._chars); } |
michael@0 | 365 | /* |
michael@0 | 366 | int Collate(const CStringBase& s) const |
michael@0 | 367 | { return MyStringCollate(_chars, s._chars); } |
michael@0 | 368 | int CollateNoCase(const CStringBase& s) const |
michael@0 | 369 | { return MyStringCollateNoCase(_chars, s._chars); } |
michael@0 | 370 | */ |
michael@0 | 371 | |
michael@0 | 372 | int Find(T c) const { return Find(c, 0); } |
michael@0 | 373 | int Find(T c, int startIndex) const |
michael@0 | 374 | { |
michael@0 | 375 | T *p = _chars + startIndex; |
michael@0 | 376 | while (true) |
michael@0 | 377 | { |
michael@0 | 378 | if (*p == c) |
michael@0 | 379 | return (int)(p - _chars); |
michael@0 | 380 | if (*p == 0) |
michael@0 | 381 | return -1; |
michael@0 | 382 | p = GetNextCharPointer(p); |
michael@0 | 383 | } |
michael@0 | 384 | } |
michael@0 | 385 | int Find(const CStringBase &s) const { return Find(s, 0); } |
michael@0 | 386 | int Find(const CStringBase &s, int startIndex) const |
michael@0 | 387 | { |
michael@0 | 388 | if (s.IsEmpty()) |
michael@0 | 389 | return startIndex; |
michael@0 | 390 | for (; startIndex < _length; startIndex++) |
michael@0 | 391 | { |
michael@0 | 392 | int j; |
michael@0 | 393 | for (j = 0; j < s._length && startIndex + j < _length; j++) |
michael@0 | 394 | if (_chars[startIndex+j] != s._chars[j]) |
michael@0 | 395 | break; |
michael@0 | 396 | if (j == s._length) |
michael@0 | 397 | return startIndex; |
michael@0 | 398 | } |
michael@0 | 399 | return -1; |
michael@0 | 400 | } |
michael@0 | 401 | int ReverseFind(T c) const |
michael@0 | 402 | { |
michael@0 | 403 | if (_length == 0) |
michael@0 | 404 | return -1; |
michael@0 | 405 | T *p = _chars + _length - 1; |
michael@0 | 406 | while (true) |
michael@0 | 407 | { |
michael@0 | 408 | if (*p == c) |
michael@0 | 409 | return (int)(p - _chars); |
michael@0 | 410 | if (p == _chars) |
michael@0 | 411 | return -1; |
michael@0 | 412 | p = GetPrevCharPointer(_chars, p); |
michael@0 | 413 | } |
michael@0 | 414 | } |
michael@0 | 415 | int FindOneOf(const CStringBase &s) const |
michael@0 | 416 | { |
michael@0 | 417 | for(int i = 0; i < _length; i++) |
michael@0 | 418 | if (s.Find(_chars[i]) >= 0) |
michael@0 | 419 | return i; |
michael@0 | 420 | return -1; |
michael@0 | 421 | } |
michael@0 | 422 | |
michael@0 | 423 | void TrimLeft(T c) |
michael@0 | 424 | { |
michael@0 | 425 | const T *p = _chars; |
michael@0 | 426 | while (c == *p) |
michael@0 | 427 | p = GetNextCharPointer(p); |
michael@0 | 428 | Delete(0, p - _chars); |
michael@0 | 429 | } |
michael@0 | 430 | private: |
michael@0 | 431 | CStringBase GetTrimDefaultCharSet() |
michael@0 | 432 | { |
michael@0 | 433 | CStringBase<T> charSet; |
michael@0 | 434 | for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / |
michael@0 | 435 | sizeof(kTrimDefaultCharSet[0])); i++) |
michael@0 | 436 | charSet += (T)kTrimDefaultCharSet[i]; |
michael@0 | 437 | return charSet; |
michael@0 | 438 | } |
michael@0 | 439 | public: |
michael@0 | 440 | |
michael@0 | 441 | void TrimLeft() |
michael@0 | 442 | { |
michael@0 | 443 | TrimLeftWithCharSet(GetTrimDefaultCharSet()); |
michael@0 | 444 | } |
michael@0 | 445 | void TrimRight() |
michael@0 | 446 | { |
michael@0 | 447 | TrimRightWithCharSet(GetTrimDefaultCharSet()); |
michael@0 | 448 | } |
michael@0 | 449 | void TrimRight(T c) |
michael@0 | 450 | { |
michael@0 | 451 | const T *p = _chars; |
michael@0 | 452 | const T *pLast = NULL; |
michael@0 | 453 | while (*p != 0) |
michael@0 | 454 | { |
michael@0 | 455 | if (*p == c) |
michael@0 | 456 | { |
michael@0 | 457 | if (pLast == NULL) |
michael@0 | 458 | pLast = p; |
michael@0 | 459 | } |
michael@0 | 460 | else |
michael@0 | 461 | pLast = NULL; |
michael@0 | 462 | p = GetNextCharPointer(p); |
michael@0 | 463 | } |
michael@0 | 464 | if(pLast != NULL) |
michael@0 | 465 | { |
michael@0 | 466 | int i = pLast - _chars; |
michael@0 | 467 | Delete(i, _length - i); |
michael@0 | 468 | } |
michael@0 | 469 | } |
michael@0 | 470 | void Trim() |
michael@0 | 471 | { |
michael@0 | 472 | TrimRight(); |
michael@0 | 473 | TrimLeft(); |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | int Insert(int index, T c) |
michael@0 | 477 | { |
michael@0 | 478 | InsertSpace(index, 1); |
michael@0 | 479 | _chars[index] = c; |
michael@0 | 480 | _length++; |
michael@0 | 481 | return _length; |
michael@0 | 482 | } |
michael@0 | 483 | int Insert(int index, const CStringBase &s) |
michael@0 | 484 | { |
michael@0 | 485 | CorrectIndex(index); |
michael@0 | 486 | if (s.IsEmpty()) |
michael@0 | 487 | return _length; |
michael@0 | 488 | int numInsertChars = s.Length(); |
michael@0 | 489 | InsertSpace(index, numInsertChars); |
michael@0 | 490 | for(int i = 0; i < numInsertChars; i++) |
michael@0 | 491 | _chars[index + i] = s[i]; |
michael@0 | 492 | _length += numInsertChars; |
michael@0 | 493 | return _length; |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | // !!!!!!!!!!!!!!! test it if newChar = '\0' |
michael@0 | 497 | int Replace(T oldChar, T newChar) |
michael@0 | 498 | { |
michael@0 | 499 | if (oldChar == newChar) |
michael@0 | 500 | return 0; |
michael@0 | 501 | int number = 0; |
michael@0 | 502 | int pos = 0; |
michael@0 | 503 | while (pos < Length()) |
michael@0 | 504 | { |
michael@0 | 505 | pos = Find(oldChar, pos); |
michael@0 | 506 | if (pos < 0) |
michael@0 | 507 | break; |
michael@0 | 508 | _chars[pos] = newChar; |
michael@0 | 509 | pos++; |
michael@0 | 510 | number++; |
michael@0 | 511 | } |
michael@0 | 512 | return number; |
michael@0 | 513 | } |
michael@0 | 514 | int Replace(const CStringBase &oldString, const CStringBase &newString) |
michael@0 | 515 | { |
michael@0 | 516 | if (oldString.IsEmpty()) |
michael@0 | 517 | return 0; |
michael@0 | 518 | if (oldString == newString) |
michael@0 | 519 | return 0; |
michael@0 | 520 | int oldStringLength = oldString.Length(); |
michael@0 | 521 | int newStringLength = newString.Length(); |
michael@0 | 522 | int number = 0; |
michael@0 | 523 | int pos = 0; |
michael@0 | 524 | while (pos < _length) |
michael@0 | 525 | { |
michael@0 | 526 | pos = Find(oldString, pos); |
michael@0 | 527 | if (pos < 0) |
michael@0 | 528 | break; |
michael@0 | 529 | Delete(pos, oldStringLength); |
michael@0 | 530 | Insert(pos, newString); |
michael@0 | 531 | pos += newStringLength; |
michael@0 | 532 | number++; |
michael@0 | 533 | } |
michael@0 | 534 | return number; |
michael@0 | 535 | } |
michael@0 | 536 | int Delete(int index, int count = 1 ) |
michael@0 | 537 | { |
michael@0 | 538 | if (index + count > _length) |
michael@0 | 539 | count = _length - index; |
michael@0 | 540 | if (count > 0) |
michael@0 | 541 | { |
michael@0 | 542 | MoveItems(index, index + count); |
michael@0 | 543 | _length -= count; |
michael@0 | 544 | } |
michael@0 | 545 | return _length; |
michael@0 | 546 | } |
michael@0 | 547 | }; |
michael@0 | 548 | |
michael@0 | 549 | template <class T> |
michael@0 | 550 | CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) |
michael@0 | 551 | { |
michael@0 | 552 | CStringBase<T> result(s1); |
michael@0 | 553 | result += s2; |
michael@0 | 554 | return result; |
michael@0 | 555 | } |
michael@0 | 556 | |
michael@0 | 557 | template <class T> |
michael@0 | 558 | CStringBase<T> operator+(const CStringBase<T>& s, T c) |
michael@0 | 559 | { |
michael@0 | 560 | CStringBase<T> result(s); |
michael@0 | 561 | result += c; |
michael@0 | 562 | return result; |
michael@0 | 563 | } |
michael@0 | 564 | |
michael@0 | 565 | template <class T> |
michael@0 | 566 | CStringBase<T> operator+(T c, const CStringBase<T>& s) |
michael@0 | 567 | { |
michael@0 | 568 | CStringBase<T> result(c); |
michael@0 | 569 | result += s; |
michael@0 | 570 | return result; |
michael@0 | 571 | } |
michael@0 | 572 | |
michael@0 | 573 | template <class T> |
michael@0 | 574 | CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) |
michael@0 | 575 | { |
michael@0 | 576 | CStringBase<T> result(s); |
michael@0 | 577 | result += chars; |
michael@0 | 578 | return result; |
michael@0 | 579 | } |
michael@0 | 580 | |
michael@0 | 581 | template <class T> |
michael@0 | 582 | CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) |
michael@0 | 583 | { |
michael@0 | 584 | CStringBase<T> result(chars); |
michael@0 | 585 | result += s; |
michael@0 | 586 | return result; |
michael@0 | 587 | } |
michael@0 | 588 | |
michael@0 | 589 | template <class T> |
michael@0 | 590 | bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) |
michael@0 | 591 | { return (s1.Compare(s2) == 0); } |
michael@0 | 592 | |
michael@0 | 593 | template <class T> |
michael@0 | 594 | bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) |
michael@0 | 595 | { return (s1.Compare(s2) < 0); } |
michael@0 | 596 | |
michael@0 | 597 | template <class T> |
michael@0 | 598 | bool operator==(const T *s1, const CStringBase<T>& s2) |
michael@0 | 599 | { return (s2.Compare(s1) == 0); } |
michael@0 | 600 | |
michael@0 | 601 | template <class T> |
michael@0 | 602 | bool operator==(const CStringBase<T>& s1, const T *s2) |
michael@0 | 603 | { return (s1.Compare(s2) == 0); } |
michael@0 | 604 | |
michael@0 | 605 | template <class T> |
michael@0 | 606 | bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) |
michael@0 | 607 | { return (s1.Compare(s2) != 0); } |
michael@0 | 608 | |
michael@0 | 609 | template <class T> |
michael@0 | 610 | bool operator!=(const T *s1, const CStringBase<T>& s2) |
michael@0 | 611 | { return (s2.Compare(s1) != 0); } |
michael@0 | 612 | |
michael@0 | 613 | template <class T> |
michael@0 | 614 | bool operator!=(const CStringBase<T>& s1, const T *s2) |
michael@0 | 615 | { return (s1.Compare(s2) != 0); } |
michael@0 | 616 | |
michael@0 | 617 | typedef CStringBase<char> AString; |
michael@0 | 618 | typedef CStringBase<wchar_t> UString; |
michael@0 | 619 | |
michael@0 | 620 | typedef CObjectVector<AString> AStringVector; |
michael@0 | 621 | typedef CObjectVector<UString> UStringVector; |
michael@0 | 622 | |
michael@0 | 623 | #ifdef _UNICODE |
michael@0 | 624 | typedef UString CSysString; |
michael@0 | 625 | #else |
michael@0 | 626 | typedef AString CSysString; |
michael@0 | 627 | #endif |
michael@0 | 628 | |
michael@0 | 629 | typedef CObjectVector<CSysString> CSysStringVector; |
michael@0 | 630 | |
michael@0 | 631 | #endif |