mflt *lv_prv_num_inx (sbs_blk *root, mval *key) { sbs_blk *blk; sbs_flt_struct *p, *bot; mval tmp ; assert (root); assert (root->cnt); assert (root->ptr.sbs_flt[0].lv); MV_ASGN_FLT2MVAL(tmp,root->ptr.sbs_flt[0].flt); if (eb_atmost(key, &tmp)) return 0; for (blk = root; ; blk = blk->nxt) { if (!blk->nxt) break; MV_ASGN_FLT2MVAL(tmp,blk->nxt->ptr.sbs_flt[0].flt); if (eb_atmost(key, &tmp)) break; } bot = blk->ptr.sbs_flt ; p = &blk->ptr.sbs_flt[blk->cnt - 1]; while (MV_ASGN_FLT2MVAL(tmp,p->flt) , eb_atmost(key, &tmp)) { --p; if (p < bot) return 0; } return &p->flt; }
lv_val *lv_get_num_inx(sbs_blk *root, mval *key, sbs_search_status *status) { sbs_blk *blk, *nxt, *prev; sbs_flt_struct *p, *top; mval tmp ; int4 x ; assert(root); prev = root; for (blk = root; ; prev = blk, blk = nxt) { if (!(nxt = blk->nxt)) { break; } MV_ASGN_FLT2MVAL(tmp,nxt->ptr.sbs_flt[0].flt) ; if (key->mvtype & MV_INT & tmp.mvtype) x = key->m[1] - tmp.m[1]; else x = numcmp(key,&tmp) ; if (x < 0) { break; } if (x == 0) { status->blk = nxt; status->prev = blk; status->ptr = (char*)&nxt->ptr.sbs_str[0]; return(nxt->ptr.sbs_flt[0].lv); } } status->blk = blk; status->prev = prev; for (p = (sbs_flt_struct*)&blk->ptr.sbs_flt[0], top = (sbs_flt_struct*)&blk->ptr.sbs_flt[blk->cnt]; p < top; p++) { MV_ASGN_FLT2MVAL(tmp,p->flt); if (key->mvtype & MV_INT & tmp.mvtype) x = key->m[1] - tmp.m[1]; else x = numcmp(key,&tmp) ; if (x < 0) { break; } if (x == 0) { status->ptr = (char*)p; return(p->lv); } } status->ptr = (char*)p; return(0); }
void op_fnorder(lv_val *src, mval *key, mval *dst) { int cur_subscr; mval tmp_sbs; int length; sbs_blk *num, *str; boolean_t found, is_neg; int4 i; lv_val **lv; lv_sbs_tbl *tbl; sbs_search_status status; boolean_t is_fnnext; is_fnnext = in_op_fnnext; in_op_fnnext = FALSE; found = FALSE; if (src) { if (tbl = src->ptrs.val_ent.children) { MV_FORCE_DEFINED(key); num = tbl->num; str = tbl->str; assert(tbl->ident == MV_SBS); if ((MV_IS_STRING(key) && key->str.len == 0) || (is_fnnext && MV_IS_INT(key) && key->m[1] == MINUS_ONE)) { /* With GT.M collation , if last subscript is null, $o returns the first subscript in that level */ if (tbl->int_flag) { assert(num); for (i = 0, lv = &num->ptr.lv[0]; i < SBS_NUM_INT_ELE; i++, lv++) { if (*lv) { MV_FORCE_MVAL(dst,i); found = TRUE; break; } } } else if (num) { assert(num->cnt); MV_ASGN_FLT2MVAL((*dst),num->ptr.sbs_flt[0].flt); found = TRUE; } } else { if (MV_IS_CANONICAL(key)) { MV_FORCE_NUM(key); if (tbl->int_flag) { assert(num); is_neg = (key->mvtype & MV_INT) ? key->m[1] < 0 : key->sgn; if (is_neg) i = 0; else { if (!is_fnnext && (1 == numcmp(key, (mval *)&SBS_MVAL_INT_ELE))) i = SBS_NUM_INT_ELE; else { i = MV_FORCE_INT(key); i++; } } for (lv = &num->ptr.lv[i]; i < SBS_NUM_INT_ELE; i++, lv++) { if (*lv) { MV_FORCE_MVAL(dst,i); found = TRUE; break; } } } else if (num && lv_nxt_num_inx(num, key, &status)) { MV_ASGN_FLT2MVAL((*dst),((sbs_flt_struct*)status.ptr)->flt); found = TRUE; } } else { if (local_collseq) { ALLOC_XFORM_BUFF(&key->str); tmp_sbs.mvtype = MV_STR; tmp_sbs.str.len = max_lcl_coll_xform_bufsiz; assert(NULL != lcl_coll_xform_buff); tmp_sbs.str.addr = lcl_coll_xform_buff; do_xform(local_collseq, XFORM, &key->str, &tmp_sbs.str, &length); tmp_sbs.str.len = length; s2pool(&(tmp_sbs.str)); key = &tmp_sbs; } if (str && lv_nxt_str_inx(str, &key->str, &status)) { dst->mvtype = MV_STR; dst->str = ((sbs_str_struct *)status.ptr)->str; } else { if (!is_fnnext) { dst->mvtype = MV_STR; dst->str.len = 0; } else MV_FORCE_MVAL(dst, -1); } found = TRUE; } } if (!found && str) { /* We are here because * a. key is "" and there is no numeric subscript, OR * b. key is numeric and it is >= the largest numeric subscript at this level implying a switch from * numeric to string subscripts * Either case, return the first string subscript. However, for STDNULLCOLL, skip to the next * subscript should the first subscript be "" */ assert(str->cnt); dst->mvtype = MV_STR; dst->str = str->ptr.sbs_str[0].str; found = TRUE; if (local_collseq_stdnull && 0 == dst->str.len) { assert(lv_null_subs); if (lv_nxt_str_inx(str, &dst->str, &status)) { dst->str = ((sbs_str_struct*)status.ptr)->str; } else found = FALSE; } } } } if (!found) { if (!is_fnnext) { dst->mvtype = MV_STR; dst->str.len = 0; } else MV_FORCE_MVAL(dst, -1); } else if (dst->mvtype == MV_STR && local_collseq) { ALLOC_XFORM_BUFF(&dst->str); assert(NULL != lcl_coll_xform_buff); tmp_sbs.str.addr = lcl_coll_xform_buff; tmp_sbs.str.len = max_lcl_coll_xform_bufsiz; do_xform(local_collseq, XBACK, &dst->str, &tmp_sbs.str, &length); tmp_sbs.str.len = length; s2pool(&(tmp_sbs.str)); dst->str = tmp_sbs.str; } }