1 // Copyright (C) 2015 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "aemu/base/system/Win32UnicodeString.h"
16
17 #include <algorithm>
18
19 #include <windows.h>
20
21 #include <string.h>
22
23 namespace android {
24 namespace base {
25
Win32UnicodeString()26 Win32UnicodeString::Win32UnicodeString() : mStr(nullptr), mSize(0u) {}
27
Win32UnicodeString(const char * str,size_t len)28 Win32UnicodeString::Win32UnicodeString(const char* str, size_t len)
29 : mStr(nullptr), mSize(0u) {
30 reset(str, strlen(str));
31 }
32
Win32UnicodeString(const char * str)33 Win32UnicodeString::Win32UnicodeString(const char* str)
34 : mStr(nullptr), mSize(0u) {
35 reset(str);
36 }
37
Win32UnicodeString(const std::string & str)38 Win32UnicodeString::Win32UnicodeString(const std::string& str)
39 : mStr(nullptr), mSize(0u) {
40 reset(str.c_str());
41 }
42
Win32UnicodeString(size_t size)43 Win32UnicodeString::Win32UnicodeString(size_t size) : mStr(nullptr), mSize(0u) {
44 resize(size);
45 }
46
Win32UnicodeString(const wchar_t * str)47 Win32UnicodeString::Win32UnicodeString(const wchar_t* str)
48 : mStr(nullptr), mSize(0u) {
49 size_t len = str ? wcslen(str) : 0u;
50 resize(len);
51 ::memcpy(mStr, str ? str : L"", len * sizeof(wchar_t));
52 }
53
Win32UnicodeString(const Win32UnicodeString & other)54 Win32UnicodeString::Win32UnicodeString(const Win32UnicodeString& other)
55 : mStr(nullptr), mSize(0u) {
56 resize(other.mSize);
57 ::memcpy(mStr, other.c_str(), other.mSize * sizeof(wchar_t));
58 }
59
~Win32UnicodeString()60 Win32UnicodeString::~Win32UnicodeString() {
61 delete[] mStr;
62 }
63
operator =(const Win32UnicodeString & other)64 Win32UnicodeString& Win32UnicodeString::operator=(
65 const Win32UnicodeString& other) {
66 resize(other.mSize);
67 ::memcpy(mStr, other.c_str(), other.mSize * sizeof(wchar_t));
68 return *this;
69 }
70
operator =(const wchar_t * str)71 Win32UnicodeString& Win32UnicodeString::operator=(const wchar_t* str) {
72 size_t len = str ? wcslen(str) : 0u;
73 resize(len);
74 ::memcpy(mStr, str ? str : L"", len * sizeof(wchar_t));
75 return *this;
76 }
77
data()78 wchar_t* Win32UnicodeString::data() {
79 if (!mStr) {
80 // Ensure the function never returns NULL.
81 // it is safe to const_cast the pointer here - user isn't allowed to
82 // write into it anyway
83 return const_cast<wchar_t*>(L"");
84 }
85 return mStr;
86 }
87
toString() const88 std::string Win32UnicodeString::toString() const {
89 return convertToUtf8(mStr, mSize);
90 }
91
reset(const char * str,size_t len)92 void Win32UnicodeString::reset(const char* str, size_t len) {
93 if (mStr) {
94 delete[] mStr;
95 }
96 const int utf16Len = calcUtf16BufferLength(str, len);
97 mStr = new wchar_t[utf16Len + 1];
98 mSize = static_cast<size_t>(utf16Len);
99 convertFromUtf8(mStr, utf16Len, str, len);
100 mStr[mSize] = L'\0';
101 }
102
reset(const char * str)103 void Win32UnicodeString::reset(const char* str) {
104 reset(str, strlen(str));
105 }
106
resize(size_t newSize)107 void Win32UnicodeString::resize(size_t newSize) {
108 if (newSize == 0) {
109 delete [] mStr;
110 mStr = nullptr;
111 mSize = 0;
112 } else if (newSize <= mSize) {
113 mStr[newSize] = 0;
114 mSize = newSize;
115 } else {
116 wchar_t* oldStr = mStr;
117 mStr = new wchar_t[newSize + 1u];
118 size_t copySize = std::min<size_t>(newSize, mSize);
119 ::memcpy(mStr, oldStr ? oldStr : L"", copySize * sizeof(wchar_t));
120 mStr[copySize] = L'\0';
121 mStr[newSize] = L'\0';
122 mSize = newSize;
123 delete[] oldStr;
124 }
125 }
126
append(const wchar_t * str)127 void Win32UnicodeString::append(const wchar_t* str) {
128 append(str, wcslen(str));
129 }
130
append(const wchar_t * str,size_t len)131 void Win32UnicodeString::append(const wchar_t* str, size_t len) {
132 // NOTE: This method should be rarely used, so don't try to optimize
133 // storage with larger capacity values and exponential increments.
134 if (!str || !len) {
135 return;
136 }
137 size_t oldSize = size();
138 resize(oldSize + len);
139 memmove(mStr + oldSize, str, len * sizeof(wchar_t));
140 }
141
append(const Win32UnicodeString & other)142 void Win32UnicodeString::append(const Win32UnicodeString& other) {
143 append(other.c_str(), other.size());
144 }
145
release()146 wchar_t* Win32UnicodeString::release() {
147 wchar_t* result = mStr;
148 mStr = nullptr;
149 mSize = 0u;
150 return result;
151 }
152
153 // static
convertToUtf8(const wchar_t * str,int len)154 std::string Win32UnicodeString::convertToUtf8(const wchar_t* str, int len) {
155 std::string result;
156 const int utf8Len = calcUtf8BufferLength(str, len);
157 if (utf8Len > 0) {
158 result.resize(static_cast<size_t>(utf8Len));
159 convertToUtf8(&result[0], utf8Len, str, len);
160 if (len == -1) {
161 result.resize(utf8Len - 1); // get rid of the null-terminator
162 }
163 }
164 return result;
165 }
166
167 // returns the return value of a Win32UnicodeString public conversion function
168 // from a WinAPI conversion function returned code
convertRetVal(int winapiResult)169 static int convertRetVal(int winapiResult) {
170 return winapiResult ? winapiResult : -1;
171 }
172
173 // static
calcUtf8BufferLength(const wchar_t * str,int len)174 int Win32UnicodeString::calcUtf8BufferLength(const wchar_t* str, int len) {
175 if (len < 0 && len != -1) {
176 return -1;
177 }
178 if (len == 0) {
179 return 0;
180 }
181 const int utf8Len = WideCharToMultiByte(CP_UTF8, // CodePage
182 0, // dwFlags
183 str, // lpWideCharStr
184 len, // cchWideChar
185 nullptr, // lpMultiByteStr
186 0, // cbMultiByte
187 nullptr, // lpDefaultChar
188 nullptr); // lpUsedDefaultChar
189
190 return convertRetVal(utf8Len);
191 }
192
193 // static
calcUtf16BufferLength(const char * str,int len)194 int Win32UnicodeString::calcUtf16BufferLength(const char* str, int len) {
195 if (len < 0 && len != -1) {
196 return -1;
197 }
198 if (len == 0) {
199 return 0;
200 }
201 const int utf16Len = MultiByteToWideChar(CP_UTF8, // CodePage
202 0, // dwFlags
203 str, // lpMultiByteStr
204 len, // cbMultiByte
205 nullptr, // lpWideCharStr
206 0); // cchWideChar
207
208 return convertRetVal(utf16Len);
209 }
210
211 // static
convertToUtf8(char * outStr,int outLen,const wchar_t * str,int len)212 int Win32UnicodeString::convertToUtf8(char* outStr, int outLen,
213 const wchar_t* str, int len) {
214 if (!outStr || outLen < 0 || !str || (len < 0 && len != -1)) {
215 return -1;
216 }
217 if (len == 0) {
218 return 0;
219 }
220
221 const int utf8Len = WideCharToMultiByte(CP_UTF8, // CodePage
222 0, // dwFlags
223 str, // lpWideCharStr
224 len, // cchWideChar
225 outStr, // lpMultiByteStr
226 outLen, // cbMultiByte
227 nullptr, // lpDefaultChar
228 nullptr); // lpUsedDefaultChar
229 return convertRetVal(utf8Len);
230 }
231
232 // static
convertFromUtf8(wchar_t * outStr,int outLen,const char * str,int len)233 int Win32UnicodeString::convertFromUtf8(wchar_t* outStr, int outLen,
234 const char* str, int len) {
235 if (!outStr || outLen < 0 || !str || (len < 0 && len != -1)) {
236 return -1;
237 }
238 if (len == 0) {
239 return 0;
240 }
241
242 const int utf16Len = MultiByteToWideChar(CP_UTF8, // CodePage
243 0, // dwFlags
244 str, // lpMultiByteStr
245 len, // cbMultiByte
246 outStr, // lpWideCharStr
247 outLen); // cchWideChar
248 return convertRetVal(utf16Len);
249 }
250
251 } // namespace base
252 } // namespace android
253