12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346 |
- #pragma once
- #include <string>
- #include "BFPlatform.h"
- #include "Array.h"
- #include "SizedArray.h"
- NS_BF_BEGIN;
- template <const int TBufSize>
- class StringT;
- typedef StringT<16> String;
- struct StringSplitEnumerator;
- class StringView
- {
- public:
- enum CompareKind
- {
- CompareKind_CurrentCulture = 0,
- CompareKind_CurrentCultureIgnoreCase = 1,
- CompareKind_InvariantCulture = 2,
- CompareKind_InvariantCultureIgnoreCase = 3,
- CompareKind_Ordinal = 4,
- CompareKind_OrdinalIgnoreCase = 5,
- };
- public:
- const char* mPtr;
- intptr mLength;
- public:
- struct iterator
- {
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef char value_type;
- typedef intptr difference_type;
- typedef char* pointer;
- typedef char& reference;
- public:
- char* mPtr;
- public:
- iterator(char* ptr)
- {
- mPtr = ptr;
- }
- iterator& operator++()
- {
- mPtr++;
- return *this;
- }
- iterator operator++(int)
- {
- auto prevVal = *this;
- mPtr++;
- return prevVal;
- }
- bool operator!=(const iterator& itr) const
- {
- return itr.mPtr != mPtr;
- }
- bool operator==(const iterator& itr) const
- {
- return itr.mPtr == mPtr;
- }
- intptr operator-(const iterator& itr) const
- {
- return mPtr - itr.mPtr;
- }
- iterator operator+(intptr offset) const
- {
- iterator itr(mPtr + offset);
- return itr;
- }
- char& operator*()
- {
- return *mPtr;
- }
- char* operator->()
- {
- return mPtr;
- }
- bool operator<(const iterator& val2)
- {
- return mPtr < val2.mPtr;
- }
- };
- struct const_iterator
- {
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef char value_type;
- typedef intptr difference_type;
- typedef const char* pointer;
- typedef const char& reference;
- public:
- const char* mPtr;
- public:
- const_iterator(const char* ptr)
- {
- mPtr = ptr;
- }
- const_iterator& operator++()
- {
- mPtr++;
- return *this;
- }
- const_iterator operator++(int)
- {
- auto prevVal = *this;
- mPtr++;
- return prevVal;
- }
- bool operator!=(const const_iterator& itr) const
- {
- return itr.mPtr != mPtr;
- }
- bool operator==(const const_iterator& itr) const
- {
- return itr.mPtr == mPtr;
- }
- intptr operator-(const iterator& itr) const
- {
- return mPtr - itr.mPtr;
- }
- const_iterator operator+(intptr offset) const
- {
- const_iterator itr(mPtr + offset);
- return itr;
- }
- const char& operator*()
- {
- return *mPtr;
- }
- const char* operator->()
- {
- return mPtr;
- }
- bool operator<(const const_iterator& val2)
- {
- return mPtr < val2.mPtr;
- }
- };
- public:
- StringView()
- {
- this->mPtr = NULL;
- this->mLength = 0;
- }
- StringView(const StringView& sv)
- {
- this->mPtr = sv.mPtr;
- this->mLength = sv.mLength;
- }
- StringView(const StringView& sv, int offset)
- {
- this->mPtr = sv.mPtr + offset;
- this->mLength = sv.mLength - offset;
- }
- StringView(const StringView& sv, int offset, int length)
- {
- this->mPtr = sv.mPtr + offset;
- this->mLength = length;
- }
- StringView(const StringImpl& str);
- StringView(const StringImpl& str, int offset);
- StringView(const StringImpl& str, int offset, int length);
- StringView(char c);
- StringView(const char* ptr)
- {
- this->mPtr = ptr;
- this->mLength = (int)strlen(ptr);
- }
- StringView(const char* ptr, int length)
- {
- this->mPtr = ptr;
- this->mLength = length;
- }
- const char& operator[](intptr idx) const
- {
- BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
- return this->mPtr[idx];
- }
- StringView& operator=(const StringImpl& str);
- StringView& operator=(const StringView& str)
- {
- this->mPtr = str.mPtr;
- this->mLength = str.mLength;
- return *this;
- }
- StringView& operator=(const char* str)
- {
- this->mPtr = str;
- this->mLength = (int)strlen(str);
- return *this;
- }
- bool operator==(const StringImpl& strB) const;
- bool operator!=(const StringImpl& strB) const;
- bool operator==(const StringView& strB) const
- {
- if (this->mLength != strB.mLength)
- return false;
- return strncmp(this->mPtr, strB.mPtr, this->mLength) == 0;
- }
- bool operator!=(const StringView& strB) const
- {
- if (this->mLength != strB.mLength)
- return true;
- return strncmp(this->mPtr, strB.mPtr, this->mLength) != 0;
- }
- bool operator==(const char* strB) const
- {
- if (strncmp(mPtr, strB, mLength) != 0)
- return false;
- return strB[mLength] == 0;
- }
- bool operator!=(const char* strB) const
- {
- if (strncmp(mPtr, strB, mLength) != 0)
- return true;
- return strB[mLength] != 0;
- }
- bool IsEmpty() const
- {
- return mLength == 0;
- }
- intptr length() const
- {
- return mLength;
- }
- bool StartsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const;
- bool EndsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const;
- bool StartsWith(char c) const
- {
- if (this->mLength == 0)
- return false;
- return this->mPtr[0] == c;
- }
- bool EndsWith(char c) const
- {
- if (this->mLength == 0)
- return false;
- return this->mPtr[this->mLength - 1] == c;
- }
- intptr IndexOf(const StringView& subStr, bool ignoreCase = false) const;
- intptr IndexOf(const StringView& subStr, int32 startIdx) const;
- intptr IndexOf(const StringView& subStr, int64 startIdx) const;
- intptr IndexOf(char c, int32 startIdx = 0) const;
- intptr IndexOf(char c, int64 startIdx) const;
- intptr LastIndexOf(char c) const;
- intptr LastIndexOf(char c, int startCheck) const;
- intptr LastIndexOf(char c, int64 startCheck) const;
- String ToString() const;
- void ToString(StringImpl& str) const;
- void RemoveFromStart(intptr length)
- {
- BF_ASSERT((uintptr)length <= (uintptr)mLength);
- mPtr += length;
- mLength -= (int)length;
- }
- void RemoveToEnd(intptr startIdx)
- {
- RemoveFromEnd(mLength - startIdx);
- }
- void RemoveFromEnd(intptr length)
- {
- mLength -= length;
- }
- bool Contains(char c) const
- {
- return IndexOf(c) != -1;
- }
- bool Contains(const StringView& str) const
- {
- return IndexOf(str) != -1;
- }
- StringSplitEnumerator Split(char c);
- const_iterator begin() const
- {
- return mPtr;
- }
- const_iterator end() const
- {
- return mPtr + this->mLength;
- }
- };
- struct StringSplitEnumerator
- {
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef char value_type;
- typedef intptr difference_type;
- typedef char* pointer;
- typedef char& reference;
- public:
- char mSplitChar0;
- SizedArray<char, 8> mSplitChars;
- const char* mPtr;
- int32 mStrLen;
- int32 mCurCount;
- int32 mMaxCount;
- int32 mPos;
- int32 mMatchPos;
- bool mRemoveEntryEntries;
- StringSplitEnumerator(const char* ptr, int strLength, const char* splitCharsPtr, int splitCharCount, int count, bool removeEmptyEntries)
- {
- mPtr = ptr;
- mStrLen = strLength;
- // if (splitChars.Count > 0)
- // mSplitChar0 = splitChars[0];
- // else
- // mSplitChar0 = '\0';
- mSplitChar0 = splitCharsPtr[0];
- if (splitCharCount > 1)
- {
- mSplitChars.Insert(0, splitCharsPtr + 1, splitCharCount - 1);
- }
- mCurCount = 0;
- mMaxCount = (int32)count;
- mPos = 0;
- mMatchPos = -1;
- MoveNext();
- //mSplitOptions = splitOptions;
- }
- StringSplitEnumerator(const char* ptr, int strLength, char splitChar, int count, bool removeEmptyEntries)
- {
- mPtr = ptr;
- mStrLen = strLength;
- mSplitChar0 = splitChar;
- mCurCount = 0;
- mMaxCount = (int32)count;
- mPos = 0;
- mMatchPos = -1;
- //mSplitOptions = splitOptions;
- MoveNext();
- }
- bool MoveNext()
- {
- if (mCurCount >= mMaxCount)
- return false;
- mPos = mMatchPos + 1;
- mCurCount++;
- if (mCurCount == mMaxCount)
- {
- mMatchPos = mStrLen;
- if (mPos > mMatchPos)
- return false;
- if ((mMatchPos == mPos) && (mRemoveEntryEntries))
- return false;
- return true;
- }
- int endDiff = mStrLen - mMatchPos;
- if (endDiff == 0)
- return false;
- while (true)
- {
- mMatchPos++;
- endDiff--;
- bool foundMatch = false;
- if (endDiff == 0)
- {
- foundMatch = true;
- }
- else
- {
- char c = mPtr[mMatchPos];
- if (c == mSplitChar0)
- {
- foundMatch = true;
- }
- else if (mSplitChars.mSize > 0)
- {
- for (int i = 1; i < mSplitChars.mSize; i++)
- if (c == mSplitChars[i])
- foundMatch = true;
- }
- }
- if (foundMatch)
- {
- if ((mMatchPos > mPos + 1) || (!mRemoveEntryEntries))
- return true;
- mPos = mMatchPos + 1;
- if (mPos >= mStrLen)
- return false;
- }
- }
- }
- StringSplitEnumerator& operator++()
- {
- MoveNext();
- return *this;
- }
- StringSplitEnumerator operator++(int)
- {
- auto prevVal = *this;
- MoveNext();
- return prevVal;
- }
- bool operator!=(const StringSplitEnumerator& itr) const
- {
- return
- (itr.mPtr != mPtr) ||
- (itr.mPos != mPos) ||
- (itr.mMatchPos != mMatchPos);
- }
- bool operator==(const StringSplitEnumerator& itr) const
- {
- return
- (itr.mPtr == mPtr) &&
- (itr.mPos == mPos) &&
- (itr.mMatchPos == mMatchPos);
- }
- StringView operator*()
- {
- return StringView(mPtr + mPos, mMatchPos - mPos);
- }
- StringView operator->()
- {
- return StringView(mPtr + mPos, mMatchPos - mPos);
- }
- bool operator<(const StringSplitEnumerator& val2)
- {
- return mPtr < val2.mPtr;
- }
- StringSplitEnumerator begin()
- {
- return *this;
- }
- StringSplitEnumerator end()
- {
- StringSplitEnumerator endVal = *this;
- endVal.mPos = endVal.mStrLen + 1;
- endVal.mMatchPos = endVal.mStrLen;
- return endVal;
- }
- };
- class StringImpl
- {
- public:
- enum CompareKind
- {
- CompareKind_CurrentCulture = 0,
- CompareKind_CurrentCultureIgnoreCase = 1,
- CompareKind_InvariantCulture = 2,
- CompareKind_InvariantCultureIgnoreCase = 3,
- CompareKind_Ordinal = 4,
- CompareKind_OrdinalIgnoreCase = 5,
- };
- friend class StringView;
- public:
- typedef int int_strsize;
- const static uint32 SizeFlags = 0x3FFFFFFF;
- const static uint32 DynAllocFlag = 0x80000000;
- const static uint32 StrPtrFlag = 0x40000000;
- const static uint32 AttrFlags = 0xC0000000;
- int mLength;
- uint32 mAllocSizeAndFlags;
- char* mPtr;
- public:
- protected:
- void EnsureMutable()
- {
- if ((mAllocSizeAndFlags & AttrFlags) == StrPtrFlag)
- {
- // It's a reference
- int allocSize = (int)BF_MAX(GetAllocSize(), this->mLength + 1);
- char* newPtr = AllocPtr(allocSize);
- memcpy(newPtr, this->mPtr, this->mLength);
- newPtr[this->mLength] = 0;
- this->mPtr = newPtr;
- mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
- }
- }
- char* AllocPtr(intptr size)
- {
- return (char*)malloc(size);
- }
- void DeletePtr()
- {
- free(this->mPtr);
- }
- intptr CalcNewSize(intptr minSize);
- void Realloc(intptr newSize, bool copyStr = true);
- void Realloc(char* newPtr, intptr newSize);
- static bool EqualsHelper(const char* a, const char* b, intptr length);
- static bool EqualsIgnoreCaseHelper(const char* a, const char* b, intptr length);
- static int CompareOrdinalIgnoreCaseHelper(const StringImpl& strA, const StringImpl& strB);
- static intptr CompareOrdinalIgnoreCaseHelper(const char* strA, intptr lengthA, const char* strB, intptr lengthB);
- static intptr CompareOrdinalIgnoreCaseHelper(const StringImpl& strA, intptr indexA, intptr lengthA, const StringImpl& strB, intptr indexB, intptr lengthB);
- static intptr CompareOrdinalHelper(const char* strA, intptr lengthA, const char* strB, intptr lengthB);
- static intptr CompareOrdinalHelper(const StringImpl& strA, intptr indexA, intptr lengthA, const StringImpl& strB, intptr indexB, intptr lengthB);
- void Init(const char* charPtr, intptr count)
- {
- int_strsize internalSize = (int_strsize)(sizeof(StringImpl) - offsetof(StringImpl, mPtr));
- int_strsize allocSize = (int_strsize)count + 1;
- if (allocSize <= internalSize)
- {
- // Fits
- auto ptr = (char*)&this->mPtr;
- memcpy(ptr, charPtr, count);
- ptr[count] = 0;
- mAllocSizeAndFlags = internalSize;
- this->mLength = (int_strsize)count;
- }
- else
- {
- // Too big, must alloc
- auto ptr = AllocPtr(allocSize);
- memcpy(ptr, charPtr, count);
- ptr[count] = 0;
- this->mPtr = ptr;
- mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
- this->mLength = (int_strsize)count;
- }
- }
- protected:
- // Use "String" or "StringT<>"
- StringImpl()
- {
- }
- public:
- static StringImpl MakeRef(const char* charPtr)
- {
- StringImpl str;
- // This is just a ref - called when we pass a literal to a method (for example)
- str.mPtr = (char*)charPtr;
- str.mLength = (int_strsize)strlen(charPtr);
- str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
- return str;
- }
- static StringImpl MakeRef(const char* charPtr, intptr length)
- {
- StringImpl str;
- // This is just a ref - called when we pass a literal to a method (for example)
- str.mPtr = (char*)charPtr;
- str.mLength = (int_strsize)length;
- str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
- return str;
- }
- static StringImpl MakeRef(const StringView& strView)
- {
- StringImpl str;
- // This is just a ref - called when we pass a literal to a method (for example)
- str.mPtr = (char*)strView.mPtr;
- str.mLength = (int_strsize)strView.mLength;
- str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
- return str;
- }
- StringImpl(const char* charPtr)
- {
- // This is just a ref - called when we pass a literal to a method (for example)
- this->mPtr = (char*)charPtr;
- this->mLength = (int_strsize)strlen(charPtr);
- mAllocSizeAndFlags = this->mLength | StrPtrFlag;
- }
- StringImpl(const char* charPtr, const char* charPtrEnd)
- {
- Init(charPtr, (int_strsize)(charPtrEnd - charPtr));
- }
- StringImpl(const char* charPtr, intptr length)
- {
- Init(charPtr, (int_strsize)length);
- }
- StringImpl(const StringImpl& str)
- {
- Init(str.GetPtr(), str.mLength);
- }
- StringImpl(const StringView& str);
- StringImpl(const StringImpl& str, intptr offset)
- {
- Init(str.GetPtr() + offset, (int_strsize)(str.mLength - offset));
- }
- StringImpl(const StringImpl& str, intptr offset, intptr length)
- {
- Init(str.GetPtr() + offset, (int_strsize)length);
- }
- StringImpl(const std::string& str)
- {
- // This is just a ref - called when we pass a std::string to a method (for example)
- this->mPtr = (char*)str.c_str();
- this->mLength = (int_strsize)str.length();
- mAllocSizeAndFlags = this->mLength | StrPtrFlag;
- }
- StringImpl(StringImpl&& str)
- {
- if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
- {
- this->mPtr = str.mPtr;
- mAllocSizeAndFlags = str.mAllocSizeAndFlags;
- this->mLength = str.mLength;
- str.mAllocSizeAndFlags = 0;
- }
- else
- {
- // If there's an internal buffer then we have to copy
- int_strsize count = (int_strsize)str.mLength;
- int_strsize allocSize = count + 1;
- auto ptr = AllocPtr(allocSize);
- memcpy(ptr, str.GetPtr(), count + 1);
- ptr[count] = 0;
- this->mPtr = ptr;
- mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
- this->mLength = count;
- }
- }
- ~StringImpl()
- {
- if (IsDynAlloc())
- DeletePtr();
- }
- char& operator[](intptr idx)
- {
- BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
- switch (mAllocSizeAndFlags & AttrFlags)
- {
- case 0:
- return ((char*)&this->mPtr)[idx];
- case StrPtrFlag:
- EnsureMutable();
- default:
- return this->mPtr[idx];
- }
- }
- const char& operator[](intptr idx) const
- {
- BF_ASSERT((uintptr)idx < (uintptr)this->mLength);
- return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr[idx] : ((char*)&this->mPtr)[idx];
- }
- bool operator==(const StringImpl& strB) const
- {
- if (this->mLength != strB.mLength)
- return false;
- return strncmp(GetPtr(), strB.GetPtr(), this->mLength) == 0;
- }
- bool operator!=(const StringImpl& strB) const
- {
- if (this->mLength != strB.mLength)
- return true;
- return strncmp(GetPtr(), strB.GetPtr(), this->mLength) != 0;
- }
- bool operator==(const StringView& strB) const
- {
- if (this->mLength != strB.mLength)
- return false;
- return strncmp(GetPtr(), strB.mPtr, this->mLength) == 0;
- }
- bool operator!=(const StringView& strB) const
- {
- if (this->mLength != strB.mLength)
- return true;
- return strncmp(GetPtr(), strB.mPtr, this->mLength) != 0;
- }
- bool operator==(const char* strB) const
- {
- return strcmp(GetPtr(), strB) == 0;
- }
- bool operator!=(const char* strB) const
- {
- return strcmp(GetPtr(), strB) != 0;
- }
- bool operator<(const StringImpl& strB) const
- {
- return strcmp(GetPtr(), strB.GetPtr()) < 0;
- }
- bool operator>(const StringImpl& strB) const
- {
- return strcmp(GetPtr(), strB.GetPtr()) > 0;
- }
- StringImpl& operator=(const StringImpl& str)
- {
- if (&str != this)
- {
- this->mLength = 0;
- Append(str.GetPtr(), str.mLength);
- }
- return *this;
- }
- StringImpl& operator=(StringImpl&& str)
- {
- if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
- {
- if (IsDynAlloc())
- DeletePtr();
- this->mPtr = str.mPtr;
- mAllocSizeAndFlags = str.mAllocSizeAndFlags;
- this->mLength = str.mLength;
- str.mAllocSizeAndFlags = 0;
- }
- else
- {
- // If there's an internal buffer then we have to copy
- int_strsize count = (int_strsize)str.mLength;
- int_strsize allocSize = count + 1;
- if (allocSize > GetAllocSize())
- Realloc(allocSize, false);
- auto ptr = GetMutablePtr();
- memcpy(ptr, str.GetPtr(), count + 1);
- ptr[count] = 0;
- this->mLength = count;
- }
- return *this;
- }
- StringImpl& operator=(const std::string& str)
- {
- this->mLength = 0;
- Append(str.c_str(), (intptr)str.length());
- return *this;
- }
- StringImpl& operator=(const char* str)
- {
- this->mLength = 0;
- Append(str, strlen(str));
- return *this;
- }
- StringImpl& operator=(char c)
- {
- this->mLength = 0;
- Append(c);
- return *this;
- }
- StringImpl& operator+=(const StringImpl& str)
- {
- Append(str.GetPtr(), str.mLength);
- return *this;
- }
- StringImpl& operator+=(const StringView& str)
- {
- Append(str.mPtr, str.mLength);
- return *this;
- }
- StringImpl& operator+=(const char* str)
- {
- Append(str, strlen(str));
- return *this;
- }
- StringImpl& operator+=(char c)
- {
- Append(c);
- return *this;
- }
- operator std::string() const
- {
- return std::string(GetPtr(), GetPtr() + this->mLength);
- }
- intptr length() const
- {
- return this->mLength;
- }
- int GetLength() const
- {
- return this->mLength;
- }
- intptr GetAllocSize() const
- {
- return (int_strsize)(mAllocSizeAndFlags & SizeFlags);
- }
- bool IsDynAlloc() const
- {
- return (mAllocSizeAndFlags & DynAllocFlag) != 0;
- }
- const char* GetPtr() const
- {
- return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr : (char*)&this->mPtr;
- }
- const char* c_str() const
- {
- return ((mAllocSizeAndFlags & StrPtrFlag) != 0) ? this->mPtr : (char*)&this->mPtr;
- }
- char* GetMutablePtr()
- {
- switch (mAllocSizeAndFlags & AttrFlags)
- {
- case 0:
- return ((char*)&this->mPtr);
- case StrPtrFlag:
- EnsureMutable();
- default:
- return this->mPtr;
- }
- }
- void Reference(const char* str);
- void Reference(const char* str, intptr length);
- void Reference(const StringView& strView);
- void Reference(const StringImpl& str);
- static String CreateReference(const StringView& strView);
- void Reserve(intptr newSize);
- void Append(const char* appendPtr);
- void Append(const char* appendPtr, intptr length);
- void Append(const StringView& str);
- void Append(const StringImpl& str);
- void Append(const StringImpl& str, const StringImpl& str2);
- void Append(const StringImpl& str, const StringImpl& str2, const StringImpl& str3);
- void Append(char c, int count = 1);
- void Release()
- {
- if (IsDynAlloc())
- DeletePtr();
- this->mLength = 0;
- this->mPtr = NULL;
- this->mAllocSizeAndFlags = 0;
- }
- void Clear()
- {
- this->mLength = 0;
- GetMutablePtr()[0] = 0;
- }
- void clear()
- {
- this->mLength = 0;
- GetMutablePtr()[0] = 0;
- }
- String Substring(intptr startIdx) const;
- String Substring(intptr startIdx, intptr length) const;
- void Remove(intptr startIdx, intptr length);
- void Remove(intptr char8Idx);
- void RemoveToEnd(intptr startIdx);
- void RemoveFromEnd(intptr length);
- void Insert(intptr idx, const StringImpl& addString);
- void Insert(intptr idx, const char* str, intptr len);
- void Insert(intptr idx, char c);
- intptr CompareTo(const StringImpl& strB, bool ignoreCase = false) const
- {
- if (ignoreCase)
- return CompareOrdinalIgnoreCaseHelper(GetPtr(), GetLength(), strB.GetPtr(), strB.GetLength());
- return CompareOrdinalHelper(GetPtr(), GetLength(), strB.GetPtr(), strB.GetLength());
- }
- static intptr Compare(const StringImpl& strA, const StringImpl& strB, bool ignoreCase)
- {
- if (ignoreCase)
- return CompareOrdinalIgnoreCaseHelper(strA.GetPtr(), strA.GetLength(), strB.GetPtr(), strB.GetLength());
- return CompareOrdinalHelper(strA.GetPtr(), strA.GetLength(), strB.GetPtr(), strB.GetLength());
- }
- static intptr Compare(const StringImpl& strA, intptr indexA, const StringImpl& strB, intptr indexB, intptr length, bool ignoreCase);
- bool Equals(const StringImpl& b, CompareKind comparisonType = CompareKind_Ordinal) const
- {
- return Equals(*this, b, comparisonType);
- }
- static bool Equals(const StringImpl& a, const StringImpl& b, CompareKind comparisonType = CompareKind_Ordinal)
- {
- if (a.mLength != b.mLength)
- return false;
- if (comparisonType == CompareKind_OrdinalIgnoreCase)
- return EqualsIgnoreCaseHelper(a.GetPtr(), b.GetPtr(), a.mLength);
- return EqualsHelper(a.GetPtr(), b.GetPtr(), a.mLength);
- }
- bool StartsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const
- {
- if (this->mLength < b.mLength)
- return false;
- if (comparisonType == CompareKind_OrdinalIgnoreCase)
- return EqualsIgnoreCaseHelper(this->GetPtr(), b.mPtr, b.mLength);
- return EqualsHelper(this->GetPtr(), b.mPtr, b.mLength);
- }
- bool EndsWith(const StringView& b, CompareKind comparisonType = CompareKind_Ordinal) const
- {
- if (this->mLength < b.mLength)
- return false;
- if (comparisonType == CompareKind_OrdinalIgnoreCase)
- return EqualsIgnoreCaseHelper(this->GetPtr() + this->mLength - b.mLength, b.mPtr, b.mLength);
- return EqualsHelper(this->GetPtr() + this->mLength - b.mLength, b.mPtr, b.mLength);
- }
- bool StartsWith(char c) const
- {
- if (this->mLength == 0)
- return false;
- return GetPtr()[0] == c;
- }
- bool EndsWith(char c) const
- {
- if (this->mLength == 0)
- return false;
- return GetPtr()[this->mLength - 1] == c;
- }
- void ReplaceLargerHelper(const StringView& find, const StringView& replace);
- void Replace(char find, char replace);
- void Replace(const StringView& find, const StringView& replace);
- void TrimEnd();
- void TrimStart();
- void Trim();
- bool IsWhitespace() const;
- bool IsEmpty() const
- {
- return this->mLength == 0;
- }
- bool empty() const
- {
- return this->mLength == 0;
- }
- bool HasMultibyteChars();
- intptr IndexOf(const StringView& subStr, bool ignoreCase = false) const;
- intptr IndexOf(const StringView& subStr, int32 startIdx) const;
- intptr IndexOf(const StringView& subStr, int64 startIdx) const;
- intptr IndexOf(char c, int32 startIdx = 0) const;
- intptr IndexOf(char c, int64 startIdx) const;
- intptr LastIndexOf(char c) const;
- intptr LastIndexOf(char c, intptr startCheck) const;
- StringSplitEnumerator Split(char c)
- {
- return StringSplitEnumerator(GetPtr(), mLength, c, 0x7FFFFFFF, false);
- }
- bool Contains(char c) const
- {
- return IndexOf(c) != -1;
- }
- bool Contains(const StringView& str) const
- {
- return IndexOf(str) != -1;
- }
- StringView::const_iterator begin() const
- {
- return GetPtr();
- }
- StringView::const_iterator end() const
- {
- return GetPtr() + this->mLength;
- }
- StringView::iterator begin()
- {
- return GetMutablePtr();
- }
- StringView::iterator end()
- {
- return GetMutablePtr() + this->mLength;
- }
- };
- template <const int TBufSize = 16>
- class StringT : public StringImpl
- {
- protected:
- void Init(const char* charPtr, int_strsize count)
- {
- int_strsize internalSize = (int_strsize)(sizeof(StringT) - offsetof(StringImpl, mPtr));
- int_strsize allocSize = count + 1;
- if (allocSize <= internalSize)
- {
- // Fits
- auto ptr = (char*)&this->mPtr;
- memcpy(ptr, charPtr, count);
- ptr[count] = 0;
- mAllocSizeAndFlags = internalSize;
- this->mLength = count;
- }
- else
- {
- // Too big, must alloc
- auto ptr = AllocPtr(allocSize);
- memcpy(ptr, charPtr, count);
- ptr[count] = 0;
- this->mPtr = ptr;
- mAllocSizeAndFlags = allocSize | DynAllocFlag | StrPtrFlag;
- this->mLength = count;
- }
- }
- public:
- char mInternalBuffer[TBufSize - sizeof(intptr)];
- using StringImpl::operator=;
- StringT()
- {
- int_strsize internalSize = (int_strsize)(sizeof(StringT) - offsetof(StringImpl, mPtr));
- this->mPtr = 0;
- mAllocSizeAndFlags = internalSize;
- this->mLength = 0;
- }
- StringT(const char* charPtr)
- {
- Init(charPtr, (int_strsize)strlen(charPtr));
- }
- StringT(const char* charPtr, const char* charPtrEnd)
- {
- Init(charPtr, (int_strsize)(charPtrEnd - charPtr));
- }
- StringT(const char* charPtr, intptr length)
- {
- Init(charPtr, (int_strsize)length);
- }
- StringT(const StringT& str)
- {
- Init(str.GetPtr(), str.mLength);
- }
- StringT(StringT&& str)
- {
- if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
- {
- this->mPtr = str.mPtr;
- mAllocSizeAndFlags = str.mAllocSizeAndFlags;
- this->mLength = str.mLength;
- str.mAllocSizeAndFlags = 0;
- }
- else
- {
- // If there's an internal buffer then we have to copy
- Init(str.GetPtr(), str.mLength);
- }
- }
- StringT(const StringT& str, intptr offset)
- {
- Init(str.GetPtr() + offset, (int_strsize)(str.mLength - offset));
- }
- StringT(const StringT& str, intptr offset, intptr length)
- {
- BF_ASSERT(offset >= 0);
- BF_ASSERT((uintptr)offset + (uintptr)length <= (uintptr)str.mLength);
- Init(str.GetPtr() + offset, (int_strsize)length);
- }
- StringT(const StringImpl& str)
- {
- Init(str.GetPtr(), str.mLength);
- }
- StringT(const std::string& str)
- {
- Init(str.c_str(), (int_strsize)str.length());
- }
- StringT(StringImpl&& str)
- {
- if ((str.mAllocSizeAndFlags & StrPtrFlag) != 0)
- {
- this->mPtr = str.mPtr;
- mAllocSizeAndFlags = str.mAllocSizeAndFlags;
- this->mLength = str.mLength;
- str.mAllocSizeAndFlags = 0;
- }
- else
- {
- // If there's an internal buffer then we have to copy
- Init(str.GetPtr(), str.mLength);
- }
- }
- StringImpl& operator=(StringT&& str)
- {
- return StringImpl::operator=(std::move(str));
- }
- StringImpl& operator=(const StringT& str)
- {
- return StringImpl::operator=(str);
- }
- };
- class StringSimple : public StringView
- {
- public:
- StringSimple()
- {
- }
- StringSimple(const StringView& sv)
- {
- this->mPtr = new char[sv.mLength + 1];
- this->mLength = sv.mLength;
- memcpy((char*)this->mPtr, sv.mPtr, this->mLength);
- ((char*)this->mPtr)[this->mLength] = 0;
- }
- StringSimple(const StringImpl& str)
- {
- this->mPtr = new char[str.mLength + 1];
- this->mLength = str.mLength;
- memcpy((char*)this->mPtr, str.GetPtr(), this->mLength);
- ((char*)mPtr)[this->mLength] = 0;
- }
- StringSimple& operator=(const StringView& sv)
- {
- delete this->mPtr;
- this->mPtr = new char[sv.mLength + 1];
- this->mLength = sv.mLength;
- memcpy((char*)this->mPtr, sv.mPtr, this->mLength);
- ((char*)this->mPtr)[this->mLength] = 0;
- return *this;
- }
- ~StringSimple()
- {
- delete this->mPtr;
- }
- const char* c_str()
- {
- return this->mPtr;
- }
- };
- class UTF16String : public Array<uint16>
- {
- public:
- UTF16String();
- UTF16String(const wchar_t* str);
- UTF16String(const wchar_t* str, int len);
- void Set(const wchar_t* str, int len);
- void Set(const wchar_t* str);
- const wchar_t* c_str() const;
- size_t length() const;
- };
- #define BF_SPECIALIZE_STR(size) \
- template <> class StringT<size> : public StringImpl \
- { \
- public: \
- using StringImpl::StringImpl; \
- using StringImpl::operator=; \
- StringT() { mPtr = NULL; mLength = 0; mAllocSizeAndFlags = 0; } \
- explicit StringT(const char* str) { Init(str, (int_strsize)strlen(str)); } \
- StringT(const std::string& str) { Init(str.c_str(), (int_strsize)str.length()); } \
- StringT(const StringImpl& str) : StringImpl(str) {} \
- StringT(StringImpl&& str) : StringImpl(std::move(str)) {} \
- };
- BF_SPECIALIZE_STR(0)
- BF_SPECIALIZE_STR(1)
- BF_SPECIALIZE_STR(2)
- BF_SPECIALIZE_STR(3)
- #ifdef BF64
- BF_SPECIALIZE_STR(4)
- BF_SPECIALIZE_STR(5)
- BF_SPECIALIZE_STR(6)
- #endif
- #undef BF_SPECIALIZE_STR
- String operator+(const StringImpl& lhs, const StringImpl& rhs);
- String operator+(const StringImpl& lhs, const StringView& rhs);
- String operator+(const StringImpl& lhs, const char* rhs);
- String operator+(const StringImpl& lhs, char rhs);
- String operator+(const char* lhs, const StringImpl& rhs);
- String operator+(const char* lhs, const StringView& rhs);
- bool operator==(const char* lhs, const StringImpl& rhs);
- bool operator!=(const char* lhs, const StringImpl& rhs);
- // bool operator==(const StringView& lhs, const StringImpl& rhs);
- // bool operator!=(const StringView& lhs, const StringImpl& rhs);
- NS_BF_END;
- namespace std
- {
- template<>
- struct hash<Beefy::StringImpl>
- {
- size_t operator()(const Beefy::StringImpl& val) const
- {
- return HashBytes((const uint8*)val.GetPtr(), val.mLength);
- }
- };
- template<>
- struct hash<Beefy::StringView>
- {
- size_t operator()(const Beefy::StringView& val) const
- {
- return HashBytes((const uint8*)val.mPtr, val.mLength);
- }
- };
- template<>
- struct hash<Beefy::String>
- {
- size_t operator()(const Beefy::String& val) const
- {
- return HashBytes((const uint8*)val.GetPtr(), val.mLength);
- }
- };
- }
|