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 ) {
62 const char* pStr = _pStr;
67 return strcpy( new char[ strlen( pStr ) + 1 ], pStr );
70 inline char* Q_StrDup( const char* pStr ) {
75 return strcpy( new char[strlen(pStr)+1], pStr );
78 #if defined (__linux__) || defined (__APPLE__)
79 #define strcmpi strcasecmp
80 #define stricmp strcasecmp
81 #define strnicmp strncasecmp
83 inline char* strlwr(char* string)
86 for (cp = string; *cp; ++cp)
88 if ('A' <= *cp && *cp <= 'Z')
95 inline char* strupr(char* string)
98 for (cp = string; *cp; ++cp)
100 if ('a' <= *cp && *cp <= 'z')
108 static char *g_pStrWork = NULL;
119 m_bIgnoreCase = true;
120 m_pStr = new char[1];
126 m_bIgnoreCase = true;
127 m_pStr = __StrDup(p);
132 m_bIgnoreCase = true;
133 m_pStr = __StrDup(p);
136 Str(const unsigned char *p)
138 m_bIgnoreCase = true;
139 m_pStr = __StrDup((const char *)p);
144 m_bIgnoreCase = true;
145 m_pStr = new char[2];
150 const char* GetBuffer() const
157 m_bIgnoreCase = true;
158 m_pStr = __StrDup(s.GetBuffer());
170 m_pStr = new char[n];
176 m_pStr = __StrDup("");
182 // NOTE TTimo: someone explain this g_pStrWork to me?
207 char* lpszLast = NULL;
208 while (*lpsz != '\0')
212 if (lpszLast == NULL)
220 if (lpszLast != NULL)
222 // truncate at trailing space start
229 // find first non-space character
231 while (isspace(*lpsz))
234 // fix up data and length
235 int nDataLength = GetLength() - (lpsz - m_pStr);
236 memmove(m_pStr, lpsz, (nDataLength+1));
239 int Find(const char *p)
241 char *pf = strstr(m_pStr, p);
242 return (pf) ? (pf - m_pStr) : -1;
245 // search starting at a given offset
246 int Find(const char *p, int offset)
248 char *pf = strstr(m_pStr+offset, p);
249 return (pf) ? (pf - m_pStr) : -1;
252 int Find(const char ch)
254 char *pf = strchr (m_pStr, ch);
255 return (pf) ? (pf - m_pStr) : -1;
258 int ReverseFind(const char ch)
260 char *pf = strrchr(m_pStr, ch);
261 return (pf) ? (pf - m_pStr) : -1;
264 int Compare (const char* str) const
266 return strcmp (m_pStr, str);
269 int CompareNoCase (const char* str) const
271 return strcasecmp (m_pStr, str);
276 return (m_pStr) ? strlen(m_pStr) : 0;
279 const char* Left(int n)
284 g_pStrWork = new char[n+1];
285 strncpy(g_pStrWork, m_pStr, n);
286 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';
330 g_pStrWork = new char[1];
331 g_pStrWork[0] = '\0';
337 void Format(const char* fmt, ...)
342 va_start (args, fmt);
343 buffer = g_strdup_vprintf (fmt, args);
347 m_pStr = __StrDup(buffer);
351 void Format(const char* fmt, ...)
354 m_pStr = new char[1024];
356 va_start (args, fmt);
357 vsprintf (m_pStr, fmt, args);
362 void SetAt(int n, char ch)
364 if (n >= 0 && n < GetLength ())
368 // NOTE: unlike CString, this looses the pointer
369 void ReleaseBuffer(int n = -1)
376 m_pStr = __StrDup(tmp);
380 char* GetBufferSetLength(int n)
385 char *p = new char[n+1];
386 strncpy (p, m_pStr, n);
393 // char& operator *() { return *m_pStr; }
394 // char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
395 operator void*() { return m_pStr; }
396 operator char*() { return m_pStr; }
397 operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
398 operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
399 operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
400 Str& operator =(const Str& rhs)
405 m_pStr = __StrDup(rhs.m_pStr);
410 Str& operator =(const char* pStr)
415 m_pStr = __StrDup(pStr);
420 Str& operator +=(const char ch)
422 int len = GetLength ();
423 char *p = new char[len + 1 + 1];
433 m_pStr[len+1] = '\0';
438 Str& operator +=(const char *pStr)
444 char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
452 m_pStr = __StrDup(pStr);
459 bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
460 bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
461 bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
462 bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
463 bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
464 bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
465 bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }
466 bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
467 bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
468 bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }
469 bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
470 bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
471 char& operator [](int nIndex) { return m_pStr[nIndex]; }
472 char& operator [](int nIndex) const { return m_pStr[nIndex]; }
473 const char GetAt (int nIndex) { return m_pStr[nIndex]; }