1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: str.h 4362 2010-12-31 13:29:30Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2010 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 //
26 //	Dynamic string class.
27 //
28 //**************************************************************************
29 
30 #define TEXT_COLOUR_ESCAPE		'\034'
31 
32 class VStr
33 {
34 private:
35 	char*		Str;
36 
37 	void Resize(int NewLen);
38 
39 public:
40 	//	Constructors.
VStr()41 	VStr()
42 	: Str(NULL)
43 	{}
VStr(ENoInit)44 	VStr(ENoInit)
45 	{}
VStr(const char * InStr)46 	VStr(const char* InStr)
47 	: Str(NULL)
48 	{
49 		if (*InStr)
50 		{
51 			Resize(int(Length(InStr)));
52 			Cpy(Str, InStr);
53 		}
54 	}
VStr(const VStr & InStr)55 	VStr(const VStr& InStr)
56 	: Str(NULL)
57 	{
58 		if (InStr.Str)
59 		{
60 			Resize(int(InStr.Length()));
61 			Cpy(Str, InStr.Str);
62 		}
63 	}
64 	VStr(const VStr& InStr, int Start, int Len);
VStr(char InChr)65 	explicit VStr(char InChr)
66 	: Str(NULL)
67 	{
68 		Resize(1);
69 		Str[0] = InChr;
70 	}
VStr(bool InBool)71 	explicit VStr(bool InBool)
72 	: Str(NULL)
73 	{
74 		if (InBool)
75 		{
76 			Resize(4);
77 			Cpy(Str, "true");
78 		}
79 		else
80 		{
81 			Resize(5);
82 			Cpy(Str, "false");
83 		}
84 	}
VStr(int InInt)85 	explicit VStr(int InInt)
86 	: Str(NULL)
87 	{
88 		char Buf[64];
89 
90 		sprintf(Buf, "%d", InInt);
91 		Resize(int(Length(Buf)));
92 		Cpy(Str, Buf);
93 	}
VStr(unsigned InInt)94 	explicit VStr(unsigned InInt)
95 	: Str(NULL)
96 	{
97 		char Buf[64];
98 
99 		sprintf(Buf, "%u", InInt);
100 		Resize(int(Length(Buf)));
101 		Cpy(Str, Buf);
102 	}
VStr(float InFloat)103 	explicit VStr(float InFloat)
104 	: Str(NULL)
105 	{
106 		char Buf[64];
107 
108 		sprintf(Buf, "%f", InFloat);
109 		Resize(int(Length(Buf)));
110 		Cpy(Str, Buf);
111 	}
VStr(const VName & InName)112 	explicit VStr(const VName& InName)
113 	: Str(NULL)
114 	{
115 		Resize(int(Length(*InName)));
116 		Cpy(Str, *InName);
117 	}
118 
119 	//	Destructor.
~VStr()120 	~VStr()
121 	{
122 		Clean();
123 	}
124 
125 	//	Clears the string.
Clean()126 	void Clean()
127 	{
128 		Resize(0);
129 	}
130 	//	Return length of the string.
Length()131 	size_t Length() const
132 	{
133 		return Str ? ((int*)Str)[-1] : 0;
134 	}
135 	//	Return number of characters in a UTF-8 string.
Utf8Length()136 	size_t Utf8Length() const
137 	{
138 		return Str ? Utf8Length(Str) : 0;
139 	}
140 	//	Return C string.
141 	const char* operator*() const
142 	{
143 		return Str ? Str : "";
144 	}
145 	//	Check if string is empty.
IsEmpty()146 	bool IsEmpty() const
147 	{
148 		return !Str;
149 	}
IsNotEmpty()150 	bool IsNotEmpty() const
151 	{
152 		return !!Str;
153 	}
154 
155 	//	Character ancestors.
156 	char operator[](int Idx) const
157 	{
158 		return Str[Idx];
159 	}
160 	char& operator[](int Idx)
161 	{
162 		return Str[Idx];
163 	}
164 
165 	//	Assignement operators.
166 	VStr& operator=(const char* InStr)
167 	{
168 		Resize(int(Length(InStr)));
169 		if (*InStr)
170 			Cpy(Str, InStr);
171 		return *this;
172 	}
173 	VStr& operator=(const VStr& InStr)
174 	{
175 		Resize(int(InStr.Length()));
176 		if (InStr.Str)
177 			Cpy(Str, InStr.Str);
178 		return *this;
179 	}
180 
181 	//	Concatenation operators.
182 	VStr& operator+=(const char* InStr)
183 	{
184 		if (*InStr)
185 		{
186 			int l = int(Length());
187 			Resize(int(l + Length(InStr)));
188 			Cpy(Str + l, InStr);
189 		}
190 		return *this;
191 	}
192 	VStr& operator+=(const VStr& InStr)
193 	{
194 		if (InStr.Length())
195 		{
196 			int l = int(Length());
197 			Resize(int(l + InStr.Length()));
198 			Cpy(Str + l, *InStr);
199 		}
200 		return *this;
201 	}
202 	VStr& operator+=(char InChr)
203 	{
204 		int l = int(Length());
205 		Resize(int(l + 1));
206 		Str[l] = InChr;
207 		return *this;
208 	}
209 	VStr& operator+=(bool InBool)
210 	{
211 		return operator+=(InBool ? "true" : "false");
212 	}
213 	VStr& operator+=(int InInt)
214 	{
215 		char Buf[64];
216 
217 		sprintf(Buf, "%d", InInt);
218 		return operator+=(Buf);
219 	}
220 	VStr& operator+=(unsigned InInt)
221 	{
222 		char Buf[64];
223 
224 		sprintf(Buf, "%u", InInt);
225 		return operator+=(Buf);
226 	}
227 	VStr& operator+=(float InFloat)
228 	{
229 		char Buf[64];
230 
231 		sprintf(Buf, "%f", InFloat);
232 		return operator+=(Buf);
233 	}
234 	VStr& operator+=(const VName& InName)
235 	{
236 		return operator+=(*InName);
237 	}
238 	friend VStr operator+(const VStr& S1, const char* S2)
239 	{
240 		VStr Ret(S1);
241 		Ret += S2;
242 		return Ret;
243 	}
244 	friend VStr operator+(const VStr& S1, const VStr& S2)
245 	{
246 		VStr Ret(S1);
247 		Ret += S2;
248 		return Ret;
249 	}
250 	friend VStr operator+(const VStr& S1, char S2)
251 	{
252 		VStr Ret(S1);
253 		Ret += S2;
254 		return Ret;
255 	}
256 	friend VStr operator+(const VStr& S1, bool InBool)
257 	{
258 		VStr Ret(S1);
259 		Ret += InBool;
260 		return Ret;
261 	}
262 	friend VStr operator+(const VStr& S1, int InInt)
263 	{
264 		VStr Ret(S1);
265 		Ret += InInt;
266 		return Ret;
267 	}
268 	friend VStr operator+(const VStr& S1, unsigned InInt)
269 	{
270 		VStr Ret(S1);
271 		Ret += InInt;
272 		return Ret;
273 	}
274 	friend VStr operator+(const VStr& S1, float InFloat)
275 	{
276 		VStr Ret(S1);
277 		Ret += InFloat;
278 		return Ret;
279 	}
280 	friend VStr operator+(const VStr& S1, const VName& InName)
281 	{
282 		VStr Ret(S1);
283 		Ret += InName;
284 		return Ret;
285 	}
286 
287 	//	Comparison operators.
288 	friend bool operator==(const VStr& S1, const char* S2)
289 	{
290 		return !Cmp(*S1, S2);
291 	}
292 	friend bool operator==(const VStr& S1, const VStr& S2)
293 	{
294 		return !Cmp(*S1, *S2);
295 	}
296 	friend bool operator!=(const VStr& S1, const char* S2)
297 	{
298 		return !!Cmp(*S1, S2);
299 	}
300 	friend bool operator!=(const VStr& S1, const VStr& S2)
301 	{
302 		return !!Cmp(*S1, *S2);
303 	}
304 
305 	//	Comparison functions.
Cmp(const char * S2)306 	int Cmp(const char* S2) const
307 	{
308 		return Cmp(**this, S2);
309 	}
Cmp(const VStr & S2)310 	int Cmp(const VStr& S2) const
311 	{
312 		return Cmp(**this, *S2);
313 	}
ICmp(const char * S2)314 	int ICmp(const char* S2) const
315 	{
316 		return ICmp(**this, S2);
317 	}
ICmp(const VStr & S2)318 	int ICmp(const VStr& S2) const
319 	{
320 		return ICmp(**this, *S2);
321 	}
322 
323 	bool StartsWith(const char*) const;
324 	bool StartsWith(const VStr&) const;
325 	bool EndsWith(const char*) const;
326 	bool EndsWith(const VStr&) const;
327 
328 	VStr ToLower() const;
329 	VStr ToUpper() const;
330 
331 	int IndexOf(char) const;
332 	int IndexOf(const char*) const;
333 	int IndexOf(const VStr&) const;
334 	int LastIndexOf(char) const;
335 	int LastIndexOf(const char*) const;
336 	int LastIndexOf(const VStr&) const;
337 
338 	VStr Replace(const char*, const char*) const;
339 	VStr Replace(const VStr&, const VStr&) const;
340 
341 	VStr Utf8Substring(int, int) const;
342 
343 	void Split(char, TArray<VStr>&) const;
344 	void Split(const char*, TArray<VStr>&) const;
345 
346 	bool IsValidUtf8() const;
347 	VStr Latin1ToUtf8() const;
348 
349 	//	Serialisation operator.
350 	friend VStream& operator<<(VStream& Strm, VStr& S)
351 	{
352 		if (Strm.IsLoading())
353 		{
354 			vint32 Len;
355 			Strm << STRM_INDEX(Len);
356 			if (Len < 0)
357 				Len = 0;
358 			S.Resize(Len);
359 			if (Len)
360 				Strm.Serialise(S.Str, Len + 1);
361 		}
362 		else
363 		{
364 			vint32 Len = vint32(S.Length());
365 			Strm << STRM_INDEX(Len);
366 			if (Len)
367 				Strm.Serialise(S.Str, Len + 1);
368 		}
369 		return Strm;
370 	}
371 
372 	VStr EvalEscapeSequences() const;
373 
374 	VStr RemoveColours() const;
375 
376 	VStr ExtractFilePath() const;
377 	VStr ExtractFileName() const;
378 	VStr ExtractFileBase() const;
379 	VStr ExtractFileExtension() const;
380 	VStr StripExtension() const;
381 	VStr DefaultPath(const VStr& basepath) const;
382 	VStr DefaultExtension(const VStr& extension) const;
383 	VStr FixFileSlashes() const;
384 
385 	static size_t Length(const char*);
386 	static size_t Utf8Length(const char*);
387 	static size_t ByteLengthForUtf8(const char*, size_t);
388 	static int GetChar(const char*&);
389 	static VStr FromChar(int);
390 	static int Cmp(const char*, const char*);
391 	static int NCmp(const char*, const char*, size_t);
392 	static int ICmp(const char*, const char*);
393 	static int NICmp(const char*, const char*, size_t);
394 	static void Cpy(char*, const char*);
395 	static void NCpy(char*, const char*, size_t);
396 	static char ToUpper(char);
397 	static char ToLower(char);
398 };
399 
400 char *va(const char *text, ...) __attribute__ ((format(printf, 1, 2)));
401