greenplumn charpad 源码
greenplumn charpad 代码
文件路径:/gpcontrib/orafce/charpad.c
/*----------------------------------------------------------------------------
*
* charpad.c
* LPAD and RPAD SQL functions for PostgreSQL.
*
*----------------------------------------------------------------------------
*/
#include "postgres.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "mb/pg_wchar.h"
#include "fmgr.h"
#include "orafce.h"
#include "builtins.h"
/* flags */
#define ON true
#define OFF false
/* Upper limit on total width of the padded output of *pad functions */
#define PAD_MAX 4000
PG_FUNCTION_INFO_V1(orafce_lpad);
PG_FUNCTION_INFO_V1(orafce_rpad);
/*
* orafce_lpad(string text, length int32 [, fill text])
*
* Fill up the string to length 'length' by prepending
* the characters fill (a half-width space by default)
*/
Datum
orafce_lpad(PG_FUNCTION_ARGS)
{
text *string1 = PG_GETARG_TEXT_PP(0);
int32 output_width = PG_GETARG_INT32(1);
text *string2 = PG_GETARG_TEXT_PP(2);
text *ret;
char *ptr1,
*ptr2 = NULL,
*ptr2start = NULL,
*ptr2end = NULL,
*ptr_ret,
*spc = " ";
int mlen,
dsplen,
s1blen,
s2blen,
hslen,
total_blen = 0,
s1_width = 0,
s2_add_width = 0,
s1_add_blen = 0,
s2_add_blen = 0;
bool s2_operate = ON,
half_space = OFF,
init_ptr = ON;
/* validate output width (the 2nd argument) */
if (output_width < 0)
output_width = 0;
if (output_width > PAD_MAX)
output_width = PAD_MAX;
/* get byte-length of the 1st and 3rd argument strings */
s1blen = VARSIZE_ANY_EXHDR(string1);
s2blen = VARSIZE_ANY_EXHDR(string2);
/* validate the lengths */
if (s1blen < 0)
s1blen = 0;
if (s2blen < 0)
s2blen = 0;
/* if the filler length is zero disable filling */
if (s2blen == 0)
{
s2_operate = OFF; /* turn off string2 processing flag */
output_width = 0; /* same behavior as Oracle database */
}
/* byte-length of half-width space */
hslen = pg_mblen(spc);
/*
* Calculate the length of the portion of string1 to include in
* the final output
*/
ptr1 = VARDATA_ANY(string1);
while (s1blen > 0)
{
/* byte-length and display length per character of string1 */
mlen = pg_mblen(ptr1);
dsplen = pg_dsplen(ptr1);
/* accumulate display length of string1 */
s1_width += dsplen;
/*
* if string1 is longer/wider than the requested output_width,
* discard this character and prepend a half-width space instead
*/
if(s1_width >= output_width)
{
if(s1_width != output_width)
{
/* secure bytes for a half-width space in the final output */
if (output_width != 0)
{
s1_add_blen += hslen;
half_space = ON;
}
}
else /* exactly fits, so include this chracter */
{
s1_add_blen += mlen;
}
/*
* turn off string2 processing because string1 already
* consumed output_width
*/
s2_operate = OFF;
/* done with string1 */
break;
}
/* accumulate string1's portion of byte-length of the output */
s1_add_blen += mlen;
/* advance one character within string1 */
ptr1 += mlen;
/* loop counter */
s1blen -= mlen;
}
/* Calculate the length of the portion composed of string2 to use for padding */
if (s2_operate)
{
/* remaining part of output_width is composed of string2 */
s2_add_width = output_width - s1_width;
ptr2 = ptr2start = VARDATA_ANY(string2);
ptr2end = ptr2 + s2blen;
while (s2_add_width > 0)
{
/* byte-length and display length per character of string2 */
mlen = pg_mblen(ptr2);
dsplen = pg_dsplen(ptr2);
/*
* output_width can not fit this character of string2, so discard it and
* prepend a half-width space instead
*/
if(dsplen > s2_add_width)
{
s2_add_blen += hslen;
half_space = ON;
/* done with string2 */
break;
}
/* accumulate string2's portion of byte-length of the output */
s2_add_blen += mlen;
/* loop counter */
s2_add_width -= dsplen;
/* advance one character within string2 */
ptr2 += mlen;
/* when get to the end of string2, reset ptr2 to the start */
if (ptr2 == ptr2end)
ptr2 = ptr2start;
}
}
/* allocate enough space to contain output_width worth of characters */
total_blen = s1_add_blen + s2_add_blen;
ret = (text *) palloc(VARHDRSZ + total_blen);
ptr_ret = VARDATA(ret);
/*
* add a half-width space as a padding necessary to satisfy the required
* output_width
*
* (memory already allocated as reserved by either s1_add_blen
* or s2_add_blen)
*/
if (half_space)
{
memcpy(ptr_ret, spc, hslen);
ptr_ret += hslen;
}
/* prepend string2 padding */
while(s2_add_blen > 0)
{
/* reset ptr2 to the string2 start */
if(init_ptr)
{
init_ptr = OFF;
ptr2 = ptr2start;
}
mlen = pg_mblen(ptr2);
if ( s2_add_blen < mlen )
break;
memcpy(ptr_ret, ptr2, mlen);
ptr_ret += mlen;
ptr2 += mlen;
/* loop counter */
s2_add_blen -= mlen;
/* when get to the end of string2, reset ptr2 back to the start */
if (ptr2 == ptr2end)
ptr2 = ptr2start;
}
init_ptr = ON;
/* string1 */
while(s1_add_blen > 0)
{
/* reset ptr1 back to the start of string1 */
if(init_ptr)
{
init_ptr = OFF;
ptr1 = VARDATA_ANY(string1);
}
mlen = pg_mblen(ptr1);
if( s1_add_blen < mlen )
break;
memcpy(ptr_ret, ptr1, mlen);
ptr_ret += mlen;
ptr1 += mlen;
/* loop counter */
s1_add_blen -= mlen;
}
SET_VARSIZE(ret, ptr_ret - (char *) ret);
PG_RETURN_TEXT_P(ret);
}
/*
* orafce_rpad(string text, length int32 [, fill text])
*
* Fill up the string to length 'length' by appending
* the characters fill (a half-width space by default)
*/
Datum
orafce_rpad(PG_FUNCTION_ARGS)
{
text *string1 = PG_GETARG_TEXT_PP(0);
int32 output_width = PG_GETARG_INT32(1);
text *string2 = PG_GETARG_TEXT_PP(2);
text *ret;
char *ptr1,
*ptr2 = NULL,
*ptr2start = NULL,
*ptr2end = NULL,
*ptr_ret,
*spc = " ";
int mlen,
dsplen,
s1blen,
s2blen,
hslen,
total_blen = 0,
s1_width = 0,
s2_add_width = 0,
s1_add_blen = 0,
s2_add_blen = 0;
bool s2_operate = ON,
half_space = OFF,
init_ptr = ON;
/* validate output width (the 2nd argument) */
if (output_width < 0)
output_width = 0;
if (output_width > PAD_MAX)
output_width = PAD_MAX;
/* get byte-length of the 1st and 3rd argument strings */
s1blen = VARSIZE_ANY_EXHDR(string1);
s2blen = VARSIZE_ANY_EXHDR(string2);
/* validate the lengths */
if (s1blen < 0)
s1blen = 0;
if (s2blen < 0)
s2blen = 0;
/* if the filler length is zero disable filling */
if (s2blen == 0)
{
s2_operate = OFF; /* turn off string2 processing flag */
output_width = 0; /* same behavior as Oracle database */
}
/* byte-length of half-width space */
hslen = pg_mblen(spc);
/*
* Calculate the length of the portion of string1 to include in
* the final output
*/
ptr1 = VARDATA_ANY(string1);
while (s1blen > 0)
{
/* byte-length and display length per character of string1 */
mlen = pg_mblen(ptr1);
dsplen = pg_dsplen(ptr1);
/* accumulate display length of string1 */
s1_width += dsplen;
/*
* if string1 is longer/wider than the requested output_width,
* discard this character and prepend a half-width space instead
*/
if(s1_width >= output_width)
{
if(s1_width != output_width)
{
/* secure bytes for a half-width space in the final output */
if (output_width != 0)
{
s1_add_blen += hslen;
half_space = ON;
}
}
else /* exactly fits, so include this chracter */
{
s1_add_blen += mlen;
}
/*
* turn off string2 processing because string1 already
* consumed output_width
*/
s2_operate = OFF;
/* done with string1 */
break;
}
/* accumulate string1's portion of byte-length of the output */
s1_add_blen += mlen;
/* advance one character within string1 */
ptr1 += mlen;
/* loop counter */
s1blen -= mlen;
}
/* Calculate the length of the portion composed of string2 to use for padding */
if (s2_operate)
{
/* remaining part of output_width is composed of string2 */
s2_add_width = output_width - s1_width;
ptr2 = ptr2start = VARDATA_ANY(string2);
ptr2end = ptr2 + s2blen;
while (s2_add_width > 0)
{
/* byte-length and display length per character of string2 */
mlen = pg_mblen(ptr2);
dsplen = pg_dsplen(ptr2);
/*
* output_width can not fit this character of string2, so discard it and
* prepend a half-width space instead
*/
if(dsplen > s2_add_width)
{
s2_add_blen += hslen;
half_space = ON;
/* done with string2 */
break;
}
/* accumulate string2's portion of byte-length of the output */
s2_add_blen += mlen;
/* loop counter */
s2_add_width -= dsplen;
/* advance one character within string2 */
ptr2 += mlen;
/* when get to the end of string2, reset ptr2 to the start */
if (ptr2 == ptr2end)
ptr2 = ptr2start;
}
}
/* allocate enough space to contain output_width worth of characters */
total_blen = s1_add_blen + s2_add_blen;
ret = (text *) palloc(VARHDRSZ + total_blen);
ptr_ret = VARDATA(ret);
/* string1 */
while(s1_add_blen > 0)
{
/* reset ptr1 back to the start of string1 */
if(init_ptr)
{
init_ptr = OFF;
ptr1 = VARDATA_ANY(string1);
}
mlen = pg_mblen(ptr1);
if( s1_add_blen < mlen )
break;
memcpy(ptr_ret, ptr1, mlen);
ptr_ret += mlen;
ptr1 += mlen;
/* loop counter */
s1_add_blen -= mlen;
}
init_ptr = ON;
/* append string2 padding */
while(s2_add_blen > 0)
{
/* reset ptr2 to the string2 start */
if(init_ptr)
{
init_ptr = OFF;
ptr2 = ptr2start;
}
mlen = pg_mblen(ptr2);
if ( s2_add_blen < mlen )
break;
memcpy(ptr_ret, ptr2, mlen);
ptr_ret += mlen;
ptr2 += mlen;
/* loop counter */
s2_add_blen -= mlen;
/* when get to the end of string2, reset ptr2 back to the start */
if (ptr2 == ptr2end)
ptr2 = ptr2start;
}
/*
* add a half-width space as a padding necessary to satisfy the required
* output_width
*
* (memory already allocated as reserved by either s1_add_blen
* or s2_add_blen)
*/
if (half_space)
{
memcpy(ptr_ret, spc, hslen);
ptr_ret += hslen;
}
SET_VARSIZE(ret, ptr_ret - (char *) ret);
PG_RETURN_TEXT_P(ret);
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦