88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.80 2001/06/09 23:21:55 petere Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.81 2001/07/15 11:07:37 ishii Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -73,33 +73,65 @@ bpcharin(PG_FUNCTION_ARGS)
7373char * r ;
7474size_t len ,maxlen ;
7575int i ;
76+ #ifdef MULTIBYTE
77+ int charlen ;/* number of charcters in the input string */
78+ #endif
7679
7780len = strlen (s );
81+ #ifdef MULTIBYTE
82+ charlen = pg_mbstrlen (s );
83+ #endif
7884
7985/* If typmod is -1 (or invalid), use the actual string length */
8086if (atttypmod < (int32 )VARHDRSZ )
87+ #ifdef MULTIBYTE
88+ maxlen = charlen ;
89+ #else
8190maxlen = len ;
91+ #endif
8292else
8393maxlen = atttypmod - VARHDRSZ ;
8494
95+ #ifdef MULTIBYTE
96+ if (charlen > maxlen )
97+ #else
8598if (len > maxlen )
99+ #endif
86100{
87101/* Verify that extra characters are spaces, and clip them off */
88102#ifdef MULTIBYTE
89- size_t mbmaxlen = pg_mbcliplen (s ,len ,maxlen );
90-
103+ size_t mbmaxlen = pg_mbcharcliplen (s ,len ,maxlen );
104+ /*
105+ * at this point, len is the actual BYTE length of the
106+ * input string, maxlen is the max number of
107+ * CHARACTERS allowed for this bpchar type.
108+ */
91109if (strspn (s + mbmaxlen ," " )== len - mbmaxlen )
92110len = mbmaxlen ;
93111else
94112elog (ERROR ,"value too long for type character(%d)" ,maxlen );
95- Assert (len <=maxlen );
113+ /*
114+ * XXX: at this point, maxlen is the necessary byte
115+ * length, not the number of CHARACTERS!
116+ */
117+ maxlen = len ;
96118#else
97119if (strspn (s + maxlen ," " )== len - maxlen )
98120len = maxlen ;
99121else
100122elog (ERROR ,"value too long for type character(%d)" ,maxlen );
101123#endif
102124}
125+ #ifdef MULTIBYTE
126+ else
127+ {
128+ /*
129+ * XXX: at this point, maxlen is the necessary byte
130+ * length, not the number of CHARACTERS!
131+ */
132+ maxlen = len + (maxlen - charlen );
133+ }
134+ #endif
103135
104136result = palloc (maxlen + VARHDRSZ );
105137VARATT_SIZEP (result )= maxlen + VARHDRSZ ;
@@ -158,19 +190,29 @@ bpchar(PG_FUNCTION_ARGS)
158190char * r ;
159191char * s ;
160192int i ;
193+ #ifdef MULTIBYTE
194+ int charlen ;/* number of charcters in the input string
195+ + VARHDRSZ*/
196+ #endif
161197
162198len = VARSIZE (source );
199+ #ifdef MULTIBYTE
200+ charlen = pg_mbstrlen_with_len (VARDATA (source ),len - VARHDRSZ )+ VARHDRSZ ;
201+ #endif
163202/* No work if typmod is invalid or supplied data matches it already */
164203if (maxlen < (int32 )VARHDRSZ || len == maxlen )
165204PG_RETURN_BPCHAR_P (source );
166-
205+ #ifdef MULTIBYTE
206+ if (charlen > maxlen )
207+ #else
167208if (len > maxlen )
209+ #endif
168210{
169211/* Verify that extra characters are spaces, and clip them off */
170212#ifdef MULTIBYTE
171213size_t maxmblen ;
172214
173- maxmblen = pg_mbcliplen (VARDATA (source ),len - VARHDRSZ ,
215+ maxmblen = pg_mbcharcliplen (VARDATA (source ),len - VARHDRSZ ,
174216maxlen - VARHDRSZ )+ VARHDRSZ ;
175217
176218for (i = maxmblen - VARHDRSZ ;i < len - VARHDRSZ ;i ++ )
@@ -179,7 +221,11 @@ bpchar(PG_FUNCTION_ARGS)
179221maxlen - VARHDRSZ );
180222
181223len = maxmblen ;
182- Assert (len <=maxlen );
224+ /*
225+ * XXX: at this point, maxlen is the necessary byte
226+ * length+VARHDRSZ, not the number of CHARACTERS!
227+ */
228+ maxlen = len ;
183229#else
184230for (i = maxlen - VARHDRSZ ;i < len - VARHDRSZ ;i ++ )
185231if (* (VARDATA (source )+ i )!= ' ' )
@@ -189,6 +235,16 @@ bpchar(PG_FUNCTION_ARGS)
189235len = maxlen ;
190236#endif
191237}
238+ #ifdef MULTIBYTE
239+ else
240+ {
241+ /*
242+ * XXX: at this point, maxlen is the necessary byte
243+ * length+VARHDRSZ, not the number of CHARACTERS!
244+ */
245+ maxlen = len + (maxlen - charlen );
246+ }
247+ #endif
192248
193249s = VARDATA (source );
194250
@@ -333,9 +389,12 @@ name_bpchar(PG_FUNCTION_ARGS)
333389 * Convert a C string to VARCHAR internal representation. atttypmod
334390 * is the declared length of the type plus VARHDRSZ.
335391 *
336- * If the C string is too long, raise an error, unless the extra
337- * characters are spaces, in which case they're truncated. (per SQL)
338- */
392+ * Note that if MULTIBYTE is enabled, atttypmod is regarded as the
393+ * number of characters, rather than number of bytes.
394+ *
395+ * If the C string is too long,
396+ * raise an error, unless the extra characters are spaces, in which
397+ * case they're truncated. (per SQL) */
339398Datum
340399varcharin (PG_FUNCTION_ARGS )
341400{
@@ -354,7 +413,7 @@ varcharin(PG_FUNCTION_ARGS)
354413{
355414/* Verify that extra characters are spaces, and clip them off */
356415#ifdef MULTIBYTE
357- size_t mbmaxlen = pg_mbcliplen (s ,len ,maxlen );
416+ size_t mbmaxlen = pg_mbcharcliplen (s ,len ,maxlen );
358417
359418if (strspn (s + mbmaxlen ," " )== len - mbmaxlen )
360419len = mbmaxlen ;
@@ -428,7 +487,7 @@ varchar(PG_FUNCTION_ARGS)
428487size_t maxmblen ;
429488
430489/* truncate multi-byte string preserving multi-byte boundary */
431- maxmblen = pg_mbcliplen (VARDATA (source ),len - VARHDRSZ ,
490+ maxmblen = pg_mbcharcliplen (VARDATA (source ),len - VARHDRSZ ,
432491maxlen - VARHDRSZ )+ VARHDRSZ ;
433492
434493for (i = maxmblen - VARHDRSZ ;i < len - VARHDRSZ ;i ++ )
@@ -515,22 +574,9 @@ bpcharlen(PG_FUNCTION_ARGS)
515574BpChar * arg = PG_GETARG_BPCHAR_P (0 );
516575
517576#ifdef MULTIBYTE
518- unsignedchar * s ;
519- int len ,
520- l ,
521- wl ;
522-
523- l = VARSIZE (arg )- VARHDRSZ ;
524- len = 0 ;
525- s = VARDATA (arg );
526- while (l > 0 )
527- {
528- wl = pg_mblen (s );
529- l -= wl ;
530- s += wl ;
531- len ++ ;
532- }
533- PG_RETURN_INT32 (len );
577+ PG_RETURN_INT32 (
578+ pg_mbstrlen_with_len (VARDATA (arg ),VARSIZE (arg )- VARHDRSZ )
579+ );
534580#else
535581PG_RETURN_INT32 (VARSIZE (arg )- VARHDRSZ );
536582#endif
@@ -736,22 +782,9 @@ varcharlen(PG_FUNCTION_ARGS)
736782VarChar * arg = PG_GETARG_VARCHAR_P (0 );
737783
738784#ifdef MULTIBYTE
739- unsignedchar * s ;
740- int len ,
741- l ,
742- wl ;
743-
744- len = 0 ;
745- s = VARDATA (arg );
746- l = VARSIZE (arg )- VARHDRSZ ;
747- while (l > 0 )
748- {
749- wl = pg_mblen (s );
750- l -= wl ;
751- s += wl ;
752- len ++ ;
753- }
754- PG_RETURN_INT32 (len );
785+ PG_RETURN_INT32 (
786+ pg_mbstrlen_with_len (VARDATA (arg ),VARSIZE (arg )- VARHDRSZ )
787+ );
755788#else
756789PG_RETURN_INT32 (VARSIZE (arg )- VARHDRSZ );
757790#endif