]>
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
, int 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 rely too heavily on C string
26 * functions to allow reliable manipulations of these strings.
30 /** Type of string lengths (sizes) and positions (indexes). */
31 typedef unsigned int 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 strncpy(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 s
= StringAllocate(s_
+ first
, last
- first
);
96 sSize
= sLen
= (s
) ? strlen(s
) : 0;
98 SString(int i
) : sizeGrowth(sizeGrowthDefault
) {
100 sprintf(number
, "%0d", i
);
101 s
= StringAllocate(number
);
102 sSize
= sLen
= (s
) ? strlen(s
) : 0;
104 SString(double d
, int precision
) : sizeGrowth(sizeGrowthDefault
) {
106 sprintf(number
, "%.*f", precision
, d
);
107 s
= StringAllocate(number
);
108 sSize
= sLen
= (s
) ? strlen(s
) : 0;
122 /** Size of buffer. */
123 lenpos_t
size() const {
129 /** Size of string in buffer. */
130 lenpos_t
length() const {
133 SString
&operator=(const char *source
) {
134 return assign(source
);
136 SString
&operator=(const SString
&source
) {
137 if (this != &source
) {
138 assign(source
.c_str());
142 bool operator==(const SString
&sOther
) const {
143 if ((s
== 0) && (sOther
.s
== 0))
145 if ((s
== 0) || (sOther
.s
== 0))
147 return strcmp(s
, sOther
.s
) == 0;
149 bool operator!=(const SString
&sOther
) const {
150 return !operator==(sOther
);
152 bool operator==(const char *sOther
) const {
153 if ((s
== 0) && (sOther
== 0))
155 if ((s
== 0) || (sOther
== 0))
157 return strcmp(s
, sOther
) == 0;
159 bool operator!=(const char *sOther
) const {
160 return !operator==(sOther
);
162 bool contains(char ch
) {
164 return strchr(s
, ch
) != 0;
168 void setsizegrowth(lenpos_t sizeGrowth_
) {
169 sizeGrowth
= sizeGrowth_
;
171 const char *c_str() const {
177 /** Give ownership of buffer to caller which must use delete[] to free buffer. */
185 char operator[](lenpos_t i
) const {
186 if (s
&& i
< sSize
) // Or < sLen? Depends on the use, both are OK
191 SString
&append(const char *sOther
, lenpos_t sLenOther
=measure_length
, char sep
= '\0') {
195 if (sLenOther
== measure_length
) {
196 sLenOther
= strlen(sOther
);
199 if (sLen
&& sep
) { // Only add a separator if not empty
202 lenpos_t lenNew
= sLen
+ sLenOther
+ lenSep
;
203 // Conservative about growing the buffer: don't do it, unless really needed
204 if ((lenNew
+ 1 < sSize
) || (grow(lenNew
))) {
209 strncpy(&s
[sLen
], sOther
, sLenOther
);
215 SString
&operator+=(const char *sOther
) {
216 return append(sOther
, static_cast<lenpos_t
>(measure_length
));
218 SString
&operator+=(const SString
&sOther
) {
219 return append(sOther
.s
, sOther
.sSize
);
221 SString
&operator+=(char ch
) {
222 return append(&ch
, 1);
224 SString
&appendwithseparator(const char *sOther
, char sep
) {
225 return append(sOther
, strlen(sOther
), sep
);
227 SString
&insert(lenpos_t pos
, const char *sOther
, lenpos_t sLenOther
=measure_length
) {
231 if (sLenOther
== measure_length
) {
232 sLenOther
= strlen(sOther
);
234 lenpos_t lenNew
= sLen
+ sLenOther
;
235 // Conservative about growing the buffer: don't do it, unless really needed
236 if ((lenNew
+ 1 < sSize
) || grow(lenNew
)) {
237 lenpos_t moveChars
= sLen
- pos
+ 1;
238 for (lenpos_t i
= moveChars
; i
> 0; i
--) {
239 s
[pos
+ sLenOther
+ i
- 1] = s
[pos
+ i
- 1];
241 memcpy(s
+ pos
, sOther
, sLenOther
);
246 /** Remove @a len characters from the @a pos position, included.
247 * Characters at pos + len and beyond replace characters at pos.
248 * If @a len is 0, or greater than the length of the string
249 * starting at @a pos, the string is just truncated at @a pos.
251 void remove(lenpos_t pos
, lenpos_t len
) {
252 if (len
< 1 || pos
+ len
>= sLen
) {
256 for (lenpos_t i
= pos
; i
< sLen
- len
+ 1; i
++) {
262 /** Read an integral numeric value from the string. */
269 int search(const char *sFind
, lenpos_t start
=0) {
271 const char *sFound
= strstr(s
+ start
, sFind
);
278 bool contains(const char *sFind
) {
279 return search(sFind
) >= 0;
281 int substitute(char chFind
, char chReplace
) {
285 t
= strchr(t
, chFind
);
294 int substitute(const char *sFind
, const char *sReplace
) {
296 lenpos_t lenFind
= strlen(sFind
);
297 lenpos_t lenReplace
= strlen(sReplace
);
298 int posFound
= search(sFind
);
299 while (posFound
>= 0) {
300 remove(posFound
, lenFind
);
301 insert(posFound
, sReplace
, lenReplace
);
302 posFound
= search(sFind
, posFound
+ lenReplace
);
307 int remove(const char *sFind
) {
308 return substitute(sFind
, "");
311 * Duplicate a C string.
312 * Allocate memory of the given size, or big enough to fit the string if length isn't given;
313 * then copy the given string in the allocated memory.
314 * @return the pointer to the new string
316 static char *StringAllocate(
317 const char *s
, ///< The string to duplicate
318 lenpos_t len
=measure_length
) ///< The length of memory to allocate. Optional.
323 if (len
== measure_length
) {
326 char *sNew
= new char[len
+ 1];
328 strncpy(sNew
, s
, len
);
336 * Duplicate a C string.
337 * Allocate memory of the given size, or big enough to fit the string if length isn't given;
338 * then copy the given string in the allocated memory.
339 * @return the pointer to the new string
341 inline char *StringDup(
342 const char *s
, ///< The string to duplicate
343 SString::lenpos_t len
=SString::measure_length
) ///< The length of memory to allocate. Optional.
345 return SString::StringAllocate(s
, len
);