]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/include/SString.h
   1 // SciTE - Scintilla based Text Editor 
   3  ** A simple string class. 
   5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> 
   6 // The License.txt file describes the conditions under which this software may be distributed. 
  11 // These functions are implemented because each platform calls them something different. 
  12 int CompareCaseInsensitive(const char *a
, const char *b
); 
  13 int CompareNCaseInsensitive(const char *a
, const char *b
, size_t len
); 
  14 bool EqualCaseInsensitive(const char *a
, const char *b
); 
  16 // Define another string class. 
  17 // While it would be 'better' to use std::string, that doubles the executable size. 
  18 // An SString may contain embedded nul characters. 
  21  * @brief A simple string class. 
  23  * Hold the length of the string for quick operations, 
  24  * can have a buffer bigger than the string to avoid too many memory allocations and copies. 
  25  * May have embedded zeroes as a result of @a substitute, but relies too heavily on C string 
  26  * functions to allow reliable manipulations of these strings, other than simple appends, etc. 
  30         /** Type of string lengths (sizes) and positions (indexes). */ 
  31         typedef size_t lenpos_t
; 
  32         /** Out of bounds value indicating that the string argument should be measured. */ 
  33         enum { measure_length
=0xffffffffU
}; 
  36         char *s
;                                ///< The C string 
  37         lenpos_t sSize
;                 ///< The size of the buffer, less 1: ie. the maximum size of the string 
  38         lenpos_t sLen
;                  ///< The size of the string in s 
  39         lenpos_t sizeGrowth
;    ///< Minimum growth size when appending strings 
  40         enum { sizeGrowthDefault 
= 64 }; 
  41         bool grow(lenpos_t lenNew
) { 
  42                 while (sizeGrowth 
* 6 < lenNew
) { 
  45                 char *sNew 
= new char[lenNew 
+ sizeGrowth 
+ 1]; 
  48                                 memcpy(sNew
, s
, sLen
); 
  53                         sSize 
= lenNew 
+ sizeGrowth
; 
  58         SString 
&assign(const char *sOther
, lenpos_t sSize_
=measure_length
) { 
  61                 } else if (sSize_ 
== measure_length
) { 
  62                         sSize_ 
= strlen(sOther
); 
  64                 if (sSize 
> 0 && sSize_ 
<= sSize
) {     // Does not allocate new buffer if the current is big enough 
  66                                 memcpy(s
, sOther
, sSize_
); 
  72                         s 
= StringAllocate(sOther
, sSize_
); 
  74                                 sSize 
= sSize_
; // Allow buffer bigger than real string, thus providing space to grow 
  84         SString() : s(0), sSize(0), sLen(0), sizeGrowth(sizeGrowthDefault
) { 
  86         SString(const SString 
&source
) : sizeGrowth(sizeGrowthDefault
) { 
  87                 s 
= StringAllocate(source
.s
); 
  88                 sSize 
= sLen 
= (s
) ? strlen(s
) : 0; 
  90         SString(const char *s_
) : sizeGrowth(sizeGrowthDefault
) { 
  91                 s 
= StringAllocate(s_
); 
  92                 sSize 
= sLen 
= (s
) ? strlen(s
) : 0; 
  94         SString(const char *s_
, lenpos_t first
, lenpos_t last
) : sizeGrowth(sizeGrowthDefault
) { 
  95                 // note: expects the "last" argument to point one beyond the range end (a la STL iterators) 
  96                 s 
= StringAllocate(s_ 
+ first
, last 
- first
); 
  97                 sSize 
= sLen 
= (s
) ? strlen(s
) : 0; 
  99         SString(int i
) : sizeGrowth(sizeGrowthDefault
) { 
 101                 sprintf(number
, "%0d", i
); 
 102                 s 
= StringAllocate(number
); 
 103                 sSize 
= sLen 
= (s
) ? strlen(s
) : 0; 
 105         SString(double d
, int precision
) : sizeGrowth(sizeGrowthDefault
) { 
 107                 sprintf(number
, "%.*f", precision
, d
); 
 108                 s 
= StringAllocate(number
); 
 109                 sSize 
= sLen 
= (s
) ? strlen(s
) : 0; 
 123         /** Size of buffer. */ 
 124         lenpos_t 
size() const { 
 130         /** Size of string in buffer. */ 
 131         lenpos_t 
length() const { 
 134         SString 
&operator=(const char *source
) { 
 135                 return assign(source
); 
 137         SString 
&operator=(const SString 
&source
) { 
 138                 if (this != &source
) { 
 139                         assign(source
.c_str()); 
 143         bool operator==(const SString 
&sOther
) const { 
 144                 if ((s 
== 0) && (sOther
.s 
== 0)) 
 146                 if ((s 
== 0) || (sOther
.s 
== 0)) 
 148                 return strcmp(s
, sOther
.s
) == 0; 
 150         bool operator!=(const SString 
&sOther
) const { 
 151                 return !operator==(sOther
); 
 153         bool operator==(const char *sOther
) const { 
 154                 if ((s 
== 0) && (sOther 
== 0)) 
 156                 if ((s 
== 0) || (sOther 
== 0)) 
 158                 return strcmp(s
, sOther
) == 0; 
 160         bool operator!=(const char *sOther
) const { 
 161                 return !operator==(sOther
); 
 163         bool contains(char ch
) { 
 165                         return strchr(s
, ch
) != 0; 
 169         void setsizegrowth(lenpos_t sizeGrowth_
) { 
 170                 sizeGrowth 
= sizeGrowth_
; 
 172         const char *c_str() const { 
 178         /** Give ownership of buffer to caller which must use delete[] to free buffer. */ 
 186         char operator[](lenpos_t i
) const { 
 187                 if (s 
&& i 
< sSize
)     // Or < sLen? Depends on the use, both are OK 
 192         SString 
substr(lenpos_t subPos
, lenpos_t subLen
=measure_length
) const { 
 193                 if (subPos 
>= sLen
) { 
 194                         return SString();                                       // return a null string if start index is out of bounds 
 196                 if ((subLen 
== measure_length
) || (subPos 
+ subLen 
> sLen
)) { 
 197                         subLen 
= sLen 
- subPos
;         // can't substr past end of source string 
 199                 return SString(s
, subPos
, subPos 
+ subLen
); 
 201         SString 
&lowercase(lenpos_t subPos 
= 0, lenpos_t subLen
=measure_length
) { 
 202                 if ((subLen 
== measure_length
) || (subPos 
+ subLen 
> sLen
)) { 
 203                         subLen 
= sLen 
- subPos
;         // don't apply past end of string 
 205                 for (lenpos_t i 
= subPos
; i 
< subPos 
+ subLen
; i
++) { 
 206                         if (s
[i
] < 'A' || s
[i
] > 'Z') 
 209                                 s
[i
] = static_cast<char>(s
[i
] - 'A' + 'a'); 
 213         SString 
&append(const char *sOther
, lenpos_t sLenOther
=measure_length
, char sep 
= '\0') { 
 217                 if (sLenOther 
== measure_length
) { 
 218                         sLenOther 
= strlen(sOther
); 
 221                 if (sLen 
&& sep
) {      // Only add a separator if not empty 
 224                 lenpos_t lenNew 
= sLen 
+ sLenOther 
+ lenSep
; 
 225                 // Conservative about growing the buffer: don't do it, unless really needed 
 226                 if ((lenNew 
+ 1 < sSize
) || (grow(lenNew
))) { 
 231                         memcpy(&s
[sLen
], sOther
, sLenOther
); 
 237         SString 
&operator+=(const char *sOther
) { 
 238                 return append(sOther
, static_cast<lenpos_t
>(measure_length
)); 
 240         SString 
&operator+=(const SString 
&sOther
) { 
 241                 return append(sOther
.s
, sOther
.sLen
); 
 243         SString 
&operator+=(char ch
) { 
 244                 return append(&ch
, 1); 
 246         SString 
&appendwithseparator(const char *sOther
, char sep
) { 
 247                 return append(sOther
, strlen(sOther
), sep
); 
 249         SString 
&insert(lenpos_t pos
, const char *sOther
, lenpos_t sLenOther
=measure_length
) { 
 253                 if (sLenOther 
== measure_length
) { 
 254                         sLenOther 
= strlen(sOther
); 
 256                 lenpos_t lenNew 
= sLen 
+ sLenOther
; 
 257                 // Conservative about growing the buffer: don't do it, unless really needed 
 258                 if ((lenNew 
+ 1 < sSize
) || grow(lenNew
)) { 
 259                         lenpos_t moveChars 
= sLen 
- pos 
+ 1; 
 260                         for (lenpos_t i 
= moveChars
; i 
> 0; i
--) { 
 261                                 s
[pos 
+ sLenOther 
+ i 
- 1] = s
[pos 
+ i 
- 1]; 
 263                         memcpy(s 
+ pos
, sOther
, sLenOther
); 
 268         /** Remove @a len characters from the @a pos position, included. 
 269          * Characters at pos + len and beyond replace characters at pos. 
 270          * If @a len is 0, or greater than the length of the string 
 271          * starting at @a pos, the string is just truncated at @a pos. 
 273         void remove(lenpos_t pos
, lenpos_t len
) { 
 274                 if (len 
< 1 || pos 
+ len 
>= sLen
) { 
 278                         for (lenpos_t i 
= pos
; i 
< sLen 
- len 
+ 1; i
++) { 
 284         SString 
&change(lenpos_t pos
, char ch
) { 
 285                 if (pos 
>= sLen
) {                                      // character changed must be in string bounds 
 291         /** Read an integral numeric value from the string. */ 
 298         int search(const char *sFind
, lenpos_t start
=0) const { 
 300                         const char *sFound 
= strstr(s 
+ start
, sFind
); 
 307         bool contains(const char *sFind
) { 
 308                 return search(sFind
) >= 0; 
 310         int substitute(char chFind
, char chReplace
) { 
 314                         t 
= strchr(t
, chFind
); 
 323         int substitute(const char *sFind
, const char *sReplace
) { 
 325                 lenpos_t lenFind 
= strlen(sFind
); 
 326                 lenpos_t lenReplace 
= strlen(sReplace
); 
 327                 int posFound 
= search(sFind
); 
 328                 while (posFound 
>= 0) { 
 329                         remove(posFound
, lenFind
); 
 330                         insert(posFound
, sReplace
, lenReplace
); 
 331                         posFound 
= search(sFind
, posFound 
+ lenReplace
); 
 336         int remove(const char *sFind
) { 
 337                 return substitute(sFind
, ""); 
 340          * Duplicate a C string. 
 341          * Allocate memory of the given size, or big enough to fit the string if length isn't given; 
 342          * then copy the given string in the allocated memory. 
 343          * @return the pointer to the new string 
 345         static char *StringAllocate( 
 346                 const char *s
,                  ///< The string to duplicate 
 347                 lenpos_t len
=measure_length
)    ///< The length of memory to allocate. Optional. 
 352                 if (len 
== measure_length
) { 
 355                 char *sNew 
= new char[len 
+ 1]; 
 357                         memcpy(sNew
, s
, len
); 
 365  * Duplicate a C string. 
 366  * Allocate memory of the given size, or big enough to fit the string if length isn't given; 
 367  * then copy the given string in the allocated memory. 
 368  * @return the pointer to the new string 
 370 inline char *StringDup( 
 371         const char *s
,                  ///< The string to duplicate 
 372         SString::lenpos_t len
=SString::measure_length
)  ///< The length of memory to allocate. Optional. 
 374         return SString::StringAllocate(s
, len
);