aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/oracle_compat.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-08-24 17:50:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-08-24 17:50:00 +0000
commit767a9021b3ca60080fdeb8302559d06d2646f99a (patch)
treef085045db6619c2a2420f249434b04828514dd7e /src/backend/utils/adt/oracle_compat.c
parenta0a0bc02b72e6ad4f50470050da7f0c1147e697a (diff)
downloadpostgresql-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.c113
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