fis-gtm/sr_port/op_fnzprevious.c

105 lines
3.3 KiB
C

/****************************************************************
* *
* Copyright 2001, 2011 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 "lv_val.h"
#include "collseq.h"
#include "stringpool.h"
#include "op.h"
#include "do_xform.h"
#include "numcmp.h"
#include "mvalconv.h"
#include "promodemo.h" /* for "demote" prototype used in LV_NODE_GET_KEY */
void op_fnzprevious(lv_val *src, mval *key, mval *dst)
{
int cur_subscr, length;
mval tmp_sbs;
lvTreeNode *node;
lvTree *lvt;
boolean_t is_canonical, get_last;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
if (src && (lvt = LV_GET_CHILD(src))) /* caution: assignment */
{
MV_FORCE_DEFINED(key);
/* If last subscript is null, $zprev returns the last subscript in that level. */
get_last = FALSE;
if (MV_IS_STRING(key) && (0 == key->str.len))
get_last = TRUE;
if (get_last)
node = lvAvlTreeLast(lvt);
else
{
is_canonical = MV_IS_CANONICAL(key);
if (!is_canonical)
{
assert(!TREE_KEY_SUBSCR_IS_CANONICAL(key->mvtype));
if (TREF(local_collseq))
{
ALLOC_XFORM_BUFF(key->str.len);
tmp_sbs.mvtype = MV_STR;
tmp_sbs.str.len = TREF(max_lcl_coll_xform_bufsiz);
assert(NULL != TREF(lcl_coll_xform_buff));
tmp_sbs.str.addr = TREF(lcl_coll_xform_buff);
do_xform(TREF(local_collseq), XFORM, &key->str, &tmp_sbs.str, &length);
tmp_sbs.str.len = length;
s2pool(&(tmp_sbs.str));
key = &tmp_sbs;
}
} else
{ /* Need to set canonical bit before calling tree search functions.
* But input mval could be read-only so cannot modify that even if temporarily.
* So take a copy of the mval and modify that instead.
*/
tmp_sbs = *key;
key = &tmp_sbs;
MV_FORCE_NUM(key);
TREE_KEY_SUBSCR_SET_MV_CANONICAL_BIT(key); /* used by the lvAvlTreeKeyPrev function */
}
node = lvAvlTreeKeyPrev(lvt, key);
}
/* If STDNULLCOLL, skip to the previous subscript should the current subscript be "" */
if (TREF(local_collseq_stdnull) && (NULL != node) && LV_NODE_KEY_IS_NULL_SUBS(node))
{
assert(LVNULLSUBS_OK == TREF(lv_null_subs));
node = lvAvlTreePrev(node);
}
} else
node = NULL;
if (NULL == node)
{
dst->mvtype = MV_STR;
dst->str.len = 0;
} else
{
LV_NODE_GET_KEY(node, dst); /* Get node key into "dst" depending on the structure type of "node" */
/* Code outside lv_tree.c does not currently know to make use of MV_CANONICAL bit so reset it
* until the entire codebase gets fixed to maintain MV_CANONICAL bit accurately at which point,
* this RESET can be removed */
TREE_KEY_SUBSCR_RESET_MV_CANONICAL_BIT(dst);
if (TREF(local_collseq) && MV_IS_STRING(dst))
{
ALLOC_XFORM_BUFF(dst->str.len);
assert(NULL != TREF(lcl_coll_xform_buff));
tmp_sbs.str.addr = TREF(lcl_coll_xform_buff);
tmp_sbs.str.len = TREF(max_lcl_coll_xform_bufsiz);
do_xform(TREF(local_collseq), XBACK, &dst->str, &tmp_sbs.str, &length);
tmp_sbs.str.len = length;
s2pool(&(tmp_sbs.str));
dst->str = tmp_sbs.str;
}
}
return;
}