summaryrefslogtreecommitdiffstats
path: root/other-licenses/7zstub/src/CPP/Common/MyString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'other-licenses/7zstub/src/CPP/Common/MyString.cpp')
-rw-r--r--other-licenses/7zstub/src/CPP/Common/MyString.cpp1659
1 files changed, 1659 insertions, 0 deletions
diff --git a/other-licenses/7zstub/src/CPP/Common/MyString.cpp b/other-licenses/7zstub/src/CPP/Common/MyString.cpp
new file mode 100644
index 000000000..bf62303df
--- /dev/null
+++ b/other-licenses/7zstub/src/CPP/Common/MyString.cpp
@@ -0,0 +1,1659 @@
+// Common/MyString.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include <wchar.h>
+#else
+#include <ctype.h>
+#endif
+
+#include "IntToString.h"
+
+#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
+#include "StringConvert.h"
+#endif
+
+#include "MyString.h"
+
+#define MY_STRING_NEW(_T_, _size_) new _T_[_size_]
+// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))
+
+/*
+inline const char* MyStringGetNextCharPointer(const char *p) throw()
+{
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ return CharNextA(p);
+ #else
+ return p + 1;
+ #endif
+}
+*/
+
+#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_)
+#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_)
+
+
+int FindCharPosInString(const char *s, char c) throw()
+{
+ for (const char *p = s;; p++)
+ {
+ if (*p == c)
+ return (int)(p - s);
+ if (*p == 0)
+ return -1;
+ // MyStringGetNextCharPointer(p);
+ }
+}
+
+int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
+{
+ for (const wchar_t *p = s;; p++)
+ {
+ if (*p == c)
+ return (int)(p - s);
+ if (*p == 0)
+ return -1;
+ }
+}
+
+/*
+void MyStringUpper_Ascii(char *s) throw()
+{
+ for (;;)
+ {
+ char c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharUpper_Ascii(c);
+ }
+}
+
+void MyStringUpper_Ascii(wchar_t *s) throw()
+{
+ for (;;)
+ {
+ wchar_t c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharUpper_Ascii(c);
+ }
+}
+*/
+
+void MyStringLower_Ascii(char *s) throw()
+{
+ for (;;)
+ {
+ char c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharLower_Ascii(c);
+ }
+}
+
+void MyStringLower_Ascii(wchar_t *s) throw()
+{
+ for (;;)
+ {
+ wchar_t c = *s;
+ if (c == 0)
+ return;
+ *s++ = MyCharLower_Ascii(c);
+ }
+}
+
+#ifdef _WIN32
+
+#ifdef _UNICODE
+
+// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
+// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
+// for WinCE - FString - char
+// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }
+
+#else
+
+// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }
+// char * MyStringUpper(char *s) { return CharUpperA(s); }
+// char * MyStringLower(char *s) { return CharLowerA(s); }
+
+wchar_t MyCharUpper_WIN(wchar_t c) throw()
+{
+ wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return (wchar_t)(unsigned)(UINT_PTR)res;
+ const int kBufSize = 4;
+ char s[kBufSize + 1];
+ int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
+ if (numChars == 0 || numChars > kBufSize)
+ return c;
+ s[numChars] = 0;
+ ::CharUpperA(s);
+ ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+ return c;
+}
+
+/*
+wchar_t MyCharLower_WIN(wchar_t c)
+{
+ wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return (wchar_t)(unsigned)(UINT_PTR)res;
+ const int kBufSize = 4;
+ char s[kBufSize + 1];
+ int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
+ if (numChars == 0 || numChars > kBufSize)
+ return c;
+ s[numChars] = 0;
+ ::CharLowerA(s);
+ ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+ return c;
+}
+*/
+
+/*
+wchar_t * MyStringUpper(wchar_t *s)
+{
+ if (s == 0)
+ return 0;
+ wchar_t *res = CharUpperW(s);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return res;
+ AString a = UnicodeStringToMultiByte(s);
+ a.MakeUpper();
+ MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+ return s;
+}
+*/
+
+/*
+wchar_t * MyStringLower(wchar_t *s)
+{
+ if (s == 0)
+ return 0;
+ wchar_t *res = CharLowerW(s);
+ if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return res;
+ AString a = UnicodeStringToMultiByte(s);
+ a.MakeLower();
+ MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+ return s;
+}
+*/
+
+#endif
+
+#endif
+
+bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;
+ unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;
+ }
+}
+
+bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;
+ if (c1 == 0) return true;
+ }
+}
+
+// ---------- ASCII ----------
+
+bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
+{
+ const char *s1 = _chars;
+ for (;;)
+ {
+ char c2 = *s++;
+ if (c2 == 0)
+ return true;
+ char c1 = *s1++;
+ if (MyCharLower_Ascii(c1) !=
+ MyCharLower_Ascii(c2))
+ return false;
+ }
+}
+
+bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
+{
+ const wchar_t *s1 = _chars;
+ for (;;)
+ {
+ char c2 = *s++;
+ if (c2 == 0)
+ return true;
+ wchar_t c1 = *s1++;
+ if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
+ return false;
+ }
+}
+
+bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
+{
+ for (;;)
+ {
+ unsigned char c = *a;
+ if (c != *u)
+ return false;
+ if (c == 0)
+ return true;
+ a++;
+ u++;
+ }
+}
+
+bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
+ return false;
+ if (c1 == 0)
+ return true;
+ }
+}
+
+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
+ return false;
+ if (c1 == 0)
+ return true;
+ }
+}
+
+bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c1 = *s1++;
+ char c2 = *s2++;
+ if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
+ return false;
+ if (c1 == 0)
+ return true;
+ }
+}
+
+bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c2 = *s2++; if (c2 == 0) return true;
+ wchar_t c1 = *s1++; if (c1 != c2) return false;
+ }
+}
+
+bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
+ wchar_t c1 = *s1++; if (c1 != c2) return false;
+ }
+}
+
+bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
+{
+ for (;;)
+ {
+ char c2 = *s2++; if (c2 == 0) return true;
+ wchar_t c1 = *s1++;
+ if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
+ return false;
+ }
+}
+
+bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c2 = *s2++; if (c2 == 0) return true;
+ wchar_t c1 = *s1++;
+ if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
+ return false;
+ }
+}
+
+// NTFS order: uses upper case
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
+{
+ for (;;)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2)
+ {
+ wchar_t u1 = MyCharUpper(c1);
+ wchar_t u2 = MyCharUpper(c2);
+ if (u1 < u2) return -1;
+ if (u1 > u2) return 1;
+ }
+ if (c1 == 0) return 0;
+ }
+}
+
+/*
+int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
+{
+ for (; num != 0; num--)
+ {
+ wchar_t c1 = *s1++;
+ wchar_t c2 = *s2++;
+ if (c1 != c2)
+ {
+ wchar_t u1 = MyCharUpper(c1);
+ wchar_t u2 = MyCharUpper(c2);
+ if (u1 < u2) return -1;
+ if (u1 > u2) return 1;
+ }
+ if (c1 == 0) return 0;
+ }
+ return 0;
+}
+*/
+
+// ---------- AString ----------
+
+void AString::InsertSpace(unsigned &index, unsigned size)
+{
+ Grow(size);
+ MoveItems(index + size, index);
+}
+
+#define k_Alloc_Len_Limit 0x40000000
+
+void AString::ReAlloc(unsigned newLimit)
+{
+ if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
+ // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
+ char *newBuf = MY_STRING_NEW_char(newLimit + 1);
+ memcpy(newBuf, _chars, (size_t)(_len + 1));
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = newLimit;
+}
+
+void AString::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
+ // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
+ char *newBuf = MY_STRING_NEW_char(newLimit + 1);
+ newBuf[0] = 0;
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = newLimit;
+}
+
+void AString::SetStartLen(unsigned len)
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW_char(len + 1);
+ _len = len;
+ _limit = len;
+}
+
+void AString::Grow_1()
+{
+ unsigned next = _len;
+ next += next / 2;
+ next += 16;
+ next &= ~(unsigned)15;
+ ReAlloc(next - 1);
+}
+
+void AString::Grow(unsigned n)
+{
+ unsigned freeSize = _limit - _len;
+ if (n <= freeSize)
+ return;
+
+ unsigned next = _len + n;
+ next += next / 2;
+ next += 16;
+ next &= ~(unsigned)15;
+ ReAlloc(next - 1);
+}
+
+AString::AString(unsigned num, const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (num > len)
+ num = len;
+ SetStartLen(num);
+ memcpy(_chars, s, num);
+ _chars[num] = 0;
+}
+
+AString::AString(unsigned num, const AString &s)
+{
+ if (num > s._len)
+ num = s._len;
+ SetStartLen(num);
+ memcpy(_chars, s._chars, num);
+ _chars[num] = 0;
+}
+
+AString::AString(const AString &s, char c)
+{
+ SetStartLen(s.Len() + 1);
+ char *chars = _chars;
+ unsigned len = s.Len();
+ memcpy(chars, s, len);
+ chars[len] = c;
+ chars[(size_t)len + 1] = 0;
+}
+
+AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
+{
+ SetStartLen(num1 + num2);
+ char *chars = _chars;
+ memcpy(chars, s1, num1);
+ memcpy(chars + num1, s2, num2 + 1);
+}
+
+AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
+AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
+AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
+
+static const unsigned kStartStringCapacity = 4;
+
+AString::AString()
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW_char(kStartStringCapacity);
+ _len = 0;
+ _limit = kStartStringCapacity - 1;
+ _chars[0] = 0;
+}
+
+AString::AString(char c)
+{
+ SetStartLen(1);
+ char *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+}
+
+AString::AString(const char *s)
+{
+ SetStartLen(MyStringLen(s));
+ MyStringCopy(_chars, s);
+}
+
+AString::AString(const AString &s)
+{
+ SetStartLen(s._len);
+ MyStringCopy(_chars, s._chars);
+}
+
+AString &AString::operator=(char c)
+{
+ if (1 > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(1 + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = 1;
+ }
+ _len = 1;
+ char *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+ return *this;
+}
+
+AString &AString::operator=(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ MyStringCopy(_chars, s);
+ return *this;
+}
+
+AString &AString::operator=(const AString &s)
+{
+ if (&s == this)
+ return *this;
+ unsigned len = s._len;
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ MyStringCopy(_chars, s._chars);
+ return *this;
+}
+
+void AString::SetFromWStr_if_Ascii(const wchar_t *s)
+{
+ unsigned len = 0;
+ {
+ for (;; len++)
+ {
+ wchar_t c = s[len];
+ if (c == 0)
+ break;
+ if (c >= 0x80)
+ return;
+ }
+ }
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ char *dest = _chars;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ dest[i] = (char)s[i];
+ dest[i] = 0;
+}
+
+/*
+void AString::SetFromBstr_if_Ascii(BSTR s)
+{
+ unsigned len = ::SysStringLen(s);
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (s[i] <= 0 || s[i] >= 0x80)
+ return;
+ }
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ char *dest = _chars;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ dest[i] = (char)s[i];
+ dest[i] = 0;
+}
+*/
+
+void AString::Add_Space() { operator+=(' '); }
+void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
+void AString::Add_LF() { operator+=('\n'); }
+
+AString &AString::operator+=(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ Grow(len);
+ MyStringCopy(_chars + _len, s);
+ _len += len;
+ return *this;
+}
+
+void AString::Add_OptSpaced(const char *s)
+{
+ Add_Space_if_NotEmpty();
+ (*this) += s;
+}
+
+AString &AString::operator+=(const AString &s)
+{
+ Grow(s._len);
+ MyStringCopy(_chars + _len, s._chars);
+ _len += s._len;
+ return *this;
+}
+
+void AString::Add_UInt32(UInt32 v)
+{
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ (*this) += sz;
+}
+
+void AString::SetFrom(const char *s, unsigned len) // no check
+{
+ if (len > _limit)
+ {
+ char *newBuf = MY_STRING_NEW_char(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ if (len != 0)
+ memcpy(_chars, s, len);
+ _chars[len] = 0;
+ _len = len;
+}
+
+void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
+{
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (s[i] == 0)
+ break;
+ SetFrom(s, i);
+}
+
+int AString::Find(const char *s, unsigned startIndex) const throw()
+{
+ const char *fs = strstr(_chars + startIndex, s);
+ if (!fs)
+ return -1;
+ return (int)(fs - _chars);
+
+ /*
+ if (s[0] == 0)
+ return startIndex;
+ unsigned len = MyStringLen(s);
+ const char *p = _chars + startIndex;
+ for (;; p++)
+ {
+ const char c = *p;
+ if (c != s[0])
+ {
+ if (c == 0)
+ return -1;
+ continue;
+ }
+ unsigned i;
+ for (i = 1; i < len; i++)
+ if (p[i] != s[i])
+ break;
+ if (i == len)
+ return (int)(p - _chars);
+ }
+ */
+}
+
+int AString::ReverseFind(char c) const throw()
+{
+ if (_len == 0)
+ return -1;
+ const char *p = _chars + _len - 1;
+ for (;;)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--; // p = GetPrevCharPointer(_chars, p);
+ }
+}
+
+int AString::ReverseFind_PathSepar() const throw()
+{
+ if (_len == 0)
+ return -1;
+ const char *p = _chars + _len - 1;
+ for (;;)
+ {
+ char c = *p;
+ if (IS_PATH_SEPAR(c))
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--;
+ }
+}
+
+void AString::TrimLeft() throw()
+{
+ const char *p = _chars;
+ for (;; p++)
+ {
+ char c = *p;
+ if (c != ' ' && c != '\n' && c != '\t')
+ break;
+ }
+ unsigned pos = (unsigned)(p - _chars);
+ if (pos != 0)
+ {
+ MoveItems(0, pos);
+ _len -= pos;
+ }
+}
+
+void AString::TrimRight() throw()
+{
+ const char *p = _chars;
+ unsigned i;
+ for (i = _len; i != 0; i--)
+ {
+ char c = p[(size_t)i - 1];
+ if (c != ' ' && c != '\n' && c != '\t')
+ break;
+ }
+ if (i != _len)
+ {
+ _chars[i] = 0;
+ _len = i;
+ }
+}
+
+void AString::InsertAtFront(char c)
+{
+ if (_limit == _len)
+ Grow_1();
+ MoveItems(1, 0);
+ _chars[0] = c;
+ _len++;
+}
+
+/*
+void AString::Insert(unsigned index, char c)
+{
+ InsertSpace(index, 1);
+ _chars[index] = c;
+ _len++;
+}
+*/
+
+void AString::Insert(unsigned index, const char *s)
+{
+ unsigned num = MyStringLen(s);
+ if (num != 0)
+ {
+ InsertSpace(index, num);
+ memcpy(_chars + index, s, num);
+ _len += num;
+ }
+}
+
+void AString::Insert(unsigned index, const AString &s)
+{
+ unsigned num = s.Len();
+ if (num != 0)
+ {
+ InsertSpace(index, num);
+ memcpy(_chars + index, s, num);
+ _len += num;
+ }
+}
+
+void AString::RemoveChar(char ch) throw()
+{
+ char *src = _chars;
+
+ for (;;)
+ {
+ char c = *src++;
+ if (c == 0)
+ return;
+ if (c == ch)
+ break;
+ }
+
+ char *dest = src - 1;
+
+ for (;;)
+ {
+ char c = *src++;
+ if (c == 0)
+ break;
+ if (c != ch)
+ *dest++ = c;
+ }
+
+ *dest = 0;
+ _len = (unsigned)(dest - _chars);
+}
+
+// !!!!!!!!!!!!!!! test it if newChar = '\0'
+void AString::Replace(char oldChar, char newChar) throw()
+{
+ if (oldChar == newChar)
+ return; // 0;
+ // unsigned number = 0;
+ int pos = 0;
+ char *chars = _chars;
+ while ((unsigned)pos < _len)
+ {
+ pos = Find(oldChar, pos);
+ if (pos < 0)
+ break;
+ chars[(unsigned)pos] = newChar;
+ pos++;
+ // number++;
+ }
+ return; // number;
+}
+
+void AString::Replace(const AString &oldString, const AString &newString)
+{
+ if (oldString.IsEmpty())
+ return; // 0;
+ if (oldString == newString)
+ return; // 0;
+ unsigned oldLen = oldString.Len();
+ unsigned newLen = newString.Len();
+ // unsigned number = 0;
+ int pos = 0;
+ while ((unsigned)pos < _len)
+ {
+ pos = Find(oldString, pos);
+ if (pos < 0)
+ break;
+ Delete(pos, oldLen);
+ Insert(pos, newString);
+ pos += newLen;
+ // number++;
+ }
+ // return number;
+}
+
+void AString::Delete(unsigned index) throw()
+{
+ MoveItems(index, index + 1);
+ _len--;
+}
+
+void AString::Delete(unsigned index, unsigned count) throw()
+{
+ if (index + count > _len)
+ count = _len - index;
+ if (count > 0)
+ {
+ MoveItems(index, index + count);
+ _len -= count;
+ }
+}
+
+void AString::DeleteFrontal(unsigned num) throw()
+{
+ if (num != 0)
+ {
+ MoveItems(0, num);
+ _len -= num;
+ }
+}
+
+/*
+AString operator+(const AString &s1, const AString &s2)
+{
+ AString result(s1);
+ result += s2;
+ return result;
+}
+
+AString operator+(const AString &s, const char *chars)
+{
+ AString result(s);
+ result += chars;
+ return result;
+}
+
+AString operator+(const char *chars, const AString &s)
+{
+ AString result(chars);
+ result += s;
+ return result;
+}
+
+AString operator+(const AString &s, char c)
+{
+ AString result(s);
+ result += c;
+ return result;
+}
+*/
+
+/*
+AString operator+(char c, const AString &s)
+{
+ AString result(c);
+ result += s;
+ return result;
+}
+*/
+
+
+
+
+// ---------- UString ----------
+
+void UString::InsertSpace(unsigned index, unsigned size)
+{
+ Grow(size);
+ MoveItems(index + size, index);
+}
+
+void UString::ReAlloc(unsigned newLimit)
+{
+ if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
+ // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
+ wmemcpy(newBuf, _chars, _len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = newLimit;
+}
+
+void UString::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
+ // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
+ newBuf[0] = 0;
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = newLimit;
+}
+
+void UString::SetStartLen(unsigned len)
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW_wchar_t(len + 1);
+ _len = len;
+ _limit = len;
+}
+
+void UString::Grow_1()
+{
+ unsigned next = _len;
+ next += next / 2;
+ next += 16;
+ next &= ~(unsigned)15;
+ ReAlloc(next - 1);
+}
+
+void UString::Grow(unsigned n)
+{
+ unsigned freeSize = _limit - _len;
+ if (n <= freeSize)
+ return;
+
+ unsigned next = _len + n;
+ next += next / 2;
+ next += 16;
+ next &= ~(unsigned)15;
+ ReAlloc(next - 1);
+}
+
+
+UString::UString(unsigned num, const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ if (num > len)
+ num = len;
+ SetStartLen(num);
+ wmemcpy(_chars, s, num);
+ _chars[num] = 0;
+}
+
+
+UString::UString(unsigned num, const UString &s)
+{
+ if (num > s._len)
+ num = s._len;
+ SetStartLen(num);
+ wmemcpy(_chars, s._chars, num);
+ _chars[num] = 0;
+}
+
+UString::UString(const UString &s, wchar_t c)
+{
+ SetStartLen(s.Len() + 1);
+ wchar_t *chars = _chars;
+ unsigned len = s.Len();
+ wmemcpy(chars, s, len);
+ chars[len] = c;
+ chars[(size_t)len + 1] = 0;
+}
+
+UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
+{
+ SetStartLen(num1 + num2);
+ wchar_t *chars = _chars;
+ wmemcpy(chars, s1, num1);
+ wmemcpy(chars + num1, s2, num2 + 1);
+}
+
+UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
+UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
+UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
+
+UString::UString()
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
+ _len = 0;
+ _limit = kStartStringCapacity - 1;
+ _chars[0] = 0;
+}
+
+UString::UString(wchar_t c)
+{
+ SetStartLen(1);
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+}
+
+UString::UString(char c)
+{
+ SetStartLen(1);
+ wchar_t *chars = _chars;
+ chars[0] = (unsigned char)c;
+ chars[1] = 0;
+}
+
+UString::UString(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wmemcpy(_chars, s, len + 1);
+}
+
+UString::UString(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+}
+
+UString::UString(const UString &s)
+{
+ SetStartLen(s._len);
+ wmemcpy(_chars, s._chars, s._len + 1);
+}
+
+UString &UString::operator=(wchar_t c)
+{
+ if (1 > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = 1;
+ }
+ _len = 1;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+ return *this;
+}
+
+UString &UString::operator=(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ wmemcpy(_chars, s, len + 1);
+ return *this;
+}
+
+UString &UString::operator=(const UString &s)
+{
+ if (&s == this)
+ return *this;
+ unsigned len = s._len;
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ wmemcpy(_chars, s._chars, len + 1);
+ return *this;
+}
+
+void UString::SetFrom(const wchar_t *s, unsigned len) // no check
+{
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ if (len != 0)
+ wmemcpy(_chars, s, len);
+ _chars[len] = 0;
+ _len = len;
+}
+
+void UString::SetFromBstr(BSTR s)
+{
+ unsigned len = ::SysStringLen(s);
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ _len = len;
+ // if (s)
+ wmemcpy(_chars, s, len + 1);
+}
+
+UString &UString::operator=(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _limit)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ _limit = len;
+ }
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+ _len = len;
+ return *this;
+}
+
+void UString::Add_Space() { operator+=(L' '); }
+void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
+
+void UString::Add_LF()
+{
+ if (_limit == _len)
+ Grow_1();
+ unsigned len = _len;
+ wchar_t *chars = _chars;
+ chars[len++] = L'\n';
+ chars[len] = 0;
+ _len = len;
+}
+
+UString &UString::operator+=(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ Grow(len);
+ wmemcpy(_chars + _len, s, len + 1);
+ _len += len;
+ return *this;
+}
+
+UString &UString::operator+=(const UString &s)
+{
+ Grow(s._len);
+ wmemcpy(_chars + _len, s._chars, s._len + 1);
+ _len += s._len;
+ return *this;
+}
+
+UString &UString::operator+=(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ Grow(len);
+ wchar_t *chars = _chars + _len;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+ _len += len;
+ return *this;
+}
+
+
+void UString::Add_UInt32(UInt32 v)
+{
+ char sz[16];
+ ConvertUInt32ToString(v, sz);
+ (*this) += sz;
+}
+
+
+int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
+{
+ const wchar_t *fs = wcsstr(_chars + startIndex, s);
+ if (!fs)
+ return -1;
+ return (int)(fs - _chars);
+
+ /*
+ if (s[0] == 0)
+ return startIndex;
+ unsigned len = MyStringLen(s);
+ const wchar_t *p = _chars + startIndex;
+ for (;; p++)
+ {
+ const wchar_t c = *p;
+ if (c != s[0])
+ {
+ if (c == 0)
+ return -1;
+ continue;
+ }
+ unsigned i;
+ for (i = 1; i < len; i++)
+ if (p[i] != s[i])
+ break;
+ if (i == len)
+ return (int)(p - _chars);
+ }
+ */
+}
+
+int UString::ReverseFind(wchar_t c) const throw()
+{
+ if (_len == 0)
+ return -1;
+ const wchar_t *p = _chars + _len - 1;
+ for (;;)
+ {
+ if (*p == c)
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--;
+ }
+}
+
+int UString::ReverseFind_PathSepar() const throw()
+{
+ if (_len == 0)
+ return -1;
+ const wchar_t *p = _chars + _len - 1;
+ for (;;)
+ {
+ wchar_t c = *p;
+ if (IS_PATH_SEPAR(c))
+ return (int)(p - _chars);
+ if (p == _chars)
+ return -1;
+ p--;
+ }
+}
+
+void UString::TrimLeft() throw()
+{
+ const wchar_t *p = _chars;
+ for (;; p++)
+ {
+ wchar_t c = *p;
+ if (c != ' ' && c != '\n' && c != '\t')
+ break;
+ }
+ unsigned pos = (unsigned)(p - _chars);
+ if (pos != 0)
+ {
+ MoveItems(0, pos);
+ _len -= pos;
+ }
+}
+
+void UString::TrimRight() throw()
+{
+ const wchar_t *p = _chars;
+ unsigned i;
+ for (i = _len; i != 0; i--)
+ {
+ wchar_t c = p[(size_t)i - 1];
+ if (c != ' ' && c != '\n' && c != '\t')
+ break;
+ }
+ if (i != _len)
+ {
+ _chars[i] = 0;
+ _len = i;
+ }
+}
+
+void UString::InsertAtFront(wchar_t c)
+{
+ if (_limit == _len)
+ Grow_1();
+ MoveItems(1, 0);
+ _chars[0] = c;
+ _len++;
+}
+
+/*
+void UString::Insert(unsigned index, wchar_t c)
+{
+ InsertSpace(index, 1);
+ _chars[index] = c;
+ _len++;
+}
+*/
+
+void UString::Insert(unsigned index, const wchar_t *s)
+{
+ unsigned num = MyStringLen(s);
+ if (num != 0)
+ {
+ InsertSpace(index, num);
+ wmemcpy(_chars + index, s, num);
+ _len += num;
+ }
+}
+
+void UString::Insert(unsigned index, const UString &s)
+{
+ unsigned num = s.Len();
+ if (num != 0)
+ {
+ InsertSpace(index, num);
+ wmemcpy(_chars + index, s, num);
+ _len += num;
+ }
+}
+
+void UString::RemoveChar(wchar_t ch) throw()
+{
+ wchar_t *src = _chars;
+
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == 0)
+ return;
+ if (c == ch)
+ break;
+ }
+
+ wchar_t *dest = src - 1;
+
+ for (;;)
+ {
+ wchar_t c = *src++;
+ if (c == 0)
+ break;
+ if (c != ch)
+ *dest++ = c;
+ }
+
+ *dest = 0;
+ _len = (unsigned)(dest - _chars);
+}
+
+// !!!!!!!!!!!!!!! test it if newChar = '\0'
+void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
+{
+ if (oldChar == newChar)
+ return; // 0;
+ // unsigned number = 0;
+ int pos = 0;
+ wchar_t *chars = _chars;
+ while ((unsigned)pos < _len)
+ {
+ pos = Find(oldChar, pos);
+ if (pos < 0)
+ break;
+ chars[(unsigned)pos] = newChar;
+ pos++;
+ // number++;
+ }
+ return; // number;
+}
+
+void UString::Replace(const UString &oldString, const UString &newString)
+{
+ if (oldString.IsEmpty())
+ return; // 0;
+ if (oldString == newString)
+ return; // 0;
+ unsigned oldLen = oldString.Len();
+ unsigned newLen = newString.Len();
+ // unsigned number = 0;
+ int pos = 0;
+ while ((unsigned)pos < _len)
+ {
+ pos = Find(oldString, pos);
+ if (pos < 0)
+ break;
+ Delete(pos, oldLen);
+ Insert(pos, newString);
+ pos += newLen;
+ // number++;
+ }
+ // return number;
+}
+
+void UString::Delete(unsigned index) throw()
+{
+ MoveItems(index, index + 1);
+ _len--;
+}
+
+void UString::Delete(unsigned index, unsigned count) throw()
+{
+ if (index + count > _len)
+ count = _len - index;
+ if (count > 0)
+ {
+ MoveItems(index, index + count);
+ _len -= count;
+ }
+}
+
+void UString::DeleteFrontal(unsigned num) throw()
+{
+ if (num != 0)
+ {
+ MoveItems(0, num);
+ _len -= num;
+ }
+}
+
+
+// ---------- UString2 ----------
+
+void UString2::ReAlloc2(unsigned newLimit)
+{
+ if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
+ // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
+ _chars = MY_STRING_NEW_wchar_t(newLimit + 1);
+}
+
+void UString2::SetStartLen(unsigned len)
+{
+ _chars = 0;
+ _chars = MY_STRING_NEW_wchar_t(len + 1);
+ _len = len;
+}
+
+
+/*
+UString2::UString2(wchar_t c)
+{
+ SetStartLen(1);
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+}
+*/
+
+UString2::UString2(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ SetStartLen(len);
+ wmemcpy(_chars, s, len + 1);
+}
+
+UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
+{
+ if (s._chars)
+ {
+ SetStartLen(s._len);
+ wmemcpy(_chars, s._chars, s._len + 1);
+ }
+}
+
+/*
+UString2 &UString2::operator=(wchar_t c)
+{
+ if (1 > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = 1;
+ wchar_t *chars = _chars;
+ chars[0] = c;
+ chars[1] = 0;
+ return *this;
+}
+*/
+
+UString2 &UString2::operator=(const wchar_t *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = len;
+ MyStringCopy(_chars, s);
+ return *this;
+}
+
+void UString2::SetFromAscii(const char *s)
+{
+ unsigned len = MyStringLen(s);
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ wchar_t *chars = _chars;
+ for (unsigned i = 0; i < len; i++)
+ chars[i] = (unsigned char)s[i];
+ chars[len] = 0;
+ _len = len;
+}
+
+UString2 &UString2::operator=(const UString2 &s)
+{
+ if (&s == this)
+ return *this;
+ unsigned len = s._len;
+ if (len > _len)
+ {
+ wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
+ if (_chars)
+ MY_STRING_DELETE(_chars);
+ _chars = newBuf;
+ }
+ _len = len;
+ MyStringCopy(_chars, s._chars);
+ return *this;
+}
+
+bool operator==(const UString2 &s1, const UString2 &s2)
+{
+ return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
+}
+
+bool operator==(const UString2 &s1, const wchar_t *s2)
+{
+ if (s1.IsEmpty())
+ return (*s2 == 0);
+ return wcscmp(s1.GetRawPtr(), s2) == 0;
+}
+
+bool operator==(const wchar_t *s1, const UString2 &s2)
+{
+ if (s2.IsEmpty())
+ return (*s1 == 0);
+ return wcscmp(s1, s2.GetRawPtr()) == 0;
+}
+
+
+
+// ----------------------------------------
+
+/*
+int MyStringCompareNoCase(const char *s1, const char *s2)
+{
+ return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
+}
+*/
+
+static inline UINT GetCurrentCodePage()
+{
+ #if defined(UNDER_CE) || !defined(_WIN32)
+ return CP_ACP;
+ #else
+ return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+ #endif
+}
+
+#ifdef USE_UNICODE_FSTRING
+
+#ifndef _UNICODE
+
+AString fs2fas(CFSTR s)
+{
+ return UnicodeStringToMultiByte(s, GetCurrentCodePage());
+}
+
+FString fas2fs(const char *s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
+FString fas2fs(const AString &s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
+#endif
+
+#else
+
+UString fs2us(const FChar *s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
+UString fs2us(const FString &s)
+{
+ return MultiByteToUnicodeString(s, GetCurrentCodePage());
+}
+
+FString us2fs(const wchar_t *s)
+{
+ return UnicodeStringToMultiByte(s, GetCurrentCodePage());
+}
+
+#endif