]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/str.h
more eol-style
[xonotic/netradiant.git] / libs / str.h
index 8bb56ea971b418c49847587f4915a32bb67d1953..8cb8a716793b0c9c6c54bc96160152f2aa1d97cb 100644 (file)
-/*\r
-Copyright (c) 2001, Loki software, inc.\r
-All rights reserved.\r
-\r
-Redistribution and use in source and binary forms, with or without modification, \r
-are permitted provided that the following conditions are met:\r
-\r
-Redistributions of source code must retain the above copyright notice, this list \r
-of conditions and the following disclaimer.\r
-\r
-Redistributions in binary form must reproduce the above copyright notice, this\r
-list of conditions and the following disclaimer in the documentation and/or\r
-other materials provided with the distribution.\r
-\r
-Neither the name of Loki software nor the names of its contributors may be used \r
-to endorse or promote products derived from this software without specific prior \r
-written permission. \r
-\r
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' \r
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \r
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \r
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY \r
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES \r
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; \r
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS \r
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \r
-*/\r
-\r
-#ifndef __STR__\r
-#define __STR__\r
-\r
-//\r
-// class Str\r
-// loose replacement for CString from MFC\r
-//\r
-\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <stdarg.h>\r
-\r
-#ifdef __APPLE__\r
-  #ifdef NULL\r
-    #undef NULL\r
-    #define NULL 0\r
-  #endif\r
-#endif\r
-\r
-\r
-#ifdef _WIN32\r
-#define strcasecmp strcmpi\r
-#endif\r
-\r
-// NOTE TTimo __StrDup was initially implemented in pakstuff.cpp\r
-//   causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)\r
-//   Q_StrDup should be used now, using a #define __StrDup for easy transition\r
-\r
-#define __StrDup Q_StrDup\r
-\r
-inline char* Q_StrDup(char* pStr)\r
-{\r
-  if (pStr == NULL)\r
-    pStr = "";\r
-\r
-  return strcpy(new char[strlen(pStr)+1], pStr); \r
-}\r
-\r
-inline char* Q_StrDup(const char* pStr)\r
-{ \r
-  if (pStr == NULL)\r
-    pStr = "";\r
-\r
-  return strcpy(new char[strlen(pStr)+1], pStr); \r
-}\r
-\r
-#if defined (__linux__) || defined (__APPLE__)\r
-#define strcmpi strcasecmp\r
-#define stricmp strcasecmp\r
-#define strnicmp strncasecmp\r
-\r
-inline char* strlwr(char* string)\r
-{\r
-  char *cp;\r
-  for (cp = string; *cp; ++cp)\r
-  {\r
-    if ('A' <= *cp && *cp <= 'Z')\r
-      *cp += 'a' - 'A';\r
-  }\r
-\r
-  return string;\r
-}\r
-\r
-inline char* strupr(char* string)\r
-{\r
-  char *cp;\r
-  for (cp = string; *cp; ++cp)\r
-  {\r
-    if ('a' <= *cp && *cp <= 'z')\r
-      *cp += 'A' - 'a';\r
-  }\r
-\r
-  return string;\r
-}\r
-#endif\r
-\r
-static char *g_pStrWork = NULL;\r
-\r
-class Str\r
-{\r
-protected:\r
-  bool m_bIgnoreCase;\r
-  char *m_pStr;\r
-\r
-public:\r
-  Str()\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = new char[1];\r
-    m_pStr[0] = '\0';\r
-  }\r
-\r
-  Str(char *p)\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = __StrDup(p);\r
-  }\r
-\r
-  Str(const char *p)\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = __StrDup(p);\r
-  }\r
-\r
-  Str(const unsigned char *p)\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = __StrDup((const char *)p);\r
-  }\r
-\r
-  Str(const char c)\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = new char[2];\r
-    m_pStr[0] = c;\r
-    m_pStr[1] = '\0';    \r
-  }\r
-\r
-  const char* GetBuffer() const\r
-  {\r
-    return m_pStr;\r
-  }\r
-\r
-  Str(const Str &s)\r
-  {\r
-    m_bIgnoreCase = true;\r
-    m_pStr = __StrDup(s.GetBuffer());\r
-  }\r
-\r
-  void Deallocate()\r
-  {\r
-    delete []m_pStr;\r
-    m_pStr = NULL;\r
-  }\r
-\r
-  void Allocate(int n)\r
-  {\r
-    Deallocate();\r
-    m_pStr = new char[n];\r
-  }\r
-\r
-  void MakeEmpty()\r
-  {\r
-    Deallocate();\r
-    m_pStr = __StrDup("");\r
-  }\r
-\r
-  virtual ~Str()\r
-  {\r
-    Deallocate();\r
-    // NOTE TTimo: someone explain this g_pStrWork to me?\r
-    if (g_pStrWork)\r
-      delete []g_pStrWork;\r
-    g_pStrWork = NULL;\r
-  }\r
-\r
-  void MakeLower()\r
-  {\r
-    if (m_pStr)\r
-    {\r
-      strlwr(m_pStr);\r
-    }\r
-  }\r
-\r
-  void MakeUpper()\r
-  {\r
-    if (m_pStr)\r
-    {\r
-      strupr(m_pStr);\r
-    }\r
-  }\r
-\r
-  void TrimRight()\r
-    {\r
-      char* lpsz = m_pStr;\r
-      char* lpszLast = NULL;\r
-      while (*lpsz != '\0')\r
-      {\r
-       if (isspace(*lpsz))\r
-       {\r
-         if (lpszLast == NULL)\r
-           lpszLast = lpsz;\r
-       }\r
-       else\r
-         lpszLast = NULL;\r
-       lpsz++;\r
-      }\r
\r
-      if (lpszLast != NULL)\r
-      {\r
-       // truncate at trailing space start\r
-       *lpszLast = '\0';\r
-      }\r
-    }\r
-\r
-  void TrimLeft()\r
-    {\r
-      // find first non-space character\r
-      char* lpsz = m_pStr;\r
-      while (isspace(*lpsz))\r
-       lpsz++;\r
\r
-      // fix up data and length\r
-      int nDataLength = GetLength() - (lpsz - m_pStr);\r
-      memmove(m_pStr, lpsz, (nDataLength+1));\r
-    }\r
-\r
-  int Find(const char *p)\r
-  {\r
-    char *pf = strstr(m_pStr, p);\r
-    return (pf) ? (pf - m_pStr) : -1;\r
-  }\r
-\r
-  // search starting at a given offset\r
-  int Find(const char *p, int offset)\r
-  {\r
-    char *pf = strstr(m_pStr+offset, p);\r
-    return (pf) ? (pf - m_pStr) : -1;\r
-  }\r
-\r
-  int Find(const char ch)\r
-  {\r
-    char *pf = strchr (m_pStr, ch);\r
-    return (pf) ? (pf - m_pStr) : -1;\r
-  }\r
-\r
-  int ReverseFind(const char ch)\r
-  {\r
-    char *pf = strrchr(m_pStr, ch);\r
-    return (pf) ? (pf - m_pStr) : -1;\r
-  }\r
-\r
-  int Compare (const char* str) const\r
-  {\r
-    return strcmp (m_pStr, str);\r
-  }\r
-  \r
-  int CompareNoCase (const char* str) const\r
-  {\r
-    return strcasecmp (m_pStr, str);\r
-  }\r
-\r
-  int GetLength()\r
-  {\r
-    return (m_pStr) ? strlen(m_pStr) : 0;\r
-  }\r
-\r
-  const char* Left(int n)\r
-  {\r
-    delete []g_pStrWork;\r
-    if (n > 0)\r
-    {\r
-      g_pStrWork = new char[n+1];\r
-      strncpy(g_pStrWork, m_pStr, n);\r
-      g_pStrWork[n] = '\0';\r
-    }\r
-    else\r
-    {\r
-      g_pStrWork = "";\r
-      g_pStrWork = new char[1];\r
-      g_pStrWork[0] = '\0';\r
-    }\r
-    return g_pStrWork;\r
-  }\r
-\r
-  const char* Right(int n)\r
-  {\r
-    delete []g_pStrWork;\r
-    if (n > 0)\r
-    {\r
-      g_pStrWork = new char[n+1];\r
-      int nStart = GetLength() - n;\r
-      strncpy(g_pStrWork, &m_pStr[nStart], n);\r
-      g_pStrWork[n] = '\0';\r
-    }\r
-    else\r
-    {\r
-      g_pStrWork = new char[1];\r
-      g_pStrWork[0] = '\0';\r
-    }\r
-    return g_pStrWork;\r
-  }\r
-\r
-  const char* Mid(int nFirst) const\r
-    {\r
-      return Mid(nFirst, strlen (m_pStr) - nFirst);\r
-    }\r
-\r
-  const char* Mid(int first, int n) const\r
-  {\r
-    delete []g_pStrWork;\r
-    if (n > 0)\r
-    {\r
-      g_pStrWork = new char[n+1];\r
-      strncpy(g_pStrWork, m_pStr+first, n);\r
-      g_pStrWork[n] = '\0';\r
-    }\r
-    else\r
-    {\r
-      g_pStrWork = "";\r
-      g_pStrWork = new char[1];\r
-      g_pStrWork[0] = '\0';\r
-    }\r
-    return g_pStrWork;\r
-  }\r
-\r
-#ifdef __G_LIB_H__\r
-  void Format(const char* fmt, ...)\r
-  {\r
-    va_list args;\r
-    char *buffer;\r
-  \r
-    va_start (args, fmt);\r
-    buffer = g_strdup_vprintf (fmt, args);\r
-    va_end (args);\r
-\r
-    delete[] m_pStr;\r
-    m_pStr = __StrDup(buffer);\r
-    g_free (buffer);\r
-  }\r
-#else\r
-  void Format(const char* fmt, ...)\r
-  {\r
-    va_list args;\r
-    m_pStr = new char[1024];\r
-\r
-    va_start (args, fmt);\r
-    vsprintf (m_pStr, fmt, args);\r
-    va_end (args);\r
-  }\r
-#endif\r
-\r
-  void SetAt(int n, char ch)\r
-  {\r
-    if (n >= 0 && n < GetLength ())\r
-      m_pStr[n] = ch;\r
-  }\r
-\r
-       // NOTE: unlike CString, this looses the pointer\r
-  void ReleaseBuffer(int n = -1)\r
-  {\r
-    if (n == -1)\r
-      n = GetLength ();\r
-\r
-    char* tmp = m_pStr;\r
-    tmp[n] = '\0';\r
-    m_pStr = __StrDup(tmp);\r
-    delete []tmp;\r
-  }\r
-\r
-  char* GetBufferSetLength(int n)\r
-  {\r
-    if (n < 0)\r
-      n = 0;\r
-\r
-    char *p = new char[n+1];\r
-    strncpy (p, m_pStr, n);\r
-               p[n] = '\0';\r
-    delete []m_pStr;\r
-    m_pStr = p;\r
-    return m_pStr;\r
-  }\r
-\r
-  //  char& operator *() { return *m_pStr; }\r
-  //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }\r
-  operator void*() { return m_pStr; }\r
-  operator char*() { return m_pStr; }\r
-  operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }\r
-  operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }\r
-  operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }\r
-  Str& operator =(const Str& rhs)\r
-  {\r
-    if (&rhs != this)\r
-    {\r
-      delete[] m_pStr;\r
-      m_pStr = __StrDup(rhs.m_pStr);\r
-    }\r
-    return *this;\r
-  }\r
-  \r
-  Str& operator =(const char* pStr)\r
-  {\r
-    if (m_pStr != pStr)\r
-    {\r
-      delete[] m_pStr;\r
-      m_pStr = __StrDup(pStr);\r
-    }\r
-    return *this;\r
-  }\r
-\r
-  Str& operator +=(const char ch)\r
-  {\r
-    int len = GetLength ();\r
-    char *p = new char[len + 1 + 1];\r
-\r
-    if (m_pStr)\r
-    {\r
-      strcpy(p, m_pStr);\r
-      delete[] m_pStr;\r
-    }\r
-\r
-    m_pStr = p;\r
-    m_pStr[len] = ch;\r
-    m_pStr[len+1] = '\0';\r
-\r
-    return *this;\r
-  }\r
-\r
-  Str& operator +=(const char *pStr)\r
-  {\r
-    if (pStr)\r
-    {\r
-      if (m_pStr)\r
-      {\r
-        char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];\r
-        strcpy(p, m_pStr);\r
-        strcat(p, pStr);\r
-        delete[] m_pStr;\r
-        m_pStr = p;\r
-      }\r
-      else\r
-      {\r
-        m_pStr = __StrDup(pStr);\r
-      }\r
-    }\r
-    return *this;\r
-  }\r
-  \r
-\r
-  bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }\r
-  bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }\r
-  bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }\r
-  bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }\r
-  bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }\r
-  bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }\r
-  bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }\r
-  bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }\r
-  bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }\r
-  bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }\r
-  bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }\r
-  bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }\r
-  char& operator [](int nIndex) { return m_pStr[nIndex]; }\r
-  char& operator [](int nIndex) const { return m_pStr[nIndex]; }\r
-  const char GetAt (int nIndex) { return m_pStr[nIndex]; }\r
-};\r
-\r
-\r
-\r
-#endif\r
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef __STR__
+#define __STR__
+
+//
+// class Str
+// loose replacement for CString from MFC
+//
+
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifdef __APPLE__
+  #ifdef NULL
+    #undef NULL
+    #define NULL 0
+  #endif
+#endif
+
+
+#ifdef _WIN32
+#define strcasecmp strcmpi
+#endif
+
+// NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
+//   causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)
+//   Q_StrDup should be used now, using a #define __StrDup for easy transition
+
+#define __StrDup Q_StrDup
+
+inline char* Q_StrDup(char* pStr)
+{
+  if (pStr == NULL)
+    pStr = "";
+
+  return strcpy(new char[strlen(pStr)+1], pStr); 
+}
+
+inline char* Q_StrDup(const char* pStr)
+{ 
+  if (pStr == NULL)
+    pStr = "";
+
+  return strcpy(new char[strlen(pStr)+1], pStr); 
+}
+
+#if defined (__linux__) || defined (__APPLE__)
+#define strcmpi strcasecmp
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+inline char* strlwr(char* string)
+{
+  char *cp;
+  for (cp = string; *cp; ++cp)
+  {
+    if ('A' <= *cp && *cp <= 'Z')
+      *cp += 'a' - 'A';
+  }
+
+  return string;
+}
+
+inline char* strupr(char* string)
+{
+  char *cp;
+  for (cp = string; *cp; ++cp)
+  {
+    if ('a' <= *cp && *cp <= 'z')
+      *cp += 'A' - 'a';
+  }
+
+  return string;
+}
+#endif
+
+static char *g_pStrWork = NULL;
+
+class Str
+{
+protected:
+  bool m_bIgnoreCase;
+  char *m_pStr;
+
+public:
+  Str()
+  {
+    m_bIgnoreCase = true;
+    m_pStr = new char[1];
+    m_pStr[0] = '\0';
+  }
+
+  Str(char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(p);
+  }
+
+  Str(const char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(p);
+  }
+
+  Str(const unsigned char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup((const char *)p);
+  }
+
+  Str(const char c)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = new char[2];
+    m_pStr[0] = c;
+    m_pStr[1] = '\0';    
+  }
+
+  const char* GetBuffer() const
+  {
+    return m_pStr;
+  }
+
+  Str(const Str &s)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(s.GetBuffer());
+  }
+
+  void Deallocate()
+  {
+    delete []m_pStr;
+    m_pStr = NULL;
+  }
+
+  void Allocate(int n)
+  {
+    Deallocate();
+    m_pStr = new char[n];
+  }
+
+  void MakeEmpty()
+  {
+    Deallocate();
+    m_pStr = __StrDup("");
+  }
+
+  virtual ~Str()
+  {
+    Deallocate();
+    // NOTE TTimo: someone explain this g_pStrWork to me?
+    if (g_pStrWork)
+      delete []g_pStrWork;
+    g_pStrWork = NULL;
+  }
+
+  void MakeLower()
+  {
+    if (m_pStr)
+    {
+      strlwr(m_pStr);
+    }
+  }
+
+  void MakeUpper()
+  {
+    if (m_pStr)
+    {
+      strupr(m_pStr);
+    }
+  }
+
+  void TrimRight()
+    {
+      char* lpsz = m_pStr;
+      char* lpszLast = NULL;
+      while (*lpsz != '\0')
+      {
+       if (isspace(*lpsz))
+       {
+         if (lpszLast == NULL)
+           lpszLast = lpsz;
+       }
+       else
+         lpszLast = NULL;
+       lpsz++;
+      }
+      if (lpszLast != NULL)
+      {
+       // truncate at trailing space start
+       *lpszLast = '\0';
+      }
+    }
+
+  void TrimLeft()
+    {
+      // find first non-space character
+      char* lpsz = m_pStr;
+      while (isspace(*lpsz))
+       lpsz++;
+      // fix up data and length
+      int nDataLength = GetLength() - (lpsz - m_pStr);
+      memmove(m_pStr, lpsz, (nDataLength+1));
+    }
+
+  int Find(const char *p)
+  {
+    char *pf = strstr(m_pStr, p);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  // search starting at a given offset
+  int Find(const char *p, int offset)
+  {
+    char *pf = strstr(m_pStr+offset, p);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int Find(const char ch)
+  {
+    char *pf = strchr (m_pStr, ch);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int ReverseFind(const char ch)
+  {
+    char *pf = strrchr(m_pStr, ch);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int Compare (const char* str) const
+  {
+    return strcmp (m_pStr, str);
+  }
+  
+  int CompareNoCase (const char* str) const
+  {
+    return strcasecmp (m_pStr, str);
+  }
+
+  int GetLength()
+  {
+    return (m_pStr) ? strlen(m_pStr) : 0;
+  }
+
+  const char* Left(int n)
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      strncpy(g_pStrWork, m_pStr, n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = "";
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+  const char* Right(int n)
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      int nStart = GetLength() - n;
+      strncpy(g_pStrWork, &m_pStr[nStart], n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+  const char* Mid(int nFirst) const
+    {
+      return Mid(nFirst, strlen (m_pStr) - nFirst);
+    }
+
+  const char* Mid(int first, int n) const
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      strncpy(g_pStrWork, m_pStr+first, n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = "";
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+#ifdef __G_LIB_H__
+  void Format(const char* fmt, ...)
+  {
+    va_list args;
+    char *buffer;
+  
+    va_start (args, fmt);
+    buffer = g_strdup_vprintf (fmt, args);
+    va_end (args);
+
+    delete[] m_pStr;
+    m_pStr = __StrDup(buffer);
+    g_free (buffer);
+  }
+#else
+  void Format(const char* fmt, ...)
+  {
+    va_list args;
+    m_pStr = new char[1024];
+
+    va_start (args, fmt);
+    vsprintf (m_pStr, fmt, args);
+    va_end (args);
+  }
+#endif
+
+  void SetAt(int n, char ch)
+  {
+    if (n >= 0 && n < GetLength ())
+      m_pStr[n] = ch;
+  }
+
+       // NOTE: unlike CString, this looses the pointer
+  void ReleaseBuffer(int n = -1)
+  {
+    if (n == -1)
+      n = GetLength ();
+
+    char* tmp = m_pStr;
+    tmp[n] = '\0';
+    m_pStr = __StrDup(tmp);
+    delete []tmp;
+  }
+
+  char* GetBufferSetLength(int n)
+  {
+    if (n < 0)
+      n = 0;
+
+    char *p = new char[n+1];
+    strncpy (p, m_pStr, n);
+               p[n] = '\0';
+    delete []m_pStr;
+    m_pStr = p;
+    return m_pStr;
+  }
+
+  //  char& operator *() { return *m_pStr; }
+  //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
+  operator void*() { return m_pStr; }
+  operator char*() { return m_pStr; }
+  operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
+  operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
+  operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
+  Str& operator =(const Str& rhs)
+  {
+    if (&rhs != this)
+    {
+      delete[] m_pStr;
+      m_pStr = __StrDup(rhs.m_pStr);
+    }
+    return *this;
+  }
+  
+  Str& operator =(const char* pStr)
+  {
+    if (m_pStr != pStr)
+    {
+      delete[] m_pStr;
+      m_pStr = __StrDup(pStr);
+    }
+    return *this;
+  }
+
+  Str& operator +=(const char ch)
+  {
+    int len = GetLength ();
+    char *p = new char[len + 1 + 1];
+
+    if (m_pStr)
+    {
+      strcpy(p, m_pStr);
+      delete[] m_pStr;
+    }
+
+    m_pStr = p;
+    m_pStr[len] = ch;
+    m_pStr[len+1] = '\0';
+
+    return *this;
+  }
+
+  Str& operator +=(const char *pStr)
+  {
+    if (pStr)
+    {
+      if (m_pStr)
+      {
+        char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
+        strcpy(p, m_pStr);
+        strcat(p, pStr);
+        delete[] m_pStr;
+        m_pStr = p;
+      }
+      else
+      {
+        m_pStr = __StrDup(pStr);
+      }
+    }
+    return *this;
+  }
+  
+
+  bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
+  bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+  bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+  bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
+  bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+  bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+  bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }
+  bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
+  bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
+  bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }
+  bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
+  bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
+  char& operator [](int nIndex) { return m_pStr[nIndex]; }
+  char& operator [](int nIndex) const { return m_pStr[nIndex]; }
+  const char GetAt (int nIndex) { return m_pStr[nIndex]; }
+};
+
+
+
+#endif