You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
8.5 KiB
280 lines
8.5 KiB
// 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
|
|
|