5 #ifndef ICE_ICONV_STRING_CONVERTER
6 #define ICE_ICONV_STRING_CONVERTER
24 #if (defined(__APPLE__) && _LIBICONV_VERSION < 0x010B)
28 # define ICE_CONST_ICONV_INBUF 1
50 #ifndef ICE_CPP11_COMPILER
66 #ifndef ICE_CPP11_MAPPING
97 template<
typename charT>
102 IconvStringConverter(
const std::string&);
104 virtual ~IconvStringConverter();
108 virtual void fromUTF8(
const Ice::Byte*,
const Ice::Byte*, std::basic_string<charT>&)
const;
112 std::pair<iconv_t, iconv_t> createDescriptors()
const;
113 std::pair<iconv_t, iconv_t> getDescriptors()
const;
115 static void cleanupKey(
void*);
116 static void close(std::pair<iconv_t, iconv_t>);
118 mutable pthread_key_t _key;
119 const std::string _internalCode;
129 typedef void (*IcePthreadKeyDestructor)(
void*);
133 template<
typename charT>
134 IconvStringConverter<charT>::IconvStringConverter(
const std::string& internalCode) :
135 _internalCode(internalCode)
142 close(createDescriptors());
153 int rs = pthread_key_create(&_key,
reinterpret_cast<IcePthreadKeyDestructor
>(&cleanupKey));
155 int rs = pthread_key_create(&_key, &cleanupKey);
164 template<
typename charT>
165 IconvStringConverter<charT>::~IconvStringConverter()
167 void* val = pthread_getspecific(_key);
172 if(pthread_key_delete(_key) != 0)
178 template<
typename charT> std::pair<iconv_t, iconv_t>
179 IconvStringConverter<charT>::createDescriptors()
const
181 std::pair<iconv_t, iconv_t> cdp;
183 const char* externalCode =
"UTF-8";
185 cdp.first = iconv_open(_internalCode.c_str(), externalCode);
186 if(cdp.first == iconv_t(-1))
188 std::ostringstream os;
189 os <<
"iconv cannot convert from " << externalCode <<
" to " << _internalCode;
193 cdp.second = iconv_open(externalCode, _internalCode.c_str());
194 if(cdp.second == iconv_t(-1))
196 iconv_close(cdp.first);
197 std::ostringstream os;
198 os <<
"iconv cannot convert from " << _internalCode <<
" to " << externalCode;
204 template<
typename charT> std::pair<iconv_t, iconv_t>
205 IconvStringConverter<charT>::getDescriptors()
const
207 void* val = pthread_getspecific(_key);
210 return *
static_cast<std::pair<iconv_t, iconv_t>*
>(val);
214 std::pair<iconv_t, iconv_t> cdp = createDescriptors();
215 int rs = pthread_setspecific(_key,
new std::pair<iconv_t, iconv_t>(cdp));
224 template<
typename charT>
void
225 IconvStringConverter<charT>::cleanupKey(
void* val)
227 std::pair<iconv_t, iconv_t>* cdp =
static_cast<std::pair<iconv_t, iconv_t>*
>(val);
233 template<
typename charT>
void
234 IconvStringConverter<charT>::close(std::pair<iconv_t, iconv_t> cdp)
237 int rs = iconv_close(cdp.first);
240 rs = iconv_close(cdp.second);
243 iconv_close(cdp.first);
244 iconv_close(cdp.second);
249 IconvStringConverter<charT>::toUTF8(
const charT* sourceStart,
250 const charT* sourceEnd,
253 iconv_t cd = getDescriptors().second;
259 iconv(cd, 0, 0, 0, 0);
261 size_t rs = iconv(cd, 0, 0, 0, 0);
265 #ifdef ICE_CONST_ICONV_INBUF
266 const char* inbuf =
reinterpret_cast<const char*
>(sourceStart);
268 char* inbuf =
reinterpret_cast<char*
>(
const_cast<charT*
>(sourceStart));
270 size_t inbytesleft =
static_cast<size_t>(sourceEnd - sourceStart) *
sizeof(charT);
279 size_t howMany = std::max(inbytesleft,
size_t(4));
280 outbuf =
reinterpret_cast<char*
>(buf.
getMoreBytes(howMany,
282 count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &howMany);
283 }
while(count ==
size_t(-1) && errno == E2BIG);
285 if(count ==
size_t(-1))
288 errno == 0 ?
"Unknown error" : IceUtilInternal::errorToString(errno));
290 return reinterpret_cast<Ice::Byte*
>(outbuf);
293 template<
typename charT>
void
294 IconvStringConverter<charT>::fromUTF8(
const Ice::Byte* sourceStart,
const Ice::Byte* sourceEnd,
295 std::basic_string<charT>& target)
const
297 iconv_t cd = getDescriptors().first;
303 iconv(cd, 0, 0, 0, 0);
305 size_t rs = iconv(cd, 0, 0, 0, 0);
309 #ifdef ICE_CONST_ICONV_INBUF
310 const char* inbuf =
reinterpret_cast<const char*
>(sourceStart);
312 char* inbuf =
reinterpret_cast<char*
>(
const_cast<Ice::Byte*
>(sourceStart));
314 assert(sourceEnd > sourceStart);
315 size_t inbytesleft =
static_cast<size_t>(sourceEnd - sourceStart);
318 size_t outbytesleft = 0;
326 size_t bytesused = 0;
329 bytesused =
static_cast<size_t>(outbuf -
reinterpret_cast<const char*
>(target.data()));
332 const size_t increment = std::max<size_t>(inbytesleft, 4);
333 target.resize(target.size() + increment);
334 outbuf =
const_cast<char*
>(
reinterpret_cast<const char*
>(target.data())) + bytesused;
335 outbytesleft += increment *
sizeof(charT);
337 count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
339 }
while(count ==
size_t(-1) && errno == E2BIG);
341 if(count ==
size_t(-1))
344 errno == 0 ?
"Unknown error" : IceUtilInternal::errorToString(errno));
347 target.resize(target.size() - (outbytesleft /
sizeof(charT)));
360 template<
typename charT>
361 ICE_HANDLE<IceUtil::BasicStringConverter<charT> >
364 std::string internalCode = internalCodeWithDefault;
366 if(internalCode.empty())
368 internalCode = nl_langinfo(CODESET);
371 return ICE_MAKE_SHARED(IceInternal::IconvStringConverter<charT>, internalCode);