]>
Commit | Line | Data |
---|---|---|
65ec6247 RD |
1 | // SciTE - Scintilla based Text Editor |
2 | /** @file SString.h | |
3 | ** A simple string class. | |
4 | **/ | |
591d01be | 5 | // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> |
65ec6247 RD |
6 | // The License.txt file describes the conditions under which this software may be distributed. |
7 | ||
8 | #ifndef SSTRING_H | |
9 | #define SSTRING_H | |
10 | ||
7e0c58e9 | 11 | |
1a2fb4cd | 12 | // These functions are implemented because each platform calls them something different. |
65ec6247 | 13 | int CompareCaseInsensitive(const char *a, const char *b); |
a834585d | 14 | int CompareNCaseInsensitive(const char *a, const char *b, size_t len); |
65ec6247 RD |
15 | bool EqualCaseInsensitive(const char *a, const char *b); |
16 | ||
7e0c58e9 RD |
17 | #ifdef SCI_NAMESPACE |
18 | namespace Scintilla { | |
19 | #endif | |
20 | ||
65ec6247 RD |
21 | // Define another string class. |
22 | // While it would be 'better' to use std::string, that doubles the executable size. | |
23 | // An SString may contain embedded nul characters. | |
24 | ||
65ec6247 | 25 | /** |
591d01be RD |
26 | * Base class from which the two other classes (SBuffer & SString) |
27 | * are derived. | |
28 | */ | |
29 | class SContainer { | |
1a2fb4cd RD |
30 | public: |
31 | /** Type of string lengths (sizes) and positions (indexes). */ | |
a834585d | 32 | typedef size_t lenpos_t; |
1a2fb4cd RD |
33 | /** Out of bounds value indicating that the string argument should be measured. */ |
34 | enum { measure_length=0xffffffffU}; | |
35 | ||
591d01be | 36 | protected: |
1a2fb4cd RD |
37 | char *s; ///< The C string |
38 | lenpos_t sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string | |
591d01be RD |
39 | |
40 | SContainer() : s(0), sSize(0) {} | |
41 | ~SContainer() { | |
42 | delete []s; // Suppose it was allocated using StringAllocate | |
43 | s = 0; | |
44 | sSize = 0; | |
45 | } | |
46 | /** Size of buffer. */ | |
47 | lenpos_t size() const { | |
48 | if (s) { | |
49 | return sSize; | |
50 | } else { | |
51 | return 0; | |
1a2fb4cd | 52 | } |
1a2fb4cd | 53 | } |
591d01be RD |
54 | public: |
55 | /** | |
56 | * Allocate uninitialized memory big enough to fit a string of the given length. | |
57 | * @return the pointer to the new string | |
58 | */ | |
59 | static char *StringAllocate(lenpos_t len); | |
60 | /** | |
61 | * Duplicate a buffer/C string. | |
62 | * Allocate memory of the given size, or big enough to fit the string if length isn't given; | |
63 | * then copy the given string in the allocated memory. | |
64 | * @return the pointer to the new string | |
65 | */ | |
66 | static char *StringAllocate( | |
67 | const char *s, ///< The string to duplicate | |
68 | lenpos_t len=measure_length); ///< The length of memory to allocate. Optional. | |
69 | }; | |
65ec6247 | 70 | |
591d01be RD |
71 | |
72 | /** | |
73 | * @brief A string buffer class. | |
74 | * | |
75 | * Main use is to ask an API the length of a string it can provide, | |
76 | * then to allocate a buffer of the given size, and to provide this buffer | |
77 | * to the API to put the string. | |
78 | * This class is intended to be shortlived, to be transformed as SString | |
79 | * as soon as it holds the string, so it has little members. | |
80 | * Note: we assume the buffer is filled by the API. If the length can be shorter, | |
81 | * we should set sLen to strlen(sb.ptr()) in related SString constructor and assignment. | |
82 | */ | |
83 | class SBuffer : protected SContainer { | |
84 | public: | |
85 | SBuffer(lenpos_t len) { | |
86 | s = StringAllocate(len); | |
87 | if (s) { | |
88 | *s = '\0'; | |
89 | sSize = len; | |
1a2fb4cd | 90 | } else { |
591d01be RD |
91 | sSize = 0; |
92 | } | |
93 | } | |
94 | private: | |
95 | /// Copy constructor | |
96 | // Here only to be on the safe size, user should avoid returning SBuffer values. | |
97 | SBuffer(const SBuffer &source) : SContainer() { | |
98 | s = StringAllocate(source.s, source.sSize); | |
99 | sSize = (s) ? source.sSize : 0; | |
100 | } | |
101 | /// Default assignment operator | |
102 | // Same here, shouldn't be used | |
103 | SBuffer &operator=(const SBuffer &source) { | |
104 | if (this != &source) { | |
1a2fb4cd | 105 | delete []s; |
591d01be RD |
106 | s = StringAllocate(source.s, source.sSize); |
107 | sSize = (s) ? source.sSize : 0; | |
1a2fb4cd RD |
108 | } |
109 | return *this; | |
110 | } | |
1a2fb4cd | 111 | public: |
591d01be RD |
112 | /** Provide direct read/write access to buffer. */ |
113 | char *ptr() { | |
114 | return s; | |
65ec6247 | 115 | } |
591d01be RD |
116 | /** Ownership of the buffer have been taken, so release it. */ |
117 | void reset() { | |
118 | s = 0; | |
119 | sSize = 0; | |
120 | } | |
121 | /** Size of buffer. */ | |
122 | lenpos_t size() const { | |
123 | return SContainer::size(); | |
124 | } | |
125 | }; | |
126 | ||
127 | ||
128 | /** | |
129 | * @brief A simple string class. | |
130 | * | |
131 | * Hold the length of the string for quick operations, | |
132 | * can have a buffer bigger than the string to avoid too many memory allocations and copies. | |
133 | * May have embedded zeroes as a result of @a substitute, but relies too heavily on C string | |
134 | * functions to allow reliable manipulations of these strings, other than simple appends, etc. | |
135 | */ | |
136 | class SString : protected SContainer { | |
137 | lenpos_t sLen; ///< The size of the string in s | |
138 | lenpos_t sizeGrowth; ///< Minimum growth size when appending strings | |
139 | enum { sizeGrowthDefault = 64 }; | |
140 | ||
141 | bool grow(lenpos_t lenNew); | |
142 | SString &assign(const char *sOther, lenpos_t sSize_=measure_length); | |
143 | ||
144 | public: | |
145 | SString() : sLen(0), sizeGrowth(sizeGrowthDefault) {} | |
146 | SString(const SString &source) : SContainer(), sizeGrowth(sizeGrowthDefault) { | |
147 | s = StringAllocate(source.s, source.sLen); | |
148 | sSize = sLen = (s) ? source.sLen : 0; | |
65ec6247 RD |
149 | } |
150 | SString(const char *s_) : sizeGrowth(sizeGrowthDefault) { | |
1a2fb4cd | 151 | s = StringAllocate(s_); |
65ec6247 RD |
152 | sSize = sLen = (s) ? strlen(s) : 0; |
153 | } | |
591d01be RD |
154 | SString(SBuffer &buf) : sizeGrowth(sizeGrowthDefault) { |
155 | s = buf.ptr(); | |
156 | sSize = sLen = buf.size(); | |
157 | // Consumes the given buffer! | |
158 | buf.reset(); | |
159 | } | |
1a2fb4cd | 160 | SString(const char *s_, lenpos_t first, lenpos_t last) : sizeGrowth(sizeGrowthDefault) { |
a834585d | 161 | // note: expects the "last" argument to point one beyond the range end (a la STL iterators) |
1a2fb4cd | 162 | s = StringAllocate(s_ + first, last - first); |
591d01be | 163 | sSize = sLen = (s) ? last - first : 0; |
65ec6247 | 164 | } |
591d01be RD |
165 | SString(int i); |
166 | SString(double d, int precision); | |
65ec6247 | 167 | ~SString() { |
65ec6247 RD |
168 | sLen = 0; |
169 | } | |
1a2fb4cd | 170 | void clear() { |
65ec6247 RD |
171 | if (s) { |
172 | *s = '\0'; | |
173 | } | |
174 | sLen = 0; | |
175 | } | |
176 | /** Size of buffer. */ | |
1a2fb4cd | 177 | lenpos_t size() const { |
591d01be | 178 | return SContainer::size(); |
65ec6247 RD |
179 | } |
180 | /** Size of string in buffer. */ | |
1a2fb4cd | 181 | lenpos_t length() const { |
65ec6247 RD |
182 | return sLen; |
183 | } | |
591d01be RD |
184 | /** Read access to a character of the string. */ |
185 | char operator[](lenpos_t i) const { | |
186 | return (s && i < sSize) ? s[i] : '\0'; | |
187 | } | |
65ec6247 RD |
188 | SString &operator=(const char *source) { |
189 | return assign(source); | |
190 | } | |
191 | SString &operator=(const SString &source) { | |
192 | if (this != &source) { | |
591d01be | 193 | assign(source.s, source.sLen); |
65ec6247 RD |
194 | } |
195 | return *this; | |
196 | } | |
591d01be | 197 | bool operator==(const SString &sOther) const; |
65ec6247 RD |
198 | bool operator!=(const SString &sOther) const { |
199 | return !operator==(sOther); | |
200 | } | |
591d01be | 201 | bool operator==(const char *sOther) const; |
65ec6247 RD |
202 | bool operator!=(const char *sOther) const { |
203 | return !operator==(sOther); | |
204 | } | |
1e9bafca | 205 | bool contains(char ch) const { |
591d01be | 206 | return (s && *s) ? strchr(s, ch) != 0 : false; |
65ec6247 | 207 | } |
1a2fb4cd | 208 | void setsizegrowth(lenpos_t sizeGrowth_) { |
65ec6247 RD |
209 | sizeGrowth = sizeGrowth_; |
210 | } | |
211 | const char *c_str() const { | |
591d01be | 212 | return s ? s : ""; |
65ec6247 RD |
213 | } |
214 | /** Give ownership of buffer to caller which must use delete[] to free buffer. */ | |
215 | char *detach() { | |
216 | char *sRet = s; | |
217 | s = 0; | |
218 | sSize = 0; | |
219 | sLen = 0; | |
220 | return sRet; | |
221 | } | |
591d01be RD |
222 | SString substr(lenpos_t subPos, lenpos_t subLen=measure_length) const; |
223 | SString &lowercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); | |
224 | SString &uppercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); | |
225 | SString &append(const char *sOther, lenpos_t sLenOther=measure_length, char sep = '\0'); | |
1a2fb4cd RD |
226 | SString &operator+=(const char *sOther) { |
227 | return append(sOther, static_cast<lenpos_t>(measure_length)); | |
65ec6247 | 228 | } |
1a2fb4cd | 229 | SString &operator+=(const SString &sOther) { |
9e730a78 | 230 | return append(sOther.s, sOther.sLen); |
65ec6247 | 231 | } |
1a2fb4cd | 232 | SString &operator+=(char ch) { |
65ec6247 RD |
233 | return append(&ch, 1); |
234 | } | |
1a2fb4cd | 235 | SString &appendwithseparator(const char *sOther, char sep) { |
65ec6247 RD |
236 | return append(sOther, strlen(sOther), sep); |
237 | } | |
591d01be RD |
238 | SString &insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther=measure_length); |
239 | ||
240 | /** | |
241 | * Remove @a len characters from the @a pos position, included. | |
1a2fb4cd RD |
242 | * Characters at pos + len and beyond replace characters at pos. |
243 | * If @a len is 0, or greater than the length of the string | |
244 | * starting at @a pos, the string is just truncated at @a pos. | |
245 | */ | |
591d01be RD |
246 | void remove(lenpos_t pos, lenpos_t len); |
247 | ||
a834585d | 248 | SString &change(lenpos_t pos, char ch) { |
591d01be RD |
249 | if (pos < sLen) { // character changed must be in string bounds |
250 | *(s + pos) = ch; | |
a834585d | 251 | } |
a834585d RD |
252 | return *this; |
253 | } | |
1a2fb4cd | 254 | /** Read an integral numeric value from the string. */ |
65ec6247 | 255 | int value() const { |
591d01be | 256 | return s ? atoi(s) : 0; |
1a2fb4cd | 257 | } |
591d01be RD |
258 | bool startswith(const char *prefix); |
259 | bool endswith(const char *suffix); | |
260 | int search(const char *sFind, lenpos_t start=0) const; | |
1e9bafca | 261 | bool contains(const char *sFind) const { |
1a2fb4cd RD |
262 | return search(sFind) >= 0; |
263 | } | |
591d01be RD |
264 | int substitute(char chFind, char chReplace); |
265 | int substitute(const char *sFind, const char *sReplace); | |
1a2fb4cd RD |
266 | int remove(const char *sFind) { |
267 | return substitute(sFind, ""); | |
268 | } | |
65ec6247 RD |
269 | }; |
270 | ||
591d01be | 271 | |
1a2fb4cd RD |
272 | /** |
273 | * Duplicate a C string. | |
274 | * Allocate memory of the given size, or big enough to fit the string if length isn't given; | |
275 | * then copy the given string in the allocated memory. | |
276 | * @return the pointer to the new string | |
277 | */ | |
278 | inline char *StringDup( | |
279 | const char *s, ///< The string to duplicate | |
591d01be | 280 | SContainer::lenpos_t len=SContainer::measure_length) ///< The length of memory to allocate. Optional. |
1a2fb4cd | 281 | { |
591d01be | 282 | return SContainer::StringAllocate(s, len); |
1a2fb4cd RD |
283 | } |
284 | ||
7e0c58e9 RD |
285 | #ifdef SCI_NAMESPACE |
286 | } | |
287 | #endif | |
288 | ||
65ec6247 | 289 | #endif |