// Common/MyString.cpp #include "StdAfx.h" #ifdef _WIN32 #include #include #else #include #endif #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 } */ 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(wchar_t *s) { for (;;) { wchar_t c = *s; if (c == 0) return; *s++ = MyCharUpper_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; } } // 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) throw() { 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); } void AString::ReAlloc(unsigned newLimit) { if (newLimit < _len || newLimit >= 0x20000000) 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::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[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()); } AString::AString() { _chars = 0; _chars = MY_STRING_NEW(char, 4); _len = 0; _limit = 4 - 1; _chars[0] = 0; } AString::AString(char c) { SetStartLen(1); _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; _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; } AString &AString::operator+=(const char *s) { unsigned len = MyStringLen(s); Grow(len); MyStringCopy(_chars + _len, s); _len += len; return *this; } AString &AString::operator+=(const AString &s) { Grow(s._len); MyStringCopy(_chars + _len, s._chars); _len += s._len; return *this; } 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; } memcpy(_chars, s, len); _chars[len] = 0; _len = len; } int AString::Find(const AString &s, unsigned startIndex) const throw() { if (s.IsEmpty()) return startIndex; for (; startIndex < _len; startIndex++) { unsigned j; for (j = 0; j < s._len && startIndex + j < _len; j++) if (_chars[startIndex + j] != s._chars[j]) break; if (j == s._len) return (int)startIndex; } return -1; } 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); } } 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; int i; for (i = _len - 1; i >= 0; i--) { char c = p[i]; if (c != ' ' && c != '\n' && c != '\t') break; } i++; if ((unsigned)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() { int pos = Find(ch); if (pos < 0) return; const char *src = _chars; char *dest = _chars + pos; pos++; unsigned len = _len; for (; (unsigned)pos < len; pos++) { char c = src[(unsigned)pos]; 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; while ((unsigned)pos < _len) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[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 >= 0x20000000) 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::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[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, 4); _len = 0; _limit = 4 - 1; _chars[0] = 0; } UString::UString(wchar_t c) { SetStartLen(1); _chars[0] = c; _chars[1] = 0; } UString::UString(const wchar_t *s) { SetStartLen(MyStringLen(s)); MyStringCopy(_chars, s); } UString::UString(const UString &s) { SetStartLen(s._len); MyStringCopy(_chars, s._chars); } 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; _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; MyStringCopy(_chars, s); 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; MyStringCopy(_chars, s._chars); return *this; } UString &UString::operator+=(const wchar_t *s) { unsigned len = MyStringLen(s); Grow(len); MyStringCopy(_chars + _len, s); _len += len; return *this; } UString &UString::operator+=(const UString &s) { Grow(s._len); MyStringCopy(_chars + _len, s._chars); _len += s._len; 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; } wmemcpy(_chars, s, len); _chars[len] = 0; _len = len; } void UString::SetFromAscii(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] = s[i]; chars[len] = 0; _len = len; } void UString::AddAsciiStr(const char *s) { unsigned len = MyStringLen(s); Grow(len); wchar_t *chars = _chars + _len; for (unsigned i = 0; i < len; i++) chars[i] = s[i]; chars[len] = 0; _len += len; } int UString::Find(const UString &s, unsigned startIndex) const throw() { if (s.IsEmpty()) return startIndex; for (; startIndex < _len; startIndex++) { unsigned j; for (j = 0; j < s._len && startIndex + j < _len; j++) if (_chars[startIndex + j] != s._chars[j]) break; if (j == s._len) return (int)startIndex; } return -1; } 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--; } } 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; int i; for (i = _len - 1; i >= 0; i--) { wchar_t c = p[i]; if (c != ' ' && c != '\n' && c != '\t') break; } i++; if ((unsigned)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() { int pos = Find(ch); if (pos < 0) return; const wchar_t *src = _chars; wchar_t *dest = _chars + pos; pos++; unsigned len = _len; for (; (unsigned)pos < len; pos++) { wchar_t c = src[(unsigned)pos]; 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; while ((unsigned)pos < _len) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[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; } } // ---------------------------------------- /* 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 AString &s) { return MultiByteToUnicodeString(s, GetCurrentCodePage()); } #endif #else UString fs2us(const FString &s) { return MultiByteToUnicodeString((AString)s, GetCurrentCodePage()); } FString us2fs(const wchar_t *s) { return UnicodeStringToMultiByte(s, GetCurrentCodePage()); } #endif