X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/65ec6247df6af7b6489257b1ac04ca2242dc14ec..f53b1c1e6f5546e9916debbf5f93c652edca0ef6:/contrib/src/stc/scintilla/include/SString.h diff --git a/contrib/src/stc/scintilla/include/SString.h b/contrib/src/stc/scintilla/include/SString.h index aeb5940502..01602df781 100644 --- a/contrib/src/stc/scintilla/include/SString.h +++ b/contrib/src/stc/scintilla/include/SString.h @@ -8,72 +8,104 @@ #ifndef SSTRING_H #define SSTRING_H -// These functions are implemented because each platform calls them something different +// These functions are implemented because each platform calls them something different. int CompareCaseInsensitive(const char *a, const char *b); -int CompareNCaseInsensitive(const char *a, const char *b, int len); +int CompareNCaseInsensitive(const char *a, const char *b, size_t len); bool EqualCaseInsensitive(const char *a, const char *b); // Define another string class. // While it would be 'better' to use std::string, that doubles the executable size. // An SString may contain embedded nul characters. -/** - * 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 - */ -inline char *StringDup( - const char *s, ///< The string to duplicate - int len=-1) ///< The length of memory to allocate. Optional. -{ - if (!s) - return 0; - if (len == -1) - len = strlen(s); - char *sNew = new char[len + 1]; - if (sNew) { - strncpy(sNew, s, len); - sNew[len] = '\0'; - } - return sNew; -} - /** * @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 rely too heavily on C string - * functions to allow reliable manipulations of these strings. + * 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 { - char *s; ///< The C string - int sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string - int sLen; ///< The size of the string in s - int sizeGrowth; ///< Minimum growth size when appending strings +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: + 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; + } + return sNew != 0; + } -public: - typedef int size_type; + 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_; + } else { + 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; + } + } + return *this; + } +public: SString() : s(0), sSize(0), sLen(0), sizeGrowth(sizeGrowthDefault) { } SString(const SString &source) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(source.s); + s = StringAllocate(source.s); sSize = sLen = (s) ? strlen(s) : 0; } SString(const char *s_) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(s_); + s = StringAllocate(s_); sSize = sLen = (s) ? strlen(s) : 0; } - SString(const char *s_, int first, int last) : sizeGrowth(sizeGrowthDefault) { - s = StringDup(s_ + first, last - first); + 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 = StringDup(number); + 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; } ~SString() { @@ -82,51 +114,23 @@ public: sSize = 0; sLen = 0; } - void clear(void) { + void clear() { if (s) { *s = '\0'; } sLen = 0; } /** Size of buffer. */ - size_type size(void) const { ///< + lenpos_t size() const { if (s) return sSize; else return 0; } /** Size of string in buffer. */ - int length() const { + lenpos_t length() const { return sLen; } - SString &assign(const char* sOther, int sSize_ = -1) { - if (!sOther) { - sSize_ = 0; - } - if (sSize_ < 0) { - sSize_ = strlen(sOther); - } - if (sSize > 0 && sSize_ <= sSize) { // Does not allocate new buffer if the current is big enough - if (s && sSize_) { - strncpy(s, sOther, sSize_); - } - s[sSize_] = '\0'; - sLen = sSize_; - } else { - delete []s; - s = StringDup(sOther, sSize_); - if (s) { - sSize = sSize_; // Allow buffer bigger than real string, thus providing space to grow - sLen = strlen(s); - } else { - sSize = sLen = 0; - } - } - return *this; - } - SString &assign(const SString& sOther, int sSize_ = -1) { - return assign(sOther.s, sSize_); - } SString &operator=(const char *source) { return assign(source); } @@ -162,7 +166,7 @@ public: else return false; } - void setsizegrowth(int sizeGrowth_) { + void setsizegrowth(lenpos_t sizeGrowth_) { sizeGrowth = sizeGrowth_; } const char *c_str() const { @@ -179,77 +183,195 @@ public: sLen = 0; return sRet; } - char operator[](int i) const { + 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 &append(const char* sOther, int sLenOther=-1, char sep=0) { - if (sLenOther < 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 + if (sLen && sep) { // Only add a separator if not empty lenSep = 1; - int lenNew = sLen + sLenOther + lenSep; - if (lenNew + 1 < sSize) { - // Conservative about growing the buffer: don't do it, unless really needed + } + 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++; } - strncpy(&s[sLen], sOther, sLenOther); - s[sLen + sLenOther] = '\0'; + memcpy(&s[sLen], sOther, sLenOther); sLen += sLenOther; - } else { - // Grow the buffer bigger than really needed, to have room for other appends - char *sNew = new char[lenNew + sizeGrowth + 1]; - if (sNew) { - if (s) { - memcpy(sNew, s, sLen); - delete []s; - } - s = sNew; - sSize = lenNew + sizeGrowth; - if (lenSep) { - s[sLen] = sep; - sLen++; - } - strncpy(&s[sLen], sOther, sLenOther); - sNew[sLen + sLenOther] = '\0'; - sLen += sLenOther; - } + s[sLen] = '\0'; } return *this; } - SString &operator +=(const char *sOther) { - return append(sOther, -1); + SString &operator+=(const char *sOther) { + return append(sOther, static_cast(measure_length)); } - SString &operator +=(const SString &sOther) { - return append(sOther.s, sOther.sSize); + SString &operator+=(const SString &sOther) { + return append(sOther.s, sOther.sLen); } - SString &operator +=(char ch) { + SString &operator+=(char ch) { return append(&ch, 1); } - SString &appendwithseparator(const char* sOther, char sep) { + 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. + * 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; + } + } + SString &change(lenpos_t pos, char ch) { + if (pos >= sLen) { // character changed must be in string bounds + return *this; + } + *(s + pos) = ch; + return *this; + } + /** Read an integral numeric value from the string. */ int value() const { if (s) return atoi(s); else return 0; } - void substitute(char find, char replace) { + 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; + } + bool contains(const char *sFind) { + return search(sFind) >= 0; + } + int substitute(char chFind, char chReplace) { + int c = 0; char *t = s; while (t) { - t = strchr(t, find); + t = strchr(t, chFind); if (t) { - *t = replace; + *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 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; + * then copy the given string in the allocated memory. + * @return the pointer to the new string + */ +inline char *StringDup( + const char *s, ///< The string to duplicate + SString::lenpos_t len=SString::measure_length) ///< The length of memory to allocate. Optional. +{ + return SString::StringAllocate(s, len); +} + #endif