00001
00002
00003
00004
00005 #ifndef __COMMON_STRING_H
00006 #define __COMMON_STRING_H
00007
00008 #include <string.h>
00009
00010 #include "Vector.h"
00011
00012 #ifdef _WIN32
00013 #include "MyWindows.h"
00014 #endif
00015
00016 static const char *kTrimDefaultCharSet = " \n\t";
00017
00018 template <class T>
00019 inline int MyStringLen(const T *s)
00020 {
00021 int i;
00022 for (i = 0; s[i] != '\0'; i++);
00023 return i;
00024 }
00025
00026 template <class T>
00027 inline T * MyStringCopy(T *dest, const T *src)
00028 {
00029 T *destStart = dest;
00030 while((*dest++ = *src++) != 0);
00031 return destStart;
00032 }
00033
00034 inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
00035 { return (p + 1); }
00036 inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
00037 { return (p + 1); }
00038 inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
00039 { return (p - 1); }
00040 inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
00041 { return (p - 1); }
00042
00043 #ifdef _WIN32
00044
00045 inline char* MyStringGetNextCharPointer(char *p)
00046 { return CharNextA(p); }
00047 inline const char* MyStringGetNextCharPointer(const char *p)
00048 { return CharNextA(p); }
00049
00050 inline char* MyStringGetPrevCharPointer(char *base, char *p)
00051 { return CharPrevA(base, p); }
00052 inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
00053 { return CharPrevA(base, p); }
00054
00055 inline char MyCharUpper(char c)
00056 { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); }
00057 #ifdef _UNICODE
00058 inline wchar_t MyCharUpper(wchar_t c)
00059 { return (wchar_t)CharUpperW((LPWSTR)c); }
00060 #else
00061 wchar_t MyCharUpper(wchar_t c);
00062 #endif
00063
00064 inline char MyCharLower(char c)
00065 { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); }
00066 #ifdef _UNICODE
00067 inline wchar_t MyCharLower(wchar_t c)
00068 { return (wchar_t)CharLowerW((LPWSTR)c); }
00069 #else
00070 wchar_t MyCharLower(wchar_t c);
00071 #endif
00072
00073 inline char * MyStringUpper(char *s) { return CharUpperA(s); }
00074 #ifdef _UNICODE
00075 inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
00076 #else
00077 wchar_t * MyStringUpper(wchar_t *s);
00078 #endif
00079
00080 inline char * MyStringLower(char *s) { return CharLowerA(s); }
00081 #ifdef _UNICODE
00082 inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
00083 #else
00084 wchar_t * MyStringLower(wchar_t *s);
00085 #endif
00086
00087 #else
00088 wchar_t MyCharUpper(wchar_t c);
00089 #endif
00090
00091 int MyStringCompare(const char *s1, const char *s2);
00092 int MyStringCompare(const wchar_t *s1, const wchar_t *s2);
00093
00094 #ifdef _WIN32
00095 int MyStringCompareNoCase(const char *s1, const char *s2);
00096 #endif
00097
00098 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);
00099
00100 template <class T>
00101 class CStringBase
00102 {
00103 void TrimLeftWithCharSet(const CStringBase &charSet)
00104 {
00105 const T *p = _chars;
00106 while (charSet.Find(*p) >= 0 && (*p != 0))
00107 p = GetNextCharPointer(p);
00108 Delete(0, (int)(p - _chars));
00109 }
00110 void TrimRightWithCharSet(const CStringBase &charSet)
00111 {
00112 const T *p = _chars;
00113 const T *pLast = NULL;
00114 while (*p != 0)
00115 {
00116 if (charSet.Find(*p) >= 0)
00117 {
00118 if (pLast == NULL)
00119 pLast = p;
00120 }
00121 else
00122 pLast = NULL;
00123 p = GetNextCharPointer(p);
00124 }
00125 if(pLast != NULL)
00126 {
00127 int i = (int)(pLast - _chars);
00128 Delete(i, _length - i);
00129 }
00130
00131 }
00132 void MoveItems(int destIndex, int srcIndex)
00133 {
00134 memmove(_chars + destIndex, _chars + srcIndex,
00135 sizeof(T) * (_length - srcIndex + 1));
00136 }
00137
00138 void InsertSpace(int &index, int size)
00139 {
00140 CorrectIndex(index);
00141 GrowLength(size);
00142 MoveItems(index + size, index);
00143 }
00144
00145 static T *GetNextCharPointer(T *p)
00146 { return MyStringGetNextCharPointer(p); }
00147 static const T *GetNextCharPointer(const T *p)
00148 { return MyStringGetNextCharPointer(p); }
00149 static T *GetPrevCharPointer(T *base, T *p)
00150 { return MyStringGetPrevCharPointer(base, p); }
00151 static const T *GetPrevCharPointer(const T *base, const T *p)
00152 { return MyStringGetPrevCharPointer(base, p); }
00153 protected:
00154 T *_chars;
00155 int _length;
00156 int _capacity;
00157
00158 void SetCapacity(int newCapacity)
00159 {
00160 int realCapacity = newCapacity + 1;
00161 if(realCapacity == _capacity)
00162 return;
00163
00164 T *newBuffer = new T[realCapacity];
00165 if(_capacity > 0)
00166 {
00167 for (int i = 0; i < (_length + 1); i++)
00168 newBuffer[i] = _chars[i];
00169 delete []_chars;
00170 _chars = newBuffer;
00171 }
00172 else
00173 {
00174 _chars = newBuffer;
00175 _chars[0] = 0;
00176 }
00177 _capacity = realCapacity;
00178 }
00179
00180 void GrowLength(int n)
00181 {
00182 int freeSize = _capacity - _length - 1;
00183 if (n <= freeSize)
00184 return;
00185 int delta;
00186 if (_capacity > 64)
00187 delta = _capacity / 2;
00188 else if (_capacity > 8)
00189 delta = 16;
00190 else
00191 delta = 4;
00192 if (freeSize + delta < n)
00193 delta = n - freeSize;
00194 SetCapacity(_capacity + delta);
00195 }
00196
00197 void CorrectIndex(int &index) const
00198 {
00199 if (index > _length)
00200 index = _length;
00201 }
00202
00203 public:
00204 CStringBase(): _chars(0), _length(0), _capacity(0)
00205 { SetCapacity(16 - 1); }
00206 CStringBase(T c): _chars(0), _length(0), _capacity(0)
00207 {
00208 SetCapacity(1);
00209 _chars[0] = c;
00210 _chars[1] = 0;
00211 _length = 1;
00212 }
00213 CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)
00214 {
00215 int length = MyStringLen(chars);
00216 SetCapacity(length);
00217 MyStringCopy(_chars, chars);
00218 _length = length;
00219 }
00220 CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0)
00221 {
00222 SetCapacity(s._length);
00223 MyStringCopy(_chars, s._chars);
00224 _length = s._length;
00225 }
00226 ~CStringBase() { delete []_chars; }
00227
00228 operator const T*() const { return _chars;}
00229
00230
00231
00232 T* GetBuffer(int minBufLength)
00233 {
00234 if(minBufLength >= _capacity)
00235 SetCapacity(minBufLength + 1);
00236 return _chars;
00237 }
00238 void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
00239 void ReleaseBuffer(int newLength)
00240 {
00241
00242 _chars[newLength] = 0;
00243 _length = newLength;
00244 }
00245
00246 CStringBase& operator=(T c)
00247 {
00248 Empty();
00249 SetCapacity(1);
00250 _chars[0] = c;
00251 _chars[1] = 0;
00252 _length = 1;
00253 return *this;
00254 }
00255 CStringBase& operator=(const T *chars)
00256 {
00257 Empty();
00258 int length = MyStringLen(chars);
00259 SetCapacity(length);
00260 MyStringCopy(_chars, chars);
00261 _length = length;
00262 return *this;
00263 }
00264 CStringBase& operator=(const CStringBase& s)
00265 {
00266 if(&s == this)
00267 return *this;
00268 Empty();
00269 SetCapacity(s._length);
00270 MyStringCopy(_chars, s._chars);
00271 _length = s._length;
00272 return *this;
00273 }
00274
00275 CStringBase& operator+=(T c)
00276 {
00277 GrowLength(1);
00278 _chars[_length] = c;
00279 _chars[++_length] = 0;
00280 return *this;
00281 }
00282 CStringBase& operator+=(const T *s)
00283 {
00284 int len = MyStringLen(s);
00285 GrowLength(len);
00286 MyStringCopy(_chars + _length, s);
00287 _length += len;
00288 return *this;
00289 }
00290 CStringBase& operator+=(const CStringBase &s)
00291 {
00292 GrowLength(s._length);
00293 MyStringCopy(_chars + _length, s._chars);
00294 _length += s._length;
00295 return *this;
00296 }
00297 void Empty()
00298 {
00299 _length = 0;
00300 _chars[0] = 0;
00301 }
00302 int Length() const { return _length; }
00303 bool IsEmpty() const { return (_length == 0); }
00304
00305 CStringBase Mid(int startIndex) const
00306 { return Mid(startIndex, _length - startIndex); }
00307 CStringBase Mid(int startIndex, int count ) const
00308 {
00309 if (startIndex + count > _length)
00310 count = _length - startIndex;
00311
00312 if (startIndex == 0 && startIndex + count == _length)
00313 return *this;
00314
00315 CStringBase<T> result;
00316 result.SetCapacity(count);
00317
00318 for (int i = 0; i < count; i++)
00319 result._chars[i] = _chars[startIndex + i];
00320 result._chars[count] = 0;
00321 result._length = count;
00322 return result;
00323 }
00324 CStringBase Left(int count) const
00325 { return Mid(0, count); }
00326 CStringBase Right(int count) const
00327 {
00328 if (count > _length)
00329 count = _length;
00330 return Mid(_length - count, count);
00331 }
00332
00333 void MakeUpper()
00334 { MyStringUpper(_chars); }
00335 void MakeLower()
00336 { MyStringLower(_chars); }
00337
00338 int Compare(const CStringBase& s) const
00339 { return MyStringCompare(_chars, s._chars); }
00340
00341 int CompareNoCase(const CStringBase& s) const
00342 { return MyStringCompareNoCase(_chars, s._chars); }
00343
00344
00345 int Find(T c) const { return Find(c, 0); }
00346 int Find(T c, int startIndex) const
00347 {
00348 T *p = _chars + startIndex;
00349 while (true)
00350 {
00351 if (*p == c)
00352 return (int)(p - _chars);
00353 if (*p == 0)
00354 return -1;
00355 p = GetNextCharPointer(p);
00356 }
00357 }
00358 int Find(const CStringBase &s) const { return Find(s, 0); }
00359 int Find(const CStringBase &s, int startIndex) const
00360 {
00361 if (s.IsEmpty())
00362 return startIndex;
00363 for (; startIndex < _length; startIndex++)
00364 {
00365 int j;
00366 for (j = 0; j < s._length && startIndex + j < _length; j++)
00367 if (_chars[startIndex+j] != s._chars[j])
00368 break;
00369 if (j == s._length)
00370 return startIndex;
00371 }
00372 return -1;
00373 }
00374 int ReverseFind(T c) const
00375 {
00376 if (_length == 0)
00377 return -1;
00378 T *p = _chars + _length - 1;
00379 while (true)
00380 {
00381 if (*p == c)
00382 return (int)(p - _chars);
00383 if (p == _chars)
00384 return -1;
00385 p = GetPrevCharPointer(_chars, p);
00386 }
00387 }
00388 int FindOneOf(const CStringBase &s) const
00389 {
00390 for(int i = 0; i < _length; i++)
00391 if (s.Find(_chars[i]) >= 0)
00392 return i;
00393 return -1;
00394 }
00395
00396 void TrimLeft(T c)
00397 {
00398 const T *p = _chars;
00399 while (c == *p)
00400 p = GetNextCharPointer(p);
00401 Delete(0, p - _chars);
00402 }
00403 private:
00404 CStringBase GetTrimDefaultCharSet()
00405 {
00406 CStringBase<T> charSet;
00407 for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) /
00408 sizeof(kTrimDefaultCharSet[0])); i++)
00409 charSet += (T)kTrimDefaultCharSet[i];
00410 return charSet;
00411 }
00412 public:
00413
00414 void TrimLeft()
00415 {
00416 TrimLeftWithCharSet(GetTrimDefaultCharSet());
00417 }
00418 void TrimRight()
00419 {
00420 TrimRightWithCharSet(GetTrimDefaultCharSet());
00421 }
00422 void TrimRight(T c)
00423 {
00424 const T *p = _chars;
00425 const T *pLast = NULL;
00426 while (*p != 0)
00427 {
00428 if (*p == c)
00429 {
00430 if (pLast == NULL)
00431 pLast = p;
00432 }
00433 else
00434 pLast = NULL;
00435 p = GetNextCharPointer(p);
00436 }
00437 if(pLast != NULL)
00438 {
00439 int i = pLast - _chars;
00440 Delete(i, _length - i);
00441 }
00442 }
00443 void Trim()
00444 {
00445 TrimRight();
00446 TrimLeft();
00447 }
00448
00449 int Insert(int index, T c)
00450 {
00451 InsertSpace(index, 1);
00452 _chars[index] = c;
00453 _length++;
00454 return _length;
00455 }
00456 int Insert(int index, const CStringBase &s)
00457 {
00458 CorrectIndex(index);
00459 if (s.IsEmpty())
00460 return _length;
00461 int numInsertChars = s.Length();
00462 InsertSpace(index, numInsertChars);
00463 for(int i = 0; i < numInsertChars; i++)
00464 _chars[index + i] = s[i];
00465 _length += numInsertChars;
00466 return _length;
00467 }
00468
00469
00470 int Replace(T oldChar, T newChar)
00471 {
00472 if (oldChar == newChar)
00473 return 0;
00474 int number = 0;
00475 int pos = 0;
00476 while (pos < Length())
00477 {
00478 pos = Find(oldChar, pos);
00479 if (pos < 0)
00480 break;
00481 _chars[pos] = newChar;
00482 pos++;
00483 number++;
00484 }
00485 return number;
00486 }
00487 int Replace(const CStringBase &oldString, const CStringBase &newString)
00488 {
00489 if (oldString.IsEmpty())
00490 return 0;
00491 if (oldString == newString)
00492 return 0;
00493 int oldStringLength = oldString.Length();
00494 int newStringLength = newString.Length();
00495 int number = 0;
00496 int pos = 0;
00497 while (pos < _length)
00498 {
00499 pos = Find(oldString, pos);
00500 if (pos < 0)
00501 break;
00502 Delete(pos, oldStringLength);
00503 Insert(pos, newString);
00504 pos += newStringLength;
00505 number++;
00506 }
00507 return number;
00508 }
00509 int Delete(int index, int count = 1 )
00510 {
00511 if (index + count > _length)
00512 count = _length - index;
00513 if (count > 0)
00514 {
00515 MoveItems(index, index + count);
00516 _length -= count;
00517 }
00518 return _length;
00519 }
00520 };
00521
00522 template <class T>
00523 CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
00524 {
00525 CStringBase<T> result(s1);
00526 result += s2;
00527 return result;
00528 }
00529
00530 template <class T>
00531 CStringBase<T> operator+(const CStringBase<T>& s, T c)
00532 {
00533 CStringBase<T> result(s);
00534 result += c;
00535 return result;
00536 }
00537
00538 template <class T>
00539 CStringBase<T> operator+(T c, const CStringBase<T>& s)
00540 {
00541 CStringBase<T> result(c);
00542 result += s;
00543 return result;
00544 }
00545
00546 template <class T>
00547 CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
00548 {
00549 CStringBase<T> result(s);
00550 result += chars;
00551 return result;
00552 }
00553
00554 template <class T>
00555 CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
00556 {
00557 CStringBase<T> result(chars);
00558 result += s;
00559 return result;
00560 }
00561
00562 template <class T>
00563 bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
00564 { return (s1.Compare(s2) == 0); }
00565
00566 template <class T>
00567 bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
00568 { return (s1.Compare(s2) < 0); }
00569
00570 template <class T>
00571 bool operator==(const T *s1, const CStringBase<T>& s2)
00572 { return (s2.Compare(s1) == 0); }
00573
00574 template <class T>
00575 bool operator==(const CStringBase<T>& s1, const T *s2)
00576 { return (s1.Compare(s2) == 0); }
00577
00578 template <class T>
00579 bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
00580 { return (s1.Compare(s2) != 0); }
00581
00582 template <class T>
00583 bool operator!=(const T *s1, const CStringBase<T>& s2)
00584 { return (s2.Compare(s1) != 0); }
00585
00586 template <class T>
00587 bool operator!=(const CStringBase<T>& s1, const T *s2)
00588 { return (s1.Compare(s2) != 0); }
00589
00590 typedef CStringBase<char> AString;
00591 typedef CStringBase<wchar_t> UString;
00592
00593 typedef CObjectVector<AString> AStringVector;
00594 typedef CObjectVector<UString> UStringVector;
00595
00596 #ifdef _UNICODE
00597 typedef UString CSysString;
00598 #else
00599 typedef AString CSysString;
00600 #endif
00601
00602 typedef CObjectVector<CSysString> CSysStringVector;
00603
00604 #endif