]>
git.saurik.com Git - wxWidgets.git/blob - contrib/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
);