2 Copyright (c) 2001, Loki software, inc.
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this list
9 of conditions and the following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
15 Neither the name of Loki software nor the names of its contributors may be used
16 to endorse or promote products derived from this software without specific prior
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // loose replacement for CString from MFC
52 #define strcasecmp strcmpi
55 // NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
56 // causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)
57 // Q_StrDup should be used now, using a #define __StrDup for easy transition
59 #define __StrDup Q_StrDup
61 inline char* Q_StrDup(char* pStr)
66 return strcpy(new char[strlen(pStr)+1], pStr);
69 inline char* Q_StrDup(const char* pStr)
74 return strcpy(new char[strlen(pStr)+1], pStr);
77 #if defined (__linux__) || defined (__APPLE__)
78 #define strcmpi strcasecmp
79 #define stricmp strcasecmp
80 #define strnicmp strncasecmp
82 inline char* strlwr(char* string)
85 for (cp = string; *cp; ++cp)
87 if ('A' <= *cp && *cp <= 'Z')
94 inline char* strupr(char* string)
97 for (cp = string; *cp; ++cp)
99 if ('a' <= *cp && *cp <= 'z')
107 static char *g_pStrWork = NULL;
118 m_bIgnoreCase = true;
119 m_pStr = new char[1];
125 m_bIgnoreCase = true;
126 m_pStr = __StrDup(p);
131 m_bIgnoreCase = true;
132 m_pStr = __StrDup(p);
135 Str(const unsigned char *p)
137 m_bIgnoreCase = true;
138 m_pStr = __StrDup((const char *)p);
143 m_bIgnoreCase = true;
144 m_pStr = new char[2];
149 const char* GetBuffer() const
156 m_bIgnoreCase = true;
157 m_pStr = __StrDup(s.GetBuffer());
169 m_pStr = new char[n];
175 m_pStr = __StrDup("");
181 // NOTE TTimo: someone explain this g_pStrWork to me?
206 char* lpszLast = NULL;
207 while (*lpsz != '\0')
211 if (lpszLast == NULL)
219 if (lpszLast != NULL)
221 // truncate at trailing space start
228 // find first non-space character
230 while (isspace(*lpsz))
233 // fix up data and length
234 int nDataLength = GetLength() - (lpsz - m_pStr);
235 memmove(m_pStr, lpsz, (nDataLength+1));
238 int Find(const char *p)
240 char *pf = strstr(m_pStr, p);
241 return (pf) ? (pf - m_pStr) : -1;
244 // search starting at a given offset
245 int Find(const char *p, int offset)
247 char *pf = strstr(m_pStr+offset, p);
248 return (pf) ? (pf - m_pStr) : -1;
251 int Find(const char ch)
253 char *pf = strchr (m_pStr, ch);
254 return (pf) ? (pf - m_pStr) : -1;
257 int ReverseFind(const char ch)
259 char *pf = strrchr(m_pStr, ch);
260 return (pf) ? (pf - m_pStr) : -1;
263 int Compare (const char* str) const
265 return strcmp (m_pStr, str);
268 int CompareNoCase (const char* str) const
270 return strcasecmp (m_pStr, str);
275 return (m_pStr) ? strlen(m_pStr) : 0;
278 const char* Left(int n)
283 g_pStrWork = new char[n+1];
284 strncpy(g_pStrWork, m_pStr, n);
285 g_pStrWork[n] = '\0';
290 g_pStrWork = new char[1];
291 g_pStrWork[0] = '\0';
296 const char* Right(int n)
301 g_pStrWork = new char[n+1];
302 int nStart = GetLength() - n;
303 strncpy(g_pStrWork, &m_pStr[nStart], n);
304 g_pStrWork[n] = '\0';
308 g_pStrWork = new char[1];
309 g_pStrWork[0] = '\0';
314 const char* Mid(int nFirst) const
316 return Mid(nFirst, strlen (m_pStr) - nFirst);
319 const char* Mid(int first, int n) const
324 g_pStrWork = new char[n+1];
325 strncpy(g_pStrWork, m_pStr+first, n);
326 g_pStrWork[n] = '\0';
331 g_pStrWork = new char[1];
332 g_pStrWork[0] = '\0';
338 void Format(const char* fmt, ...)
343 va_start (args, fmt);
344 buffer = g_strdup_vprintf (fmt, args);
348 m_pStr = __StrDup(buffer);
352 void Format(const char* fmt, ...)
355 m_pStr = new char[1024];
357 va_start (args, fmt);
358 vsprintf (m_pStr, fmt, args);
363 void SetAt(int n, char ch)
365 if (n >= 0 && n < GetLength ())
369 // NOTE: unlike CString, this looses the pointer
370 void ReleaseBuffer(int n = -1)
377 m_pStr = __StrDup(tmp);
381 char* GetBufferSetLength(int n)
386 char *p = new char[n+1];
387 strncpy (p, m_pStr, n);
394 // char& operator *() { return *m_pStr; }
395 // char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
396 operator void*() { return m_pStr; }
397 operator char*() { return m_pStr; }
398 operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
399 operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
400 operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
401 Str& operator =(const Str& rhs)
406 m_pStr = __StrDup(rhs.m_pStr);
411 Str& operator =(const char* pStr)
416 m_pStr = __StrDup(pStr);
421 Str& operator +=(const char ch)
423 int len = GetLength ();
424 char *p = new char[len + 1 + 1];
434 m_pStr[len+1] = '\0';
439 Str& operator +=(const char *pStr)
445 char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
453 m_pStr = __StrDup(pStr);
460 bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
461 bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
462 bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
463 bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
464 bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
465 bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
466 bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }
467 bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
468 bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
469 bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }
470 bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
471 bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
472 char& operator [](int nIndex) { return m_pStr[nIndex]; }
473 char& operator [](int nIndex) const { return m_pStr[nIndex]; }
474 const char GetAt (int nIndex) { return m_pStr[nIndex]; }