@ -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 ) ;
}