summaryrefslogtreecommitdiff
path: root/cpp/include/IceUtil
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/include/IceUtil')
-rw-r--r--cpp/include/IceUtil/Exception.h21
-rw-r--r--cpp/include/IceUtil/FileUtil.h1
-rw-r--r--cpp/include/IceUtil/IceUtil.h4
-rw-r--r--cpp/include/IceUtil/IconvStringConverter.h302
-rw-r--r--cpp/include/IceUtil/StringConverter.h193
-rw-r--r--cpp/include/IceUtil/UndefSysMacros.h42
-rw-r--r--cpp/include/IceUtil/Unicode.h7
7 files changed, 568 insertions, 2 deletions
diff --git a/cpp/include/IceUtil/Exception.h b/cpp/include/IceUtil/Exception.h
index 2709b64ee31..b3dca7824d5 100644
--- a/cpp/include/IceUtil/Exception.h
+++ b/cpp/include/IceUtil/Exception.h
@@ -135,6 +135,27 @@ private:
static const char* _name;
};
+#ifndef _WIN32
+class ICE_UTIL_API IconvInitializationException : public Exception
+{
+public:
+
+ IconvInitializationException(const char*, int, const std::string&);
+ virtual ~IconvInitializationException() throw();
+ virtual std::string ice_name() const;
+ virtual void ice_print(std::ostream&) const;
+ virtual IconvInitializationException* ice_clone() const;
+ virtual void ice_throw() const;
+
+ std::string reason() const;
+
+private:
+
+ static const char* _name;
+ std::string _reason;
+};
+#endif
+
}
#endif
diff --git a/cpp/include/IceUtil/FileUtil.h b/cpp/include/IceUtil/FileUtil.h
index 7cb2cd55407..7fabce927b9 100644
--- a/cpp/include/IceUtil/FileUtil.h
+++ b/cpp/include/IceUtil/FileUtil.h
@@ -70,6 +70,7 @@ ICE_UTIL_API int rmdir(const std::string&);
ICE_UTIL_API int mkdir(const std::string&, int);
ICE_UTIL_API FILE* fopen(const std::string&, const std::string&);
+ICE_UTIL_API FILE* freopen(const std::string&, const std::string&, FILE*);
ICE_UTIL_API int open(const std::string&, int);
#ifndef ICE_OS_WINRT
diff --git a/cpp/include/IceUtil/IceUtil.h b/cpp/include/IceUtil/IceUtil.h
index cba2207c079..b5e126a34c2 100644
--- a/cpp/include/IceUtil/IceUtil.h
+++ b/cpp/include/IceUtil/IceUtil.h
@@ -41,4 +41,8 @@
#include <IceUtil/Unicode.h>
#include <IceUtil/UniquePtr.h>
+#ifndef _WIN32
+# include <IceUtil/IconvStringConverter.h>
+#endif
+
#endif
diff --git a/cpp/include/IceUtil/IconvStringConverter.h b/cpp/include/IceUtil/IconvStringConverter.h
new file mode 100644
index 00000000000..e6bef3c6d82
--- /dev/null
+++ b/cpp/include/IceUtil/IconvStringConverter.h
@@ -0,0 +1,302 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_UTIL_ICONV_STRING_CONVERTER
+#define ICE_UTIL_ICONV_STRING_CONVERTER
+
+#include <IceUtil/StringConverter.h>
+#include <IceUtil/UndefSysMacros.h>
+
+#include <algorithm>
+#include <iconv.h>
+#include <langinfo.h>
+#include <string.h> // For strerror
+
+#if (defined(__APPLE__) && _LIBICONV_VERSION < 0x010B) || defined(__FreeBSD__)
+ //
+ // See http://sourceware.org/bugzilla/show_bug.cgi?id=2962
+ //
+# define ICE_CONST_ICONV_INBUF 1
+#endif
+
+namespace IceUtil
+{
+
+//
+// Converts charT encoded with internalCode to and from UTF-8 byte sequences
+//
+// The implementation allocates a pair of iconv_t on each thread, to avoid
+// opening / closing iconv_t objects all the time.
+//
+//
+template<typename charT>
+class IconvStringConverter : public BasicStringConverter<charT>
+{
+public:
+
+ IconvStringConverter(const char* = nl_langinfo(CODESET));
+
+ virtual ~IconvStringConverter();
+
+ virtual Byte* toUTF8(const charT*, const charT*, UTF8Buffer&) const;
+
+ virtual void fromUTF8(const Byte*, const Byte*, std::basic_string<charT>&) const;
+
+private:
+
+ std::pair<iconv_t, iconv_t> createDescriptors() const;
+ std::pair<iconv_t, iconv_t> getDescriptors() const;
+
+ static void cleanupKey(void*);
+ static void close(std::pair<iconv_t, iconv_t>);
+
+ mutable pthread_key_t _key;
+ const std::string _internalCode;
+};
+
+//
+// Implementation
+//
+
+#ifdef __SUNPRO_CC
+extern "C"
+{
+ typedef void (*IcePthreadKeyDestructor)(void*);
+}
+#endif
+
+template<typename charT>
+IconvStringConverter<charT>::IconvStringConverter(const char* internalCode) :
+ _internalCode(internalCode)
+{
+ //
+ // Verify that iconv supports conversion to/from internalCode
+ //
+ try
+ {
+ close(createDescriptors());
+ }
+ catch(const IllegalConversionException& sce)
+ {
+ throw IconvInitializationException(__FILE__, __LINE__, sce.reason());
+ }
+
+ //
+ // Create thread-specific key
+ //
+#ifdef __SUNPRO_CC
+ int rs = pthread_key_create(&_key, reinterpret_cast<IcePthreadKeyDestructor>(&cleanupKey));
+#else
+ int rs = pthread_key_create(&_key, &cleanupKey);
+#endif
+
+ if(rs != 0)
+ {
+ throw ThreadSyscallException(__FILE__, __LINE__, rs);
+ }
+}
+
+template<typename charT>
+IconvStringConverter<charT>::~IconvStringConverter()
+{
+ void* val = pthread_getspecific(_key);
+ if(val != 0)
+ {
+ cleanupKey(val);
+ }
+ if(pthread_key_delete(_key) != 0)
+ {
+ assert(0);
+ }
+}
+
+template<typename charT> std::pair<iconv_t, iconv_t>
+IconvStringConverter<charT>::createDescriptors() const
+{
+ std::pair<iconv_t, iconv_t> cdp;
+
+ const char* externalCode = "UTF-8";
+
+ cdp.first = iconv_open(_internalCode.c_str(), externalCode);
+ if(cdp.first == iconv_t(-1))
+ {
+ std::ostringstream os;
+ os << "iconv cannot convert from " << externalCode << " to " << _internalCode;
+ throw IllegalConversionException(__FILE__, __LINE__, os.str());
+ }
+
+ cdp.second = iconv_open(externalCode, _internalCode.c_str());
+ if(cdp.second == iconv_t(-1))
+ {
+ iconv_close(cdp.first);
+ std::ostringstream os;
+ os << "iconv cannot convert from " << _internalCode << " to " << externalCode;
+ throw IllegalConversionException(__FILE__, __LINE__, os.str());
+ }
+ return cdp;
+}
+
+template<typename charT> std::pair<iconv_t, iconv_t>
+IconvStringConverter<charT>::getDescriptors() const
+{
+ void* val = pthread_getspecific(_key);
+ if(val != 0)
+ {
+ return *static_cast<std::pair<iconv_t, iconv_t>*>(val);
+ }
+ else
+ {
+ std::pair<iconv_t, iconv_t> cdp = createDescriptors();
+ int rs = pthread_setspecific(_key, new std::pair<iconv_t, iconv_t>(cdp));
+ if(rs != 0)
+ {
+ throw ThreadSyscallException(__FILE__, __LINE__, rs);
+ }
+ return cdp;
+ }
+}
+
+template<typename charT> /*static*/ void
+IconvStringConverter<charT>::cleanupKey(void* val)
+{
+ std::pair<iconv_t, iconv_t>* cdp = static_cast<std::pair<iconv_t, iconv_t>*>(val);
+
+ close(*cdp);
+ delete cdp;
+}
+
+template<typename charT> /*static*/ void
+IconvStringConverter<charT>::close(std::pair<iconv_t, iconv_t> cdp)
+{
+#ifndef NDEBUG
+ int rs = iconv_close(cdp.first);
+ assert(rs == 0);
+
+ rs = iconv_close(cdp.second);
+ assert(rs == 0);
+#else
+ iconv_close(cdp.first);
+ iconv_close(cdp.second);
+#endif
+}
+
+template<typename charT> Byte*
+IconvStringConverter<charT>::toUTF8(const charT* sourceStart, const charT* sourceEnd, UTF8Buffer& buf) const
+{
+ iconv_t cd = getDescriptors().second;
+
+ //
+ // Reset cd
+ //
+#ifdef NDEBUG
+ iconv(cd, 0, 0, 0, 0);
+#else
+ size_t rs = iconv(cd, 0, 0, 0, 0);
+ assert(rs == 0);
+#endif
+
+#ifdef ICE_CONST_ICONV_INBUF
+ const char* inbuf = reinterpret_cast<const char*>(sourceStart);
+#else
+ char* inbuf = reinterpret_cast<char*>(const_cast<charT*>(sourceStart));
+#endif
+ size_t inbytesleft = (sourceEnd - sourceStart) * sizeof(charT);
+ char* outbuf = 0;
+
+ size_t count = 0;
+ //
+ // Loop while we need more buffer space
+ //
+ do
+ {
+ size_t howMany = std::max(inbytesleft, size_t(4));
+ outbuf = reinterpret_cast<char*>(buf.getMoreBytes(howMany, reinterpret_cast<Byte*>(outbuf)));
+ count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &howMany);
+ } while(count == size_t(-1) && errno == E2BIG);
+
+ if(count == size_t(-1))
+ {
+ throw IllegalConversionException(__FILE__, __LINE__, errno != 0 ? strerror(errno) : "Unknown error");
+ }
+ return reinterpret_cast<Byte*>(outbuf);
+}
+
+template<typename charT> void
+IconvStringConverter<charT>::fromUTF8(const Byte* sourceStart, const Byte* sourceEnd,
+ std::basic_string<charT>& target) const
+{
+ iconv_t cd = getDescriptors().first;
+
+ //
+ // Reset cd
+ //
+#ifdef NDEBUG
+ iconv(cd, 0, 0, 0, 0);
+#else
+ size_t rs = iconv(cd, 0, 0, 0, 0);
+ assert(rs == 0);
+#endif
+
+#ifdef ICE_CONST_ICONV_INBUF
+ const char* inbuf = reinterpret_cast<const char*>(sourceStart);
+#else
+ char* inbuf = reinterpret_cast<char*>(const_cast<Byte*>(sourceStart));
+#endif
+ size_t inbytesleft = sourceEnd - sourceStart;
+
+ //
+ // Result buffer
+ //
+ char* buf = 0;
+ size_t bufsize = 0;
+
+ char* outbuf = 0;
+ size_t outbytesleft = 0;
+
+ size_t count = 0;
+
+ //
+ // Loop while we need more buffer space
+ //
+ do
+ {
+ size_t increment = std::max(inbytesleft * sizeof(wchar_t), size_t(8));
+ bufsize += increment;
+ char* newbuf = static_cast<char*>(realloc(buf, bufsize));
+
+ if(newbuf == 0)
+ {
+ free(buf);
+ throw IllegalConversionException(__FILE__, __LINE__, "Out of memory");
+ }
+
+ outbuf = newbuf + (outbuf - buf);
+ outbytesleft += increment;
+
+ buf = newbuf;
+
+ count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ } while(count == size_t(-1) && errno == E2BIG);
+
+ if(count == size_t(-1))
+ {
+ free(buf);
+ throw IllegalConversionException(__FILE__, __LINE__, errno != 0 ? strerror(errno) : "Unknown error");
+ }
+
+ size_t length = (bufsize - outbytesleft) / sizeof(charT);
+
+ std::basic_string<charT> result(reinterpret_cast<charT*>(buf), length);
+ target.swap(result);
+ free(buf);
+}
+
+}
+
+#endif
diff --git a/cpp/include/IceUtil/StringConverter.h b/cpp/include/IceUtil/StringConverter.h
new file mode 100644
index 00000000000..b3e8d62f2b7
--- /dev/null
+++ b/cpp/include/IceUtil/StringConverter.h
@@ -0,0 +1,193 @@
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_UTIL_STRING_CONVERTER_H
+#define ICE_UTIL_STRING_CONVERTER_H
+
+#include <IceUtil/Config.h>
+#include <IceUtil/Exception.h>
+#include <IceUtil/Shared.h>
+#include <IceUtil/Handle.h>
+#include <IceUtil/Unicode.h>
+
+#include <string>
+
+namespace IceUtil
+{
+
+//
+// Raised by string converters when an encoding converseion fails.
+//
+class ICE_UTIL_API IllegalConversionException : public ::IceUtil::Exception
+{
+public:
+
+ IllegalConversionException(const char*, int);
+ IllegalConversionException(const char*, int, const ::std::string&);
+ virtual ~IllegalConversionException() throw();
+
+ virtual ::std::string ice_name() const;
+ virtual void ice_print(::std::ostream&) const;
+ virtual IllegalConversionException* ice_clone() const;
+ virtual void ice_throw() const;
+
+ std::string reason() const;
+
+private:
+
+ std::string _reason;
+};
+
+//
+// Provides bytes to toUTF8. Raises MemoryLimitException when too many
+// bytes are requested.
+//
+class ICE_UTIL_API UTF8Buffer
+{
+public:
+ virtual Byte* getMoreBytes(size_t howMany, Byte* firstUnused) = 0;
+
+ virtual ~UTF8Buffer() {}
+};
+
+//
+// A StringConverter converts narrow or wide-strings to and from UTF-8 byte sequences.
+// It's used by the communicator during marshaling (toUTF8) and unmarshaling (fromUTF8).
+// It report errors by raising IllegalConversionException or MemoryLimitException.
+//
+template<typename charT>
+class BasicStringConverter : public IceUtil::Shared
+{
+public:
+ //
+ // Returns a pointer to byte after the last written byte (which may be
+ // past the last byte returned by getMoreBytes).
+ //
+ virtual Byte* toUTF8(const charT* sourceStart, const charT* sourceEnd,
+ UTF8Buffer&) const = 0;
+
+ //
+ // Unmarshals a UTF-8 sequence into a basic_string
+ //
+ virtual void fromUTF8(const Byte* sourceStart, const Byte* sourceEnd,
+ std::basic_string<charT>& target) const = 0;
+};
+
+typedef BasicStringConverter<char> StringConverter;
+typedef IceUtil::Handle<StringConverter> StringConverterPtr;
+
+typedef BasicStringConverter<wchar_t> WstringConverter;
+typedef IceUtil::Handle<WstringConverter> WstringConverterPtr;
+
+//
+// Converts to and from UTF-16 or UTF-32 depending on sizeof(wchar_t)
+//
+class ICE_UTIL_API UnicodeWstringConverter : public WstringConverter
+{
+public:
+
+ UnicodeWstringConverter(ConversionFlags = lenientConversion);
+
+ virtual Byte* toUTF8(const wchar_t*, const wchar_t*, UTF8Buffer&) const;
+
+ virtual void fromUTF8(const Byte*, const Byte*, std::wstring&) const;
+
+private:
+ const ConversionFlags _conversionFlags;
+};
+
+#ifdef _WIN32
+
+//
+// Converts to/from UTF-8 using MultiByteToWideChar and WideCharToMultiByte
+//
+class ICE_UTIL_API WindowsStringConverter : public StringConverter
+{
+public:
+
+ explicit WindowsStringConverter(unsigned int);
+
+ virtual Byte* toUTF8(const char*, const char*, UTF8Buffer&) const;
+
+ virtual void fromUTF8(const Byte*, const Byte*, std::string& target) const;
+
+private:
+ unsigned int _cp;
+ UnicodeWstringConverter _unicodeWstringConverter;
+};
+#endif
+
+//
+// Retrive the per process narrow string converter. Access to the
+// converter is protected by a static mutex.
+//
+ICE_UTIL_API StringConverterPtr getProcessStringConverter();
+
+//
+// Set the per process narrow string converter. Access to the
+// converter is protected by a static mutex.
+//
+ICE_UTIL_API void setProcessStringConverter(const StringConverterPtr&);
+
+//
+// Retrive the per process wide string converter. Access to the
+// converter is protected by a static mutex.
+//
+ICE_UTIL_API WstringConverterPtr getProcessWstringConverter();
+
+//
+// Set the per process wide string converter. Access to the
+// converter is protected by a static mutex.
+//
+ICE_UTIL_API void setProcessWstringConverter(const WstringConverterPtr&);
+
+//
+// Convert the given wide string from the native wide string encoding to a
+// narrow string with the native narrow string encoding.
+//
+// The StringConverter param can be null in that case the default narrow
+// string encoding is assumed to be UTF8.
+//
+// The WstringConverter param can be null in that case the default wide
+// string encoding is assumed, that would be UTF16 or UTF32 depending of
+// the platform.
+//
+ICE_UTIL_API std::string
+wnativeToNative(const StringConverterPtr&, const WstringConverterPtr&, const std::wstring&);
+
+//
+// Convert the given narrow string from the native narrow string encoding
+// to a wide string with the native wide string encoding.
+//
+// The StringConverter param can be null in that case the default narrow
+// string encoding is assumed to be UTF8.
+//
+// The WstringConverter param can be null in that case the default wide
+// string encoding is assumed, that would be UTF16 or UTF32 depending of
+// the platform.
+//
+ICE_UTIL_API std::wstring
+nativeToWnative(const StringConverterPtr&, const WstringConverterPtr&, const std::string&);
+
+//
+// Converts the given string from the native narrow string encoding to
+// UTF8 using the given converter. If the converter is null, returns
+// the given string.
+//
+ICE_UTIL_API std::string
+nativeToUTF8(const StringConverterPtr&, const std::string&);
+
+//
+// Converts the given string from UTF8 to the native narrow string
+// encoding using the given converter. If the converter is null,
+// returns the given string.
+//
+ICE_UTIL_API std::string
+UTF8ToNative(const StringConverterPtr&, const std::string&);
+
+}
+
+#endif
diff --git a/cpp/include/IceUtil/UndefSysMacros.h b/cpp/include/IceUtil/UndefSysMacros.h
new file mode 100644
index 00000000000..2dc931daf08
--- /dev/null
+++ b/cpp/include/IceUtil/UndefSysMacros.h
@@ -0,0 +1,42 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_UTIL_UNDEF_SYS_MACROS_H
+#define ICE_UTIL_UNDEF_SYS_MACROS_H
+
+//
+// This header includes macros that can end up being dragged into
+// the generated code from system headers, such as major() or NDEBUG.
+// If a Slice symbol has the same name as a macro, the generated
+// code most likely won't compile (but, depending how the macro is
+// defined, may even compile).
+//
+// Here, we undefine symbols that cause such problems.
+//
+// The #ifdef ... #endif protection is necessary to prevent
+// warnings on some platforms.
+//
+
+#ifdef major
+#undef major
+#endif
+
+#ifdef minor
+#undef minor
+#endif
+
+#ifdef min
+#undef min
+#endif
+
+#ifdef max
+#undef max
+#endif
+
+#endif
diff --git a/cpp/include/IceUtil/Unicode.h b/cpp/include/IceUtil/Unicode.h
index 40f002fa545..71a52b3e62f 100644
--- a/cpp/include/IceUtil/Unicode.h
+++ b/cpp/include/IceUtil/Unicode.h
@@ -22,8 +22,11 @@ enum ConversionFlags
lenientConversion
};
-ICE_UTIL_API std::string wstringToString(const std::wstring&, ConversionFlags = lenientConversion);
-ICE_UTIL_API std::wstring stringToWstring(const std::string&, ConversionFlags = lenientConversion);
+ICE_DEPRECATED_API std::string
+wstringToString(const std::wstring&, ConversionFlags = lenientConversion);
+
+ICE_DEPRECATED_API std::wstring
+stringToWstring(const std::string&, ConversionFlags = lenientConversion);
typedef unsigned char Byte;