Move wchar2char() and char2wchar() from tsearch into /mb to be easier to
authorBruce Momjian <bruce@momjian.us>
Wed, 18 Jun 2008 18:42:54 +0000 (18:42 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 18 Jun 2008 18:42:54 +0000 (18:42 +0000)
use for other modules;  also move pnstrdup().

Clean up code slightly.

src/backend/tsearch/ts_locale.c
src/backend/tsearch/ts_utils.c
src/backend/utils/mb/mbutils.c
src/backend/utils/mmgr/mcxt.c
src/include/mb/pg_wchar.h
src/include/tsearch/ts_locale.h
src/include/tsearch/ts_public.h
src/include/utils/palloc.h

index 7ed6522e7a1c0ea685ef30cff4da939c50169984..7937d85196b6ba3454a2b08f1876a3f7b29cfeb5 100644 (file)
 #include "tsearch/ts_locale.h"
 #include "tsearch/ts_public.h"
 
-
 #ifdef USE_WIDE_UPPER_LOWER
 
-/*
- * wchar2char --- convert wide characters to multibyte format
- *
- * This has the same API as the standard wcstombs() function; in particular,
- * tolen is the maximum number of bytes to store at *to, and *from must be
- * zero-terminated.  The output will be zero-terminated iff there is room.
- */
-size_t
-wchar2char(char *to, const wchar_t *from, size_t tolen)
-{
-       if (tolen == 0)
-               return 0;
-
-#ifdef WIN32
-       if (GetDatabaseEncoding() == PG_UTF8)
-       {
-               int                     r;
-
-               r = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
-                                                               NULL, NULL);
-
-               if (r <= 0)
-                       return (size_t) -1;
-
-               Assert(r <= tolen);
-
-               /* Microsoft counts the zero terminator in the result */
-               return r - 1;
-       }
-#endif   /* WIN32 */
-
-       return wcstombs(to, from, tolen);
-}
-
-/*
- * char2wchar --- convert multibyte characters to wide characters
- *
- * This has almost the API of mbstowcs(), except that *from need not be
- * null-terminated; instead, the number of input bytes is specified as
- * fromlen.  Also, we ereport() rather than returning -1 for invalid
- * input encoding.     tolen is the maximum number of wchar_t's to store at *to.
- * The output will be zero-terminated iff there is room.
- */
-size_t
-char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen)
-{
-       if (tolen == 0)
-               return 0;
-
-#ifdef WIN32
-       if (GetDatabaseEncoding() == PG_UTF8)
-       {
-               int                     r;
-
-               /* stupid Microsloth API does not work for zero-length input */
-               if (fromlen == 0)
-                       r = 0;
-               else
-               {
-                       r = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
-
-                       if (r <= 0)
-                       {
-                               /* see notes in oracle_compat.c about error reporting */
-                               pg_verifymbstr(from, fromlen, 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 < tolen);
-               to[r] = 0;
-
-               return r;
-       }
-#endif   /* WIN32 */
-
-       if (lc_ctype_is_c())
-       {
-               /*
-                * pg_mb2wchar_with_len always adds trailing '\0', so 'to' should be
-                * allocated with sufficient space
-                */
-               return pg_mb2wchar_with_len(from, (pg_wchar *) to, fromlen);
-       }
-       else
-       {
-               /*
-                * mbstowcs requires ending '\0'
-                */
-               char       *str = pnstrdup(from, fromlen);
-               size_t          result;
-
-               result = mbstowcs(to, str, tolen);
-
-               pfree(str);
-
-               if (result == (size_t) -1)
-               {
-                       pg_verifymbstr(from, fromlen, 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.")));
-               }
-
-               if (result < tolen)
-                       to[result] = 0;
-
-               return result;
-       }
-}
-
-
 int
 t_isdigit(const char *ptr)
 {
index f15a013679ef3424c0c5f04061b09b7b319bdc1a..8dc28a6f645cc96d9887ae3a30752240ae77f8ca 100644 (file)
@@ -153,13 +153,3 @@ searchstoplist(StopList *s, char *key)
                        bsearch(&key, s->stop, s->len,
                                        sizeof(char *), comparestr)) ? true : false;
 }
-
-char *
-pnstrdup(const char *in, int len)
-{
-       char       *out = palloc(len + 1);
-
-       memcpy(out, in, len);
-       out[len] = '\0';
-       return out;
-}
index 96335393251f09d6bcaa408f2c9bfbd28bb0ebad..cf07467e7a8c3b093d64ea984ff7440c9d2da262 100644 (file)
@@ -555,6 +555,134 @@ perform_default_encoding_conversion(const char *src, int len, bool is_client_to_
        return result;
 }
 
+
+
+#ifdef USE_WIDE_UPPER_LOWER
+
+/*
+ * wchar2char --- convert wide characters to multibyte format
+ *
+ * This has the same API as the standard wcstombs() function; in particular,
+ * tolen is the maximum number of bytes to store at *to, and *from must be
+ * zero-terminated.  The output will be zero-terminated iff there is room.
+ */
+size_t
+wchar2char(char *to, const wchar_t *from, size_t tolen)
+{
+       size_t result;
+       
+       if (tolen == 0)
+               return 0;
+
+#ifdef WIN32
+       /*
+        * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding,
+        * and for some reason mbstowcs and wcstombs won't do this for us,
+        * so we use MultiByteToWideChar().
+        */
+       if (GetDatabaseEncoding() == PG_UTF8)
+       {
+               result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
+                                                               NULL, NULL);
+               /* A zero return is failure */
+               if (result <= 0)
+                       result = -1;
+               else
+               {
+                       Assert(result <= tolen);
+                       /* Microsoft counts the zero terminator in the result */
+                       result--;
+               }
+       }
+       else
+#endif   /* WIN32 */
+               result = wcstombs(to, from, tolen);
+       return result;
+}
+
+/*
+ * char2wchar --- convert multibyte characters to wide characters
+ *
+ * This has almost the API of mbstowcs(), except that *from need not be
+ * null-terminated; instead, the number of input bytes is specified as
+ * fromlen.  Also, we ereport() rather than returning -1 for invalid
+ * input encoding.     tolen is the maximum number of wchar_t's to store at *to.
+ * The output will be zero-terminated iff there is room.
+ */
+size_t
+char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen)
+{
+       size_t          result;
+
+       if (tolen == 0)
+               return 0;
+
+#ifdef WIN32
+       /* See WIN32 "Unicode" comment above */
+       if (GetDatabaseEncoding() == PG_UTF8)
+       {
+               /* Win32 API does not work for zero-length input */
+               if (fromlen == 0)
+                       result = 0;
+               else
+               {
+                       result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
+                       /* A zero return is failure */
+                       if (result == 0)
+                               result = -1;
+               }
+
+               if (result != -1)
+               {
+                       Assert(result < tolen);
+                       /* Append trailing null wchar (MultiByteToWideChar() does not) */
+                       to[result] = 0;
+               }
+       }
+       else
+#endif   /* WIN32 */
+       {
+               if (lc_ctype_is_c())
+               {
+                       /*
+                        * pg_mb2wchar_with_len always adds trailing '\0', so 'to' should be
+                        * allocated with sufficient space
+                        */
+                       result = pg_mb2wchar_with_len(from, (pg_wchar *) to, fromlen);
+               }
+               else
+               {
+                       /* mbstowcs requires ending '\0' */
+                       char       *str = pnstrdup(from, fromlen);
+
+                       result = mbstowcs(to, str, tolen);
+                       pfree(str);
+               }
+       }
+
+       if (result == -1)
+       {
+               /*
+                * Invalid multibyte character encountered.  We try to give a useful
+                * error message by letting pg_verifymbstr check the string.  But it's
+                * possible that the string is OK to us, and not OK to mbstowcs ---
+                * this suggests that the LC_CTYPE locale is different from the
+                * database encoding.  Give a generic error message if verifymbstr
+                * can't find anything wrong.
+                */
+               pg_verifymbstr(from, fromlen, false);   /* might not return */
+               /* but if it does ... */
+               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.")));
+       }       
+
+       return result;
+}
+
+#endif
+
 /* convert a multibyte string to a wchar */
 int
 pg_mb2wchar(const char *from, pg_wchar *to)
index 0d06f72e6787a3fe89653959543d1758d455a10e..42aa4f3d12708417032b1b6097cd1f33c1393095 100644 (file)
@@ -624,6 +624,18 @@ repalloc(void *pointer, Size size)
                                                                                                 pointer, size);
 }
 
+/* Like pstrdup(), but append null byte */
+char *
+pnstrdup(const char *in, int len)
+{
+       char       *out = palloc(len + 1);
+
+       memcpy(out, in, len);
+       out[len] = '\0';
+       return out;
+}
+
+
 /*
  * MemoryContextSwitchTo
  *             Returns the current context; installs the given context.
index cc867f9f0c5d02a0fceb2a4a2f5fbf10e8df8f09..b0a091195402b76c3eedbfa348e4f34854f08c0f 100644 (file)
@@ -362,6 +362,11 @@ extern int pg_mbcharcliplen(const char *mbstr, int len, int imit);
 extern int     pg_encoding_max_length(int encoding);
 extern int     pg_database_encoding_max_length(void);
 
+#ifdef USE_WIDE_UPPER_LOWER
+extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen);
+extern size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen);
+#endif
+
 extern void SetDefaultClientEncoding(void);
 extern int     SetClientEncoding(int encoding, bool doit);
 extern void InitializeClientEncoding(void);
index 2beb3a5f926b15373ac34fed40b40b14a59a25c9..4f91d2c96cc20c57a7cb4b153f077dbf165c0452 100644 (file)
@@ -33,9 +33,6 @@
 
 #ifdef USE_WIDE_UPPER_LOWER
 
-extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen);
-extern size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen);
-
 extern int     t_isdigit(const char *ptr);
 extern int     t_isspace(const char *ptr);
 extern int     t_isalpha(const char *ptr);
index 1f738223f7fa76521766fbf5b18353a5a9f54613..9c0edca45390b132a987df55bb2d8eefbb22d9ad 100644 (file)
@@ -62,8 +62,6 @@ typedef struct
 extern char *get_tsearch_config_filename(const char *basename,
                                                        const char *extension);
 
-extern char *pnstrdup(const char *in, int len);
-
 /*
  * Often useful stopword list management
  */
index 89f05fb32f461866f7d8c2587ec7e3b3ab69451a..f981ae99be4941b6900463b0dd4378decb88813e 100644 (file)
@@ -70,6 +70,8 @@ extern void pfree(void *pointer);
 
 extern void *repalloc(void *pointer, Size size);
 
+extern char *pnstrdup(const char *in, int len);
+
 /*
  * MemoryContextSwitchTo can't be a macro in standard C compilers.
  * But we can make it an inline function when using GCC.