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