mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-04 04:06:49 +02:00
Make lpad/rpad/translate multibyte aware. Also add Copright notice etc.
This commit is contained in:
parent
be629abfc8
commit
bb2bf2d401
@ -1,8 +1,17 @@
|
|||||||
/*
|
/*-------------------------------------------------------------------------
|
||||||
* Edmund Mergl <E.Mergl@bawue.de>
|
* oracle_compat.c
|
||||||
|
* Oracle compatible functions.
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.34 2001/09/22 03:30:39 ishii Exp $
|
* Copyright (c) 1997-2001, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
|
* Author: Edmund Mergl <E.Mergl@bawue.de>
|
||||||
|
* Multibyte enhancement: Tatsuo Ishii <ishii@postgresql.org>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* IDENTIFICATION
|
||||||
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.35 2001/09/23 11:02:01 ishii Exp $
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
@ -162,6 +171,9 @@ lpad(PG_FUNCTION_ARGS)
|
|||||||
int m,
|
int m,
|
||||||
s1len,
|
s1len,
|
||||||
s2len;
|
s2len;
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
int bytelen;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Negative len is silently taken as zero */
|
/* Negative len is silently taken as zero */
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
@ -175,32 +187,62 @@ lpad(PG_FUNCTION_ARGS)
|
|||||||
if (s2len < 0)
|
if (s2len < 0)
|
||||||
s2len = 0; /* shouldn't happen */
|
s2len = 0; /* shouldn't happen */
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
s1len = pg_mbstrlen_with_len(VARDATA(string1),s1len);
|
||||||
|
#endif
|
||||||
if (s1len > len)
|
if (s1len > len)
|
||||||
s1len = len; /* truncate string1 to len chars */
|
s1len = len; /* truncate string1 to len chars */
|
||||||
|
|
||||||
if (s2len <= 0)
|
if (s2len <= 0)
|
||||||
len = s1len; /* nothing to pad with, so don't pad */
|
len = s1len; /* nothing to pad with, so don't pad */
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
bytelen = pg_database_encoding_max_length() * len;
|
||||||
|
ret = (text *) palloc(VARHDRSZ + bytelen);
|
||||||
|
VARATT_SIZEP(ret) = VARHDRSZ + bytelen;
|
||||||
|
#else
|
||||||
ret = (text *) palloc(VARHDRSZ + len);
|
ret = (text *) palloc(VARHDRSZ + len);
|
||||||
VARATT_SIZEP(ret) = VARHDRSZ + len;
|
VARATT_SIZEP(ret) = VARHDRSZ + len;
|
||||||
|
#endif
|
||||||
m = len - s1len;
|
m = len - s1len;
|
||||||
|
|
||||||
ptr2 = VARDATA(string2);
|
ptr2 = VARDATA(string2);
|
||||||
ptr2end = ptr2 + s2len;
|
ptr2end = ptr2 + s2len;
|
||||||
ptr_ret = VARDATA(ret);
|
ptr_ret = VARDATA(ret);
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
while (m--)
|
||||||
|
{
|
||||||
|
int mlen = pg_mblen(ptr2);
|
||||||
|
memcpy(ptr_ret, ptr2, mlen);
|
||||||
|
ptr_ret += mlen;
|
||||||
|
ptr2 += mlen;
|
||||||
|
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
||||||
|
ptr2 = VARDATA(string2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
while (m--)
|
while (m--)
|
||||||
{
|
{
|
||||||
*ptr_ret++ = *ptr2++;
|
*ptr_ret++ = *ptr2++;
|
||||||
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
||||||
ptr2 = VARDATA(string2);
|
ptr2 = VARDATA(string2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ptr1 = VARDATA(string1);
|
ptr1 = VARDATA(string1);
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
while (s1len--)
|
||||||
|
{
|
||||||
|
int mlen = pg_mblen(ptr1);
|
||||||
|
memcpy(ptr_ret, ptr1, mlen);
|
||||||
|
ptr_ret += mlen;
|
||||||
|
ptr1 += mlen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
while (s1len--)
|
while (s1len--)
|
||||||
*ptr_ret++ = *ptr1++;
|
*ptr_ret++ = *ptr1++;
|
||||||
|
#endif
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(ret);
|
PG_RETURN_TEXT_P(ret);
|
||||||
}
|
}
|
||||||
@ -236,6 +278,9 @@ rpad(PG_FUNCTION_ARGS)
|
|||||||
int m,
|
int m,
|
||||||
s1len,
|
s1len,
|
||||||
s2len;
|
s2len;
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
int bytelen;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Negative len is silently taken as zero */
|
/* Negative len is silently taken as zero */
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
@ -249,32 +294,63 @@ rpad(PG_FUNCTION_ARGS)
|
|||||||
if (s2len < 0)
|
if (s2len < 0)
|
||||||
s2len = 0; /* shouldn't happen */
|
s2len = 0; /* shouldn't happen */
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
s1len = pg_mbstrlen_with_len(VARDATA(string1),s1len);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s1len > len)
|
if (s1len > len)
|
||||||
s1len = len; /* truncate string1 to len chars */
|
s1len = len; /* truncate string1 to len chars */
|
||||||
|
|
||||||
if (s2len <= 0)
|
if (s2len <= 0)
|
||||||
len = s1len; /* nothing to pad with, so don't pad */
|
len = s1len; /* nothing to pad with, so don't pad */
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
bytelen = pg_database_encoding_max_length() * len;
|
||||||
|
ret = (text *) palloc(VARHDRSZ + bytelen);
|
||||||
|
VARATT_SIZEP(ret) = VARHDRSZ + bytelen;
|
||||||
|
#else
|
||||||
ret = (text *) palloc(VARHDRSZ + len);
|
ret = (text *) palloc(VARHDRSZ + len);
|
||||||
VARATT_SIZEP(ret) = VARHDRSZ + len;
|
VARATT_SIZEP(ret) = VARHDRSZ + len;
|
||||||
|
#endif
|
||||||
m = len - s1len;
|
m = len - s1len;
|
||||||
|
|
||||||
ptr1 = VARDATA(string1);
|
ptr1 = VARDATA(string1);
|
||||||
ptr_ret = VARDATA(ret);
|
ptr_ret = VARDATA(ret);
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
while (s1len--)
|
||||||
|
{
|
||||||
|
int mlen = pg_mblen(ptr1);
|
||||||
|
memcpy(ptr_ret, ptr1, mlen);
|
||||||
|
ptr_ret += mlen;
|
||||||
|
ptr1 += mlen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
while (s1len--)
|
while (s1len--)
|
||||||
*ptr_ret++ = *ptr1++;
|
*ptr_ret++ = *ptr1++;
|
||||||
|
#endif
|
||||||
|
|
||||||
ptr2 = VARDATA(string2);
|
ptr2 = VARDATA(string2);
|
||||||
ptr2end = ptr2 + s2len;
|
ptr2end = ptr2 + s2len;
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
while (m--)
|
||||||
|
{
|
||||||
|
int mlen = pg_mblen(ptr2);
|
||||||
|
memcpy(ptr_ret, ptr2, mlen);
|
||||||
|
ptr_ret += mlen;
|
||||||
|
ptr2 += mlen;
|
||||||
|
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
||||||
|
ptr2 = VARDATA(string2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
while (m--)
|
while (m--)
|
||||||
{
|
{
|
||||||
*ptr_ret++ = *ptr2++;
|
*ptr_ret++ = *ptr2++;
|
||||||
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
if (ptr2 == ptr2end) /* wrap around at end of s2 */
|
||||||
ptr2 = VARDATA(string2);
|
ptr2 = VARDATA(string2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(ret);
|
PG_RETURN_TEXT_P(ret);
|
||||||
}
|
}
|
||||||
@ -708,6 +784,13 @@ translate(PG_FUNCTION_ARGS)
|
|||||||
tolen,
|
tolen,
|
||||||
retlen,
|
retlen,
|
||||||
i;
|
i;
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
int str_len;
|
||||||
|
int estimate_len;
|
||||||
|
int len;
|
||||||
|
int source_len;
|
||||||
|
int from_index;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((m = VARSIZE(string) - VARHDRSZ) <= 0)
|
if ((m = VARSIZE(string) - VARHDRSZ) <= 0)
|
||||||
PG_RETURN_TEXT_P(string);
|
PG_RETURN_TEXT_P(string);
|
||||||
@ -717,12 +800,65 @@ translate(PG_FUNCTION_ARGS)
|
|||||||
tolen = VARSIZE(to) - VARHDRSZ;
|
tolen = VARSIZE(to) - VARHDRSZ;
|
||||||
to_ptr = VARDATA(to);
|
to_ptr = VARDATA(to);
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
str_len = VARSIZE(string);
|
||||||
|
estimate_len = (tolen*1.0/fromlen + 0.5)*str_len;
|
||||||
|
estimate_len = estimate_len>str_len?estimate_len:str_len;
|
||||||
|
result = (text *) palloc(estimate_len);
|
||||||
|
#else
|
||||||
result = (text *) palloc(VARSIZE(string));
|
result = (text *) palloc(VARSIZE(string));
|
||||||
|
#endif
|
||||||
|
|
||||||
source = VARDATA(string);
|
source = VARDATA(string);
|
||||||
target = VARDATA(result);
|
target = VARDATA(result);
|
||||||
retlen = 0;
|
retlen = 0;
|
||||||
|
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
while (m > 0)
|
||||||
|
{
|
||||||
|
source_len = pg_mblen(source);
|
||||||
|
from_index = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < fromlen; i += len)
|
||||||
|
{
|
||||||
|
len = pg_mblen(&from_ptr[i]);
|
||||||
|
if (len == source_len &&
|
||||||
|
memcmp(source, &from_ptr[i], len) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
from_index++;
|
||||||
|
}
|
||||||
|
if (i < fromlen)
|
||||||
|
{
|
||||||
|
/* substitute */
|
||||||
|
char *p = to_ptr;
|
||||||
|
for (i=0;i<from_index;i++)
|
||||||
|
{
|
||||||
|
p += pg_mblen(p);
|
||||||
|
if (p >= (to_ptr + tolen))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p < (to_ptr + tolen))
|
||||||
|
{
|
||||||
|
len = pg_mblen(p);
|
||||||
|
memcpy(target, p, len);
|
||||||
|
target += len;
|
||||||
|
retlen += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no match, so copy */
|
||||||
|
memcpy(target, source, source_len);
|
||||||
|
target += source_len;
|
||||||
|
retlen += source_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
source += source_len;
|
||||||
|
m -= source_len;
|
||||||
|
}
|
||||||
|
#else
|
||||||
while (m-- > 0)
|
while (m-- > 0)
|
||||||
{
|
{
|
||||||
char rep = *source++;
|
char rep = *source++;
|
||||||
@ -752,6 +888,7 @@ translate(PG_FUNCTION_ARGS)
|
|||||||
retlen++;
|
retlen++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
VARATT_SIZEP(result) = retlen + VARHDRSZ;
|
VARATT_SIZEP(result) = retlen + VARHDRSZ;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user