X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a834585d7492ae8388ea109bf38d55c4a502753a..80a779275ae04443c568dca919adb26cf6f5002c:/src/stc/scintilla/include/SString.h diff --git a/src/stc/scintilla/include/SString.h b/src/stc/scintilla/include/SString.h index 6bfe50fccd..38a206ccf2 100644 --- a/src/stc/scintilla/include/SString.h +++ b/src/stc/scintilla/include/SString.h @@ -2,7 +2,7 @@ /** @file SString.h ** A simple string class. **/ -// Copyright 1998-2001 by Neil Hodgson +// Copyright 1998-2004 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef SSTRING_H @@ -18,100 +18,148 @@ bool EqualCaseInsensitive(const char *a, const char *b); // An SString may contain embedded nul characters. /** - * @brief A simple string class. - * - * Hold the length of the string for quick operations, - * can have a buffer bigger than the string to avoid too many memory allocations and copies. - * May have embedded zeroes as a result of @a substitute, but relies too heavily on C string - * functions to allow reliable manipulations of these strings, other than simple appends, etc. - **/ -class SString { + * Base class from which the two other classes (SBuffer & SString) + * are derived. + */ +class SContainer { public: /** Type of string lengths (sizes) and positions (indexes). */ typedef size_t lenpos_t; /** Out of bounds value indicating that the string argument should be measured. */ enum { measure_length=0xffffffffU}; -private: +protected: char *s; ///< The C string lenpos_t sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string - lenpos_t sLen; ///< The size of the string in s - lenpos_t sizeGrowth; ///< Minimum growth size when appending strings - enum { sizeGrowthDefault = 64 }; - bool grow(lenpos_t lenNew) { - while (sizeGrowth * 6 < lenNew) { - sizeGrowth *= 2; - } - char *sNew = new char[lenNew + sizeGrowth + 1]; - if (sNew) { - if (s) { - memcpy(sNew, s, sLen); - delete []s; - } - s = sNew; - s[sLen] = '\0'; - sSize = lenNew + sizeGrowth; + + SContainer() : s(0), sSize(0) {} + ~SContainer() { + delete []s; // Suppose it was allocated using StringAllocate + s = 0; + sSize = 0; + } + /** Size of buffer. */ + lenpos_t size() const { + if (s) { + return sSize; + } else { + return 0; } - return sNew != 0; } +public: + /** + * Allocate uninitialized memory big enough to fit a string of the given length. + * @return the pointer to the new string + */ + static char *StringAllocate(lenpos_t len); + /** + * Duplicate a buffer/C string. + * Allocate memory of the given size, or big enough to fit the string if length isn't given; + * then copy the given string in the allocated memory. + * @return the pointer to the new string + */ + static char *StringAllocate( + const char *s, ///< The string to duplicate + lenpos_t len=measure_length); ///< The length of memory to allocate. Optional. +}; - SString &assign(const char *sOther, lenpos_t sSize_=measure_length) { - if (!sOther) { - sSize_ = 0; - } else if (sSize_ == measure_length) { - sSize_ = strlen(sOther); - } - if (sSize > 0 && sSize_ <= sSize) { // Does not allocate new buffer if the current is big enough - if (s && sSize_) { - memcpy(s, sOther, sSize_); - } - s[sSize_] = '\0'; - sLen = sSize_; + +/** + * @brief A string buffer class. + * + * Main use is to ask an API the length of a string it can provide, + * then to allocate a buffer of the given size, and to provide this buffer + * to the API to put the string. + * This class is intended to be shortlived, to be transformed as SString + * as soon as it holds the string, so it has little members. + * Note: we assume the buffer is filled by the API. If the length can be shorter, + * we should set sLen to strlen(sb.ptr()) in related SString constructor and assignment. + */ +class SBuffer : protected SContainer { +public: + SBuffer(lenpos_t len) { + s = StringAllocate(len); + if (s) { + *s = '\0'; + sSize = len; } else { + sSize = 0; + } + } +private: + /// Copy constructor + // Here only to be on the safe size, user should avoid returning SBuffer values. + SBuffer(const SBuffer &source) : SContainer() { + s = StringAllocate(source.s, source.sSize); + sSize = (s) ? source.sSize : 0; + } + /// Default assignment operator + // Same here, shouldn't be used + SBuffer &operator=(const SBuffer &source) { + if (this != &source) { delete []s; - s = StringAllocate(sOther, sSize_); - if (s) { - sSize = sSize_; // Allow buffer bigger than real string, thus providing space to grow - sLen = strlen(s); - } else { - sSize = sLen = 0; - } + s = StringAllocate(source.s, source.sSize); + sSize = (s) ? source.sSize : 0; } return *this; } - public: - SString() : s(0), sSize(0), sLen(0), sizeGrowth(sizeGrowthDefault) { + /** Provide direct read/write access to buffer. */ + char *ptr() { + return s; } - SString(const SString &source) : sizeGrowth(sizeGrowthDefault) { - s = StringAllocate(source.s); - sSize = sLen = (s) ? strlen(s) : 0; + /** Ownership of the buffer have been taken, so release it. */ + void reset() { + s = 0; + sSize = 0; + } + /** Size of buffer. */ + lenpos_t size() const { + return SContainer::size(); + } +}; + + +/** + * @brief A simple string class. + * + * Hold the length of the string for quick operations, + * can have a buffer bigger than the string to avoid too many memory allocations and copies. + * May have embedded zeroes as a result of @a substitute, but relies too heavily on C string + * functions to allow reliable manipulations of these strings, other than simple appends, etc. + */ +class SString : protected SContainer { + lenpos_t sLen; ///< The size of the string in s + lenpos_t sizeGrowth; ///< Minimum growth size when appending strings + enum { sizeGrowthDefault = 64 }; + + bool grow(lenpos_t lenNew); + SString &assign(const char *sOther, lenpos_t sSize_=measure_length); + +public: + SString() : sLen(0), sizeGrowth(sizeGrowthDefault) {} + SString(const SString &source) : SContainer(), sizeGrowth(sizeGrowthDefault) { + s = StringAllocate(source.s, source.sLen); + sSize = sLen = (s) ? source.sLen : 0; } SString(const char *s_) : sizeGrowth(sizeGrowthDefault) { s = StringAllocate(s_); sSize = sLen = (s) ? strlen(s) : 0; } + SString(SBuffer &buf) : sizeGrowth(sizeGrowthDefault) { + s = buf.ptr(); + sSize = sLen = buf.size(); + // Consumes the given buffer! + buf.reset(); + } SString(const char *s_, lenpos_t first, lenpos_t last) : sizeGrowth(sizeGrowthDefault) { // note: expects the "last" argument to point one beyond the range end (a la STL iterators) s = StringAllocate(s_ + first, last - first); - sSize = sLen = (s) ? strlen(s) : 0; - } - SString(int i) : sizeGrowth(sizeGrowthDefault) { - char number[32]; - sprintf(number, "%0d", i); - s = StringAllocate(number); - sSize = sLen = (s) ? strlen(s) : 0; - } - SString(double d, int precision) : sizeGrowth(sizeGrowthDefault) { - char number[32]; - sprintf(number, "%.*f", precision, d); - s = StringAllocate(number); - sSize = sLen = (s) ? strlen(s) : 0; + sSize = sLen = (s) ? last - first : 0; } + SString(int i); + SString(double d, int precision); ~SString() { - delete []s; - s = 0; - sSize = 0; sLen = 0; } void clear() { @@ -122,58 +170,41 @@ public: } /** Size of buffer. */ lenpos_t size() const { - if (s) - return sSize; - else - return 0; + return SContainer::size(); } /** Size of string in buffer. */ lenpos_t length() const { return sLen; } + /** Read access to a character of the string. */ + char operator[](lenpos_t i) const { + return (s && i < sSize) ? s[i] : '\0'; + } SString &operator=(const char *source) { return assign(source); } SString &operator=(const SString &source) { if (this != &source) { - assign(source.c_str()); + assign(source.s, source.sLen); } return *this; } - bool operator==(const SString &sOther) const { - if ((s == 0) && (sOther.s == 0)) - return true; - if ((s == 0) || (sOther.s == 0)) - return false; - return strcmp(s, sOther.s) == 0; - } + bool operator==(const SString &sOther) const; bool operator!=(const SString &sOther) const { return !operator==(sOther); } - bool operator==(const char *sOther) const { - if ((s == 0) && (sOther == 0)) - return true; - if ((s == 0) || (sOther == 0)) - return false; - return strcmp(s, sOther) == 0; - } + bool operator==(const char *sOther) const; bool operator!=(const char *sOther) const { return !operator==(sOther); } - bool contains(char ch) { - if (s && *s) - return strchr(s, ch) != 0; - else - return false; + bool contains(char ch) const { + return (s && *s) ? strchr(s, ch) != 0 : false; } void setsizegrowth(lenpos_t sizeGrowth_) { sizeGrowth = sizeGrowth_; } const char *c_str() const { - if (s) - return s; - else - return ""; + return s ? s : ""; } /** Give ownership of buffer to caller which must use delete[] to free buffer. */ char *detach() { @@ -183,62 +214,15 @@ public: sLen = 0; return sRet; } - char operator[](lenpos_t i) const { - if (s && i < sSize) // Or < sLen? Depends on the use, both are OK - return s[i]; - else - return '\0'; - } - SString substr(lenpos_t subPos, lenpos_t subLen=measure_length) const { - if (subPos >= sLen) { - return SString(); // return a null string if start index is out of bounds - } - if ((subLen == measure_length) || (subPos + subLen > sLen)) { - subLen = sLen - subPos; // can't substr past end of source string - } - return SString(s, subPos, subPos + subLen); - } - SString &lowercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length) { - if ((subLen == measure_length) || (subPos + subLen > sLen)) { - subLen = sLen - subPos; // don't apply past end of string - } - for (lenpos_t i = subPos; i < subPos + subLen; i++) { - if (s[i] < 'A' || s[i] > 'Z') - continue; - else - s[i] = static_cast(s[i] - 'A' + 'a'); - } - return *this; - } - SString &append(const char *sOther, lenpos_t sLenOther=measure_length, char sep = '\0') { - if (!sOther) { - return *this; - } - if (sLenOther == measure_length) { - sLenOther = strlen(sOther); - } - int lenSep = 0; - if (sLen && sep) { // Only add a separator if not empty - lenSep = 1; - } - lenpos_t lenNew = sLen + sLenOther + lenSep; - // Conservative about growing the buffer: don't do it, unless really needed - if ((lenNew + 1 < sSize) || (grow(lenNew))) { - if (lenSep) { - s[sLen] = sep; - sLen++; - } - memcpy(&s[sLen], sOther, sLenOther); - sLen += sLenOther; - s[sLen] = '\0'; - } - return *this; - } + SString substr(lenpos_t subPos, lenpos_t subLen=measure_length) const; + SString &lowercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); + SString &uppercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); + SString &append(const char *sOther, lenpos_t sLenOther=measure_length, char sep = '\0'); SString &operator+=(const char *sOther) { return append(sOther, static_cast(measure_length)); } SString &operator+=(const SString &sOther) { - return append(sOther.s, sOther.sSize); + return append(sOther.s, sOther.sLen); } SString &operator+=(char ch) { return append(&ch, 1); @@ -246,121 +230,40 @@ public: SString &appendwithseparator(const char *sOther, char sep) { return append(sOther, strlen(sOther), sep); } - SString &insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther=measure_length) { - if (!sOther) { - return *this; - } - if (sLenOther == measure_length) { - sLenOther = strlen(sOther); - } - lenpos_t lenNew = sLen + sLenOther; - // Conservative about growing the buffer: don't do it, unless really needed - if ((lenNew + 1 < sSize) || grow(lenNew)) { - lenpos_t moveChars = sLen - pos + 1; - for (lenpos_t i = moveChars; i > 0; i--) { - s[pos + sLenOther + i - 1] = s[pos + i - 1]; - } - memcpy(s + pos, sOther, sLenOther); - sLen = lenNew; - } - return *this; - } - /** Remove @a len characters from the @a pos position, included. + SString &insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther=measure_length); + + /** + * Remove @a len characters from the @a pos position, included. * Characters at pos + len and beyond replace characters at pos. * If @a len is 0, or greater than the length of the string * starting at @a pos, the string is just truncated at @a pos. */ - void remove(lenpos_t pos, lenpos_t len) { - if (len < 1 || pos + len >= sLen) { - s[pos] = '\0'; - sLen = pos; - } else { - for (lenpos_t i = pos; i < sLen - len + 1; i++) { - s[i] = s[i+len]; - } - sLen -= len; - } - } + void remove(lenpos_t pos, lenpos_t len); + SString &change(lenpos_t pos, char ch) { - if (pos >= sLen) { // character changed must be in string bounds - return *this; + if (pos < sLen) { // character changed must be in string bounds + *(s + pos) = ch; } - *(s + pos) = ch; return *this; } /** Read an integral numeric value from the string. */ int value() const { - if (s) - return atoi(s); - else - return 0; - } - int search(const char *sFind, lenpos_t start=0) const { - if (start < sLen) { - const char *sFound = strstr(s + start, sFind); - if (sFound) { - return sFound - s; - } - } - return -1; + return s ? atoi(s) : 0; } - bool contains(const char *sFind) { + bool startswith(const char *prefix); + bool endswith(const char *suffix); + int search(const char *sFind, lenpos_t start=0) const; + bool contains(const char *sFind) const { return search(sFind) >= 0; } - int substitute(char chFind, char chReplace) { - int c = 0; - char *t = s; - while (t) { - t = strchr(t, chFind); - if (t) { - *t = chReplace; - t++; - c++; - } - } - return c; - } - int substitute(const char *sFind, const char *sReplace) { - int c = 0; - lenpos_t lenFind = strlen(sFind); - lenpos_t lenReplace = strlen(sReplace); - int posFound = search(sFind); - while (posFound >= 0) { - remove(posFound, lenFind); - insert(posFound, sReplace, lenReplace); - posFound = search(sFind, posFound + lenReplace); - c++; - } - return c; - } + int substitute(char chFind, char chReplace); + int substitute(const char *sFind, const char *sReplace); int remove(const char *sFind) { return substitute(sFind, ""); } - /** - * Duplicate a C string. - * Allocate memory of the given size, or big enough to fit the string if length isn't given; - * then copy the given string in the allocated memory. - * @return the pointer to the new string - */ - static char *StringAllocate( - const char *s, ///< The string to duplicate - lenpos_t len=measure_length) ///< The length of memory to allocate. Optional. - { - if (s == 0) { - return 0; - } - if (len == measure_length) { - len = strlen(s); - } - char *sNew = new char[len + 1]; - if (sNew) { - memcpy(sNew, s, len); - sNew[len] = '\0'; - } - return sNew; - } }; + /** * Duplicate a C string. * Allocate memory of the given size, or big enough to fit the string if length isn't given; @@ -369,9 +272,9 @@ public: */ inline char *StringDup( const char *s, ///< The string to duplicate - SString::lenpos_t len=SString::measure_length) ///< The length of memory to allocate. Optional. + SContainer::lenpos_t len=SContainer::measure_length) ///< The length of memory to allocate. Optional. { - return SString::StringAllocate(s, len); + return SContainer::StringAllocate(s, len); } #endif