• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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