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