138 lines
4.3 KiB
C
138 lines
4.3 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2006, 2009 Fidelity Information Services, Inc *
|
||
|
* *
|
||
|
* This source code contains the intellectual property *
|
||
|
* of its copyright holder(s), and is made available *
|
||
|
* under a license. If you do not know the terms of *
|
||
|
* the license, please stop and do not read further. *
|
||
|
* *
|
||
|
****************************************************************/
|
||
|
|
||
|
#include "mdef.h"
|
||
|
|
||
|
#include "gtm_string.h"
|
||
|
#include "stringpool.h"
|
||
|
#include "min_max.h"
|
||
|
#include "op.h"
|
||
|
#include "gtm_utf8.h"
|
||
|
|
||
|
GBLREF spdesc stringpool;
|
||
|
GBLREF boolean_t badchar_inhibit;
|
||
|
|
||
|
/*
|
||
|
* ----------------------------------------------------------
|
||
|
* Set version of $extract
|
||
|
*
|
||
|
* Arguments:
|
||
|
* src - source mval
|
||
|
* expr - expression string mval to be inserted into source
|
||
|
* schar - starting character index to be replaced
|
||
|
* echar - ending character index to be replaced
|
||
|
* dst - destination mval where the result is saved.
|
||
|
*
|
||
|
* Return:
|
||
|
* none
|
||
|
* ----------------------------------------------------------
|
||
|
*/
|
||
|
void op_setextract(mval *src, mval *expr, int schar, int echar, mval *dst)
|
||
|
{
|
||
|
int srclen, padlen, pfxlen, sfxoff, sfxlen, dstlen, bytelen, skip, char_len;
|
||
|
unsigned char *srcptr, *srcbase, *srctop, *straddr;
|
||
|
|
||
|
error_def(ERR_MAXSTRLEN);
|
||
|
|
||
|
padlen = pfxlen = sfxlen = 0;
|
||
|
MV_FORCE_STR(expr); /* Expression to put into piece place */
|
||
|
if (MV_DEFINED(src))
|
||
|
{
|
||
|
MV_FORCE_STR(src); /* Make sure is string prior to length check */
|
||
|
srclen = src->str.len;
|
||
|
} else /* Source is not defined -- treat as a null string */
|
||
|
srclen = 0;
|
||
|
schar = MAX(schar, 1); /* schar starts at 1 at a minimum */
|
||
|
|
||
|
/* There are four cases in the spec:
|
||
|
1) schar > echar or echar < 1 -- glvn and naked indicator are not changed. This is
|
||
|
handled by generated code in m_set
|
||
|
2) echar >= schar-1 > $L(src) -- dst = src_$J("",schar-1-$L(src))_expr
|
||
|
3) schar-1 <= $L(src) < echar -- dst = $E(src,1,schar-1)_expr
|
||
|
4) All others -- dst = $E(src,1,schar-1)_expr_$E(src,echar+1,$L(src))
|
||
|
*/
|
||
|
srcbase = (unsigned char *)src->str.addr;
|
||
|
srctop = srcbase + srclen;
|
||
|
for (srcptr = srcbase, skip = schar - 1; (skip > 0 && srcptr < srctop); --skip)
|
||
|
{ /* skip the first schar - 1 characters */
|
||
|
if (!UTF8_VALID(srcptr, srctop, bytelen) && !badchar_inhibit)
|
||
|
utf8_badchar(0, srcptr, srctop, 0, NULL);
|
||
|
srcptr += bytelen;
|
||
|
}
|
||
|
pfxlen = (int)(srcptr - srcbase);
|
||
|
if (skip > 0)
|
||
|
{ /* Case #2: schar is past the string length. echar test handled in generated code.
|
||
|
Should be padded with as many spaces as characters remained to be skipped */
|
||
|
padlen = skip;
|
||
|
}
|
||
|
for (skip = echar - schar + 1; (skip > 0 && srcptr < srctop); --skip)
|
||
|
{ /* skip up to the character position echar */
|
||
|
if (!UTF8_VALID(srcptr, srctop, bytelen) && !badchar_inhibit)
|
||
|
utf8_badchar(0, srcptr, srctop, 0, NULL);
|
||
|
srcptr += bytelen;
|
||
|
}
|
||
|
char_len = 0;
|
||
|
if (skip <= 0)
|
||
|
{ /* Case #4: echar is within the string length, suffix to be added */
|
||
|
sfxoff = (int)(srcptr - srcbase);
|
||
|
sfxlen = (int)(srctop - srcptr);
|
||
|
if (!badchar_inhibit && sfxlen > 0)
|
||
|
{ /* validate the suffix, and we can compute char_len as well */
|
||
|
for (; (srcptr < srctop); ++char_len)
|
||
|
{
|
||
|
if (!UTF8_VALID(srcptr, srctop, bytelen))
|
||
|
utf8_badchar(0, srcptr, srctop, 0, NULL);
|
||
|
srcptr += bytelen;
|
||
|
}
|
||
|
MV_FORCE_LEN(expr);
|
||
|
char_len += schar - 1 + expr->str.char_len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Calculate total string len */
|
||
|
dstlen = pfxlen + padlen + expr->str.len + sfxlen;
|
||
|
if (dstlen > MAX_STRLEN)
|
||
|
rts_error(VARLSTCNT(1) ERR_MAXSTRLEN);
|
||
|
ENSURE_STP_FREE_SPACE(dstlen);
|
||
|
|
||
|
srcbase = (unsigned char *)src->str.addr;
|
||
|
straddr = stringpool.free;
|
||
|
|
||
|
if (0 < pfxlen)
|
||
|
{ /* copy prefix */
|
||
|
memcpy(straddr, srcbase, pfxlen);
|
||
|
straddr += pfxlen;
|
||
|
}
|
||
|
if (0 < padlen)
|
||
|
{ /* insert padding */
|
||
|
memset(straddr, ' ', padlen);
|
||
|
straddr += padlen;
|
||
|
}
|
||
|
if (0 < expr->str.len)
|
||
|
{ /* copy expression */
|
||
|
memcpy(straddr, expr->str.addr, expr->str.len);
|
||
|
straddr += expr->str.len;
|
||
|
}
|
||
|
if (0 < sfxlen)
|
||
|
{ /* copy suffix */
|
||
|
memcpy(straddr, srcbase + sfxoff, sfxlen);
|
||
|
straddr += sfxlen;
|
||
|
}
|
||
|
assert(straddr - stringpool.free == dstlen);
|
||
|
MV_INIT_STRING(dst, straddr - stringpool.free, (char *)stringpool.free);
|
||
|
if (0 < char_len)
|
||
|
{
|
||
|
dst->mvtype |= MV_UTF_LEN;
|
||
|
dst->str.char_len = char_len;
|
||
|
}
|
||
|
stringpool.free = straddr;
|
||
|
}
|