]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/str.h
get the basics of a new scons build system together
[xonotic/netradiant.git] / libs / str.h
1 /*\r
2 Copyright (c) 2001, Loki software, inc.\r
3 All rights reserved.\r
4 \r
5 Redistribution and use in source and binary forms, with or without modification, \r
6 are permitted provided that the following conditions are met:\r
7 \r
8 Redistributions of source code must retain the above copyright notice, this list \r
9 of conditions and the following disclaimer.\r
10 \r
11 Redistributions in binary form must reproduce the above copyright notice, this\r
12 list of conditions and the following disclaimer in the documentation and/or\r
13 other materials provided with the distribution.\r
14 \r
15 Neither the name of Loki software nor the names of its contributors may be used \r
16 to endorse or promote products derived from this software without specific prior \r
17 written permission. \r
18 \r
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' \r
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \r
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY \r
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \r
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \r
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS \r
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \r
29 */\r
30 \r
31 #ifndef __STR__\r
32 #define __STR__\r
33 \r
34 //\r
35 // class Str\r
36 // loose replacement for CString from MFC\r
37 //\r
38 \r
39 #include <string.h>\r
40 #include <ctype.h>\r
41 #include <stdarg.h>\r
42 \r
43 #ifdef __APPLE__\r
44   #ifdef NULL\r
45     #undef NULL\r
46     #define NULL 0\r
47   #endif\r
48 #endif\r
49 \r
50 \r
51 #ifdef _WIN32\r
52 #define strcasecmp strcmpi\r
53 #endif\r
54 \r
55 // NOTE TTimo __StrDup was initially implemented in pakstuff.cpp\r
56 //   causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)\r
57 //   Q_StrDup should be used now, using a #define __StrDup for easy transition\r
58 \r
59 #define __StrDup Q_StrDup\r
60 \r
61 inline char* Q_StrDup(char* pStr)\r
62 {\r
63   if (pStr == NULL)\r
64     pStr = "";\r
65 \r
66   return strcpy(new char[strlen(pStr)+1], pStr); \r
67 }\r
68 \r
69 inline char* Q_StrDup(const char* pStr)\r
70\r
71   if (pStr == NULL)\r
72     pStr = "";\r
73 \r
74   return strcpy(new char[strlen(pStr)+1], pStr); \r
75 }\r
76 \r
77 #if defined (__linux__) || defined (__APPLE__)\r
78 #define strcmpi strcasecmp\r
79 #define stricmp strcasecmp\r
80 #define strnicmp strncasecmp\r
81 \r
82 inline char* strlwr(char* string)\r
83 {\r
84   char *cp;\r
85   for (cp = string; *cp; ++cp)\r
86   {\r
87     if ('A' <= *cp && *cp <= 'Z')\r
88       *cp += 'a' - 'A';\r
89   }\r
90 \r
91   return string;\r
92 }\r
93 \r
94 inline char* strupr(char* string)\r
95 {\r
96   char *cp;\r
97   for (cp = string; *cp; ++cp)\r
98   {\r
99     if ('a' <= *cp && *cp <= 'z')\r
100       *cp += 'A' - 'a';\r
101   }\r
102 \r
103   return string;\r
104 }\r
105 #endif\r
106 \r
107 static char *g_pStrWork = NULL;\r
108 \r
109 class Str\r
110 {\r
111 protected:\r
112   bool m_bIgnoreCase;\r
113   char *m_pStr;\r
114 \r
115 public:\r
116   Str()\r
117   {\r
118     m_bIgnoreCase = true;\r
119     m_pStr = new char[1];\r
120     m_pStr[0] = '\0';\r
121   }\r
122 \r
123   Str(char *p)\r
124   {\r
125     m_bIgnoreCase = true;\r
126     m_pStr = __StrDup(p);\r
127   }\r
128 \r
129   Str(const char *p)\r
130   {\r
131     m_bIgnoreCase = true;\r
132     m_pStr = __StrDup(p);\r
133   }\r
134 \r
135   Str(const unsigned char *p)\r
136   {\r
137     m_bIgnoreCase = true;\r
138     m_pStr = __StrDup((const char *)p);\r
139   }\r
140 \r
141   Str(const char c)\r
142   {\r
143     m_bIgnoreCase = true;\r
144     m_pStr = new char[2];\r
145     m_pStr[0] = c;\r
146     m_pStr[1] = '\0';    \r
147   }\r
148 \r
149   const char* GetBuffer() const\r
150   {\r
151     return m_pStr;\r
152   }\r
153 \r
154   Str(const Str &s)\r
155   {\r
156     m_bIgnoreCase = true;\r
157     m_pStr = __StrDup(s.GetBuffer());\r
158   }\r
159 \r
160   void Deallocate()\r
161   {\r
162     delete []m_pStr;\r
163     m_pStr = NULL;\r
164   }\r
165 \r
166   void Allocate(int n)\r
167   {\r
168     Deallocate();\r
169     m_pStr = new char[n];\r
170   }\r
171 \r
172   void MakeEmpty()\r
173   {\r
174     Deallocate();\r
175     m_pStr = __StrDup("");\r
176   }\r
177 \r
178   virtual ~Str()\r
179   {\r
180     Deallocate();\r
181     // NOTE TTimo: someone explain this g_pStrWork to me?\r
182     if (g_pStrWork)\r
183       delete []g_pStrWork;\r
184     g_pStrWork = NULL;\r
185   }\r
186 \r
187   void MakeLower()\r
188   {\r
189     if (m_pStr)\r
190     {\r
191       strlwr(m_pStr);\r
192     }\r
193   }\r
194 \r
195   void MakeUpper()\r
196   {\r
197     if (m_pStr)\r
198     {\r
199       strupr(m_pStr);\r
200     }\r
201   }\r
202 \r
203   void TrimRight()\r
204     {\r
205       char* lpsz = m_pStr;\r
206       char* lpszLast = NULL;\r
207       while (*lpsz != '\0')\r
208       {\r
209         if (isspace(*lpsz))\r
210         {\r
211           if (lpszLast == NULL)\r
212             lpszLast = lpsz;\r
213         }\r
214         else\r
215           lpszLast = NULL;\r
216         lpsz++;\r
217       }\r
218  \r
219       if (lpszLast != NULL)\r
220       {\r
221         // truncate at trailing space start\r
222         *lpszLast = '\0';\r
223       }\r
224     }\r
225 \r
226   void TrimLeft()\r
227     {\r
228       // find first non-space character\r
229       char* lpsz = m_pStr;\r
230       while (isspace(*lpsz))\r
231         lpsz++;\r
232  \r
233       // fix up data and length\r
234       int nDataLength = GetLength() - (lpsz - m_pStr);\r
235       memmove(m_pStr, lpsz, (nDataLength+1));\r
236     }\r
237 \r
238   int Find(const char *p)\r
239   {\r
240     char *pf = strstr(m_pStr, p);\r
241     return (pf) ? (pf - m_pStr) : -1;\r
242   }\r
243 \r
244   // search starting at a given offset\r
245   int Find(const char *p, int offset)\r
246   {\r
247     char *pf = strstr(m_pStr+offset, p);\r
248     return (pf) ? (pf - m_pStr) : -1;\r
249   }\r
250 \r
251   int Find(const char ch)\r
252   {\r
253     char *pf = strchr (m_pStr, ch);\r
254     return (pf) ? (pf - m_pStr) : -1;\r
255   }\r
256 \r
257   int ReverseFind(const char ch)\r
258   {\r
259     char *pf = strrchr(m_pStr, ch);\r
260     return (pf) ? (pf - m_pStr) : -1;\r
261   }\r
262 \r
263   int Compare (const char* str) const\r
264   {\r
265     return strcmp (m_pStr, str);\r
266   }\r
267   \r
268   int CompareNoCase (const char* str) const\r
269   {\r
270     return strcasecmp (m_pStr, str);\r
271   }\r
272 \r
273   int GetLength()\r
274   {\r
275     return (m_pStr) ? strlen(m_pStr) : 0;\r
276   }\r
277 \r
278   const char* Left(int n)\r
279   {\r
280     delete []g_pStrWork;\r
281     if (n > 0)\r
282     {\r
283       g_pStrWork = new char[n+1];\r
284       strncpy(g_pStrWork, m_pStr, n);\r
285       g_pStrWork[n] = '\0';\r
286     }\r
287     else\r
288     {\r
289       g_pStrWork = "";\r
290       g_pStrWork = new char[1];\r
291       g_pStrWork[0] = '\0';\r
292     }\r
293     return g_pStrWork;\r
294   }\r
295 \r
296   const char* Right(int n)\r
297   {\r
298     delete []g_pStrWork;\r
299     if (n > 0)\r
300     {\r
301       g_pStrWork = new char[n+1];\r
302       int nStart = GetLength() - n;\r
303       strncpy(g_pStrWork, &m_pStr[nStart], n);\r
304       g_pStrWork[n] = '\0';\r
305     }\r
306     else\r
307     {\r
308       g_pStrWork = new char[1];\r
309       g_pStrWork[0] = '\0';\r
310     }\r
311     return g_pStrWork;\r
312   }\r
313 \r
314   const char* Mid(int nFirst) const\r
315     {\r
316       return Mid(nFirst, strlen (m_pStr) - nFirst);\r
317     }\r
318 \r
319   const char* Mid(int first, int n) const\r
320   {\r
321     delete []g_pStrWork;\r
322     if (n > 0)\r
323     {\r
324       g_pStrWork = new char[n+1];\r
325       strncpy(g_pStrWork, m_pStr+first, n);\r
326       g_pStrWork[n] = '\0';\r
327     }\r
328     else\r
329     {\r
330       g_pStrWork = "";\r
331       g_pStrWork = new char[1];\r
332       g_pStrWork[0] = '\0';\r
333     }\r
334     return g_pStrWork;\r
335   }\r
336 \r
337 #ifdef __G_LIB_H__\r
338   void Format(const char* fmt, ...)\r
339   {\r
340     va_list args;\r
341     char *buffer;\r
342   \r
343     va_start (args, fmt);\r
344     buffer = g_strdup_vprintf (fmt, args);\r
345     va_end (args);\r
346 \r
347     delete[] m_pStr;\r
348     m_pStr = __StrDup(buffer);\r
349     g_free (buffer);\r
350   }\r
351 #else\r
352   void Format(const char* fmt, ...)\r
353   {\r
354     va_list args;\r
355     m_pStr = new char[1024];\r
356 \r
357     va_start (args, fmt);\r
358     vsprintf (m_pStr, fmt, args);\r
359     va_end (args);\r
360   }\r
361 #endif\r
362 \r
363   void SetAt(int n, char ch)\r
364   {\r
365     if (n >= 0 && n < GetLength ())\r
366       m_pStr[n] = ch;\r
367   }\r
368 \r
369         // NOTE: unlike CString, this looses the pointer\r
370   void ReleaseBuffer(int n = -1)\r
371   {\r
372     if (n == -1)\r
373       n = GetLength ();\r
374 \r
375     char* tmp = m_pStr;\r
376     tmp[n] = '\0';\r
377     m_pStr = __StrDup(tmp);\r
378     delete []tmp;\r
379   }\r
380 \r
381   char* GetBufferSetLength(int n)\r
382   {\r
383     if (n < 0)\r
384       n = 0;\r
385 \r
386     char *p = new char[n+1];\r
387     strncpy (p, m_pStr, n);\r
388                 p[n] = '\0';\r
389     delete []m_pStr;\r
390     m_pStr = p;\r
391     return m_pStr;\r
392   }\r
393 \r
394   //  char& operator *() { return *m_pStr; }\r
395   //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }\r
396   operator void*() { return m_pStr; }\r
397   operator char*() { return m_pStr; }\r
398   operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }\r
399   operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }\r
400   operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }\r
401   Str& operator =(const Str& rhs)\r
402   {\r
403     if (&rhs != this)\r
404     {\r
405       delete[] m_pStr;\r
406       m_pStr = __StrDup(rhs.m_pStr);\r
407     }\r
408     return *this;\r
409   }\r
410   \r
411   Str& operator =(const char* pStr)\r
412   {\r
413     if (m_pStr != pStr)\r
414     {\r
415       delete[] m_pStr;\r
416       m_pStr = __StrDup(pStr);\r
417     }\r
418     return *this;\r
419   }\r
420 \r
421   Str& operator +=(const char ch)\r
422   {\r
423     int len = GetLength ();\r
424     char *p = new char[len + 1 + 1];\r
425 \r
426     if (m_pStr)\r
427     {\r
428       strcpy(p, m_pStr);\r
429       delete[] m_pStr;\r
430     }\r
431 \r
432     m_pStr = p;\r
433     m_pStr[len] = ch;\r
434     m_pStr[len+1] = '\0';\r
435 \r
436     return *this;\r
437   }\r
438 \r
439   Str& operator +=(const char *pStr)\r
440   {\r
441     if (pStr)\r
442     {\r
443       if (m_pStr)\r
444       {\r
445         char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];\r
446         strcpy(p, m_pStr);\r
447         strcat(p, pStr);\r
448         delete[] m_pStr;\r
449         m_pStr = p;\r
450       }\r
451       else\r
452       {\r
453         m_pStr = __StrDup(pStr);\r
454       }\r
455     }\r
456     return *this;\r
457   }\r
458   \r
459 \r
460   bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }\r
461   bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }\r
462   bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }\r
463   bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }\r
464   bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }\r
465   bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }\r
466   bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }\r
467   bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }\r
468   bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }\r
469   bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }\r
470   bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }\r
471   bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }\r
472   char& operator [](int nIndex) { return m_pStr[nIndex]; }\r
473   char& operator [](int nIndex) const { return m_pStr[nIndex]; }\r
474   const char GetAt (int nIndex) { return m_pStr[nIndex]; }\r
475 };\r
476 \r
477 \r
478 \r
479 #endif\r