From: <ale...@us...> - 2012-03-16 17:08:35
|
Revision: 54184 http://firebird.svn.sourceforge.net/firebird/?rev=54184&view=rev Author: alexpeshkoff Date: 2012-03-16 17:08:24 +0000 (Fri, 16 Mar 2012) Log Message: ----------- System to UTF8 conversion on non-Windows systems Modified Paths: -------------- firebird/trunk/configure.in firebird/trunk/src/common/isc_file.cpp Modified: firebird/trunk/configure.in =================================================================== --- firebird/trunk/configure.in 2012-03-16 17:05:56 UTC (rev 54183) +++ firebird/trunk/configure.in 2012-03-16 17:08:24 UTC (rev 54184) @@ -674,6 +674,8 @@ AC_CHECK_HEADERS(atomic.h) AC_CHECK_HEADERS(atomic_ops.h) AC_CHECK_HEADERS(poll.h) +AC_CHECK_HEADERS(langinfo.h) +AC_CHECK_HEADERS(iconv.h) dnl check for ICU presence AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package)) Modified: firebird/trunk/src/common/isc_file.cpp =================================================================== --- firebird/trunk/src/common/isc_file.cpp 2012-03-16 17:05:56 UTC (rev 54183) +++ firebird/trunk/src/common/isc_file.cpp 2012-03-16 17:08:24 UTC (rev 54184) @@ -78,6 +78,12 @@ #ifdef HAVE_SYS_MOUNT_H #include <sys/mount.h> #endif +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif +#ifdef HAVE_ICONV_H +#include <iconv.h> +#endif #include "../common/config/config.h" @@ -1644,14 +1650,89 @@ } #endif // WIN_NT +#ifdef HAVE_ICONV_H +namespace { +class IConv +{ +public: + IConv(MemoryPool& p) + : toBuf(p) + { +#ifdef HAVE_LANGINFO_H + string systemCharmap = nl_langinfo(CODESET); +#else + string systemCharmap; + if (!fb_utils::readenv("LC_CTYPE", systemCharmap)) + { + systemCharmap = "ANSI_X3.4-1968"; // ascii + } +#endif + const char* utfCharmap = "UTF-8"; + + toUtf = openIconv(utfCharmap, systemCharmap.c_str()); + toSystem = openIconv(systemCharmap.c_str(), utfCharmap); + } + + void systemToUtf8(AbstractString& str) + { + convert(str, toUtf); + } + + void utf8ToSystem(AbstractString& str) + { + convert(str, toSystem); + } + +private: + iconv_t toUtf, toSystem; + Mutex mtx; + Array<char> toBuf; + + iconv_t openIconv(const char *tocode, const char *fromcode) + { + toUtf = iconv_open(tocode, fromcode); + if (toUtf == (iconv_t) -1) + { + (Arg::Gds(isc_random) << "Error opening conversion descriptor" << + Arg::Unix(errno)).raise(); + // adding text "from @1 to @2" is good idea + } + } + + void convert(AbstractString& str, iconv_t id) + { + MutexLockGuard g(mtx); + + const size_t outlength = str.length() * 4; + size_t outsize = outlength; + char* outbuf = toBuf.getBuffer(outsize); + size_t insize = str.length(); + char* inbuf = str.begin(); + if (iconv(id, &inbuf, &insize, &outbuf, &outsize) == (size_t) -1) + { + (Arg::Gds(isc_bad_conn_str) << + Arg::Gds(isc_transliteration_failed) << + Arg::Unix(errno)).raise(); + } + + outsize = outlength - outsize; + memcpy(str.getBuffer(outsize), toBuf.begin(), outsize); + } +}; + +InitInstance<IConv> iConv; + +} +#endif // HAVE_ICONV_H + // Converts a string from the system charset to UTF-8. void ISC_systemToUtf8(Firebird::AbstractString& str) { if (str.isEmpty()) return; -#ifdef WIN_NT +#if defined(WIN_NT) WCHAR utf16Buffer[MAX_PATH]; int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), utf16Buffer, sizeof(utf16Buffer) / sizeof(WCHAR)); @@ -1667,6 +1748,8 @@ status_exception::raise(Arg::Gds(isc_bad_conn_str) << Arg::Gds(isc_transliteration_failed)); memcpy(str.getBuffer(len), utf8Buffer, len); +#elif defined(HAVE_ICONV_H) + iConv().systemToUtf8(str); #endif } @@ -1677,7 +1760,7 @@ if (str.isEmpty()) return; -#ifdef WIN_NT +#if defined(WIN_NT) WCHAR utf16Buffer[MAX_PATH]; int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), utf16Buffer, sizeof(utf16Buffer) / sizeof(WCHAR)); @@ -1694,6 +1777,8 @@ status_exception::raise(Arg::Gds(isc_bad_conn_str) << Arg::Gds(isc_transliteration_failed)); memcpy(str.getBuffer(len), ansiBuffer, len); +#elif defined(HAVE_ICONV_H) + iConv().utf8ToSystem(str); #endif } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |