MyString.h 14 KB

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