diff options
Diffstat (limited to 'src/backend/utils/adt/oracle_compat.c')
-rw-r--r-- | src/backend/utils/adt/oracle_compat.c | 366 |
1 files changed, 214 insertions, 152 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index 48453c4ad6b..54730ded796 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -2,26 +2,30 @@ * oracle_compat.c * Oracle compatible functions. * - * Copyright (c) 1996-2001, PostgreSQL Global Development Group + * Copyright (c) 1996-2003, 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.43 2002/09/04 20:31:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.44 2003/05/23 22:33:20 tgl Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include <ctype.h> #include "utils/builtins.h" - #include "mb/pg_wchar.h" + +static text *dotrim(const char *string, int stringlen, + const char *set, int setlen, + bool doltrim, bool dortrim); + + /******************************************************************** * * lower @@ -349,86 +353,192 @@ btrim(PG_FUNCTION_ARGS) text *string = PG_GETARG_TEXT_P(0); text *set = PG_GETARG_TEXT_P(1); text *ret; - char *ptr, - *end, - *ptr2, - *end2; - int m; - char **mp; - int mplen; - char *p; - int mblen; - int len; + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + VARDATA(set), VARSIZE(set) - VARHDRSZ, + true, true); - if ((m = VARSIZE(string) - VARHDRSZ) <= 0 || - (VARSIZE(set) - VARHDRSZ) <= 0) - PG_RETURN_TEXT_P(string); + PG_RETURN_TEXT_P(ret); +} - ptr = VARDATA(string); +/******************************************************************** + * + * btrim1 --- btrim with set fixed as ' ' + * + ********************************************************************/ - len = m; - mp = (char **) palloc(len * sizeof(char *)); - p = ptr; - mplen = 0; +Datum +btrim1(PG_FUNCTION_ARGS) +{ + text *string = PG_GETARG_TEXT_P(0); + text *ret; - /* build the mb pointer array */ - while (len > 0) - { - mp[mplen++] = p; - mblen = pg_mblen(p); - p += mblen; - len -= mblen; - } - mplen--; - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + " ", 1, + true, true); - while (m > 0) - { - int str_len = pg_mblen(ptr); + PG_RETURN_TEXT_P(ret); +} - ptr2 = VARDATA(set); - while (ptr2 <= end2) +/* + * Common implementation for btrim, ltrim, rtrim + */ +static text * +dotrim(const char *string, int stringlen, + const char *set, int setlen, + bool doltrim, bool dortrim) +{ + text *result; + int i; + + /* Nothing to do if either string or set is empty */ + if (stringlen > 0 && setlen > 0) + { + if (pg_database_encoding_max_length() > 1) { - int set_len = pg_mblen(ptr2); + /* + * In the multibyte-encoding case, build arrays of pointers to + * character starts, so that we can avoid inefficient checks in + * the inner loops. + */ + const char **stringchars; + const char **setchars; + int *stringmblen; + int *setmblen; + int stringnchars; + int setnchars; + int resultndx; + int resultnchars; + const char *p; + int len; + int mblen; + const char *str_pos; + int str_len; + + stringchars = (const char **) palloc(stringlen * sizeof(char *)); + stringmblen = (int *) palloc(stringlen * sizeof(int)); + stringnchars = 0; + p = string; + len = stringlen; + while (len > 0) + { + stringchars[stringnchars] = p; + stringmblen[stringnchars] = mblen = pg_mblen(p); + stringnchars++; + p += mblen; + len -= mblen; + } - if (str_len == set_len && - memcmp(ptr, ptr2, str_len) == 0) - break; - ptr2 += set_len; - } - if (ptr2 > end2) - break; - ptr += str_len; - m -= str_len; - } + setchars = (const char **) palloc(setlen * sizeof(char *)); + setmblen = (int *) palloc(setlen * sizeof(int)); + setnchars = 0; + p = set; + len = setlen; + while (len > 0) + { + setchars[setnchars] = p; + setmblen[setnchars] = mblen = pg_mblen(p); + setnchars++; + p += mblen; + len -= mblen; + } - while (m > 0) - { - int str_len; + resultndx = 0; /* index in stringchars[] */ + resultnchars = stringnchars; - end = mp[mplen--]; - str_len = pg_mblen(end); - ptr2 = VARDATA(set); - while (ptr2 <= end2) + if (doltrim) + { + while (resultnchars > 0) + { + str_pos = stringchars[resultndx]; + str_len = stringmblen[resultndx]; + for (i = 0; i < setnchars; i++) + { + if (str_len == setmblen[i] && + memcmp(str_pos, setchars[i], str_len) == 0) + break; + } + if (i >= setnchars) + break; /* no match here */ + string += str_len; + stringlen -= str_len; + resultndx++; + resultnchars--; + } + } + + if (dortrim) + { + while (resultnchars > 0) + { + str_pos = stringchars[resultndx + resultnchars - 1]; + str_len = stringmblen[resultndx + resultnchars - 1]; + for (i = 0; i < setnchars; i++) + { + if (str_len == setmblen[i] && + memcmp(str_pos, setchars[i], str_len) == 0) + break; + } + if (i >= setnchars) + break; /* no match here */ + stringlen -= str_len; + resultnchars--; + } + } + + pfree(stringchars); + pfree(stringmblen); + pfree(setchars); + pfree(setmblen); + } + else { - int set_len = pg_mblen(ptr2); + /* + * In the single-byte-encoding case, we don't need such overhead. + */ + if (doltrim) + { + while (stringlen > 0) + { + char str_ch = *string; + + for (i = 0; i < setlen; i++) + { + if (str_ch == set[i]) + break; + } + if (i >= setlen) + break; /* no match here */ + string++; + stringlen--; + } + } - if (str_len == set_len && - memcmp(end, ptr2, str_len) == 0) - break; - ptr2 += set_len; + if (dortrim) + { + while (stringlen > 0) + { + char str_ch = string[stringlen - 1]; + + for (i = 0; i < setlen; i++) + { + if (str_ch == set[i]) + break; + } + if (i >= setlen) + break; /* no match here */ + stringlen--; + } + } } - if (ptr2 > end2) - break; - m -= str_len; } - pfree(mp); - ret = (text *) palloc(VARHDRSZ + m); - VARATT_SIZEP(ret) = VARHDRSZ + m; - memcpy(VARDATA(ret), ptr, m); - PG_RETURN_TEXT_P(ret); + /* Return selected portion of string */ + result = (text *) palloc(VARHDRSZ + stringlen); + VARATT_SIZEP(result) = VARHDRSZ + stringlen; + memcpy(VARDATA(result), string, stringlen); + + return result; } /******************************************************************** @@ -525,45 +635,33 @@ ltrim(PG_FUNCTION_ARGS) text *string = PG_GETARG_TEXT_P(0); text *set = PG_GETARG_TEXT_P(1); text *ret; - char *ptr, - *ptr2, - *end2; - int m; - if ((m = VARSIZE(string) - VARHDRSZ) <= 0 || - (VARSIZE(set) - VARHDRSZ) <= 0) - PG_RETURN_TEXT_P(string); + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + VARDATA(set), VARSIZE(set) - VARHDRSZ, + true, false); - ptr = VARDATA(string); - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + PG_RETURN_TEXT_P(ret); +} - while (m > 0) - { - int str_len = pg_mblen(ptr); +/******************************************************************** + * + * ltrim1 --- ltrim with set fixed as ' ' + * + ********************************************************************/ - ptr2 = VARDATA(set); - while (ptr2 <= end2) - { - int set_len = pg_mblen(ptr2); +Datum +ltrim1(PG_FUNCTION_ARGS) +{ + text *string = PG_GETARG_TEXT_P(0); + text *ret; - if (str_len == set_len && - memcmp(ptr, ptr2, str_len) == 0) - break; - ptr2 += set_len; - } - if (ptr2 > end2) - break; - ptr += str_len; - m -= str_len; - } - ret = (text *) palloc(VARHDRSZ + m); - VARATT_SIZEP(ret) = VARHDRSZ + m; - memcpy(VARDATA(ret), ptr, m); + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + " ", 1, + true, false); PG_RETURN_TEXT_P(ret); } - /******************************************************************** * * rtrim @@ -586,64 +684,28 @@ rtrim(PG_FUNCTION_ARGS) text *set = PG_GETARG_TEXT_P(1); text *ret; - char *ptr, - *end, - *ptr2, - *end2; - int m; - - char **mp; - int mplen; - char *p; - int mblen; - int len; - - if ((m = VARSIZE(string) - VARHDRSZ) <= 0 || - (VARSIZE(set) - VARHDRSZ) <= 0) - PG_RETURN_TEXT_P(string); - - ptr = VARDATA(string); + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + VARDATA(set), VARSIZE(set) - VARHDRSZ, + false, true); - len = m; - mp = (char **) palloc(len * sizeof(char *)); - p = ptr; - mplen = 0; - - /* build the mb pointer array */ - while (len > 0) - { - mp[mplen++] = p; - mblen = pg_mblen(p); - p += mblen; - len -= mblen; - } - mplen--; - end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1; + PG_RETURN_TEXT_P(ret); +} - while (m > 0) - { - int str_len; +/******************************************************************** + * + * rtrim1 --- rtrim with set fixed as ' ' + * + ********************************************************************/ - end = mp[mplen--]; - str_len = pg_mblen(end); - ptr2 = VARDATA(set); - while (ptr2 <= end2) - { - int set_len = pg_mblen(ptr2); +Datum +rtrim1(PG_FUNCTION_ARGS) +{ + text *string = PG_GETARG_TEXT_P(0); + text *ret; - if (str_len == set_len && - memcmp(end, ptr2, str_len) == 0) - break; - ptr2 += set_len; - } - if (ptr2 > end2) - break; - m -= str_len; - } - pfree(mp); - ret = (text *) palloc(VARHDRSZ + m); - VARATT_SIZEP(ret) = VARHDRSZ + m; - memcpy(VARDATA(ret), ptr, m); + ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ, + " ", 1, + false, true); PG_RETURN_TEXT_P(ret); } |