diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-08-24 17:50:00 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-08-24 17:50:00 +0000 |
commit | 767a9021b3ca60080fdeb8302559d06d2646f99a (patch) | |
tree | f085045db6619c2a2420f249434b04828514dd7e /src/backend/utils/adt/oracle_compat.c | |
parent | a0a0bc02b72e6ad4f50470050da7f0c1147e697a (diff) | |
download | postgresql-767a9021b3ca60080fdeb8302559d06d2646f99a.tar.gz postgresql-767a9021b3ca60080fdeb8302559d06d2646f99a.zip |
Add small hack to support use of Unicode-based locales on WIN32. This
is not adequately tested yet, but let's get it into beta1 so it can be
tested. Magnus Hagander and Tom Lane.
Diffstat (limited to 'src/backend/utils/adt/oracle_compat.c')
-rw-r--r-- | src/backend/utils/adt/oracle_compat.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index d0d1fc5fecf..5dd9a44ccf8 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.60 2005/05/07 15:18:17 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.61 2005/08/24 17:50:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -149,6 +149,117 @@ wcstotext(const wchar_t *str, int ncodes) #endif /* USE_WIDE_UPPER_LOWER */ +/* + * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding. + * To make use of the upper/lower functionality, we need to map UTF8 to + * UTF16, which for some reason mbstowcs and wcstombs won't do for us. + * This conversion layer takes care of it. + */ + +#ifdef WIN32 + +/* texttowcs for the case of UTF8 to UTF16 */ +static wchar_t * +win32_utf8_texttowcs(const text *txt) +{ + int nbytes = VARSIZE(txt) - VARHDRSZ; + wchar_t *result; + int r; + + /* Overflow paranoia */ + if (nbytes < 0 || + nbytes > (int) (INT_MAX / sizeof(wchar_t)) -1) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + /* Output workspace cannot have more codes than input bytes */ + result = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t)); + + /* stupid Microsloth API does not work for zero-length input */ + if (nbytes == 0) + r = 0; + else + { + /* Do the conversion */ + r = MultiByteToWideChar(CP_UTF8, 0, VARDATA(txt), nbytes, + result, nbytes); + + if (!r) /* assume it's NO_UNICODE_TRANSLATION */ + { + /* see notes above about error reporting */ + pg_verifymbstr(VARDATA(txt), nbytes, false); + ereport(ERROR, + (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), + errmsg("invalid multibyte character for locale"), + errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding."))); + } + } + + Assert(r <= nbytes); + result[r] = 0; + + return result; +} + +/* wcstotext for the case of UTF16 to UTF8 */ +static text * +win32_utf8_wcstotext(const wchar_t *str) +{ + text *result; + int nbytes; + int r; + + nbytes = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); + if (nbytes == 0) /* shouldn't happen */ + ereport(ERROR, + (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), + errmsg("UTF16 to UTF8 translation failed: %lu", + GetLastError()))); + + result = palloc(nbytes+VARHDRSZ); + + r = WideCharToMultiByte(CP_UTF8, 0, str, -1, VARDATA(result), nbytes, + NULL, NULL); + if (r == 0) /* shouldn't happen */ + ereport(ERROR, + (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), + errmsg("UTF16 to UTF8 translation failed: %lu", + GetLastError()))); + + VARATT_SIZEP(result) = nbytes + VARHDRSZ - 1; /* -1 to ignore null */ + + return result; +} + +/* interface layer to check which encoding is in use */ + +static wchar_t * +win32_texttowcs(const text *txt) +{ + if (GetDatabaseEncoding() == PG_UTF8) + return win32_utf8_texttowcs(txt); + else + return texttowcs(txt); +} + +static text * +win32_wcstotext(const wchar_t *str, int ncodes) +{ + if (GetDatabaseEncoding() == PG_UTF8) + return win32_utf8_wcstotext(str); + else + return wcstotext(str, ncodes); +} + +/* use macros to cause routines below to call interface layer */ + +#define texttowcs win32_texttowcs +#define wcstotext win32_wcstotext + +#endif /* WIN32 */ + + /******************************************************************** * * lower |