2 * This file contains public functions for conversion between
3 * client encoding and server internal encoding.
4 * (currently mule internal code (mic) is used)
6 * $Id: mbutils.c,v 1.15 2001/02/10 02:31:27 tgl Exp $
10 #include "miscadmin.h"
11 #include "mb/pg_wchar.h"
12 #include "utils/builtins.h"
14 static int client_encoding = -1;
15 static void (*client_to_mic) ();/* something to MIC */
16 static void (*client_from_mic) (); /* MIC to something */
17 static void (*server_to_mic) ();/* something to MIC */
18 static void (*server_from_mic) (); /* MIC to something */
21 * find encoding table entry by encoding
23 pg_encoding_conv_tbl *
24 pg_get_enc_ent(int encoding)
26 pg_encoding_conv_tbl *p = pg_conv_tbl;
28 for (; p->encoding >= 0; p++)
30 if (p->encoding == encoding)
37 * set the client encoding. if encoding conversion between
38 * client/server encoding is not supported, returns -1
41 pg_set_client_encoding(int encoding)
43 int current_server_encoding = GetDatabaseEncoding();
45 client_encoding = encoding;
47 if (client_encoding == current_server_encoding)
48 { /* server == client? */
49 client_to_mic = client_from_mic = 0;
50 server_to_mic = server_from_mic = 0;
52 else if (current_server_encoding == MULE_INTERNAL)
53 { /* server == MULE_INETRNAL? */
54 client_to_mic = pg_get_enc_ent(encoding)->to_mic;
55 client_from_mic = pg_get_enc_ent(encoding)->from_mic;
56 server_to_mic = server_from_mic = 0;
57 if (client_to_mic == 0 || client_from_mic == 0)
60 else if (encoding == MULE_INTERNAL)
61 { /* client == MULE_INETRNAL? */
62 client_to_mic = client_from_mic = 0;
63 server_to_mic = pg_get_enc_ent(current_server_encoding)->to_mic;
64 server_from_mic = pg_get_enc_ent(current_server_encoding)->from_mic;
65 if (server_to_mic == 0 || server_from_mic == 0)
68 else if (current_server_encoding == UNICODE)
69 { /* server == UNICODE? */
70 client_to_mic = pg_get_enc_ent(encoding)->to_unicode;
71 client_from_mic = pg_get_enc_ent(encoding)->from_unicode;
72 server_to_mic = server_from_mic = 0;
73 if (client_to_mic == 0 || client_from_mic == 0)
76 else if (encoding == UNICODE)
77 { /* client == UNICODE? */
78 client_to_mic = client_from_mic = 0;
79 server_to_mic = pg_get_enc_ent(current_server_encoding)->to_unicode;
80 server_from_mic = pg_get_enc_ent(current_server_encoding)->from_unicode;
81 if (server_to_mic == 0 || server_from_mic == 0)
86 client_to_mic = pg_get_enc_ent(encoding)->to_mic;
87 client_from_mic = pg_get_enc_ent(encoding)->from_mic;
88 server_to_mic = pg_get_enc_ent(current_server_encoding)->to_mic;
89 server_from_mic = pg_get_enc_ent(current_server_encoding)->from_mic;
90 if (client_to_mic == 0 || client_from_mic == 0)
92 if (server_to_mic == 0 || server_from_mic == 0)
99 * returns the current client encoding
102 pg_get_client_encoding()
104 if (client_encoding == -1)
106 /* this is the first time */
107 client_encoding = GetDatabaseEncoding();
109 return (client_encoding);
113 * convert client encoding to server encoding.
115 * CASE 1: if no conversion is required, then the given pointer s is returned.
117 * CASE 2: if conversion is required, a palloc'd string is returned.
119 * Callers must check whether return value differs from passed value
120 * to determine whether to pfree the result or not!
122 * Note: we assume that conversion cannot cause more than a 4-to-1 growth
123 * in the length of the string --- is this enough?
126 pg_client_to_server(unsigned char *s, int len)
128 unsigned char *result = s;
131 if (client_encoding == GetDatabaseEncoding())
135 buf = (unsigned char *) palloc(len * 4 + 1);
136 (*client_to_mic) (result, buf, len);
138 len = strlen(result);
142 buf = (unsigned char *) palloc(len * 4 + 1);
143 (*server_from_mic) (result, buf, len);
145 pfree(result); /* release first buffer */
152 * convert server encoding to client encoding.
154 * CASE 1: if no conversion is required, then the given pointer s is returned.
156 * CASE 2: if conversion is required, a palloc'd string is returned.
158 * Callers must check whether return value differs from passed value
159 * to determine whether to pfree the result or not!
161 * Note: we assume that conversion cannot cause more than a 4-to-1 growth
162 * in the length of the string --- is this enough?
165 pg_server_to_client(unsigned char *s, int len)
167 unsigned char *result = s;
170 if (client_encoding == GetDatabaseEncoding())
174 buf = (unsigned char *) palloc(len * 4 + 1);
175 (*server_to_mic) (result, buf, len);
177 len = strlen(result);
181 buf = (unsigned char *) palloc(len * 4 + 1);
182 (*client_from_mic) (result, buf, len);
184 pfree(result); /* release first buffer */
190 /* convert a multi-byte string to a wchar */
192 pg_mb2wchar(const unsigned char *from, pg_wchar * to)
194 return (*pg_wchar_table[GetDatabaseEncoding()].mb2wchar_with_len) (from, to, strlen(from));
197 /* convert a multi-byte string to a wchar with a limited length */
199 pg_mb2wchar_with_len(const unsigned char *from, pg_wchar * to, int len)
201 return (*pg_wchar_table[GetDatabaseEncoding()].mb2wchar_with_len) (from, to, len);
204 /* returns the byte length of a multi-byte word */
206 pg_mblen(const unsigned char *mbstr)
208 return ((*pg_wchar_table[GetDatabaseEncoding()].mblen) (mbstr));
211 /* returns the length (counted as a wchar) of a multi-byte string */
213 pg_mbstrlen(const unsigned char *mbstr)
219 mbstr += pg_mblen(mbstr);
225 /* returns the length (counted as a wchar) of a multi-byte string
226 (not necessarily NULL terminated) */
228 pg_mbstrlen_with_len(const unsigned char *mbstr, int limit)
233 while (*mbstr && limit > 0)
244 * returns the length of a multi-byte string
245 * (not necessarily NULL terminated)
246 * that is not longer than limit.
247 * this function does not break multi-byte word boundary.
250 pg_mbcliplen(const unsigned char *mbstr, int len, int limit)
255 while (*mbstr && len > 0)
258 if ((clen + l) > limit)
270 * fuctions for utils/init
272 static int DatabaseEncoding = MULTIBYTE;
275 SetDatabaseEncoding(int encoding)
277 DatabaseEncoding = encoding;
281 GetDatabaseEncoding()
283 return (DatabaseEncoding);
286 /* for builtin-function */
288 getdatabaseencoding(PG_FUNCTION_ARGS)
290 PG_RETURN_NAME(pg_encoding_to_char(DatabaseEncoding));