diff options
Diffstat (limited to 'include/SString.h')
-rwxr-xr-x | include/SString.h | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/include/SString.h b/include/SString.h new file mode 100755 index 0000000..38a206c --- /dev/null +++ b/include/SString.h @@ -0,0 +1,280 @@ +// SciTE - Scintilla based Text Editor +/** @file SString.h + ** A simple string class. + **/ +// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef SSTRING_H +#define SSTRING_H + +// 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, 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. + +/** + * 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}; + +protected: + char *s; ///< The C string + lenpos_t sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string + + 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; + } + } +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. +}; + + +/** + * @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(source.s, source.sSize); + sSize = (s) ? source.sSize : 0; + } + return *this; + } +public: + /** Provide direct read/write access to buffer. */ + char *ptr() { + return s; + } + /** 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) ? last - first : 0; + } + SString(int i); + SString(double d, int precision); + ~SString() { + sLen = 0; + } + void clear() { + if (s) { + *s = '\0'; + } + sLen = 0; + } + /** Size of buffer. */ + lenpos_t size() const { + 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.s, source.sLen); + } + return *this; + } + bool operator==(const SString &sOther) const; + bool operator!=(const SString &sOther) const { + return !operator==(sOther); + } + bool operator==(const char *sOther) const; + bool operator!=(const char *sOther) const { + return !operator==(sOther); + } + 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 { + return s ? s : ""; + } + /** Give ownership of buffer to caller which must use delete[] to free buffer. */ + char *detach() { + char *sRet = s; + s = 0; + sSize = 0; + sLen = 0; + return sRet; + } + 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<lenpos_t>(measure_length)); + } + SString &operator+=(const SString &sOther) { + return append(sOther.s, sOther.sLen); + } + SString &operator+=(char ch) { + return append(&ch, 1); + } + 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); + + /** + * 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); + + SString &change(lenpos_t pos, char ch) { + if (pos < sLen) { // character changed must be in string bounds + *(s + pos) = ch; + } + return *this; + } + /** Read an integral numeric value from the string. */ + int value() const { + return s ? atoi(s) : 0; + } + 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 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 + */ +inline char *StringDup( + const char *s, ///< The string to duplicate + SContainer::lenpos_t len=SContainer::measure_length) ///< The length of memory to allocate. Optional. +{ + return SContainer::StringAllocate(s, len); +} + +#endif |