String.h 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. #pragma once
  2. #include <string>
  3. #include "BFPlatform.h"
  4. #include "Array.h"
  5. #include "SizedArray.h"
  6. NS_BF_BEGIN;
  7. template <const int TBufSize>
  8. class StringT;
  9. typedef StringT<16> String;
  10. struct StringSplitEnumerator;
  11. class StringView
  12. {
  13. public:
  14. enum CompareKind
  15. {
  16. CompareKind_CurrentCulture = 0,
  17. CompareKind_CurrentCultureIgnoreCase = 1,
  18. CompareKind_InvariantCulture = 2,
  19. CompareKind_InvariantCultureIgnoreCase = 3,
  20. CompareKind_Ordinal = 4,
  21. CompareKind_OrdinalIgnoreCase = 5,
  22. };
  23. public:
  24. const char* mPtr;
  25. intptr mLength;
  26. public:
  27. struct iterator
  28. {
  29. public:
  30. typedef std::random_access_iterator_tag iterator_category;
  31. typedef char value_type;
  32. typedef intptr difference_type;
  33. typedef char* pointer;
  34. typedef char& reference;
  35. public:
  36. char* mPtr;
  37. public:
  38. iterator(char* ptr)
  39. {
  40. mPtr = ptr;
  41. }
  42. iterator& operator++()
  43. {
  44. mPtr++;
  45. return *this;
  46. }
  47. iterator operator++(int)
  48. {
  49. auto prevVal = *this;
  50. mPtr++;
  51. return prevVal;
  52. }
  53. bool operator!=(const iterator& itr) const
  54. {
  55. return itr.mPtr != mPtr;
  56. }
  57. bool operator==(const iterator& itr) const
  58. {
  59. return itr.mPtr == mPtr;
  60. }
  61. intptr operator-(const iterator& itr) const
  62. {
  63. return mPtr - itr.mPtr;
  64. }
  65. iterator operator+(intptr offset) const
  66. {
  67. iterator itr(mPtr + offset);
  68. return itr;
  69. }
  70. char& operator*()
  71. {
  72. return *mPtr;
  73. }
  74. char* operator->()
  75. {
  76. return mPtr;
  77. }
  78. bool operator<(const iterator& val2)
  79. {
  80. return mPtr < val2.mPtr;
  81. }
  82. };
  83. struct const_iterator
  84. {
  85. public:
  86. typedef std::random_access_iterator_tag iterator_category;
  87. typedef char value_type;
  88. typedef intptr difference_type;
  89. typedef const char* pointer;
  90. typedef const char& reference;
  91. public:
  92. const char* mPtr;
  93. public:
  94. const_iterator(const char* ptr)
  95. {
  96. mPtr = ptr;
  97. }
  98. const_iterator& operator++()
  99. {
  100. mPtr++;
  101. return *this;
  102. }
  103. const_iterator operator++(int)
  104. {
  105. auto prevVal = *this;
  106. mPtr++;
  107. return prevVal;
  108. }
  109. bool operator!=(const const_iterator& itr) const
  110. {
  111. return itr.mPtr != mPtr;
  112. }
  113. bool operator==(const const_iterator& itr) const
  114. {
  115. return itr.mPtr == mPtr;
  116. }
  117. intptr operator-(const iterator& itr) const
  118. {
  119. return mPtr - itr.mPtr;
  120. }
  121. const_iterator operator+(intptr offset) const
  122. {
  123. const_iterator itr(mPtr + offset);
  124. return itr;
  125. }
  126. const char& operator*()
  127. {
  128. return *mPtr;
  129. }
  130. const char* operator->()
  131. {
  132. return mPtr;
  133. }
  134. bool operator<(const const_iterator& val2)
  135. {
  136. return mPtr < val2.mPtr;
  137. }
  138. };
  139. public:
  140. StringView()
  141. {
  142. this->mPtr = NULL;
  143. this->mLength = 0;
  144. }
  145. StringView(const StringView& sv)
  146. {
  147. this->mPtr = sv.mPtr;
  148. this->mLength = sv.mLength;
  149. }
  150. StringView(const StringView& sv, int offset)
  151. {
  152. this->mPtr = sv.mPtr + offset;
  153. this->mLength = sv.mLength - offset;
  154. }
  155. StringView(const StringView& sv, int offset, int length)
  156. {
  157. this->mPtr = sv.mPtr + offset;
  158. this->mLength = length;
  159. }
  160. StringView(const StringImpl& str);
  161. StringView(const StringImpl& str, int offset);
  162. StringView(const StringImpl& str, int offset, int length);
  163. StringView(char c);
  164. StringView(const char* ptr)
  165. {
  166. this->mPtr = ptr;
  167. this->mLength = (int)strlen(ptr);
  168. }
  169. StringView(const char* ptr, int length)
  170. {
  171. this->mPtr = ptr;
  172. this->mLength = length;
  173. }
  174. const char& operator[](intptr idx) const
  175. {
  176. BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
  177. return this->mPtr[idx];
  178. }
  179. StringView& operator=(const StringImpl& str);
  180. StringView& operator=(const StringView& str)
  181. {
  182. this->mPtr = str.mPtr;
  183. this->mLength = str.mLength;
  184. return *this;
  185. }
  186. StringView& operator=(const char* str)
  187. {
  188. this->mPtr = str;
  189. this->mLength = (int)strlen(str);
  190. return *this;
  191. }
  192. bool operator==(const StringImpl& strB) const;
  193. bool operator!=(const StringImpl& strB) const;
  194. bool operator==(const StringView& strB) const
  195. {
  196. if (this->mLength != strB.mLength)
  197. return false;
  198. return strncmp(this->mPtr, strB.mPtr, this->mLength) == 0;
  199. }
  200. bool operator!=(const StringView& strB) const
  201. {
  202. if (this->mLength != strB.mLength)
  203. return true;
  204. return strncmp(this->mPtr, strB.mPtr, this->mLength) != 0;
  205. }
  206. bool operator==(const char* strB) const
  207. {
  208. if (strncmp(mPtr, strB, mLength) != 0)
  209. return false;
  210. return strB[mLength] == 0;
  211. }
  212. bool operator!=(const char* strB) const
  213. {
  214. if (strncmp(mPtr, strB, mLength) != 0)
  215. return true;
  216. return strB[mLength] != 0;
  217. }
  218. bool IsEmpty() const
  219. {
  220. return mLength == 0;
  221. }
  222. intptr length() const
  223. {
  224. return mLength;
  225. }
  226. bool StartsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const;
  227. bool EndsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const;
  228. bool StartsWith(char c) const
  229. {
  230. if (this->mLength == 0)
  231. return false;
  232. return this->mPtr[0] == c;
  233. }
  234. bool EndsWith(char c) const
  235. {
  236. if (this->mLength == 0)
  237. return false;
  238. return this->mPtr[this->mLength - 1] == c;
  239. }
  240. intptr IndexOf(const StringView& subStr, bool ignoreCase = false) const;
  241. intptr IndexOf(const StringView& subStr, int32 startIdx) const;
  242. intptr IndexOf(const StringView& subStr, int64 startIdx) const;
  243. intptr IndexOf(char c, int32 startIdx = 0) const;
  244. intptr IndexOf(char c, int64 startIdx) const;
  245. intptr LastIndexOf(char c) const;
  246. intptr LastIndexOf(char c, int startCheck) const;
  247. intptr LastIndexOf(char c, int64 startCheck) const;
  248. String ToString() const;
  249. void ToString(StringImpl& str) const;
  250. void RemoveFromStart(intptr length)
  251. {
  252. BF_ASSERT((uintptr)length <= (uintptr)mLength);
  253. mPtr += length;
  254. mLength -= (int)length;
  255. }
  256. void RemoveToEnd(intptr startIdx)
  257. {
  258. RemoveFromEnd(mLength - startIdx);
  259. }
  260. void RemoveFromEnd(intptr length)
  261. {
  262. mLength -= length;
  263. }
  264. bool Contains(char c) const
  265. {
  266. return IndexOf(c) != -1;
  267. }
  268. bool Contains(const StringView& str) const
  269. {
  270. return IndexOf(str) != -1;
  271. }
  272. StringSplitEnumerator Split(char c);
  273. const_iterator begin() const
  274. {
  275. return mPtr;
  276. }
  277. const_iterator end() const
  278. {
  279. return mPtr + this->mLength;
  280. }
  281. };
  282. struct StringSplitEnumerator
  283. {
  284. public:
  285. typedef std::random_access_iterator_tag iterator_category;
  286. typedef char value_type;
  287. typedef intptr difference_type;
  288. typedef char* pointer;
  289. typedef char& reference;
  290. public:
  291. char mSplitChar0;
  292. SizedArray<char, 8> mSplitChars;
  293. const char* mPtr;
  294. int32 mStrLen;
  295. int32 mCurCount;
  296. int32 mMaxCount;
  297. int32 mPos;
  298. int32 mMatchPos;
  299. bool mRemoveEntryEntries;
  300. StringSplitEnumerator(const char* ptr, int strLength, const char* splitCharsPtr, int splitCharCount, int count, bool removeEmptyEntries)
  301. {
  302. mPtr = ptr;
  303. mStrLen = strLength;
  304. // if (splitChars.Count > 0)
  305. // mSplitChar0 = splitChars[0];
  306. // else
  307. // mSplitChar0 = '\0';
  308. mSplitChar0 = splitCharsPtr[0];
  309. if (splitCharCount > 1)
  310. {
  311. mSplitChars.Insert(0, splitCharsPtr + 1, splitCharCount - 1);
  312. }
  313. mCurCount = 0;
  314. mMaxCount = (int32)count;
  315. mPos = 0;
  316. mMatchPos = -1;
  317. MoveNext();
  318. //mSplitOptions = splitOptions;
  319. }
  320. StringSplitEnumerator(const char* ptr, int strLength, char splitChar, int count, bool removeEmptyEntries)
  321. {
  322. mPtr = ptr;
  323. mStrLen = strLength;
  324. mSplitChar0 = splitChar;
  325. mCurCount = 0;
  326. mMaxCount = (int32)count;
  327. mPos = 0;
  328. mMatchPos = -1;
  329. //mSplitOptions = splitOptions;
  330. MoveNext();
  331. }
  332. bool MoveNext()
  333. {
  334. if (mCurCount >= mMaxCount)
  335. return false;
  336. mPos = mMatchPos + 1;
  337. mCurCount++;
  338. if (mCurCount == mMaxCount)
  339. {
  340. mMatchPos = mStrLen;
  341. if (mPos > mMatchPos)
  342. return false;
  343. if ((mMatchPos == mPos) && (mRemoveEntryEntries))
  344. return false;
  345. return true;
  346. }
  347. int endDiff = mStrLen - mMatchPos;
  348. if (endDiff == 0)
  349. return false;
  350. while (true)
  351. {
  352. mMatchPos++;
  353. endDiff--;
  354. bool foundMatch = false;
  355. if (endDiff == 0)
  356. {
  357. foundMatch = true;
  358. }
  359. else
  360. {
  361. char c = mPtr[mMatchPos];
  362. if (c == mSplitChar0)
  363. {
  364. foundMatch = true;
  365. }
  366. else if (mSplitChars.mSize > 0)
  367. {
  368. for (int i = 1; i < mSplitChars.mSize; i++)
  369. if (c == mSplitChars[i])
  370. foundMatch = true;
  371. }
  372. }
  373. if (foundMatch)
  374. {
  375. if ((mMatchPos > mPos + 1) || (!mRemoveEntryEntries))
  376. return true;
  377. mPos = mMatchPos + 1;
  378. if (mPos >= mStrLen)
  379. return false;
  380. }
  381. }
  382. }
  383. StringSplitEnumerator& operator++()
  384. {
  385. MoveNext();
  386. return *this;
  387. }
  388. StringSplitEnumerator operator++(int)
  389. {
  390. auto prevVal = *this;
  391. MoveNext();
  392. return prevVal;
  393. }
  394. bool operator!=(const StringSplitEnumerator& itr) const
  395. {
  396. return
  397. (itr.mPtr != mPtr) ||
  398. (itr.mPos != mPos) ||
  399. (itr.mMatchPos != mMatchPos);
  400. }
  401. bool operator==(const StringSplitEnumerator& itr) const
  402. {
  403. return
  404. (itr.mPtr == mPtr) &&
  405. (itr.mPos == mPos) &&
  406. (itr.mMatchPos == mMatchPos);
  407. }
  408. StringView operator*()
  409. {
  410. return StringView(mPtr + mPos, mMatchPos - mPos);
  411. }
  412. StringView operator->()
  413. {
  414. return StringView(mPtr + mPos, mMatchPos - mPos);
  415. }
  416. bool operator<(const StringSplitEnumerator& val2)
  417. {
  418. return mPtr < val2.mPtr;
  419. }
  420. StringSplitEnumerator begin()
  421. {
  422. return *this;
  423. }
  424. StringSplitEnumerator end()
  425. {
  426. StringSplitEnumerator endVal = *this;
  427. endVal.mPos = endVal.mStrLen + 1;
  428. endVal.mMatchPos = endVal.mStrLen;
  429. return endVal;
  430. }
  431. };
  432. class StringImpl
  433. {
  434. public:
  435. enum CompareKind
  436. {
  437. CompareKind_CurrentCulture = 0,
  438. CompareKind_CurrentCultureIgnoreCase = 1,
  439. CompareKind_InvariantCulture = 2,
  440. CompareKind_InvariantCultureIgnoreCase = 3,
  441. CompareKind_Ordinal = 4,
  442. CompareKind_OrdinalIgnoreCase = 5,
  443. };
  444. friend class StringView;
  445. public:
  446. typedef int int_strsize;
  447. const static uint32 SizeFlags = 0x3FFFFFFF;
  448. const static uint32 DynAllocFlag = 0x80000000;
  449. const static uint32 StrPtrFlag = 0x40000000;
  450. const static uint32 AttrFlags = 0xC0000000;
  451. int mLength;
  452. uint32 mAllocSizeAndFlags;
  453. char* mPtr;
  454. public:
  455. protected:
  456. void EnsureMutable()
  457. {
  458. if ((mAllocSizeAndFlags & AttrFlags) == StrPtrFlag)
  459. {
  460. // It's a reference
  461. int allocSize = (int)BF_MAX(GetAllocSize(), this->mLength + 1);
  462. char* newPtr = AllocPtr(allocSize);
  463. memcpy(newPtr, this->mPtr, this->mLength);
  464. newPtr[this->mLength] = 0;
  465. this->mPtr = newPtr;
  466. mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
  467. }
  468. }
  469. char* AllocPtr(intptr size)
  470. {
  471. return (char*)malloc(size);
  472. }
  473. void DeletePtr()
  474. {
  475. free(this->mPtr);
  476. }
  477. intptr CalcNewSize(intptr minSize);
  478. void Realloc(intptr newSize, bool copyStr = true);
  479. void Realloc(char* newPtr, intptr newSize);
  480. static bool EqualsHelper(const char* a, const char* b, intptr length);
  481. static bool EqualsIgnoreCaseHelper(const char* a, const char* b, intptr length);
  482. static int CompareOrdinalIgnoreCaseHelper(const StringImpl& strA, const StringImpl& strB);
  483. static intptr CompareOrdinalIgnoreCaseHelper(const char* strA, intptr lengthA, const char* strB, intptr lengthB);
  484. static intptr CompareOrdinalIgnoreCaseHelper(const StringImpl& strA, intptr indexA, intptr lengthA, const StringImpl& strB, intptr indexB, intptr lengthB);
  485. static intptr CompareOrdinalHelper(const char* strA, intptr lengthA, const char* strB, intptr lengthB);
  486. static intptr CompareOrdinalHelper(const StringImpl& strA, intptr indexA, intptr lengthA, const StringImpl& strB, intptr indexB, intptr lengthB);
  487. void Init(const char* charPtr, intptr count)
  488. {
  489. int_strsize internalSize = (int_strsize)(sizeof(StringImpl) - offsetof(StringImpl, mPtr));
  490. int_strsize allocSize = (int_strsize)count + 1;
  491. if (allocSize <= internalSize)
  492. {
  493. // Fits
  494. auto ptr = (char*)&this->mPtr;
  495. memcpy(ptr, charPtr, count);
  496. ptr[count] = 0;
  497. mAllocSizeAndFlags = internalSize;
  498. this->mLength = (int_strsize)count;
  499. }
  500. else
  501. {
  502. // Too big, must alloc
  503. auto ptr = AllocPtr(allocSize);
  504. memcpy(ptr, charPtr, count);
  505. ptr[count] = 0;
  506. this->mPtr = ptr;
  507. mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
  508. this->mLength = (int_strsize)count;
  509. }
  510. }
  511. protected:
  512. // Use "String" or "StringT<>"
  513. StringImpl()
  514. {
  515. }
  516. public:
  517. static StringImpl MakeRef(const char* charPtr)
  518. {
  519. StringImpl str;
  520. // This is just a ref - called when we pass a literal to a method (for example)
  521. str.mPtr = (char*)charPtr;
  522. str.mLength = (int_strsize)strlen(charPtr);
  523. str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
  524. return str;
  525. }
  526. static StringImpl MakeRef(const char* charPtr, intptr length)
  527. {
  528. StringImpl str;
  529. // This is just a ref - called when we pass a literal to a method (for example)
  530. str.mPtr = (char*)charPtr;
  531. str.mLength = (int_strsize)length;
  532. str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
  533. return str;
  534. }
  535. static StringImpl MakeRef(const StringView& strView)
  536. {
  537. StringImpl str;
  538. // This is just a ref - called when we pass a literal to a method (for example)
  539. str.mPtr = (char*)strView.mPtr;
  540. str.mLength = (int_strsize)strView.mLength;
  541. str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
  542. return str;
  543. }
  544. StringImpl(const char* charPtr)
  545. {
  546. // This is just a ref - called when we pass a literal to a method (for example)
  547. this->mPtr = (char*)charPtr;
  548. this->mLength = (int_strsize)strlen(charPtr);
  549. mAllocSizeAndFlags = this->mLength | StrPtrFlag;
  550. }
  551. StringImpl(const char* charPtr, const char* charPtrEnd)
  552. {
  553. Init(charPtr, (int_strsize)(charPtrEnd - charPtr));
  554. }
  555. StringImpl(const char* charPtr, intptr length)
  556. {
  557. Init(charPtr, (int_strsize)length);
  558. }
  559. StringImpl(const StringImpl& str)
  560. {
  561. Init(str.GetPtr(), str.mLength);
  562. }
  563. StringImpl(const StringView& str);
  564. StringImpl(const StringImpl& str, intptr offset)
  565. {
  566. Init(str.GetPtr() + offset, (int_strsize)(str.mLength - offset));
  567. }
  568. StringImpl(const StringImpl& str, intptr offset, intptr length)
  569. {
  570. Init(str.GetPtr() + offset, (int_strsize)length);
  571. }
  572. StringImpl(const std::string& str)
  573. {
  574. // This is just a ref - called when we pass a std::string to a method (for example)
  575. this->mPtr = (char*)str.c_str();
  576. this->mLength = (int_strsize)str.length();
  577. mAllocSizeAndFlags = this->mLength | StrPtrFlag;
  578. }
  579. StringImpl(StringImpl&& str)
  580. {
  581. if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
  582. {
  583. this->mPtr = str.mPtr;
  584. mAllocSizeAndFlags = str.mAllocSizeAndFlags;
  585. this->mLength = str.mLength;
  586. str.mAllocSizeAndFlags = 0;
  587. }
  588. else
  589. {
  590. // If there's an internal buffer then we have to copy
  591. int_strsize count = (int_strsize)str.mLength;
  592. int_strsize allocSize = count + 1;
  593. auto ptr = AllocPtr(allocSize);
  594. memcpy(ptr, str.GetPtr(), count + 1);
  595. ptr[count] = 0;
  596. this->mPtr = ptr;
  597. mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
  598. this->mLength = count;
  599. }
  600. }
  601. ~StringImpl()
  602. {
  603. if (IsDynAlloc())
  604. DeletePtr();
  605. }
  606. char& operator[](intptr idx)
  607. {
  608. BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
  609. switch (mAllocSizeAndFlags & AttrFlags)
  610. {
  611. case 0:
  612. return ((char*)&this->mPtr)[idx];
  613. case StrPtrFlag:
  614. EnsureMutable();
  615. default:
  616. return this->mPtr[idx];
  617. }
  618. }
  619. const char& operator[](intptr idx) const
  620. {
  621. BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
  622. return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr[idx] : ((char*)&this->mPtr)[idx];
  623. }
  624. bool operator==(const StringImpl& strB) const
  625. {
  626. if (this->mLength != strB.mLength)
  627. return false;
  628. return strncmp(GetPtr(), strB.GetPtr(), this->mLength) == 0;
  629. }
  630. bool operator!=(const StringImpl& strB) const
  631. {
  632. if (this->mLength != strB.mLength)
  633. return true;
  634. return strncmp(GetPtr(), strB.GetPtr(), this->mLength) != 0;
  635. }
  636. bool operator==(const StringView& strB) const
  637. {
  638. if (this->mLength != strB.mLength)
  639. return false;
  640. return strncmp(GetPtr(), strB.mPtr, this->mLength) == 0;
  641. }
  642. bool operator!=(const StringView& strB) const
  643. {
  644. if (this->mLength != strB.mLength)
  645. return true;
  646. return strncmp(GetPtr(), strB.mPtr, this->mLength) != 0;
  647. }
  648. bool operator==(const char* strB) const
  649. {
  650. return strcmp(GetPtr(), strB) == 0;
  651. }
  652. bool operator!=(const char* strB) const
  653. {
  654. return strcmp(GetPtr(), strB) != 0;
  655. }
  656. bool operator<(const StringImpl& strB) const
  657. {
  658. return strcmp(GetPtr(), strB.GetPtr()) < 0;
  659. }
  660. bool operator>(const StringImpl& strB) const
  661. {
  662. return strcmp(GetPtr(), strB.GetPtr()) > 0;
  663. }
  664. StringImpl& operator=(const StringImpl& str)
  665. {
  666. if (&str != this)
  667. {
  668. this->mLength = 0;
  669. Append(str.GetPtr(), str.mLength);
  670. }
  671. return *this;
  672. }
  673. StringImpl& operator=(StringImpl&& str)
  674. {
  675. if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
  676. {
  677. if (IsDynAlloc())
  678. DeletePtr();
  679. this->mPtr = str.mPtr;
  680. mAllocSizeAndFlags = str.mAllocSizeAndFlags;
  681. this->mLength = str.mLength;
  682. str.mAllocSizeAndFlags = 0;
  683. }
  684. else
  685. {
  686. // If there's an internal buffer then we have to copy
  687. int_strsize count = (int_strsize)str.mLength;
  688. int_strsize allocSize = count + 1;
  689. if (allocSize > GetAllocSize())
  690. Realloc(allocSize, false);
  691. auto ptr = GetMutablePtr();
  692. memcpy(ptr, str.GetPtr(), count + 1);
  693. ptr[count] = 0;
  694. this->mLength = count;
  695. }
  696. return *this;
  697. }
  698. StringImpl& operator=(const std::string& str)
  699. {
  700. this->mLength = 0;
  701. Append(str.c_str(), (intptr)str.length());
  702. return *this;
  703. }
  704. StringImpl& operator=(const char* str)
  705. {
  706. this->mLength = 0;
  707. Append(str, strlen(str));
  708. return *this;
  709. }
  710. StringImpl& operator=(char c)
  711. {
  712. this->mLength = 0;
  713. Append(c);
  714. return *this;
  715. }
  716. StringImpl& operator+=(const StringImpl& str)
  717. {
  718. Append(str.GetPtr(), str.mLength);
  719. return *this;
  720. }
  721. StringImpl& operator+=(const StringView& str)
  722. {
  723. Append(str.mPtr, str.mLength);
  724. return *this;
  725. }
  726. StringImpl& operator+=(const char* str)
  727. {
  728. Append(str, strlen(str));
  729. return *this;
  730. }
  731. StringImpl& operator+=(char c)
  732. {
  733. Append(c);
  734. return *this;
  735. }
  736. operator std::string() const
  737. {
  738. return std::string(GetPtr(), GetPtr() + this->mLength);
  739. }
  740. intptr length() const
  741. {
  742. return this->mLength;
  743. }
  744. int GetLength() const
  745. {
  746. return this->mLength;
  747. }
  748. intptr GetAllocSize() const
  749. {
  750. return (int_strsize)(mAllocSizeAndFlags & SizeFlags);
  751. }
  752. bool IsDynAlloc() const
  753. {
  754. return (mAllocSizeAndFlags & DynAllocFlag) != 0;
  755. }
  756. const char* GetPtr() const
  757. {
  758. return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr : (char*)&this->mPtr;
  759. }
  760. const char* c_str() const
  761. {
  762. return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr : (char*)&this->mPtr;
  763. }
  764. char* GetMutablePtr()
  765. {
  766. switch (mAllocSizeAndFlags & AttrFlags)
  767. {
  768. case 0:
  769. return ((char*)&this->mPtr);
  770. case StrPtrFlag:
  771. EnsureMutable();
  772. default:
  773. return this->mPtr;
  774. }
  775. }
  776. void Reference(const char* str);
  777. void Reference(const char* str, intptr length);
  778. void Reference(const StringView& strView);
  779. void Reference(const StringImpl& str);
  780. static String CreateReference(const StringView& strView);
  781. void Reserve(intptr newSize);
  782. void Append(const char* appendPtr);
  783. void Append(const char* appendPtr, intptr length);
  784. void Append(const StringView& str);
  785. void Append(const StringImpl& str);
  786. void Append(const StringImpl& str, const StringImpl& str2);
  787. void Append(const StringImpl& str, const StringImpl& str2, const StringImpl& str3);
  788. void Append(char c, int count = 1);
  789. void Release()
  790. {
  791. if (IsDynAlloc())
  792. DeletePtr();
  793. this->mLength = 0;
  794. this->mPtr = NULL;
  795. this->mAllocSizeAndFlags = 0;
  796. }
  797. void Clear()
  798. {
  799. this->mLength = 0;
  800. GetMutablePtr()[0] = 0;
  801. }
  802. void clear()
  803. {
  804. this->mLength = 0;
  805. GetMutablePtr()[0] = 0;
  806. }
  807. String Substring(intptr startIdx) const;
  808. String Substring(intptr startIdx, intptr length) const;
  809. void Remove(intptr startIdx, intptr length);
  810. void Remove(intptr char8Idx);
  811. void RemoveToEnd(intptr startIdx);
  812. void RemoveFromEnd(intptr length);
  813. void Insert(intptr idx, const StringImpl& addString);
  814. void Insert(intptr idx, const char* str, intptr len);
  815. void Insert(intptr idx, char c);
  816. intptr CompareTo(const StringImpl& strB, bool ignoreCase = false) const
  817. {
  818. if (ignoreCase)
  819. return CompareOrdinalIgnoreCaseHelper(GetPtr(), GetLength(), strB.GetPtr(), strB.GetLength());
  820. return CompareOrdinalHelper(GetPtr(), GetLength(), strB.GetPtr(), strB.GetLength());
  821. }
  822. static intptr Compare(const StringImpl& strA, const StringImpl& strB, bool ignoreCase)
  823. {
  824. if (ignoreCase)
  825. return CompareOrdinalIgnoreCaseHelper(strA.GetPtr(), strA.GetLength(), strB.GetPtr(), strB.GetLength());
  826. return CompareOrdinalHelper(strA.GetPtr(), strA.GetLength(), strB.GetPtr(), strB.GetLength());
  827. }
  828. static intptr Compare(const StringImpl& strA, intptr indexA, const StringImpl& strB, intptr indexB, intptr length, bool ignoreCase);
  829. bool Equals(const StringImpl& b, CompareKind comparisonType = CompareKind_Ordinal) const
  830. {
  831. return Equals(*this, b, comparisonType);
  832. }
  833. static bool Equals(const StringImpl& a, const StringImpl& b, CompareKind comparisonType = CompareKind_Ordinal)
  834. {
  835. if (a.mLength != b.mLength)
  836. return false;
  837. if (comparisonType == CompareKind_OrdinalIgnoreCase)
  838. return EqualsIgnoreCaseHelper(a.GetPtr(), b.GetPtr(), a.mLength);
  839. return EqualsHelper(a.GetPtr(), b.GetPtr(), a.mLength);
  840. }
  841. bool StartsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const
  842. {
  843. if (this->mLength < b.mLength)
  844. return false;
  845. if (comparisonType == CompareKind_OrdinalIgnoreCase)
  846. return EqualsIgnoreCaseHelper(this->GetPtr(), b.mPtr, b.mLength);
  847. return EqualsHelper(this->GetPtr(), b.mPtr, b.mLength);
  848. }
  849. bool EndsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const
  850. {
  851. if (this->mLength < b.mLength)
  852. return false;
  853. if (comparisonType == CompareKind_OrdinalIgnoreCase)
  854. return EqualsIgnoreCaseHelper(this->GetPtr() + this->mLength - b.mLength, b.mPtr, b.mLength);
  855. return EqualsHelper(this->GetPtr() + this->mLength - b.mLength, b.mPtr, b.mLength);
  856. }
  857. bool StartsWith(char c) const
  858. {
  859. if (this->mLength == 0)
  860. return false;
  861. return GetPtr()[0] == c;
  862. }
  863. bool EndsWith(char c) const
  864. {
  865. if (this->mLength == 0)
  866. return false;
  867. return GetPtr()[this->mLength - 1] == c;
  868. }
  869. void ReplaceLargerHelper(const StringView& find, const StringView& replace);
  870. void Replace(char find, char replace);
  871. void Replace(const StringView& find, const StringView& replace);
  872. void TrimEnd();
  873. void TrimStart();
  874. void Trim();
  875. bool IsWhitespace() const;
  876. bool IsEmpty() const
  877. {
  878. return this->mLength == 0;
  879. }
  880. bool empty() const
  881. {
  882. return this->mLength == 0;
  883. }
  884. bool HasMultibyteChars();
  885. intptr IndexOf(const StringView& subStr, bool ignoreCase = false) const;
  886. intptr IndexOf(const StringView& subStr, int32 startIdx) const;
  887. intptr IndexOf(const StringView& subStr, int64 startIdx) const;
  888. intptr IndexOf(char c, int32 startIdx = 0) const;
  889. intptr IndexOf(char c, int64 startIdx) const;
  890. intptr LastIndexOf(char c) const;
  891. intptr LastIndexOf(char c, intptr startCheck) const;
  892. StringSplitEnumerator Split(char c)
  893. {
  894. return StringSplitEnumerator(GetPtr(), mLength, c, 0x7FFFFFFF, false);
  895. }
  896. bool Contains(char c) const
  897. {
  898. return IndexOf(c) != -1;
  899. }
  900. bool Contains(const StringView& str) const
  901. {
  902. return IndexOf(str) != -1;
  903. }
  904. StringView::const_iterator begin() const
  905. {
  906. return GetPtr();
  907. }
  908. StringView::const_iterator end() const
  909. {
  910. return GetPtr() + this->mLength;
  911. }
  912. StringView::iterator begin()
  913. {
  914. return GetMutablePtr();
  915. }
  916. StringView::iterator end()
  917. {
  918. return GetMutablePtr() + this->mLength;
  919. }
  920. };
  921. template <const int TBufSize = 16>
  922. class StringT : public StringImpl
  923. {
  924. protected:
  925. void Init(const char* charPtr, int_strsize count)
  926. {
  927. int_strsize internalSize = (int_strsize)(sizeof(StringT) - offsetof(StringImpl, mPtr));
  928. int_strsize allocSize = count + 1;
  929. if (allocSize <= internalSize)
  930. {
  931. // Fits
  932. auto ptr = (char*)&this->mPtr;
  933. memcpy(ptr, charPtr, count);
  934. ptr[count] = 0;
  935. mAllocSizeAndFlags = internalSize;
  936. this->mLength = count;
  937. }
  938. else
  939. {
  940. // Too big, must alloc
  941. auto ptr = AllocPtr(allocSize);
  942. memcpy(ptr, charPtr, count);
  943. ptr[count] = 0;
  944. this->mPtr = ptr;
  945. mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
  946. this->mLength = count;
  947. }
  948. }
  949. public:
  950. char mInternalBuffer[TBufSize - sizeof(intptr)];
  951. using StringImpl::operator=;
  952. StringT()
  953. {
  954. int_strsize internalSize = (int_strsize)(sizeof(StringT) - offsetof(StringImpl, mPtr));
  955. this->mPtr = 0;
  956. mAllocSizeAndFlags = internalSize;
  957. this->mLength = 0;
  958. }
  959. StringT(const char* charPtr)
  960. {
  961. Init(charPtr, (int_strsize)strlen(charPtr));
  962. }
  963. StringT(const char* charPtr, const char* charPtrEnd)
  964. {
  965. Init(charPtr, (int_strsize)(charPtrEnd - charPtr));
  966. }
  967. StringT(const char* charPtr, intptr length)
  968. {
  969. Init(charPtr, (int_strsize)length);
  970. }
  971. StringT(const StringT& str)
  972. {
  973. Init(str.GetPtr(), str.mLength);
  974. }
  975. StringT(StringT&& str)
  976. {
  977. if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
  978. {
  979. this->mPtr = str.mPtr;
  980. mAllocSizeAndFlags = str.mAllocSizeAndFlags;
  981. this->mLength = str.mLength;
  982. str.mAllocSizeAndFlags = 0;
  983. }
  984. else
  985. {
  986. // If there's an internal buffer then we have to copy
  987. Init(str.GetPtr(), str.mLength);
  988. }
  989. }
  990. StringT(const StringT& str, intptr offset)
  991. {
  992. Init(str.GetPtr() + offset, (int_strsize)(str.mLength - offset));
  993. }
  994. StringT(const StringT& str, intptr offset, intptr length)
  995. {
  996. BF_ASSERT(offset >= 0);
  997. BF_ASSERT((uintptr)offset + (uintptr)length <= (uintptr)str.mLength);
  998. Init(str.GetPtr() + offset, (int_strsize)length);
  999. }
  1000. StringT(const StringImpl& str)
  1001. {
  1002. Init(str.GetPtr(), str.mLength);
  1003. }
  1004. StringT(const std::string& str)
  1005. {
  1006. Init(str.c_str(), (int_strsize)str.length());
  1007. }
  1008. StringT(StringImpl&& str)
  1009. {
  1010. if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
  1011. {
  1012. this->mPtr = str.mPtr;
  1013. mAllocSizeAndFlags = str.mAllocSizeAndFlags;
  1014. this->mLength = str.mLength;
  1015. str.mAllocSizeAndFlags = 0;
  1016. }
  1017. else
  1018. {
  1019. // If there's an internal buffer then we have to copy
  1020. Init(str.GetPtr(), str.mLength);
  1021. }
  1022. }
  1023. StringImpl& operator=(StringT&& str)
  1024. {
  1025. return StringImpl::operator=(std::move(str));
  1026. }
  1027. StringImpl& operator=(const StringT& str)
  1028. {
  1029. return StringImpl::operator=(str);
  1030. }
  1031. };
  1032. class StringSimple : public StringView
  1033. {
  1034. public:
  1035. StringSimple()
  1036. {
  1037. }
  1038. StringSimple(const StringView& sv)
  1039. {
  1040. this->mPtr = new char[sv.mLength + 1];
  1041. this->mLength = sv.mLength;
  1042. memcpy((char*)this->mPtr, sv.mPtr, this->mLength);
  1043. ((char*)this->mPtr)[this->mLength] = 0;
  1044. }
  1045. StringSimple(const StringImpl& str)
  1046. {
  1047. this->mPtr = new char[str.mLength + 1];
  1048. this->mLength = str.mLength;
  1049. memcpy((char*)this->mPtr, str.GetPtr(), this->mLength);
  1050. ((char*)mPtr)[this->mLength] = 0;
  1051. }
  1052. StringSimple& operator=(const StringView& sv)
  1053. {
  1054. delete this->mPtr;
  1055. this->mPtr = new char[sv.mLength + 1];
  1056. this->mLength = sv.mLength;
  1057. memcpy((char*)this->mPtr, sv.mPtr, this->mLength);
  1058. ((char*)this->mPtr)[this->mLength] = 0;
  1059. return *this;
  1060. }
  1061. ~StringSimple()
  1062. {
  1063. delete this->mPtr;
  1064. }
  1065. const char* c_str()
  1066. {
  1067. return this->mPtr;
  1068. }
  1069. };
  1070. class UTF16String : public Array<uint16>
  1071. {
  1072. public:
  1073. UTF16String();
  1074. UTF16String(const wchar_t* str);
  1075. UTF16String(const wchar_t* str, int len);
  1076. void Set(const wchar_t* str, int len);
  1077. void Set(const wchar_t* str);
  1078. const wchar_t* c_str() const;
  1079. size_t length() const;
  1080. };
  1081. #define BF_SPECIALIZE_STR(size) \
  1082. template <> class StringT<size> : public StringImpl \
  1083. { \
  1084. public: \
  1085. using StringImpl::StringImpl; \
  1086. using StringImpl::operator=; \
  1087. StringT() { mPtr = NULL; mLength = 0; mAllocSizeAndFlags = 0; } \
  1088. explicit StringT(const char* str) { Init(str, (int_strsize)strlen(str)); } \
  1089. StringT(const std::string& str) { Init(str.c_str(), (int_strsize)str.length()); } \
  1090. StringT(const StringImpl& str) : StringImpl(str) {} \
  1091. StringT(StringImpl&& str) : StringImpl(std::move(str)) {} \
  1092. };
  1093. BF_SPECIALIZE_STR(0)
  1094. BF_SPECIALIZE_STR(1)
  1095. BF_SPECIALIZE_STR(2)
  1096. BF_SPECIALIZE_STR(3)
  1097. #ifdef BF64
  1098. BF_SPECIALIZE_STR(4)
  1099. BF_SPECIALIZE_STR(5)
  1100. BF_SPECIALIZE_STR(6)
  1101. #endif
  1102. #undef BF_SPECIALIZE_STR
  1103. String operator+(const StringImpl& lhs, const StringImpl& rhs);
  1104. String operator+(const StringImpl& lhs, const StringView& rhs);
  1105. String operator+(const StringImpl& lhs, const char* rhs);
  1106. String operator+(const StringImpl& lhs, char rhs);
  1107. String operator+(const char* lhs, const StringImpl& rhs);
  1108. String operator+(const char* lhs, const StringView& rhs);
  1109. bool operator==(const char* lhs, const StringImpl& rhs);
  1110. bool operator!=(const char* lhs, const StringImpl& rhs);
  1111. // bool operator==(const StringView& lhs, const StringImpl& rhs);
  1112. // bool operator!=(const StringView& lhs, const StringImpl& rhs);
  1113. NS_BF_END;
  1114. namespace std
  1115. {
  1116. template<>
  1117. struct hash<Beefy::StringImpl>
  1118. {
  1119. size_t operator()(const Beefy::StringImpl& val) const
  1120. {
  1121. return HashBytes((const uint8*)val.GetPtr(), val.mLength);
  1122. }
  1123. };
  1124. template<>
  1125. struct hash<Beefy::StringView>
  1126. {
  1127. size_t operator()(const Beefy::StringView& val) const
  1128. {
  1129. return HashBytes((const uint8*)val.mPtr, val.mLength);
  1130. }
  1131. };
  1132. template<>
  1133. struct hash<Beefy::String>
  1134. {
  1135. size_t operator()(const Beefy::String& val) const
  1136. {
  1137. return HashBytes((const uint8*)val.GetPtr(), val.mLength);
  1138. }
  1139. };
  1140. }