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
97template<
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*);
133template<
typename charT>
134IconvStringConverter<charT>::IconvStringConverter(
const std::string& internalCode) :
135 _internalCode(internalCode)
142 close(createDescriptors());
146 throw Ice::IconvInitializationException(__FILE__, __LINE__, sce.
reason());
153 int rs = pthread_key_create(&_key,
reinterpret_cast<IcePthreadKeyDestructor
>(&cleanupKey));
155 int rs = pthread_key_create(&_key, &cleanupKey);
160 throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, rs);
164template<
typename charT>
165IconvStringConverter<charT>::~IconvStringConverter()
167 void* val = pthread_getspecific(_key);
172 if(pthread_key_delete(_key) != 0)
178template<
typename charT> std::pair<iconv_t, iconv_t>
179IconvStringConverter<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;
204template<
typename charT> std::pair<iconv_t, iconv_t>
205IconvStringConverter<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));
218 throw IceUtil::ThreadSyscallException(__FILE__, __LINE__, rs);
224template<
typename charT>
void
225IconvStringConverter<charT>::cleanupKey(
void* val)
227 std::pair<iconv_t, iconv_t>* cdp =
static_cast<std::pair<iconv_t, iconv_t>*
>(val);
233template<
typename charT>
void
234IconvStringConverter<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);
249IconvStringConverter<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);
293template<
typename charT>
void
294IconvStringConverter<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)));
360template<
typename charT>
364 std::string internalCode = internalCodeWithDefault;
366 if(internalCode.empty())
368 internalCode = nl_langinfo(CODESET);
371 return ICE_MAKE_SHARED(IceInternal::IconvStringConverter<charT>, internalCode);
#define ICE_MAKE_SHARED(T,...)
Definition Config.h:376
#define ICE_HANDLE
Definition Config.h:373
#define ICE_API
Definition Config.h:197
A StringConverter converts narrow or wide-strings to and from UTF-8 byte sequences.
Definition StringConverter.h:50
Helper template for the implementation of Ice::Exception.
Definition Exception.h:161
std::string reason() const
Provides the reason this exception was thrown.
virtual Byte * getMoreBytes(size_t howMany, Byte *firstUnused)=0
Obtains more bytes.
virtual void ice_print(std::ostream &str) const
Prints a description of this exception to the given stream.
IconvInitializationException(const char *file, int line, const std::string &reason)
Constructs the exception with a reason.
virtual IconvInitializationException * ice_clone() const
Polymorphically clones this exception.
std::string reason() const
Obtains the reason for the failure.
virtual ~IconvInitializationException()
virtual std::string ice_id() const
Obtains the Slice type ID of this exception.
Definition BuiltinSequences.h:113
IceUtil::IllegalConversionException IllegalConversionException
Indicates an error occurred during string conversion.
Definition StringConverter.h:27
unsigned char Byte
The mapping for the Slice byte type.
Definition Config.h:50
IceUtil::UTF8Buffer UTF8Buffer
Encapsulates bytes in the UTF-8 encoding.
Definition StringConverter.h:16
::IceUtil::Handle< IceUtil::BasicStringConverter< charT > > createIconvStringConverter(const std::string &internalCodeWithDefault="")
Creates a string converter for the given code.
Definition IconvStringConverter.h:362