summaryrefslogtreecommitdiffstats
path: root/CPP/Common/MyString.h
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Common/MyString.h')
-rwxr-xr-xCPP/Common/MyString.h625
1 files changed, 625 insertions, 0 deletions
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
new file mode 100755
index 0000000..ede2573
--- /dev/null
+++ b/CPP/Common/MyString.h
@@ -0,0 +1,625 @@
+// Common/String.h
+
+#ifndef __COMMON_STRING_H
+#define __COMMON_STRING_H
+
+#include <string.h>
+
+#include "MyVector.h"
+
+template <class T>
+inline int MyStringLen(const T *s)
+{
+ int i;
+ for (i = 0; s[i] != '\0'; i++);
+ return i;
+}
+
+template <class T>
+inline T * MyStringCopy(T *dest, const T *src)
+{
+ T *destStart = dest;
+ while ((*dest++ = *src++) != 0);
+ return destStart;
+}
+
+inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
+ { return (p + 1); }
+inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
+ { return (p + 1); }
+inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
+ { return (p - 1); }
+inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
+ { return (p - 1); }
+
+#ifdef _WIN32
+
+inline const char* MyStringGetNextCharPointer(const char *p)
+{
+ #ifdef UNDER_CE
+ return p + 1;
+ #else
+ return CharNextA(p);
+ #endif
+}
+
+inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
+ { return CharPrevA(base, p); }
+
+inline char MyCharUpper(char c)
+ { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
+#ifdef _UNICODE
+inline wchar_t MyCharUpper(wchar_t c)
+ { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }
+#else
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+#ifdef _UNICODE
+inline wchar_t MyCharLower(wchar_t c)
+ { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }
+#else
+wchar_t MyCharLower(wchar_t c);
+#endif
+
+inline char MyCharLower(char c)
+#ifdef UNDER_CE
+ { return (char)MyCharLower((wchar_t)c); }
+#else
+ { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
+#endif
+
+inline char * MyStringUpper(char *s) { return CharUpperA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
+#else
+wchar_t * MyStringUpper(wchar_t *s);
+#endif
+
+inline char * MyStringLower(char *s) { return CharLowerA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
+#else
+wchar_t * MyStringLower(wchar_t *s);
+#endif
+
+#else // Standard-C
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+//////////////////////////////////////
+// Compare
+
+/*
+#ifndef UNDER_CE
+int MyStringCollate(const char *s1, const char *s2);
+int MyStringCollateNoCase(const char *s1, const char *s2);
+#endif
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2);
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);
+*/
+
+int MyStringCompare(const char *s1, const char *s2);
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2);
+
+// int MyStringCompareNoCase(const char *s1, const char *s2);
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);
+
+template <class T>
+class CStringBase
+{
+ void TrimLeftWithCharSet(const CStringBase &charSet)
+ {
+ const T *p = _chars;
+ while (charSet.Find(*p) >= 0 && (*p != 0))
+ p = GetNextCharPointer(p);
+ Delete(0, (int)(p - _chars));
+ }
+ void TrimRightWithCharSet(const CStringBase &charSet)
+ {
+ const T *p = _chars;
+ const T *pLast = NULL;
+ while (*p != 0)
+ {
+ if (charSet.Find(*p) >= 0)
+ {
+ if (pLast == NULL)
+ pLast = p;
+ }
+ else
+ pLast = NULL;
+ p = GetNextCharPointer(p);
+ }
+ if (pLast != NULL)
+ {
+ int i = (int)(pLast - _chars);
+ Delete(i, _length - i);
+ }
+
+ }
+ void MoveItems(int destIndex, int srcIndex)
+ {
+ memmove(_chars + destIndex, _chars + srcIndex,
+ sizeof(T) * (_length - srcIndex + 1));
+ }
+
+ void InsertSpace(int &index, int size)
+ {
+ CorrectIndex(index);
+ GrowLength(size);
+ MoveItems(index + size, index);
+ }
+
+ static const T *GetNextCharPointer(const T *p)
+ { return MyStringGetNextCharPointer(p); }
+ static const T *GetPrevCharPointer(const T *base, const T *p)
+ { return MyStringGetPrevCharPointer(base, p); }
+protected:
+ T *_chars;
+ int _length;
+ int _capacity;
+
+ void SetCapacity(int newCapacity)
+ {
+ int realCapacity = newCapacity + 1;
+ if (realCapacity == _capacity)
+ return;
+ /*
+ const int kMaxStringSize = 0x20000000;
+ if (newCapacity > kMaxStringSize || newCapacity < _length)
+ throw 1052337;
+ */
+ T *newBuffer = new T[realCapacity];
+ if (_capacity > 0)
+ {
+ for (int i = 0; i < _length; i++)
+ newBuffer[i] = _chars[i];
+ delete []_chars;
+ }
+ _chars = newBuffer;
+ _chars[_length] = 0;
+ _capacity = realCapacity;
+ }
+
+ void GrowLength(int n)
+ {
+ int freeSize = _capacity - _length - 1;
+ if (n <= freeSize)
+ return;
+ int delta;
+ if (_capacity > 64)
+ delta = _capacity / 2;
+ else if (_capacity > 8)
+ delta = 16;
+ else
+ delta = 4;
+ if (freeSize + delta < n)
+ delta = n - freeSize;
+ SetCapacity(_capacity + delta);
+ }
+
+ void CorrectIndex(int &index) const
+ {
+ if (index > _length)
+ index = _length;
+ }
+
+public:
+ CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); }
+ CStringBase(T c): _chars(0), _length(0), _capacity(0)
+ {
+ SetCapacity(1);
+ _chars[0] = c;
+ _chars[1] = 0;
+ _length = 1;
+ }
+ CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)
+ {
+ int length = MyStringLen(chars);
+ SetCapacity(length);
+ MyStringCopy(_chars, chars); // can be optimized by memove()
+ _length = length;
+ }
+ CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0)
+ {
+ SetCapacity(s._length);
+ MyStringCopy(_chars, s._chars);
+ _length = s._length;
+ }
+ ~CStringBase() { delete []_chars; }
+
+ operator const T*() const { return _chars;}
+
+ T Back() const { return _chars[_length - 1]; }
+
+ // The minimum size of the character buffer in characters.
+ // This value does not include space for a null terminator.
+ T* GetBuffer(int minBufLength)
+ {
+ if (minBufLength >= _capacity)
+ SetCapacity(minBufLength);
+ return _chars;
+ }
+ void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
+ void ReleaseBuffer(int newLength)
+ {
+ /*
+ if (newLength >= _capacity)
+ throw 282217;
+ */
+ _chars[newLength] = 0;
+ _length = newLength;
+ }
+
+ CStringBase& operator=(T c)
+ {
+ Empty();
+ SetCapacity(1);
+ _chars[0] = c;
+ _chars[1] = 0;
+ _length = 1;
+ return *this;
+ }
+ CStringBase& operator=(const T *chars)
+ {
+ Empty();
+ int length = MyStringLen(chars);
+ SetCapacity(length);
+ MyStringCopy(_chars, chars);
+ _length = length;
+ return *this;
+ }
+ CStringBase& operator=(const CStringBase& s)
+ {
+ if (&s == this)
+ return *this;
+ Empty();
+ SetCapacity(s._length);
+ MyStringCopy(_chars, s._chars);
+ _length = s._length;
+ return *this;
+ }
+
+ CStringBase& operator+=(T c)
+ {
+ GrowLength(1);
+ _chars[_length] = c;
+ _chars[++_length] = 0;
+ return *this;
+ }
+ CStringBase& operator+=(const T *s)
+ {
+ int len = MyStringLen(s);
+ GrowLength(len);
+ MyStringCopy(_chars + _length, s);
+ _length += len;
+ return *this;
+ }
+ CStringBase& operator+=(const CStringBase &s)
+ {
+ GrowLength(s._length);
+ MyStringCopy(_chars + _length, s._chars);
+ _length += s._length;
+ return *this;
+ }
+ void Empty()
+ {
+ _length = 0;
+ _chars[0] = 0;
+ }
+ int Length() const { return _length; }
+ bool IsEmpty() const { return (_length == 0); }
+
+ CStringBase Mid(int startIndex) const
+ { return Mid(startIndex, _length - startIndex); }
+ CStringBase Mid(int startIndex, int count) const
+ {
+ if (startIndex + count > _length)
+ count = _length - startIndex;
+
+ if (startIndex == 0 && startIndex + count == _length)
+ return *this;
+
+ CStringBase<T> result;
+ result.SetCapacity(count);
+ // MyStringNCopy(result._chars, _chars + startIndex, count);
+ for (int i = 0; i < count; i++)
+ result._chars[i] = _chars[startIndex + i];
+ result._chars[count] = 0;
+ result._length = count;
+ return result;
+ }
+ CStringBase Left(int count) const
+ { return Mid(0, count); }
+ CStringBase Right(int count) const
+ {
+ if (count > _length)
+ count = _length;
+ return Mid(_length - count, count);
+ }
+
+ void MakeUpper()
+ { MyStringUpper(_chars); }
+ void MakeLower()
+ { MyStringLower(_chars); }
+
+ int Compare(const CStringBase& s) const
+ { return MyStringCompare(_chars, s._chars); }
+
+ int Compare(const T *s) const
+ { return MyStringCompare(_chars, s); }
+
+ int CompareNoCase(const CStringBase& s) const
+ { return MyStringCompareNoCase(_chars, s._chars); }
+
+ int CompareNoCase(const T *s) const
+ { return MyStringCompareNoCase(_chars, s); }
+
+ /*
+ int Collate(const CStringBase& s) const
+ { return MyStringCollate(_chars, s._chars); }
+ int CollateNoCase(const CStringBase& s) const
+ { return MyStringCollateNoCase(_chars, s._chars); }
+ */
+
+ int Find(T c) const { return Find(c, 0); }
+ int Find(T c, int startIndex) const
+ {
+ const T *p = _chars + startIndex;
+ for (;;)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (*p == 0)
+ return -1;
+ p = GetNextCharPointer(p);
+ }
+ }
+ int Find(const CStringBase &s) const { return Find(s, 0); }
+ int Find(const CStringBase &s, int startIndex) const
+ {
+ if (s.IsEmpty())
+ return startIndex;
+ for (; startIndex < _length; startIndex++)
+ {
+ int j;
+ for (j = 0; j < s._length && startIndex + j < _length; j++)
+ if (_chars[startIndex+j] != s._chars[j])
+ break;
+ if (j == s._length)
+ return startIndex;
+ }
+ return -1;
+ }
+ int ReverseFind(T c) const
+ {
+ if (_length == 0)
+ return -1;
+ const T *p = _chars + _length - 1;
+ for (;;)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p = GetPrevCharPointer(_chars, p);
+ }
+ }
+ int FindOneOf(const CStringBase &s) const
+ {
+ for (int i = 0; i < _length; i++)
+ if (s.Find(_chars[i]) >= 0)
+ return i;
+ return -1;
+ }
+
+ void TrimLeft(T c)
+ {
+ const T *p = _chars;
+ while (c == *p)
+ p = GetNextCharPointer(p);
+ Delete(0, p - _chars);
+ }
+ private:
+ CStringBase GetTrimDefaultCharSet()
+ {
+ CStringBase<T> charSet;
+ charSet += (T)' ';
+ charSet += (T)'\n';
+ charSet += (T)'\t';
+ return charSet;
+ }
+ public:
+
+ void TrimLeft()
+ {
+ TrimLeftWithCharSet(GetTrimDefaultCharSet());
+ }
+ void TrimRight()
+ {
+ TrimRightWithCharSet(GetTrimDefaultCharSet());
+ }
+ void TrimRight(T c)
+ {
+ const T *p = _chars;
+ const T *pLast = NULL;
+ while (*p != 0)
+ {
+ if (*p == c)
+ {
+ if (pLast == NULL)
+ pLast = p;
+ }
+ else
+ pLast = NULL;
+ p = GetNextCharPointer(p);
+ }
+ if (pLast != NULL)
+ {
+ int i = pLast - _chars;
+ Delete(i, _length - i);
+ }
+ }
+ void Trim()
+ {
+ TrimRight();
+ TrimLeft();
+ }
+
+ int Insert(int index, T c)
+ {
+ InsertSpace(index, 1);
+ _chars[index] = c;
+ _length++;
+ return _length;
+ }
+ int Insert(int index, const CStringBase &s)
+ {
+ CorrectIndex(index);
+ if (s.IsEmpty())
+ return _length;
+ int numInsertChars = s.Length();
+ InsertSpace(index, numInsertChars);
+ for (int i = 0; i < numInsertChars; i++)
+ _chars[index + i] = s[i];
+ _length += numInsertChars;
+ return _length;
+ }
+
+ // !!!!!!!!!!!!!!! test it if newChar = '\0'
+ int Replace(T oldChar, T newChar)
+ {
+ if (oldChar == newChar)
+ return 0;
+ int number = 0;
+ int pos = 0;
+ while (pos < Length())
+ {
+ pos = Find(oldChar, pos);
+ if (pos < 0)
+ break;
+ _chars[pos] = newChar;
+ pos++;
+ number++;
+ }
+ return number;
+ }
+ int Replace(const CStringBase &oldString, const CStringBase &newString)
+ {
+ if (oldString.IsEmpty())
+ return 0;
+ if (oldString == newString)
+ return 0;
+ int oldStringLength = oldString.Length();
+ int newStringLength = newString.Length();
+ int number = 0;
+ int pos = 0;
+ while (pos < _length)
+ {
+ pos = Find(oldString, pos);
+ if (pos < 0)
+ break;
+ Delete(pos, oldStringLength);
+ Insert(pos, newString);
+ pos += newStringLength;
+ number++;
+ }
+ return number;
+ }
+ int Delete(int index, int count = 1)
+ {
+ if (index + count > _length)
+ count = _length - index;
+ if (count > 0)
+ {
+ MoveItems(index, index + count);
+ _length -= count;
+ }
+ return _length;
+ }
+ void DeleteBack() { Delete(_length - 1); }
+};
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
+{
+ CStringBase<T> result(s1);
+ result += s2;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, T c)
+{
+ CStringBase<T> result(s);
+ result += c;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(T c, const CStringBase<T>& s)
+{
+ CStringBase<T> result(c);
+ result += s;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
+{
+ CStringBase<T> result(s);
+ result += chars;
+ return result;
+}
+
+template <class T>
+CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
+{
+ CStringBase<T> result(chars);
+ result += s;
+ return result;
+}
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) < 0); }
+
+template <class T>
+bool operator==(const T *s1, const CStringBase<T>& s2)
+ { return (s2.Compare(s1) == 0); }
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const T *s2)
+ { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
+ { return (s1.Compare(s2) != 0); }
+
+template <class T>
+bool operator!=(const T *s1, const CStringBase<T>& s2)
+ { return (s2.Compare(s1) != 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const T *s2)
+ { return (s1.Compare(s2) != 0); }
+
+typedef CStringBase<char> AString;
+typedef CStringBase<wchar_t> UString;
+
+typedef CObjectVector<AString> AStringVector;
+typedef CObjectVector<UString> UStringVector;
+
+#ifdef _UNICODE
+ typedef UString CSysString;
+#else
+ typedef AString CSysString;
+#endif
+
+typedef CObjectVector<CSysString> CSysStringVector;
+
+#endif