Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
win32_utf8conv_inl.hpp
Go to the documentation of this file.
1 //
3 // FILE: win32_utf8conv_inl.h
4 //
5 // by Giovanni Dicanio <[email protected]>
6 //
7 // Private header file containing implementations of inline functions.
8 // The public header file for this module is "utf8conv.h";
9 // users should *not* #include this private header file directly.
10 //
12 
13 #pragma once
14 
15 #ifdef _WIN32
16 #ifndef _WINDOWS_
17 #ifndef WIN32_LEAN_AND_MEAN
18 #define WIN32_LEAN_AND_MEAN
19 #endif
20 #include <windows.h>
21 #endif
22 #endif
23 
24 #include <string.h> // strlen()
25 
26 //#ifdef _WIN32
27 //#ifndef WIN32_LEAN_AND_MEAN
28 //#define WIN32_LEAN_AND_MEAN
29 //#include <windows.h>
30 //#endif
31 //#endif
32 
33 namespace utf8util
34 {
35 
36 // Implementation of utf8_conversion_error class methods
37 
39  conversion_type conversion,
40  error_code_type error_code)
41  : std::runtime_error(message)
42  , m_conversion(conversion)
43  , m_error_code(error_code)
44 {
45 }
46 
47 inline utf8_conversion_error::utf8_conversion_error(const std::string& message,
48  conversion_type conversion,
49  error_code_type error_code)
50  : std::runtime_error(message)
51  , m_conversion(conversion)
52  , m_error_code(error_code)
53 {
54 }
55 
57  conversion() const
58 {
59  return m_conversion;
60 }
61 
63  error_code() const
64 {
65  return m_error_code;
66 }
67 
68 // Implementation of module functions
69 
70 inline std::wstring UTF16FromUTF8(const std::string& utf8)
71 {
72  //
73  // Special case of empty input string
74  //
75  if (utf8.empty()) return std::wstring();
76 
77  // Fail if an invalid input character is encountered
78  const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
79 
80  //
81  // Get length (in wchar_t's) of resulting UTF-16 string
82  //
83  const int utf16Length = ::MultiByteToWideChar(
84  CP_UTF8, // convert from UTF-8
85  conversionFlags, // flags
86  utf8.data(), // source UTF-8 string
87  static_cast<int>(
88  utf8.length()), // length (in chars) of source UTF-8 string
89  nullptr, // unused - no conversion done in this step
90  static_cast<int>(0) // request size of destination buffer, in wchar_t's
91  );
92  if (utf16Length == 0) {
93  // Error
94  DWORD error = ::GetLastError();
95 
97  (error == ERROR_NO_UNICODE_TRANSLATION)
98  ? "Invalid UTF-8 sequence found in input string."
99  : "Can't get length of UTF-16 string (MultiByteToWideChar "
100  "failed).",
102  }
103 
104  //
105  // Allocate destination buffer for UTF-16 string
106  //
107  std::wstring utf16;
108  utf16.resize(utf16Length);
109 
110  //
111  // Do the conversion from UTF-8 to UTF-16
112  //
113  if (!::MultiByteToWideChar(
114  CP_UTF8, // convert from UTF-8
115  0, // validation was done in previous call,
116  // so speed up things with default flags
117  utf8.data(), // source UTF-8 string
118  static_cast<int>(
119  utf8.length()), // length (in chars) of source UTF-8 string
120  &utf16[0], // destination buffer
121  static_cast<int>(
122  utf16.length()) // size of destination buffer, in wchar_t's
123  )) {
124  // Error
125  DWORD error = ::GetLastError();
126  throw utf8_conversion_error(
127  "Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar "
128  "failed).",
130  }
131 
132  //
133  // Return resulting UTF-16 string
134  //
135  return utf16;
136 }
137 
138 inline std::wstring UTF16FromUTF8(const char* utf8)
139 {
140  //
141  // Special case of empty input string
142  //
143  if (utf8 == nullptr || *utf8 == '\0') return std::wstring();
144 
145  // Prefetch the length of the input UTF-8 string
146  const int utf8Length = static_cast<int>(strlen(utf8));
147 
148  // Fail if an invalid input character is encountered
149  const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
150 
151  //
152  // Get length (in wchar_t's) of resulting UTF-16 string
153  //
154  const int utf16Length = ::MultiByteToWideChar(
155  CP_UTF8, // convert from UTF-8
156  conversionFlags, // flags
157  utf8, // source UTF-8 string
158  utf8Length, // length (in chars) of source UTF-8 string
159  nullptr, // unused - no conversion done in this step
160  0 // request size of destination buffer, in wchar_t's
161  );
162  if (utf16Length == 0) {
163  // Error
164  DWORD error = ::GetLastError();
165  throw utf8_conversion_error(
166  (error == ERROR_NO_UNICODE_TRANSLATION)
167  ? "Invalid UTF-8 sequence found in input string."
168  : "Can't get length of UTF-16 string (MultiByteToWideChar "
169  "failed).",
171  }
172 
173  //
174  // Allocate destination buffer for UTF-16 string
175  //
176  std::wstring utf16;
177  utf16.resize(utf16Length);
178 
179  //
180  // Do the conversion from UTF-8 to UTF-16
181  //
182  if (!::MultiByteToWideChar(
183  CP_UTF8, // convert from UTF-8
184  0, // validation was done in previous call,
185  // so speed up things with default flags
186  utf8, // source UTF-8 string
187  static_cast<int>(
188  utf8Length), // length (in chars) of source UTF-8 string
189  &utf16[0], // destination buffer
190  static_cast<int>(
191  utf16.length()) // size of destination buffer, in wchar_t's
192  )) {
193  // Error
194  DWORD error = ::GetLastError();
195  throw utf8_conversion_error(
196  "Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar "
197  "failed).",
199  }
200 
201  //
202  // Return resulting UTF-16 string
203  //
204  return utf16;
205 }
206 
207 inline std::string UTF8FromUTF16(const std::wstring& utf16)
208 {
209  //
210  // Special case of empty input string
211  //
212  if (utf16.empty()) return std::string();
213 
214  //
215  // Get length (in chars) of resulting UTF-8 string
216  //
217  const int utf8Length = ::WideCharToMultiByte(
218  CP_UTF8, // convert to UTF-8
219  0, // default flags
220  utf16.data(), // source UTF-16 string
221  static_cast<int>(utf16.length()), // source string length, in wchar_t's,
222  nullptr, // unused - no conversion required in this step
223  static_cast<int>(0), // request buffer size
224  nullptr, nullptr // unused
225  );
226  if (utf8Length == 0) {
227  // Error
228  DWORD error = ::GetLastError();
229  throw utf8_conversion_error(
230  "Can't get length of UTF-8 string (WideCharToMultiByte failed).",
232  }
233 
234  //
235  // Allocate destination buffer for UTF-8 string
236  //
237  std::string utf8;
238  utf8.resize(utf8Length);
239 
240  //
241  // Do the conversion from UTF-16 to UTF-8
242  //
243  if (!::WideCharToMultiByte(
244  CP_UTF8, // convert to UTF-8
245  0, // default flags
246  utf16.data(), // source UTF-16 string
247  static_cast<int>(utf16.length()), // source string length, in
248  // wchar_t's,
249  &utf8[0], // destination buffer
250  static_cast<int>(utf8.length()), // destination buffer size, in
251  // chars
252  nullptr, nullptr // unused
253  )) {
254  // Error
255  DWORD error = ::GetLastError();
256  throw utf8_conversion_error(
257  "Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte "
258  "failed).",
260  }
261 
262  //
263  // Return resulting UTF-8 string
264  //
265  return utf8;
266 }
267 
268 inline std::string UTF8FromUTF16(const wchar_t* utf16)
269 {
270  //
271  // Special case of empty input string
272  //
273  if (utf16 == nullptr || *utf16 == L'\0') return std::string();
274 
275  // Prefetch the length of the input UTF-16 string
276  const int utf16Length = static_cast<int>(wcslen(utf16));
277 
278  //
279  // Get length (in chars) of resulting UTF-8 string
280  //
281  const int utf8Length = ::WideCharToMultiByte(
282  CP_UTF8, // convert to UTF-8
283  0, // default flags
284  utf16, // source UTF-16 string
285  utf16Length, // source string length, in wchar_t's,
286  nullptr, // unused - no conversion required in this step
287  0, // request buffer size
288  nullptr, nullptr // unused
289  );
290  if (utf8Length == 0) {
291  // Error
292  DWORD error = ::GetLastError();
293  throw utf8_conversion_error(
294  "Can't get length of UTF-8 string (WideCharToMultiByte failed).",
296  }
297 
298  //
299  // Allocate destination buffer for UTF-8 string
300  //
301  std::string utf8;
302  utf8.resize(utf8Length);
303 
304  //
305  // Do the conversion from UTF-16 to UTF-8
306  //
307  if (!::WideCharToMultiByte(
308  CP_UTF8, // convert to UTF-8
309  0, // default flags
310  utf16, // source UTF-16 string
311  static_cast<int>(utf16Length), // source string length, in
312  // wchar_t's,
313  &utf8[0], // destination buffer
314  static_cast<int>(utf8.length()), // destination buffer size, in
315  // chars
316  nullptr, nullptr // unused
317  )) {
318  // Error
319  DWORD error = ::GetLastError();
320  throw utf8_conversion_error(
321  "Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte "
322  "failed).",
324  }
325 
326  //
327  // Return resulting UTF-8 string
328  //
329  return utf8;
330 }
331 
332 } // namespace utf8util
333 
conversion_type conversion() const
utf8_conversion_error(const char *message, conversion_type conversion, error_code_type error_code)
EXPORT std::string UTF8FromUTF16(const std::wstring &utf16)
EXPORT std::wstring UTF16FromUTF8(const std::string &utf8)
error_code_type error_code() const