Library of Assembled Shared Sources
wchar_support.cpp
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2011 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#include "lass_common.h"
44#include "wchar_support.h"
45#include <cstring>
46
47#if LASS_HAVE_MULTIBYTETOWIDECHAR
48# define WIN32_LEAN_AND_MEAN
49# define NOMINMAX
50# include <windows.h>
51# include "../num/num_cast.h"
52#endif
53
54#if LASS_HAVE_ICONV
55# include <iconv.h>
56# include <errno.h>
57# include "thread.h"
58#endif
59
60namespace lass
61{
62namespace util
63{
64
65#if LASS_HAVE_WCHAR_SUPPORT
66
67std::wstring utf8ToWchar(const std::string& utf8)
68{
69 std::wstring wide;
70 utf8ToWchar(utf8.data(), utf8.length(), wide);
71 return wide;
72}
73
74std::wstring utf8ToWchar(const char* utf8)
75{
76 std::wstring wide;
77 utf8ToWchar(utf8, ::strlen(utf8), wide);
78 return wide;
79}
80
81std::wstring utf8ToWchar(const char* utf8, size_t length)
82{
83 std::wstring wide;
84 utf8ToWchar(utf8, length, wide);
85 return wide;
86}
87
88std::string wcharToUtf8(const std::wstring& wide)
89{
90 std::string utf8;
91 wcharToUtf8(wide.data(), wide.length(), utf8);
92 return utf8;
93}
94
95std::string wcharToUtf8(const wchar_t* wide)
96{
97 std::string utf8;
98 wcharToUtf8(wide, ::wcslen(wide), utf8);
99 return utf8;
100}
101
102std::string wcharToUtf8(const wchar_t* wide, size_t length)
103{
104 std::string utf8;
105 wcharToUtf8(wide, length, utf8);
106 return utf8;
107}
108
109
110
111# if LASS_HAVE_MULTIBYTETOWIDECHAR
112
113LASS_META_ASSERT( sizeof(wchar_t) == sizeof(WCHAR), wchar_t_should_be_of_same_size_as_WCHAR );
114
115void utf8ToWchar(const char* utf8, size_t length, std::wstring &wide)
116{
117 if (!length)
118 {
119 wide.clear();
120 return;
121 }
122 const int utf8Length = num::numCast<int>(length);
123 const int wideLength = LASS_ENFORCE_WINAPI(MultiByteToWideChar(CP_UTF8, 0, utf8, utf8Length, 0, 0));
124 wide.resize(num::numCast<size_t>(wideLength));
125 LASS_ENFORCE_WINAPI(MultiByteToWideChar(CP_UTF8, 0, utf8, utf8Length, &wide[0], wideLength));
126}
127
128void wcharToUtf8(const wchar_t* wide, size_t length, std::string &utf8)
129{
130 if (!length)
131 {
132 utf8.clear();
133 return;
134 }
135 const int wideLength = num::numCast<int>(length);
136 const int utf8Length = LASS_ENFORCE_WINAPI(WideCharToMultiByte(CP_UTF8, 0, wide, wideLength, 0, 0, NULL, NULL));
137 utf8.resize(num::numCast<size_t>(utf8Length));
138 LASS_ENFORCE_WINAPI(WideCharToMultiByte(CP_UTF8, 0, wide, wideLength, &utf8[0], utf8Length, NULL, NULL));
139}
140
141# elif LASS_HAVE_ICONV
142
143namespace
144{
145 LASS_META_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, expects_wchar_t_to_be_16_or_32_bit);
146
147 class Converter
148 {
149 public:
150 Converter(const char* tocode, const char* fromcode)
151 {
152 handle_ = LASS_ENFORCE_CLIB_EX( iconv_open(tocode, fromcode), (iconv_t)-1 );
153 }
154 ~Converter()
155 {
156 iconv_close(handle_);
157 }
158 template <typename string_type>
159 void convert(const char* in, size_t inBytes, string_type &result)
160 {
161 typedef typename string_type::value_type char_type;
162 iconv(handle_, 0, 0, 0, 0); // reset
163 result.clear();
164
165# if LASS_HAVE_ICONV_CONST_CHAR
166 const char* pIn = in;
167# else
168 char* pIn = const_cast<char*>(in);
169# endif
170
171 while (inBytes)
172 {
173 char* pOut = buffer_;
174 size_t outLeft = bufsize_;
175
176 if (iconv(handle_, &pIn, &inBytes, &pOut, &outLeft) == (size_t)-1)
177 {
178 if (errno == E2BIG)
179 {
180 const size_t bytes = bufsize_ - outLeft;
181 LASS_ASSERT(bytes % sizeof(char_type) == 0);
182 result.append( reinterpret_cast<char_type*>( buffer_ ), bytes / sizeof(char_type) );
183 }
184 else
185 {
186 LASS_THROW("BLABLA");
187 }
188 }
189 else
190 {
191 const size_t bytes = bufsize_ - outLeft;
192 LASS_ASSERT(bytes % sizeof(char_type) == 0 && (bytes / sizeof(char_type)) > 0);
193 result.append( reinterpret_cast<char_type*>( buffer_ ), bytes / sizeof(char_type) - 1 );
194 }
195 }
196 }
197 private:
198 enum { bufsize_ = 1024 };
199 iconv_t handle_;
200 char buffer_[bufsize_];
201 };
202
203 typedef ThreadLocalPtr<Converter> TConverterPtr;
204
205 const char* wchar_encoding =
206# if LASS_HAVE_WCHAR_T == 2
207# if LASS_HAVE_BIG_ENDIAN
208 "UTF-16BE";
209# else
210 "UTF-16LE";
211# endif
212# elif LASS_HAVE_WCHAR_T == 4
213# if LASS_HAVE_BIG_ENDIAN
214 "UTF-32BE";
215# else
216 "UTF-32LE";
217# endif
218# else
219# error "[LASS BUILD MSG] unsupported wchar_t size"
220# endif
221}
222
223void utf8ToWchar(const char* utf8, size_t length, std::wstring &wide)
224{
225 static TConverterPtr converter;
226 if ( !converter )
227 {
228 std::unique_ptr<Converter> p(new Converter(wchar_encoding, "UTF-8"));
229 converter.reset(std::move(p));
230 }
231 converter->convert( utf8, length + 1, wide );
232}
233
234void wcharToUtf8(const wchar_t* wide, size_t length, std::string &utf8)
235{
236 static TConverterPtr converter;
237 if ( !converter )
238 {
239 std::unique_ptr<Converter> p(new Converter("UTF-8", wchar_encoding));
240 converter.reset(std::move(p));
241 }
242 converter->convert( reinterpret_cast<const char*>(wide), sizeof(wchar_t) * (length + 1), utf8 );
243}
244
245# else
246
247# pragma LASS_NOTE("no wchar_t support implemented, it will be unavailable.")
248
249# endif
250
251#endif
252
253}
254}
255
256// EOF
#define LASS_META_ASSERT(expression, message)
complite time static check
ColorRGBA in(const ColorRGBA &a, const ColorRGBA &b)
part of a inside b.
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Definition config.h:53