1 //------------------------------------------------------------------------------
2 // emString.h
3 //
4 // Copyright (C) 2004-2011,2014,2020 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20
21 #ifndef emString_h
22 #define emString_h
23
24 #ifndef emStd1_h
25 #include <emCore/emStd1.h>
26 #endif
27
28
29 //==============================================================================
30 //================================== emString ==================================
31 //==============================================================================
32
33 class emString {
34
35 public:
36
37 // Class for a dynamically allocated null-terminated character string
38 // with copy-on-write behavior. This string type is designed to minimize
39 // memory consumption. That means, each change of the length requires
40 // reallocation. If you plan to perform many length-changing operations
41 // on a string, you may decide to do it with an emArray<char> for a
42 // better performance.
43
44 emString();
45 // Construct an empty string.
46
47 emString(const emString & s);
48 // Construct a copied string.
49 // Arguments:
50 // s - The string to be copied.
51
52 emString(const char * p);
53 // Construct a copied string.
54 // Arguments:
55 // p - The null-terminated string to be copied.
56
57 emString(const char * p, int len);
58 // Construct a copied string.
59 // Arguments:
60 // p - The string to be copied.
61 // len - Number of bytes in p.
62
63 emString(const char * p, int len, const char * p2, int len2);
64 // Construct a string as a concatenated copy of two strings.
65 // Arguments:
66 // p - First source string.
67 // len - Number of bytes in p.
68 // p2 - Second source string.
69 // len2 - Number of bytes in p2.
70
71 emString(char c, int len=1);
72 // Construct a string by filling it with a byte.
73 // Arguments:
74 // c - The byte to be used for filling.
75 // len - The length of the resulting string.
76
77 ~emString();
78 // Destructor.
79
80 static emString Format(const char * format, ...) EM_FUNC_ATTR_PRINTF(1);
81 static emString VFormat(const char * format, va_list args);
82 // This function creates a formatted string.
83 // Arguments:
84 // format - The format (like with printf).
85 // ... - Arguments to the format (like with printf).
86 // Returns: The formatted string.
87
88 emString & operator = (const emString & s);
89 emString & operator = (const char * p);
90 emString & operator = (char c);
91 // Copy a string or a byte to this string.
92
93 int GetCount() const;
94 int GetLen() const;
95 // Get the number of bytes in this string, excluding the
96 // terminating null. This really counts the bytes using strlen.
97
98 operator const char * () const;
99 const char * Get() const;
100 // Get a pointer to the internal null-terminated string for
101 // reading. At least because of the copy-on-write feature, the
102 // pointer is valid only until calling any non-const method or
103 // operator on this string, or giving this string as a non-const
104 // argument to any call in the world. Hint: Even methods like
105 // Add, Insert, Replace and GetSubString may make shallow
106 // copies, like the copy operator and copy constructor do.
107
108 char operator [] (int index) const;
109 char Get(int index) const;
110 // Get one byte from this string.
111 // Arguments:
112 // index - The index of the desired byte. This must be within
113 // the range of 0 to GetLen().
114 // Returns: The byte.
115
116 char * GetWritable();
117 char & GetWritable(int index);
118 // Like Get() and Get(index), but for modifying the bytes.
119 // There is no non-const version of the operator [], because
120 // compilers would make use of it too often. The rules for the
121 // validity of the pointer or reference are the same as with
122 // Get(), but modification is allowed only until doing something
123 // which could make a shallow copy of this string.
124
125 char * SetLenGetWritable(int len);
126 // Like GetWritable(), but even prepare for a new length of the
127 // string.
128 // Arguments:
129 // len - The length of the string you plan to produce.
130 // Returns:
131 // A pointer to the internal null-terminated string buffer for
132 // writing. The buffer contains up to len bytes of the
133 // original string, then there is a null, then there may be
134 // garbage (if len>GetLen()+1), and in any case there is a
135 // null at the end (at index len). You may modify all
136 // bytes within the index range of 0 to len-1.
137
138 void Add(const emString & s);
139 void Add(const char * p);
140 void Add(const char * p, int len);
141 void Add(char c, int len=1);
142 emString & operator += (const emString & s);
143 emString & operator += (const char * p);
144 emString & operator += (char c);
145 // Add a copy of something to the end of this string. Source and
146 // target memory may overlap.
147 // Arguments:
148 // s - A source string.
149 // p - A source string, null-terminated if len not given.
150 // c - A source byte.
151 // len - Length of string p, or how often to add byte c.
152
153 emString operator + (const emString & s) const;
154 emString operator + (const char * p) const;
155 emString operator + (char c) const;
156 friend emString operator + (const char * p, const emString & s);
157 friend emString operator + (char c, const emString & s);
158 // Add strings...
159
160 void Insert(int index, const emString & s);
161 void Insert(int index, const char * p);
162 void Insert(int index, const char * p, int len);
163 void Insert(int index, char c, int len=1);
164 // Insert a copy of something somewhere in this string. Source
165 // and target memory may overlap.
166 // Arguments:
167 // index - Position of insertion. This should be within the
168 // range of 0 to GetLen(), otherwise it is clipped
169 // accordingly.
170 // s - A source string to be copied for insertion.
171 // p - A source string to be copied for insertion,
172 // null-terminated if len not given.
173 // c - A source byte to be copied for insertion.
174 // len - Length of string p, or how often to insert
175 // byte c.
176
177 void Replace(int index, int exLen, const emString & s);
178 void Replace(int index, int exLen, const char * p);
179 void Replace(int index, int exLen, const char * p, int len);
180 void Replace(int index, int exLen, char c, int len=1);
181 // Replace something in this string by a copy of something.
182 // Source and target memory may overlap.
183 // Arguments:
184 // index - Position of replacement. This should be within the
185 // range of 0 to GetLen()-exLen, otherwise index and
186 // exLen are clipped accordingly.
187 // exLen - Number of bytes to be removed.
188 // s - A source string to be copied for insertion.
189 // p - A source string to be copied for insertion,
190 // null-terminated if len not given.
191 // c - A source byte to be copied for insertion.
192 // len - Length of string p, or how often to insert
193 // byte c.
194
195 emString GetSubString(int index, int len) const;
196 // Get a sub-string.
197 // Arguments:
198 // index - Index of the first byte of the sub-string.
199 // This should be within the range of 0 to
200 // GetLen()-len, otherwise index and len are clipped
201 // accordingly.
202 // len - Length of the sub-string.
203 // Returns: The sub-string.
204
205 emString Extract(int index, int len);
206 // Like GetSubString, but remove the sub-string from this
207 // string.
208
209 void Remove(int index, int len=1);
210 // Like Extract, but without returning the sub-string.
211
212 void Clear();
213 // Empty this string.
214
215 bool IsEmpty() const;
216 // Ask whether this string is empty.
217
218 bool operator == (const emString & s) const;
219 bool operator != (const emString & s) const;
220 bool operator <= (const emString & s) const;
221 bool operator >= (const emString & s) const;
222 bool operator < (const emString & s) const;
223 bool operator > (const emString & s) const;
224 bool operator == (const char * p) const;
225 bool operator != (const char * p) const;
226 bool operator <= (const char * p) const;
227 bool operator >= (const char * p) const;
228 bool operator < (const char * p) const;
229 bool operator > (const char * p) const;
230 friend bool operator == (const char * p, const emString & s);
231 friend bool operator != (const char * p, const emString & s);
232 friend bool operator <= (const char * p, const emString & s);
233 friend bool operator >= (const char * p, const emString & s);
234 friend bool operator < (const char * p, const emString & s);
235 friend bool operator > (const char * p, const emString & s);
236 // Compare null-terminated strings using strcmp.
237
238 unsigned int GetDataRefCount() const;
239 // Get number of references to the data behind this string.
240
241 void MakeNonShared();
242 // This must be called before handing the string to another
243 // thread.
244
245 private:
246
247 struct SharedData {
248 unsigned int RefCount;
249 char Buf[sizeof(unsigned int)];
250 };
251
252 emString(SharedData * d);
253 void FreeData();
254 void MakeWritable();
255 void PrivRep(int oldLen, int index, int exLen, const char * p, int len);
256 void PrivRep(int oldLen, int index, int exLen, char c, int len);
257
258 static SharedData EmptyData;
259 SharedData * Data;
260 };
261
262 #ifndef EM_NO_DATA_EXPORT
emString()263 inline emString::emString()
264 {
265 Data=&EmptyData;
266 }
267 #endif
268
emString(const emString & s)269 inline emString::emString(const emString & s)
270 {
271 Data=s.Data;
272 Data->RefCount++;
273 }
274
~emString()275 inline emString::~emString()
276 {
277 if (!--Data->RefCount) FreeData();
278 }
279
280 inline emString & emString::operator = (const emString & s)
281 {
282 s.Data->RefCount++;
283 if (!--Data->RefCount) FreeData();
284 Data=s.Data;
285 return *this;
286 }
287
GetCount()288 inline int emString::GetCount() const
289 {
290 return strlen(Data->Buf);
291 }
292
GetLen()293 inline int emString::GetLen() const
294 {
295 return strlen(Data->Buf);
296 }
297
298 inline emString::operator const char * () const
299 {
300 return Data->Buf;
301 }
302
Get()303 inline const char * emString::Get() const
304 {
305 return Data->Buf;
306 }
307
308 inline char emString::operator [] (int index) const
309 {
310 return Data->Buf[index];
311 }
312
Get(int index)313 inline char emString::Get(int index) const
314 {
315 return Data->Buf[index];
316 }
317
GetWritable()318 inline char * emString::GetWritable()
319 {
320 if (Data->RefCount>1) MakeWritable();
321 return Data->Buf;
322 }
323
GetWritable(int index)324 inline char & emString::GetWritable(int index)
325 {
326 if (Data->RefCount>1) MakeWritable();
327 return Data->Buf[index];
328 }
329
330 inline emString & emString::operator += (const emString & s)
331 {
332 Add(s);
333 return *this;
334 }
335
336 inline emString & emString::operator += (const char * p)
337 {
338 Add(p);
339 return *this;
340 }
341
342 inline emString & emString::operator += (char c)
343 {
344 Add(c);
345 return *this;
346 }
347
348 #ifndef EM_NO_DATA_EXPORT
Clear()349 inline void emString::Clear()
350 {
351 if (!--Data->RefCount) FreeData();
352 Data=&EmptyData;
353 }
354 #endif
355
IsEmpty()356 inline bool emString::IsEmpty() const
357 {
358 return !*Data->Buf;
359 }
360
361 inline bool emString::operator == (const emString & s) const
362 {
363 return strcmp(Data->Buf,s.Data->Buf)==0;
364 }
365
366 inline bool emString::operator != (const emString & s) const
367 {
368 return strcmp(Data->Buf,s.Data->Buf)!=0;
369 }
370
371 inline bool emString::operator <= (const emString & s) const
372 {
373 return strcmp(Data->Buf,s.Data->Buf)<=0;
374 }
375
376 inline bool emString::operator >= (const emString & s) const
377 {
378 return strcmp(Data->Buf,s.Data->Buf)>=0;
379 }
380
381 inline bool emString::operator < (const emString & s) const
382 {
383 return strcmp(Data->Buf,s.Data->Buf)<0;
384 }
385
386 inline bool emString::operator > (const emString & s) const
387 {
388 return strcmp(Data->Buf,s.Data->Buf)>0;
389 }
390
391 inline bool emString::operator == (const char * p) const
392 {
393 return strcmp(Data->Buf,p)==0;
394 }
395
396 inline bool emString::operator != (const char * p) const
397 {
398 return strcmp(Data->Buf,p)!=0;
399 }
400
401 inline bool emString::operator <= (const char * p) const
402 {
403 return strcmp(Data->Buf,p)<=0;
404 }
405
406 inline bool emString::operator >= (const char * p) const
407 {
408 return strcmp(Data->Buf,p)>=0;
409 }
410
411 inline bool emString::operator < (const char * p) const
412 {
413 return strcmp(Data->Buf,p)<0;
414 }
415
416 inline bool emString::operator > (const char * p) const
417 {
418 return strcmp(Data->Buf,p)>0;
419 }
420
421 inline bool operator == (const char * p, const emString & s)
422 {
423 return strcmp(p,s.Data->Buf)==0;
424 }
425
426 inline bool operator != (const char * p, const emString & s)
427 {
428 return strcmp(p,s.Data->Buf)!=0;
429 }
430
431 inline bool operator <= (const char * p, const emString & s)
432 {
433 return strcmp(p,s.Data->Buf)<=0;
434 }
435
436 inline bool operator >= (const char * p, const emString & s)
437 {
438 return strcmp(p,s.Data->Buf)>=0;
439 }
440
441 inline bool operator < (const char * p, const emString & s)
442 {
443 return strcmp(p,s.Data->Buf)<0;
444 }
445
446 inline bool operator > (const char * p, const emString & s)
447 {
448 return strcmp(p,s.Data->Buf)>0;
449 }
450
MakeNonShared()451 inline void emString::MakeNonShared()
452 {
453 MakeWritable();
454 }
455
emString(SharedData * d)456 inline emString::emString(SharedData * d)
457 {
458 Data=d;
459 }
460
461
462 #endif
463