1- /*
2- *Edmund Mergl <E.Mergl@bawue.de>
1+ /*-------------------------------------------------------------------------
2+ * oracle_compat.c
3+ *Oracle compatible functions.
34 *
4- *$Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.34 2001/09/22 03:30:39 ishii Exp $
5+ * Copyright (c) 1997- 2001, PostgreSQL Global Development Group
56 *
7+ *Author: Edmund Mergl <E.Mergl@bawue.de>
8+ *Multibyte enhancement: Tatsuo Ishii <ishii@postgresql.org>
9+ *
10+ *
11+ * IDENTIFICATION
12+ *$Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.35 2001/09/23 11:02:01 ishii Exp $
13+ *
14+ *-------------------------------------------------------------------------
615 */
716
817#include "postgres.h"
@@ -162,6 +171,9 @@ lpad(PG_FUNCTION_ARGS)
162171int m ,
163172s1len ,
164173s2len ;
174+ #ifdef MULTIBYTE
175+ int bytelen ;
176+ #endif
165177
166178/* Negative len is silently taken as zero */
167179if (len < 0 )
@@ -175,32 +187,62 @@ lpad(PG_FUNCTION_ARGS)
175187if (s2len < 0 )
176188s2len = 0 ;/* shouldn't happen */
177189
190+ #ifdef MULTIBYTE
191+ s1len = pg_mbstrlen_with_len (VARDATA (string1 ),s1len );
192+ #endif
178193if (s1len > len )
179194s1len = len ;/* truncate string1 to len chars */
180195
181196if (s2len <=0 )
182197len = s1len ;/* nothing to pad with, so don't pad */
183198
199+ #ifdef MULTIBYTE
200+ bytelen = pg_database_encoding_max_length ()* len ;
201+ ret = (text * )palloc (VARHDRSZ + bytelen );
202+ VARATT_SIZEP (ret )= VARHDRSZ + bytelen ;
203+ #else
184204ret = (text * )palloc (VARHDRSZ + len );
185205VARATT_SIZEP (ret )= VARHDRSZ + len ;
186-
206+ #endif
187207m = len - s1len ;
188208
189209ptr2 = VARDATA (string2 );
190210ptr2end = ptr2 + s2len ;
191211ptr_ret = VARDATA (ret );
192212
213+ #ifdef MULTIBYTE
214+ while (m -- )
215+ {
216+ int mlen = pg_mblen (ptr2 );
217+ memcpy (ptr_ret ,ptr2 ,mlen );
218+ ptr_ret += mlen ;
219+ ptr2 += mlen ;
220+ if (ptr2 == ptr2end )/* wrap around at end of s2 */
221+ ptr2 = VARDATA (string2 );
222+ }
223+ #else
193224while (m -- )
194225{
195226* ptr_ret ++ = * ptr2 ++ ;
196227if (ptr2 == ptr2end )/* wrap around at end of s2 */
197228ptr2 = VARDATA (string2 );
198229}
230+ #endif
199231
200232ptr1 = VARDATA (string1 );
201233
234+ #ifdef MULTIBYTE
235+ while (s1len -- )
236+ {
237+ int mlen = pg_mblen (ptr1 );
238+ memcpy (ptr_ret ,ptr1 ,mlen );
239+ ptr_ret += mlen ;
240+ ptr1 += mlen ;
241+ }
242+ #else
202243while (s1len -- )
203244* ptr_ret ++ = * ptr1 ++ ;
245+ #endif
204246
205247PG_RETURN_TEXT_P (ret );
206248}
@@ -236,6 +278,9 @@ rpad(PG_FUNCTION_ARGS)
236278int m ,
237279s1len ,
238280s2len ;
281+ #ifdef MULTIBYTE
282+ int bytelen ;
283+ #endif
239284
240285/* Negative len is silently taken as zero */
241286if (len < 0 )
@@ -249,32 +294,63 @@ rpad(PG_FUNCTION_ARGS)
249294if (s2len < 0 )
250295s2len = 0 ;/* shouldn't happen */
251296
297+ #ifdef MULTIBYTE
298+ s1len = pg_mbstrlen_with_len (VARDATA (string1 ),s1len );
299+ #endif
300+
252301if (s1len > len )
253302s1len = len ;/* truncate string1 to len chars */
254303
255304if (s2len <=0 )
256305len = s1len ;/* nothing to pad with, so don't pad */
257306
307+ #ifdef MULTIBYTE
308+ bytelen = pg_database_encoding_max_length ()* len ;
309+ ret = (text * )palloc (VARHDRSZ + bytelen );
310+ VARATT_SIZEP (ret )= VARHDRSZ + bytelen ;
311+ #else
258312ret = (text * )palloc (VARHDRSZ + len );
259313VARATT_SIZEP (ret )= VARHDRSZ + len ;
260-
314+ #endif
261315m = len - s1len ;
262316
263317ptr1 = VARDATA (string1 );
264318ptr_ret = VARDATA (ret );
265319
320+ #ifdef MULTIBYTE
321+ while (s1len -- )
322+ {
323+ int mlen = pg_mblen (ptr1 );
324+ memcpy (ptr_ret ,ptr1 ,mlen );
325+ ptr_ret += mlen ;
326+ ptr1 += mlen ;
327+ }
328+ #else
266329while (s1len -- )
267330* ptr_ret ++ = * ptr1 ++ ;
331+ #endif
268332
269333ptr2 = VARDATA (string2 );
270334ptr2end = ptr2 + s2len ;
271335
336+ #ifdef MULTIBYTE
337+ while (m -- )
338+ {
339+ int mlen = pg_mblen (ptr2 );
340+ memcpy (ptr_ret ,ptr2 ,mlen );
341+ ptr_ret += mlen ;
342+ ptr2 += mlen ;
343+ if (ptr2 == ptr2end )/* wrap around at end of s2 */
344+ ptr2 = VARDATA (string2 );
345+ }
346+ #else
272347while (m -- )
273348{
274349* ptr_ret ++ = * ptr2 ++ ;
275350if (ptr2 == ptr2end )/* wrap around at end of s2 */
276351ptr2 = VARDATA (string2 );
277352}
353+ #endif
278354
279355PG_RETURN_TEXT_P (ret );
280356}
@@ -708,6 +784,13 @@ translate(PG_FUNCTION_ARGS)
708784tolen ,
709785retlen ,
710786i ;
787+ #ifdef MULTIBYTE
788+ int str_len ;
789+ int estimate_len ;
790+ int len ;
791+ int source_len ;
792+ int from_index ;
793+ #endif
711794
712795if ((m = VARSIZE (string )- VARHDRSZ ) <=0 )
713796PG_RETURN_TEXT_P (string );
@@ -717,12 +800,65 @@ translate(PG_FUNCTION_ARGS)
717800tolen = VARSIZE (to )- VARHDRSZ ;
718801to_ptr = VARDATA (to );
719802
803+ #ifdef MULTIBYTE
804+ str_len = VARSIZE (string );
805+ estimate_len = (tolen * 1.0 /fromlen + 0.5 )* str_len ;
806+ estimate_len = estimate_len > str_len ?estimate_len :str_len ;
807+ result = (text * )palloc (estimate_len );
808+ #else
720809result = (text * )palloc (VARSIZE (string ));
810+ #endif
721811
722812source = VARDATA (string );
723813target = VARDATA (result );
724814retlen = 0 ;
725815
816+ #ifdef MULTIBYTE
817+ while (m > 0 )
818+ {
819+ source_len = pg_mblen (source );
820+ from_index = 0 ;
821+
822+ for (i = 0 ;i < fromlen ;i += len )
823+ {
824+ len = pg_mblen (& from_ptr [i ]);
825+ if (len == source_len &&
826+ memcmp (source ,& from_ptr [i ],len )== 0 )
827+ break ;
828+
829+ from_index ++ ;
830+ }
831+ if (i < fromlen )
832+ {
833+ /* substitute */
834+ char * p = to_ptr ;
835+ for (i = 0 ;i < from_index ;i ++ )
836+ {
837+ p += pg_mblen (p );
838+ if (p >= (to_ptr + tolen ))
839+ break ;
840+ }
841+ if (p < (to_ptr + tolen ))
842+ {
843+ len = pg_mblen (p );
844+ memcpy (target ,p ,len );
845+ target += len ;
846+ retlen += len ;
847+ }
848+
849+ }
850+ else
851+ {
852+ /* no match, so copy */
853+ memcpy (target ,source ,source_len );
854+ target += source_len ;
855+ retlen += source_len ;
856+ }
857+
858+ source += source_len ;
859+ m -= source_len ;
860+ }
861+ #else
726862while (m -- > 0 )
727863{
728864char rep = * source ++ ;
@@ -752,6 +888,7 @@ translate(PG_FUNCTION_ARGS)
752888retlen ++ ;
753889}
754890}
891+ #endif
755892
756893VARATT_SIZEP (result )= retlen + VARHDRSZ ;
757894