// Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "aemu/base/system/Win32UnicodeString.h" #include #include #include namespace android { namespace base { Win32UnicodeString::Win32UnicodeString() : mStr(nullptr), mSize(0u) {} Win32UnicodeString::Win32UnicodeString(const char* str, size_t len) : mStr(nullptr), mSize(0u) { reset(str, strlen(str)); } Win32UnicodeString::Win32UnicodeString(const char* str) : mStr(nullptr), mSize(0u) { reset(str); } Win32UnicodeString::Win32UnicodeString(const std::string& str) : mStr(nullptr), mSize(0u) { reset(str.c_str()); } Win32UnicodeString::Win32UnicodeString(size_t size) : mStr(nullptr), mSize(0u) { resize(size); } Win32UnicodeString::Win32UnicodeString(const wchar_t* str) : mStr(nullptr), mSize(0u) { size_t len = str ? wcslen(str) : 0u; resize(len); ::memcpy(mStr, str ? str : L"", len * sizeof(wchar_t)); } Win32UnicodeString::Win32UnicodeString(const Win32UnicodeString& other) : mStr(nullptr), mSize(0u) { resize(other.mSize); ::memcpy(mStr, other.c_str(), other.mSize * sizeof(wchar_t)); } Win32UnicodeString::~Win32UnicodeString() { delete[] mStr; } Win32UnicodeString& Win32UnicodeString::operator=( const Win32UnicodeString& other) { resize(other.mSize); ::memcpy(mStr, other.c_str(), other.mSize * sizeof(wchar_t)); return *this; } Win32UnicodeString& Win32UnicodeString::operator=(const wchar_t* str) { size_t len = str ? wcslen(str) : 0u; resize(len); ::memcpy(mStr, str ? str : L"", len * sizeof(wchar_t)); return *this; } wchar_t* Win32UnicodeString::data() { if (!mStr) { // Ensure the function never returns NULL. // it is safe to const_cast the pointer here - user isn't allowed to // write into it anyway return const_cast(L""); } return mStr; } std::string Win32UnicodeString::toString() const { return convertToUtf8(mStr, mSize); } void Win32UnicodeString::reset(const char* str, size_t len) { if (mStr) { delete[] mStr; } const int utf16Len = calcUtf16BufferLength(str, len); mStr = new wchar_t[utf16Len + 1]; mSize = static_cast(utf16Len); convertFromUtf8(mStr, utf16Len, str, len); mStr[mSize] = L'\0'; } void Win32UnicodeString::reset(const char* str) { reset(str, strlen(str)); } void Win32UnicodeString::resize(size_t newSize) { if (newSize == 0) { delete [] mStr; mStr = nullptr; mSize = 0; } else if (newSize <= mSize) { mStr[newSize] = 0; mSize = newSize; } else { wchar_t* oldStr = mStr; mStr = new wchar_t[newSize + 1u]; size_t copySize = std::min(newSize, mSize); ::memcpy(mStr, oldStr ? oldStr : L"", copySize * sizeof(wchar_t)); mStr[copySize] = L'\0'; mStr[newSize] = L'\0'; mSize = newSize; delete[] oldStr; } } void Win32UnicodeString::append(const wchar_t* str) { append(str, wcslen(str)); } void Win32UnicodeString::append(const wchar_t* str, size_t len) { // NOTE: This method should be rarely used, so don't try to optimize // storage with larger capacity values and exponential increments. if (!str || !len) { return; } size_t oldSize = size(); resize(oldSize + len); memmove(mStr + oldSize, str, len * sizeof(wchar_t)); } void Win32UnicodeString::append(const Win32UnicodeString& other) { append(other.c_str(), other.size()); } wchar_t* Win32UnicodeString::release() { wchar_t* result = mStr; mStr = nullptr; mSize = 0u; return result; } // static std::string Win32UnicodeString::convertToUtf8(const wchar_t* str, int len) { std::string result; const int utf8Len = calcUtf8BufferLength(str, len); if (utf8Len > 0) { result.resize(static_cast(utf8Len)); convertToUtf8(&result[0], utf8Len, str, len); if (len == -1) { result.resize(utf8Len - 1); // get rid of the null-terminator } } return result; } // returns the return value of a Win32UnicodeString public conversion function // from a WinAPI conversion function returned code static int convertRetVal(int winapiResult) { return winapiResult ? winapiResult : -1; } // static int Win32UnicodeString::calcUtf8BufferLength(const wchar_t* str, int len) { if (len < 0 && len != -1) { return -1; } if (len == 0) { return 0; } const int utf8Len = WideCharToMultiByte(CP_UTF8, // CodePage 0, // dwFlags str, // lpWideCharStr len, // cchWideChar nullptr, // lpMultiByteStr 0, // cbMultiByte nullptr, // lpDefaultChar nullptr); // lpUsedDefaultChar return convertRetVal(utf8Len); } // static int Win32UnicodeString::calcUtf16BufferLength(const char* str, int len) { if (len < 0 && len != -1) { return -1; } if (len == 0) { return 0; } const int utf16Len = MultiByteToWideChar(CP_UTF8, // CodePage 0, // dwFlags str, // lpMultiByteStr len, // cbMultiByte nullptr, // lpWideCharStr 0); // cchWideChar return convertRetVal(utf16Len); } // static int Win32UnicodeString::convertToUtf8(char* outStr, int outLen, const wchar_t* str, int len) { if (!outStr || outLen < 0 || !str || (len < 0 && len != -1)) { return -1; } if (len == 0) { return 0; } const int utf8Len = WideCharToMultiByte(CP_UTF8, // CodePage 0, // dwFlags str, // lpWideCharStr len, // cchWideChar outStr, // lpMultiByteStr outLen, // cbMultiByte nullptr, // lpDefaultChar nullptr); // lpUsedDefaultChar return convertRetVal(utf8Len); } // static int Win32UnicodeString::convertFromUtf8(wchar_t* outStr, int outLen, const char* str, int len) { if (!outStr || outLen < 0 || !str || (len < 0 && len != -1)) { return -1; } if (len == 0) { return 0; } const int utf16Len = MultiByteToWideChar(CP_UTF8, // CodePage 0, // dwFlags str, // lpMultiByteStr len, // cbMultiByte outStr, // lpWideCharStr outLen); // cchWideChar return convertRetVal(utf16Len); } } // namespace base } // namespace android