Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief UBF library
0003  *   The emulator of UBF library
0004  *   Enduro Execution Library
0005  *   Debug ideas:
0006  *   - on API entry take copy of FB
0007  *   - on API exit make diff of the FB memory. Also diff the memory usage
0008  *   - provide the information about count of bytes from source element added
0009  *   - on exit, dump the first BFLDID element address
0010  *
0011  * @file ubf.c
0012  */
0013 /* -----------------------------------------------------------------------------
0014  * Enduro/X Middleware Platform for Distributed Transaction Processing
0015  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0016  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0017  * This software is released under one of the following licenses:
0018  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0019  * See LICENSE file for full text.
0020  * -----------------------------------------------------------------------------
0021  * AGPL license:
0022  *
0023  * This program is free software; you can redistribute it and/or modify it under
0024  * the terms of the GNU Affero General Public License, version 3 as published
0025  * by the Free Software Foundation;
0026  *
0027  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0028  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0029  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0030  * for more details.
0031  *
0032  * You should have received a copy of the GNU Affero General Public License along 
0033  * with this program; if not, write to the Free Software Foundation, Inc.,
0034  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0035  *
0036  * -----------------------------------------------------------------------------
0037  * A commercial use license is available from Mavimax, Ltd
0038  * contact@mavimax.com
0039  * -----------------------------------------------------------------------------
0040  */
0041 
0042 /*---------------------------Includes-----------------------------------*/
0043 #include <string.h>
0044 #include <stdio.h>
0045 #include <stdlib.h>
0046 #include <memory.h>
0047 
0048 #include <ubf.h>
0049 #include <ubf_int.h>    /* Internal headers for UBF... */
0050 #include <fdatatype.h>
0051 #include <ferror.h>
0052 #include <fieldtable.h>
0053 #include <ndrstandard.h>
0054 #include <ndebug.h>
0055 #include <cf.h>
0056 #include <expr.h>
0057 #include <thlock.h>
0058 #include <typed_view.h>
0059 #include <ubfdb.h>
0060 #include <ubfutil.h>
0061 #include <nstd_int.h>
0062 #include <expluginbase.h>
0063 #include <ubf_tls.h>
0064 #include <ndebugcmn.h>
0065 /*---------------------------Externs------------------------------------*/
0066 /*---------------------------Macros-------------------------------------*/
0067 
0068 #define API_ENTRY {ndrx_Bunset_error(); \
0069     if (!M_init) { \
0070     MUTEX_LOCK; \
0071         UBF_DBG_INIT(("UBF", UBFDEBUGLEV));\
0072         M_init=EXTRUE;\
0073     MUTEX_UNLOCK;\
0074     }\
0075 }\
0076 
0077 /*
0078  * Validates user type specified
0079  */
0080 #define VALIDATE_USER_TYPE(X, Y) \
0081             /* Check data type alignity */ \
0082             if (IS_TYPE_INVALID(X)) \
0083             { \
0084                 ndrx_Bset_error_fmt(BTYPERR, "Invalid user type %d", X);\
0085                 Y;\
0086             }\
0087             if (IS_TYPE_COMPLEX(X)) \
0088             { \
0089                 ndrx_Bset_error_fmt(BEBADOP, "Invalid user type %d", X);\
0090                 Y;\
0091             }
0092 
0093 /*---------------------------Enums--------------------------------------*/
0094 /*---------------------------Typedefs-----------------------------------*/
0095 /*---------------------------Globals------------------------------------*/
0096 /*---------------------------Statics------------------------------------*/
0097 static volatile int M_init = EXFALSE;
0098 /*---------------------------Prototypes---------------------------------*/
0099 
0100 /**
0101  * Initialize UBF buffer
0102  * Size already includes last BBADFLDID! Which always must stay as BBADFLDID!
0103  */
0104 expublic int Binit (UBFH * p_ub, BFLDLEN len)
0105 {
0106     int ret=EXSUCCEED;
0107     UBF_header_t *ubf_h = (UBF_header_t *)p_ub;
0108     char *p;
0109     
0110     UBF_LOG(log_debug, "Binit p_ub=%p len=%d", p_ub, len);
0111             
0112     if (NULL==p_ub)
0113     {
0114         /* Null buffer */
0115         ndrx_Bset_error_msg(BNOTFLD, "ptr to UBFH is NULL");
0116         ret=EXFAIL;
0117     }
0118     else if (len < sizeof(UBF_header_t))
0119     {
0120         ndrx_Bset_error_fmt(BNOSPACE, "Minimum: %d, but got: %d",
0121                                     sizeof(UBF_header_t), len);
0122         ret=EXFAIL;
0123     }
0124     else
0125     {
0126 #ifdef UBF_API_DEBUG
0127         /* randomize memory... */
0128         int i;
0129         char *buf = (char *)p_ub;
0130 
0131         for (i=0; i<len; i++)
0132         {
0133             buf[i] = (char)(ndrx_rand() % 255);
0134         }
0135 
0136 #endif
0137         /* Initialise buffer */
0138         /* the last element bfldid is set to zero */
0139         memset((char *)p_ub, 0, sizeof(UBF_header_t)); /* Do we need all to be set to 0? */
0140         ubf_h->version = UBF_VERSION; /* Reset options to (all disabled) */
0141         ubf_h->buffer_type = 0; /* not used currently */
0142         memcpy(ubf_h->magic, UBF_MAGIC, sizeof(UBF_MAGIC)-1);
0143         ubf_h->buf_len = len;
0144         ubf_h->opts = 0; 
0145         ubf_h->bytes_used = sizeof(UBF_header_t) - FF_USED_BYTES;
0146     
0147     }
0148     
0149     return ret;
0150 }
0151 
0152 /**
0153  * Add value to FB...
0154  *
0155  * If adding the first value, the buffer should be large enought and last
0156  * BFLDID should stay at BADFLID, because will not be overwritten.
0157  * Also last entry always must at BBADFLDID! This is the rule.
0158  */
0159 expublic int Badd (UBFH *p_ub, BFLDID bfldid, char *buf, BFLDLEN len)
0160 {
0161     API_ENTRY;
0162     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0163     {
0164         UBF_LOG(log_warn, "Badd: arguments fail!");
0165         return EXFAIL;
0166     }
0167     
0168     return ndrx_Badd (p_ub, bfldid, buf, len, NULL, NULL);
0169 }
0170 
0171 /**
0172  * Fast path adding of data to buffer, by providing reference to last field added
0173  * ending. the next_fld shall be used only if adding occurrences of the same field
0174  * to buffer. Or you are sure that you are adding new fldid, which is greater than
0175  * fldid in last add operation
0176  * TODO: Add some checks against invalid add..
0177  * @param p_ub UBF buffer
0178  * @param bfldid field to add
0179  * @param buf value to add
0180  * @param len len of value (if needed)
0181  * @param next_fld saved from previous call. Initially memset to 0
0182  * @return EXSUCCEED/EXFAIL
0183  */
0184 expublic int Baddfast (UBFH *p_ub, BFLDID bfldid, char *buf, BFLDLEN len, 
0185     Bfld_loc_info_t *next_fld)
0186 {
0187     int ret = EXSUCCEED;
0188     
0189     API_ENTRY;
0190     
0191     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0192     {
0193         UBF_LOG(log_warn, "Badd: arguments fail!");
0194         return EXFAIL;
0195     }
0196     
0197     return ndrx_Baddfast (p_ub, bfldid, buf, len, next_fld);
0198 }
0199 
0200 /**
0201  * Fast adding to UBF buffer with user data type convert if necessary
0202  * @param p_ub UBF buffer
0203  * @param bfldid field to add
0204  * @param buf value to add
0205  * @param len len of value (if needed)
0206  * @param usrtype user data 
0207  * @param next_fld saved from previous call. Initially memset to 0
0208  * @return EXSUCCEED/EXFAIL 
0209  */
0210 expublic int CBaddfast (UBFH *p_ub, BFLDID bfldid, char *buf, BFLDLEN len,
0211         int usrtype, Bfld_loc_info_t *next_fld)
0212 {
0213     int ret=EXSUCCEED;
0214     int cvn_len=0;
0215     char *cvn_buf;
0216 
0217     char tmp_buf[CF_TEMP_BUF_MAX];
0218     int to_type = (bfldid>>EFFECTIVE_BITS);
0219     /* Buffer management */
0220     char *alloc_buf = NULL;
0221     char *p;
0222     char *fn = "CBaddfast";
0223     
0224     API_ENTRY;
0225 
0226     /* Do standard validation */
0227     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0228     {
0229         UBF_LOG(log_warn, "CBaddfast: arguments fail!");
0230         return EXFAIL;
0231     }
0232     
0233     if (NULL==next_fld)
0234     {
0235         ndrx_Bset_error_msg(BEINVAL, "next_fld must not be NULL!");
0236         return EXFAIL;
0237     }
0238     
0239     /* check that rules are OK */
0240     if (BBADFLDID!=next_fld->last_Baddfast &&
0241             bfldid < next_fld->last_Baddfast)
0242     {
0243         ndrx_Bset_error_fmt(BEINVAL, "bfldid (%u) < next_fld->last_Baddfast (%u)!",
0244                 bfldid, next_fld->last_Baddfast);
0245         return EXFAIL;
0246     }
0247 
0248     /* validate user specified type */
0249     VALIDATE_USER_TYPE(usrtype, return EXFAIL);
0250 
0251     /* if types are the same then do direct call */
0252     if (usrtype==to_type)
0253     {
0254         UBF_LOG(log_debug, "CBaddfast: the same types - direct call!");
0255         
0256         ret=ndrx_Baddfast(p_ub, bfldid, buf, len, next_fld);
0257         
0258         if (EXSUCCEED==ret)
0259         {
0260             /* Support #622 save the result */
0261             next_fld->last_Baddfast = bfldid;
0262         }
0263         
0264         return ret; /* <<<< RETURN!!! */
0265     }
0266     /* if types are not the same then go the long way... */
0267     
0268     /* validate that type is not complex */
0269     if (IS_TYPE_COMPLEX(to_type))
0270     {
0271         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", to_type);
0272         return EXFAIL;
0273     }
0274 
0275     /* Allocate the buffer dynamically */
0276     if (NULL==(p=ndrx_ubf_get_cbuf(usrtype, to_type, tmp_buf, buf, len, &alloc_buf, 
0277                                 &cvn_len, CB_MODE_DEFAULT, 0)))
0278     {
0279         UBF_LOG(log_error, "%s: Malloc failed!", fn);
0280         return EXFAIL; /* <<<< RETURN!!!! */
0281     }
0282 
0283     cvn_buf = ndrx_ubf_convert(usrtype, CNV_DIR_IN, buf, len,
0284                         to_type, p, &cvn_len);
0285 
0286     if (NULL!=cvn_buf)
0287     {
0288         ret=ndrx_Baddfast (p_ub, bfldid, cvn_buf, cvn_len, next_fld);
0289         
0290         if (EXSUCCEED==ret)
0291         {
0292             /* Support #622 save the result */
0293             next_fld->last_Baddfast = bfldid;
0294         }
0295     }
0296     else
0297     {
0298         UBF_LOG(log_error, "%s: failed to convert data!", fn);
0299         /* Error should be provided by conversation function */
0300         ret=EXFAIL;
0301     }
0302 
0303     /* Free up buffer */
0304     if (NULL!=alloc_buf)
0305     {
0306         UBF_LOG(log_debug, "%s: free alloc_buf", fn);
0307         NDRX_FREE(alloc_buf);
0308     }
0309 
0310     return ret;
0311 }
0312 
0313 /**
0314  * Read the data from buffer and loaded it into output buff
0315  * @param p_ub
0316  * @param bfldid
0317  * @param occ
0318  * @param buf
0319  * @param buflen
0320  * @return 
0321  */
0322 expublic int Bget (UBFH * p_ub, BFLDID bfldid, BFLDOCC occ,
0323                             char * buf, BFLDLEN * buflen)
0324 {
0325     API_ENTRY;
0326 
0327     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
0328     {
0329         UBF_LOG(log_warn, "Bget: arguments fail!");
0330         return EXFAIL; /* <<<< RETURN HERE! */
0331     }
0332 
0333     return ndrx_Bget (p_ub, bfldid, occ, buf, buflen);
0334 }
0335 
0336 /**
0337  * Delete specific field from buffer
0338  * @param p_ub
0339  * @param bfldid
0340  * @param occ
0341  * @return
0342  */
0343 expublic int Bdel (UBFH * p_ub, BFLDID bfldid, BFLDOCC occ)
0344 {
0345     int ret=EXSUCCEED;
0346     UBF_header_t *hdr = (UBF_header_t *)p_ub;
0347     /* BFLDID   *p_bfldid = &hdr->bfldid; */
0348     dtype_str_t *dtype;
0349     char *p;
0350     BFLDID   *p_bfldid;
0351     char *last_checked=NULL;
0352     int last_occ=-1;
0353     char *last;
0354     int remove_size;
0355     int move_size;
0356 /***************************************** DEBUG *******************************/
0357 #ifdef UBF_API_DEBUG
0358     /* Real debug stuff!! */
0359     UBF_header_t *__p_ub_copy;
0360     int __dbg_type;
0361     int *__dbg_fldptr_org;
0362     int *__dbg_fldptr_new;
0363     char *__dbg_p_org;
0364     char *__dbg_p_new;
0365     int __dbg_newuse;
0366     int __dbg_olduse;
0367     dtype_str_t *__dbg_dtype;
0368 #endif
0369 /*******************************************************************************/
0370     API_ENTRY;
0371     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
0372     {
0373         UBF_LOG(log_warn, "Bdel: arguments fail!");
0374         ret=EXFAIL;
0375         return ret; /* <<<< RETURN HERE! */
0376     }
0377 /***************************************** DEBUG *******************************/
0378 #ifdef UBF_API_DEBUG
0379     __p_ub_copy = NDRX_MALLOC(hdr->buf_len);
0380     memcpy(__p_ub_copy, p_ub, hdr->buf_len);
0381     __dbg_type = (bfldid>>EFFECTIVE_BITS);
0382     __dbg_dtype = &G_dtype_str_map[__dbg_type];
0383     UBF_LOG(log_debug, "Bdel: entry, adding\nfld=[%d/%p] occ=%d "
0384                                     "type[%hd/%s]\n"
0385                                     "FBbuflen=%d FBused=%d FBfree=%d "
0386                                     "FBstart fld=[%s/%d/%p] ",
0387                                     bfldid, bfldid, occ,
0388                                     __dbg_type, __dbg_dtype->fldname,
0389                                     hdr->buf_len, hdr->bytes_used,
0390                                     (hdr->buf_len - hdr->bytes_used),
0391                                     ndrx_Bfname_int(bfldid), bfldid, bfldid);
0392 #endif
0393 /*******************************************************************************/
0394     if (NULL!=(p=get_fld_loc(p_ub, bfldid, occ, &dtype, &last_checked, NULL, &last_occ,
0395                                             NULL)))
0396     {
0397         p_bfldid = (BFLDID *)p;
0398         /* Wipe the data out! */
0399         last = (char *)hdr;
0400         last+=(hdr->bytes_used-1);
0401         remove_size = dtype->p_next(dtype, p, NULL);
0402         /* Get the size to be moved */
0403         move_size = (last-p+1) - remove_size;
0404         /* Get some free space here!
0405          * So from last element we take off current position,
0406          * so we get lenght. to which we should move.
0407          */
0408         UBF_LOG(log_debug, "moving: to %p from %p %d bytes",
0409                             p, p+remove_size, move_size);
0410         
0411         memmove(p, p+remove_size, move_size);
0412         hdr->bytes_used-=remove_size;
0413         
0414         /* Update type offset cache: */
0415         ubf_cache_shift(p_ub, bfldid, -1*remove_size);
0416         
0417         last = (char *)hdr;
0418         last+=(hdr->bytes_used-1);
0419 #if 0
0420         /* Ensure that we reset last elements... So that we do not get
0421          * used elements
0422          */
0423         UBF_LOG(log_debug, "resetting: %p to 0 - %d bytes",
0424                             last+1, 0, remove_size);
0425         memset(last+1, 0, remove_size);
0426 #endif
0427     }
0428     else
0429     {
0430         ndrx_Bset_error(BNOTPRES);
0431         ret=EXFAIL;
0432     }
0433 
0434 /***************************************** DEBUG *******************************/
0435 #ifdef UBF_API_DEBUG
0436     __dbg_olduse = __p_ub_copy->bytes_used;
0437     __dbg_newuse = hdr->bytes_used;
0438 
0439     /* Do bellow to print out end element (last) of the array - should be bbadfldid */
0440     __dbg_p_org = (char *)__p_ub_copy;
0441     __dbg_p_org+= (__p_ub_copy->bytes_used - FF_USED_BYTES);
0442 
0443     __dbg_p_new = (char *)hdr;
0444     __dbg_p_new+= (hdr->bytes_used - FF_USED_BYTES);
0445 
0446     __dbg_fldptr_org = (int *)__dbg_p_org;
0447     __dbg_fldptr_new = (int *)__dbg_p_new;
0448 
0449     UBF_LOG(log_debug, "Bdel: returns=%d\norg_used=%d new_used=%d diff=%d "
0450                                 "org_start=%d/%p new_start=%d/%p\n"
0451                                 "old_finish=%d/%p, new_finish=%d/%p",
0452                                 ret,
0453                                 __dbg_olduse,
0454                                 __dbg_newuse,
0455                                 (__dbg_olduse - __dbg_newuse),
0456                                 __p_ub_copy->bfldid, __p_ub_copy->bfldid,
0457                                 hdr->bfldid, hdr->bfldid,
0458                                 *__dbg_fldptr_org, *__dbg_fldptr_org,
0459                                 *__dbg_fldptr_new, *__dbg_fldptr_new);
0460     /* Check the last four bytes before the end */
0461     __dbg_p_org-= FF_USED_BYTES;
0462     __dbg_p_new-= FF_USED_BYTES;
0463     __dbg_fldptr_org = (int *)__dbg_p_org;
0464     __dbg_fldptr_new = (int *)__dbg_p_new;
0465     UBF_LOG(log_debug, "Bdel: last %d bytes of data\n org=%p new %p",
0466                           FF_USED_BYTES, *__dbg_fldptr_org, *__dbg_fldptr_new);
0467     UBF_DUMP_DIFF(log_always, "After Badd", __p_ub_copy, p_ub, hdr->buf_len);
0468     UBF_DUMP(log_always, "Used buffer dump after: ",p_ub, hdr->bytes_used);
0469     NDRX_FREE(__p_ub_copy);
0470 #endif
0471 /*******************************************************************************/
0472     return ret;
0473 }
0474 
0475 /**
0476  * Change field content...
0477  * @param
0478  * @param
0479  * @param
0480  * @param
0481  * @param
0482  * @return
0483  */
0484 expublic int Bchg (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ,
0485                             char * buf, BFLDLEN len)
0486 {
0487     API_ENTRY; /* Standard initialization */
0488 
0489     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
0490     {
0491         UBF_LOG(log_warn, "Bchg: arguments fail!");
0492         return EXFAIL; /* <<<< RETURN HERE! */
0493     }
0494 
0495     return ndrx_Bchg(p_ub, bfldid, occ, buf, len, NULL, EXFALSE);
0496 }
0497 
0498 /**
0499  * Return BFLDID from name!
0500  */
0501 expublic BFLDID Bfldid (char *fldnm)
0502 {
0503     UBF_field_def_t *p_fld=NULL;
0504 
0505     API_ENTRY;
0506     
0507     if (EXSUCCEED!=ndrx_prepare_type_tables())
0508     {
0509         return BBADFLDID;
0510     }
0511 
0512     /* no such field */
0513     if (NULL==fldnm || EXEOS==fldnm[0])
0514     {
0515         return BBADFLDID;
0516     }
0517     
0518     /* Now we can try to do lookup */
0519     p_fld = ndrx_fldnmhash_get(fldnm);
0520 
0521     if (NULL!=p_fld)
0522     {
0523         return p_fld->bfldid;
0524     }
0525     else if (NULL!=ndrx_G_ubf_db)
0526     {
0527         int ret;
0528         /* lookup into db */
0529         ret=ndrx_ubfdb_Bflddbid(fldnm);
0530         return ret;
0531     }
0532     else
0533     {
0534         ndrx_Bset_error(BBADNAME);
0535         return BBADFLDID;
0536     }
0537 }
0538 /**
0539  * Return field name from given id
0540  */
0541 expublic char * Bfname (BFLDID bfldid)
0542 {
0543     UBF_field_def_t *p_fld;
0544     API_ENTRY;
0545     
0546     if (bfldid < 0)
0547     {
0548         ndrx_Bset_error_fmt(BEINVAL, "bfldid (%d) < 0", (int)bfldid);
0549         goto out;
0550     }
0551 
0552     if (EXSUCCEED!=ndrx_prepare_type_tables())
0553     {
0554         goto out;
0555     }
0556 
0557     /* Now try to find the data! */
0558     p_fld = _bfldidhash_get(bfldid);
0559     
0560     if (NULL==p_fld)
0561     {
0562         if (NULL!=ndrx_G_ubf_db)
0563         {
0564             return ndrx_ubfdb_Bflddbname(bfldid);
0565         }
0566         else
0567         {
0568             ndrx_Bset_error(BBADFLD);
0569             goto out;
0570         }
0571     }
0572     else
0573     {
0574         return p_fld->fldname;
0575     }
0576     
0577 out:
0578     return NULL;
0579 }
0580 
0581 /**
0582  * Find the entry into buffer.
0583  * Return raw pointer directly
0584  * @param p_ub
0585  * @param bfldid
0586  * @param occ
0587  * @param p_len
0588  * @return
0589  */
0590 expublic char * Bfind (UBFH * p_ub, BFLDID bfldid,
0591                                         BFLDOCC occ, BFLDLEN * p_len)
0592 {
0593     API_ENTRY;
0594 
0595     UBF_LOG(log_debug, "Bfind: bfldid: %d occ: %hd", bfldid, occ);
0596     /* Do standard validation */
0597     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
0598     {
0599         UBF_LOG(log_warn, "Bdel: arguments fail!");
0600         return NULL;
0601     }
0602 
0603     return ndrx_Bfind(p_ub, bfldid, occ, p_len, NULL);
0604 }
0605 
0606 
0607 /**
0608  * Whilte this is not called from other internal functions
0609  * we are leaving implementation in API
0610  * @param p_ub
0611  * @param bfldid
0612  * @param buf
0613  * @param len
0614  * @param usrtype
0615  * @return
0616  */
0617 expublic int CBadd (UBFH *p_ub, BFLDID bfldid, char * buf,
0618                                 BFLDLEN len, int usrtype)
0619 {
0620     int ret=EXSUCCEED;
0621     int cvn_len=0;
0622     char *cvn_buf;
0623 
0624     char tmp_buf[CF_TEMP_BUF_MAX];
0625     int to_type = (bfldid>>EFFECTIVE_BITS);
0626     /* Buffer management */
0627     char *alloc_buf = NULL;
0628     char *p;
0629     char *fn = "CBadd";
0630 /***************************************** DEBUG *******************************/
0631     #ifdef UBF_API_DEBUG
0632     dtype_ext1_t *__dbg_dtype_ext1 = &G_dtype_ext1_map[usrtype];
0633     __dbg_dtype_ext1->p_dump_data(__dbg_dtype_ext1, "CBadd adding data", buf, &len);
0634     #endif
0635 /*******************************************************************************/
0636     API_ENTRY;
0637 
0638     /* Do standard validation */
0639     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0640     {
0641         UBF_LOG(log_warn, "CBadd: arguments fail!");
0642         return EXFAIL;
0643     }
0644 
0645     /* validate user specified type */
0646     VALIDATE_USER_TYPE(usrtype, return EXFAIL);
0647     
0648     /* validate that type is not complex */
0649     if (IS_TYPE_COMPLEX(to_type))
0650     {
0651         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", to_type);
0652         return EXFAIL;
0653     }
0654 
0655     /* if types are the same then do direct call */
0656     if (usrtype==to_type)
0657     {
0658         UBF_LOG(log_debug, "CBadd: the same types - direct call!");
0659         return ndrx_Badd(p_ub, bfldid, buf, len, NULL, NULL); /* <<<< RETURN!!! */
0660     }
0661     /* if types are not the same then go the long way... */
0662 
0663     /* Allocate the buffer dynamically */
0664     if (NULL==(p=ndrx_ubf_get_cbuf(usrtype, to_type, tmp_buf, buf, len, &alloc_buf, 
0665                                 &cvn_len, CB_MODE_DEFAULT, 0)))
0666     {
0667         UBF_LOG(log_error, "%s: Malloc failed!", fn);
0668         return EXFAIL; /* <<<< RETURN!!!! */
0669     }
0670 
0671     cvn_buf = ndrx_ubf_convert(usrtype, CNV_DIR_IN, buf, len,
0672                         to_type, p, &cvn_len);
0673 
0674     if (NULL!=cvn_buf)
0675     {
0676         ret=ndrx_Badd (p_ub, bfldid, cvn_buf, cvn_len, NULL, NULL);
0677     }
0678     else
0679     {
0680         UBF_LOG(log_error, "%s: failed to convert data!", fn);
0681         /* Error should be provided by conversation function */
0682         ret=EXFAIL;
0683     }
0684 
0685     /* Free up buffer */
0686     if (NULL!=alloc_buf)
0687     {
0688         UBF_LOG(log_debug, "%s: free alloc_buf", fn);
0689         NDRX_FREE(alloc_buf);
0690     }
0691 
0692     return ret;
0693 }
0694 /**
0695  * Will we support zero lenght entries of BFLD_CARRAY? Currently it looks like yes!
0696  * But if so then we can get un-predictable results in case when doing zero lenght
0697  * conversion to other data types!
0698  * @param p_ub
0699  * @param bfldid
0700  * @param occ
0701  * @param buf
0702  * @param len
0703  * @param usrtype
0704  * @return
0705  */
0706 expublic int CBchg (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ,
0707                                 char * buf, BFLDLEN len, int usrtype)
0708 {
0709     int ret=EXSUCCEED;
0710     int cvn_len=0;
0711     char *cvn_buf;
0712     char tmp_buf[CF_TEMP_BUF_MAX];
0713     int to_type = (bfldid>>EFFECTIVE_BITS);
0714     /* Buffer management */
0715     char *alloc_buf = NULL;
0716     char *p;
0717 /***************************************** DEBUG *******************************/
0718     #ifdef UBF_API_DEBUG
0719     dtype_ext1_t *__dbg_dtype_ext1 = &G_dtype_ext1_map[usrtype];
0720     __dbg_dtype_ext1->p_dump_data(__dbg_dtype_ext1, "CBchg putting data", buf, &len);
0721     #endif
0722 /*******************************************************************************/
0723 
0724     API_ENTRY; /* Standard initialization */
0725 
0726     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
0727     {
0728         UBF_LOG(log_warn, "CBchg: arguments fail!");
0729         return EXFAIL; /* <<<< RETURN HERE! */
0730     }
0731     /* validate user specified type */
0732     VALIDATE_USER_TYPE(usrtype, return EXFAIL);
0733     
0734     
0735         /* validate that type is not complex */
0736     if (IS_TYPE_COMPLEX(to_type))
0737     {
0738         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", to_type);
0739         return EXFAIL;
0740     }
0741 
0742     /* if types are the same then do direct call */
0743     if (usrtype==to_type)
0744     {
0745         UBF_LOG(log_debug, "CBchg: the same types - direct call!");
0746         return ndrx_Bchg(p_ub, bfldid, occ, buf, len, NULL, EXFALSE); /* <<<< RETURN!!! */
0747     }
0748     /* if types are not the same then go the long way... */
0749     
0750     /* Allocate the buffer dynamically */
0751     if (NULL==(p=ndrx_ubf_get_cbuf(usrtype, to_type, tmp_buf, buf, len, &alloc_buf, &cvn_len,
0752                                 CB_MODE_DEFAULT, 0)))
0753     {
0754         UBF_LOG(log_error, "CBchg: Malloc failed!");
0755         return EXFAIL; /* <<<< RETURN!!!! */
0756     }
0757 
0758     cvn_buf = ndrx_ubf_convert(usrtype, CNV_DIR_IN, buf, len,
0759                         to_type, p, &cvn_len);
0760 
0761     if (NULL!=cvn_buf)
0762     {
0763         ret=Bchg (p_ub, bfldid, occ, cvn_buf, cvn_len);
0764     }
0765     else
0766     {
0767         UBF_LOG(log_error, "CBchg: failed to convert data!");
0768         /* Error should be provided by conversation function */
0769         ret=EXFAIL;
0770     }
0771 
0772     /* Free up buffer */
0773     if (NULL!=alloc_buf)
0774     {
0775         UBF_LOG(log_debug, "CBchg: free alloc_buf");
0776         NDRX_FREE(alloc_buf);
0777     }
0778     
0779     return ret;
0780 }
0781 
0782 /* Have to think here, not?  */
0783 expublic int CBget (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ,
0784                                 char *buf, BFLDLEN *len, int usrtype)
0785 {
0786     int ret=EXSUCCEED;
0787     int from_type = (bfldid>>EFFECTIVE_BITS);
0788     BFLDLEN tmp_len = 0;
0789     char *cvn_buf;
0790     char *fb_data;
0791 /***************************************** DEBUG *******************************/
0792     #ifdef UBF_API_DEBUG
0793     dtype_ext1_t *__dbg_dtype_ext1 = &G_dtype_ext1_map[usrtype];
0794     #endif
0795 /*******************************************************************************/
0796     
0797     API_ENTRY;
0798     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0799     {
0800         UBF_LOG(log_warn, "CBget: arguments fail!");
0801         return EXFAIL;
0802     }
0803 
0804     /* validate user specified type */
0805     VALIDATE_USER_TYPE(usrtype, return EXFAIL);
0806     
0807         /* validate that type is not complex */
0808     if (IS_TYPE_COMPLEX(from_type))
0809     {
0810         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", from_type);
0811         return EXFAIL;
0812     }
0813 
0814     /* if types are the same then do direct call */
0815     if (usrtype==from_type)
0816     {
0817         UBF_LOG(log_debug, "CBget: the same types - direct call!");
0818         return Bget(p_ub, bfldid, occ, buf, len); /* <<<< RETURN!!! */
0819     }
0820     /* if types are not the same then go the long way... */
0821     
0822     fb_data=ndrx_Bfind (p_ub, bfldid, occ, &tmp_len, NULL);
0823 
0824     if (NULL!=fb_data)
0825     {
0826 
0827         cvn_buf = ndrx_ubf_convert(from_type, CNV_DIR_OUT, fb_data, tmp_len,
0828                                     usrtype, buf, len);
0829         if (NULL==cvn_buf)
0830         {
0831             UBF_LOG(log_error, "CBget: failed to convert data!");
0832             /* Error should be provided by conversation function */
0833             ret=EXFAIL;
0834         }
0835     }
0836     else
0837     {
0838         UBF_LOG(log_error, "CBget: Field not present!");
0839         ret=EXFAIL;
0840     }
0841 /***************************************** DEBUG *******************************/
0842     #ifdef UBF_API_DEBUG
0843     if (EXSUCCEED==ret)
0844     {
0845         __dbg_dtype_ext1->p_dump_data(__dbg_dtype_ext1, "CBget got data", buf, len);
0846     }
0847     #endif
0848 /*******************************************************************************/
0849     return ret;
0850 }
0851 
0852 /**
0853  * As all other functions. Currently this does not check to see is field
0854  * aligned or not. It should provide
0855  * @param p_ub_dst
0856  * @param p_ub_src
0857  * @return
0858  */
0859 expublic int Bcpy (UBFH * p_ub_dst, UBFH * p_ub_src)
0860 {
0861     int ret=EXSUCCEED;
0862     UBF_header_t *src_h = (UBF_header_t *)p_ub_src;
0863     UBF_header_t *dst_h = (UBF_header_t *)p_ub_dst;
0864     int dst_buf_len;
0865     API_ENTRY;
0866 
0867     UBF_LOG(log_debug, "Bcpy: About to copy from FB=%p to FB=%p",
0868                                     p_ub_src, p_ub_dst);
0869 
0870     if (EXSUCCEED==ret && NULL==p_ub_src)
0871     {
0872         ndrx_Bset_error_msg(BNOTFLD, "p_ub_src is NULL!");
0873         ret=EXFAIL;
0874     }
0875 
0876     if (EXSUCCEED==ret && NULL==p_ub_dst)
0877     {
0878         ndrx_Bset_error_msg(BNOTFLD, "p_ub_dst is NULL!");
0879         ret=EXFAIL;
0880     }
0881 
0882     if (EXSUCCEED==ret && 0!=strncmp(src_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
0883     {
0884         ndrx_Bset_error_msg(BNOTFLD, "source buffer magic failed!");
0885         ret=EXFAIL;
0886     }
0887 
0888     if (EXSUCCEED==ret && 0!=strncmp(dst_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
0889     {
0890         ndrx_Bset_error_msg(BNOTFLD, "destination buffer magic failed!");
0891         ret=EXFAIL;
0892     }
0893 
0894     if (EXSUCCEED==ret && dst_h->buf_len < src_h->bytes_used)
0895     {
0896         ndrx_Bset_error_fmt(BNOSPACE, "Destination buffer too short. "
0897                                     "Dest buf len: %d source buf bytes used: %d",
0898                                     dst_h->buf_len, src_h->bytes_used);
0899         ret=EXFAIL;
0900     }
0901 
0902     if (EXSUCCEED==ret)
0903     {
0904         /* save some original characteristics of dest buffer */
0905         dst_buf_len = dst_h->buf_len;
0906         /*memset(p_ub_dst, 0, dst_h->bytes_used);*/
0907         memcpy(p_ub_dst, p_ub_src, src_h->bytes_used);
0908         dst_h->buf_len = dst_buf_len;
0909         dst_h->bytes_used = src_h->bytes_used;
0910         
0911         /* save cache fields: */
0912         dst_h->cache_long_off = src_h->cache_long_off;
0913         dst_h->cache_char_off = src_h->cache_char_off;
0914         dst_h->cache_float_off = src_h->cache_float_off;
0915         dst_h->cache_double_off = src_h->cache_double_off;
0916         dst_h->cache_string_off = src_h->cache_string_off;
0917         dst_h->cache_carray_off = src_h->cache_carray_off;
0918         
0919         dst_h->cache_ptr_off = src_h->cache_ptr_off;
0920         dst_h->cache_ubf_off = src_h->cache_ubf_off;
0921         dst_h->cache_view_off = src_h->cache_view_off;
0922     
0923         
0924     }
0925     UBF_LOG(log_debug, "Bcpy: return %d", ret);
0926     
0927     return ret;
0928 }
0929 
0930 /**
0931  * Used buffer amount.
0932  * @param p_ub
0933  * @return
0934  */
0935 expublic long Bused (UBFH *p_ub)
0936 {
0937     long ret=EXFAIL;
0938     char fn[] = "Bused";
0939     UBF_header_t *hdr = (UBF_header_t *)p_ub;
0940     API_ENTRY;
0941 
0942     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
0943     {
0944         UBF_LOG(log_warn, "%s: arguments fail!", fn);
0945         ret=EXFALSE;
0946     }
0947     else
0948     {
0949         ret=hdr->bytes_used;
0950         UBF_LOG(log_debug, "%s: Buffer used: %ld!", fn, ret);
0951     }
0952 
0953     return ret;
0954 }
0955 
0956 /**
0957  * Generate valid field ID
0958  * @param fldtype
0959  * @param bfldid
0960  * @return 
0961  */
0962 expublic BFLDID Bmkfldid (int fldtype, BFLDID bfldid)
0963 {
0964 
0965     BFLDID ret = fldtype << EFFECTIVE_BITS;
0966     ret |= bfldid;
0967     
0968     return ret;
0969 }
0970 /**
0971  * Get the total occurrance count.
0972  * API version - no error checking.
0973  * @param p_ub
0974  * @param bfldid
0975  * @return
0976  */
0977 expublic BFLDOCC Boccur (UBFH * p_ub, BFLDID bfldid)
0978 {
0979     API_ENTRY;
0980 
0981     /* Do standard validation */
0982     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
0983     {
0984         UBF_LOG(log_warn, "_Boccur: arguments fail!");
0985         return EXFAIL;
0986     }
0987 
0988     return ndrx_Boccur (p_ub, bfldid);
0989 }
0990 
0991 /**
0992  * Check the field presence
0993  * API version - no error checking.
0994  */
0995 expublic int Bpres (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ)
0996 {
0997     API_ENTRY;
0998     
0999     /* Do standard validation */
1000     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
1001     {
1002         UBF_LOG(log_warn, "_Bpres: arguments fail!");
1003         return EXFALSE;
1004     }
1005 
1006     return _Bpres(p_ub, bfldid, occ);
1007 }
1008 
1009 /**
1010  * Public version of Bfldtype
1011  * @param bfldid
1012  * @return
1013  */
1014 expublic int Bfldtype (BFLDID bfldid)
1015 {
1016     return bfldid >> EFFECTIVE_BITS;
1017 }
1018 
1019 expublic char * Bboolco (char * expr)
1020 {
1021     API_ENTRY;
1022 
1023     if (NULL==expr)
1024     {
1025          ndrx_Bset_error_fmt(BEINVAL, "expr is NULL");
1026          return NULL;
1027     }
1028 
1029     {
1030     /* Lock the region */
1031     MUTEX_LOCK;
1032     {
1033         char *ret;
1034         ret = ndrx_Bboolco (expr);
1035         MUTEX_UNLOCK;
1036         return ret;
1037     }
1038     }
1039 }
1040 
1041 /**
1042  * Evaluate boolean expression
1043  * @param[in] p_ub UBF buffer
1044  * @param[in] tree compiled expression tree
1045  * @return 0 - false, 1 - true
1046  */
1047 expublic int Bboolev (UBFH * p_ub, char *tree)
1048 {
1049     API_ENTRY;
1050     
1051     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1052     {
1053         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1054         return EXFAIL;
1055     }
1056     
1057     if (NULL==tree)
1058     {
1059          ndrx_Bset_error_fmt(BEINVAL, "tree is NULL");
1060          return EXFAIL;
1061     }
1062     
1063     return ndrx_Bboolev (p_ub, tree);
1064 }
1065 
1066 /**
1067  * This function is not tested hardly. But it should work fine.
1068  * @param p_ub
1069  * @param tree
1070  * @return
1071  */
1072 expublic double Bfloatev (UBFH * p_ub, char *tree)
1073 {
1074     API_ENTRY;
1075     
1076     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1077     {
1078         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1079         return EXFAIL;
1080     }
1081     
1082     if (NULL==tree)
1083     {
1084          ndrx_Bset_error_fmt(BEINVAL, "tree is NULL");
1085          return EXFAIL;
1086     }
1087     
1088     return ndrx_Bfloatev (p_ub, tree);
1089 }
1090 
1091 expublic void Btreefree (char *tree)
1092 {
1093     API_ENTRY;
1094     ndrx_Btreefree (tree);
1095 }
1096 
1097 /**
1098  * This function keeps it's internal state in special buffer.
1099  * So this should not be used recursively or by multiple threads.
1100  * Also check against buffer sizes is done. Buffer shall not be modified during
1101  * the enumeration!
1102  * @param bnext_state state to be passed, in start of the searc this is reset
1103  * @param p_ub UBF buffer to work on
1104  * @param bfldid field next
1105  * @param occ occurrence next
1106  * @param buf if not NULL, returns value
1107  * @param len if not NULL, on intput buf len, on output number of bytes read
1108  * @param d_ptr raw data pointer, may be left NULL
1109  * @return -1 (FAIL)/0 (End of Buffer)/1 (Found)
1110  */
1111 exprivate int  Bnext_int(Bnext_state_t *bnext_state, UBFH *p_ub, BFLDID *bfldid, 
1112     BFLDOCC *occ, char *buf, BFLDLEN *len, char **d_ptr)
1113 {
1114     char fn[] = "Bnext_int";
1115     UBF_header_t *hdr = (UBF_header_t *)p_ub;
1116     /* Seems this caused tricks for multi threading.*/
1117 
1118     API_ENTRY;
1119 
1120     /* Do standard validation */
1121     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1122     {
1123         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1124         return EXFAIL;
1125     }
1126     else if (NULL==bfldid || NULL==occ || NULL==bnext_state)
1127     {
1128         ndrx_Bset_error_msg(BEINVAL, "Bnext: ptr of bfldid, occ or bnext_state is NULL!");
1129         return EXFAIL;
1130     }
1131     else if (*bfldid != BFIRSTFLDID && bnext_state->p_ub != p_ub)
1132     {
1133         ndrx_Bset_error_fmt(BEINVAL, "%s: Different buffer [state: %p used: %p] "
1134                                     "used for different state", fn,
1135                                     bnext_state->p_ub, p_ub);
1136         return EXFAIL;
1137     }
1138     else if (*bfldid != BFIRSTFLDID && bnext_state->size!=hdr->bytes_used)
1139     {
1140         ndrx_Bset_error_fmt(BEINVAL, "%s: Buffer size changed [state: %d used: %d] "
1141                                     "from last search", fn,
1142                                     bnext_state->size, hdr->bytes_used);
1143         return EXFAIL;
1144     }
1145     else
1146     {
1147         if (*bfldid == BFIRSTFLDID)
1148         {
1149             memset(bnext_state, 0, sizeof(Bnext_state_t));
1150         }
1151 
1152         return ndrx_Bnext(bnext_state, p_ub, bfldid, occ, buf, len, d_ptr);
1153     }
1154 }
1155 
1156 /**
1157  * Wrapper for Bnext_int
1158  */
1159 expublic int  Bnext(UBFH *p_ub, BFLDID *bfldid, BFLDOCC *occ, char *buf, BFLDLEN *len)
1160 {
1161     return Bnext_int(&G_ubf_tls->bnext_state, p_ub, bfldid, occ, buf, len, NULL);
1162 }
1163 
1164 /**
1165  * Wrapper for Bnext_int
1166  */
1167 expublic int Bnext2(Bnext_state_t *bnext_state, UBFH *p_ub, BFLDID *bfldid, 
1168     BFLDOCC *occ, char *buf, BFLDLEN *len, char **d_ptr)
1169 {
1170     return Bnext_int(bnext_state, p_ub, bfldid, occ, buf, len, d_ptr);
1171 }
1172 
1173 /**
1174  * API entry for Bproj
1175  * @param p_ub
1176  * @param fldlist
1177  * @return SUCCEED/FAIL
1178  */
1179 expublic int Bproj (UBFH * p_ub, BFLDID * fldlist)
1180 {
1181     char fn[] = "Bproj";
1182     int processed;
1183     API_ENTRY;
1184     /* Do standard validation */
1185     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1186     {
1187         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1188         return EXFAIL;
1189     }
1190     else
1191     {
1192         /* Call the implementation */
1193         return ndrx_Bproj (p_ub, fldlist, PROJ_MODE_PROJ, &processed);
1194     }
1195 }
1196 
1197 /**
1198  * Projection copy on 
1199  * @param p_ub_dst
1200  * @param p_ub_src
1201  * @param fldlist
1202  * @return
1203  */
1204 expublic int Bprojcpy (UBFH * p_ub_dst, UBFH * p_ub_src,
1205                                     BFLDID * fldlist)
1206 {
1207     char fn[] = "Bprojcpy";
1208     API_ENTRY;
1209     /* Do standard validation */
1210     if (EXSUCCEED!=validate_entry(p_ub_src, 0, 0, VALIDATE_MODE_NO_FLD))
1211     {
1212         UBF_LOG(log_warn, "%s: arguments fail for src buf!", fn);
1213         ndrx_Bappend_error_msg("(Bprojcpy: arguments fail for src buf!)");
1214         return EXFAIL;
1215     }
1216     else if (EXSUCCEED!=validate_entry(p_ub_dst, 0, 0, VALIDATE_MODE_NO_FLD))
1217     {
1218         UBF_LOG(log_warn, "%s: arguments fail for dst buf!", fn);
1219         ndrx_Bappend_error_msg("(Bprojcpy: arguments fail for dst buf!)");
1220         return EXFAIL;
1221     }
1222     else
1223     {
1224         /* Call the implementation */
1225         return ndrx_Bprojcpy (p_ub_dst, p_ub_src, fldlist);
1226     }
1227 }
1228 
1229 /**
1230  * Will not implement.
1231  * @param
1232  * @param
1233  * @return
1234  */
1235 expublic int Bindex (UBFH * p_ub, BFLDOCC occ)
1236 {
1237     UBF_LOG(log_debug, "Bindex: Not implemented - ignore!");
1238     return EXSUCCEED;
1239 }
1240 
1241 /**
1242  * Not implemented & not planning to do so
1243  * @param p_ub
1244  * @return 0 - number of fields indexed.
1245  */
1246 expublic BFLDOCC Bunindex (UBFH * p_ub)
1247 {
1248     UBF_LOG(log_debug, "Bunindex: Not implemented - ignore!");
1249     return 0;
1250 }
1251 
1252 /**
1253  * Not using indexes (Not implemented & not supported)
1254  * @param p_ub
1255  * @return 0 - size used for index
1256  */
1257 expublic long Bidxused (UBFH * p_ub)
1258 {
1259     UBF_LOG(log_debug, "Bidxused: Not implemented - ignore!");
1260     return 0;
1261 }
1262 
1263 /**
1264  * Not supported & will not be implemented.
1265  * @param p_ub
1266  * @param occ
1267  * @return
1268  */
1269 expublic int Brstrindex (UBFH * p_ub, BFLDOCC occ)
1270 {
1271     UBF_LOG(log_debug, "Brstrindex: Not implemented - ignore!");
1272     return EXSUCCEED;
1273 }
1274 
1275 /**
1276  * Will re-use _Bproj for this
1277  * @param p_ub
1278  * @param bfldid
1279  * @return
1280  */
1281 expublic int Bdelall (UBFH *p_ub, BFLDID bfldid)
1282 {
1283     int ret=EXSUCCEED;
1284     char fn[] = "Bdelall";
1285     int processed;
1286     API_ENTRY;
1287     
1288     UBF_LOG(log_warn, "%s: enter", fn);
1289     /* Do standard validation */
1290     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
1291     {
1292         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1293         ret=EXFAIL;
1294     }
1295     else
1296     {
1297         /* Call the implementation */
1298         ret=ndrx_Bproj (p_ub, &bfldid, PROJ_MODE_DELALL, &processed);
1299     }
1300 
1301     if (EXSUCCEED==ret && 0==processed)
1302     {
1303         /* Set error that none of fields have been deleted */
1304         ret=EXFAIL;
1305         ndrx_Bset_error_msg(BNOTPRES, "No fields have been deleted");
1306     }
1307     
1308     UBF_LOG(log_warn, "%s: return %d", fn, ret);
1309     return ret;
1310 }
1311 
1312 /**
1313  * Will re-use _Bproj for this
1314  * @param p_ub
1315  * @param fldlist
1316  * @return
1317  */
1318 expublic int Bdelete (UBFH *p_ub, BFLDID *fldlist)
1319 {
1320     int ret=EXSUCCEED;
1321     char fn[] = "Bdelete";
1322     int processed;
1323     API_ENTRY;
1324 
1325     UBF_LOG(log_warn, "%s: enter", fn);
1326     /* Do standard validation */
1327     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1328     {
1329         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1330         ret=EXFAIL;
1331     }
1332     else
1333     {
1334         /* Call the implementation */
1335         ret=ndrx_Bproj (p_ub, fldlist, PROJ_MODE_DELETE, &processed);
1336     }
1337 
1338     if (EXSUCCEED==ret && 0==processed)
1339     {
1340         /* Set error that none of fields have been deleted */
1341         ret=EXFAIL;
1342         ndrx_Bset_error_msg(BNOTPRES, "No fields have been deleted");
1343     }
1344     
1345     UBF_LOG(log_warn, "%s: return %d", fn, ret);
1346     return ret;
1347 }
1348 
1349 /**
1350  * Returns field number out of field ID
1351  * @param bfldid
1352  * @return 
1353  */
1354 expublic BFLDOCC Bfldno (BFLDID bfldid)
1355 {
1356     UBF_LOG(log_debug, "Bfldno: Mask: %d", EFFECTIVE_BITS_MASK);
1357     return (BFLDOCC) bfldid & EFFECTIVE_BITS_MASK;
1358 }
1359 
1360 /**
1361  * returns TRUE if buffer is UBF
1362  * @param p_ub - FB to test.
1363  * @return TRUE/FALSE
1364  */
1365 expublic int Bisubf (UBFH *p_ub)
1366 {
1367     int ret=EXTRUE;
1368     char fn[] = "Bisubf";
1369     API_ENTRY;
1370     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1371     {
1372         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1373         ret=EXFALSE;
1374         ndrx_Bunset_error();
1375     }
1376     
1377     return ret;
1378 }
1379 
1380 /**
1381  * Returns free buffer space that could be used by fields.
1382  * @param p_Fb
1383  * @return -1 on error or free buffer space
1384  */
1385 expublic long Bunused (UBFH *p_ub)
1386 {
1387     long ret=EXFAIL;
1388     char fn[] = "Bunused";
1389     UBF_header_t *hdr = (UBF_header_t *)p_ub;
1390     API_ENTRY;
1391 
1392     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1393     {
1394         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1395         ret=EXFALSE;
1396     }
1397     else
1398     {
1399         ret=(hdr->buf_len - hdr->bytes_used);
1400         UBF_LOG(log_debug, "%s: Buffer free: %ld!", fn, ret);
1401     }
1402 
1403     return ret;
1404 }
1405 
1406 /**
1407  * Return buffer size
1408  * @param p_ub
1409  * @return
1410  */
1411 expublic long Bsizeof (UBFH *p_ub)
1412 {
1413     long ret=EXFAIL;
1414     char fn[] = "Bsizeof";
1415     UBF_header_t *hdr = (UBF_header_t *)p_ub;
1416     API_ENTRY;
1417 
1418     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1419     {
1420         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1421         ret=EXFALSE;
1422     }
1423     else
1424     {
1425         ret=hdr->buf_len;
1426         UBF_LOG(log_debug, "%s: Buffer size: %ld!", fn, ret);
1427     }
1428 
1429     return ret;
1430 }
1431 
1432 /**
1433  * Return string descrypting the data type
1434  * @param bfldid
1435  * @return NULL (on error)/field type descr
1436  */
1437 expublic char * Btype (BFLDID bfldid)
1438 {
1439     int type = bfldid >> EFFECTIVE_BITS;
1440     API_ENTRY;
1441     
1442     if (IS_TYPE_INVALID(type))
1443     {
1444         ndrx_Bset_error_fmt(BTYPERR, "Unknown type number %d", type);
1445         return NULL;
1446     }
1447     else
1448     {
1449         return G_dtype_str_map[type].fldname;
1450     }
1451 }
1452 
1453 /**
1454  * Free up dynamically allocated buffer.
1455  * @param p_ub
1456  * @return 
1457  */
1458 expublic int Bfree (UBFH *p_ub)
1459 {
1460     int ret=EXSUCCEED;
1461     char fn[] = "Bfree";
1462     UBF_header_t *hdr = (UBF_header_t *)p_ub;
1463     API_ENTRY;
1464     
1465     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1466     {
1467         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1468         ret=EXFAIL;
1469     }
1470     else
1471     {
1472         memset(hdr->magic, 0, UBF_MAGIC_SIZE);
1473         NDRX_FREE(p_ub);
1474     }
1475     
1476     return ret;
1477 }
1478 
1479 /**
1480  * API function for Bupdate.
1481  * @param p_ub_dst - dest buffer to update
1482  * @param p_ub_src - source buffer to take values out from.
1483  * @return SUCEED/FAIL
1484  */
1485 expublic int Bupdate (UBFH *p_ub_dst, UBFH *p_ub_src)
1486 {
1487     int ret=EXSUCCEED;
1488     API_ENTRY;
1489     /* Do standard validation */
1490     UBF_LOG(log_debug, "Entering %s", __func__);
1491     if (EXSUCCEED!=validate_entry(p_ub_src, 0, 0, VALIDATE_MODE_NO_FLD))
1492     {
1493         UBF_LOG(log_warn, "%s: arguments fail for src buf!", __func__);
1494         ndrx_Bappend_error_msg("(Bupdate: arguments fail for src buf!)");
1495         ret=EXFAIL;
1496     }
1497     else if (EXSUCCEED!=validate_entry(p_ub_dst, 0, 0, VALIDATE_MODE_NO_FLD))
1498     {
1499         UBF_LOG(log_warn, "%s: arguments fail for dst buf!", __func__);
1500         ndrx_Bappend_error_msg("(Bupdate: arguments fail for dst buf!)");
1501         ret=EXFAIL;
1502     }
1503     else
1504     {
1505         /* Call the implementation */
1506         ret=ndrx_Bupdate (p_ub_dst, p_ub_src);
1507     }
1508     UBF_LOG(log_debug, "Return %s %d", __func__, ret);
1509     return ret;
1510 }
1511 
1512 /**
1513  * Concat two buffers
1514  * @param p_ub_dst
1515  * @param p_ub_src
1516  * @return 
1517  */
1518 expublic int Bconcat (UBFH *p_ub_dst, UBFH *p_ub_src)
1519 {
1520     int ret=EXSUCCEED;
1521     API_ENTRY;
1522     /* Do standard validation */
1523     UBF_LOG(log_debug, "Entering %s", __func__);
1524     if (EXSUCCEED!=validate_entry(p_ub_src, 0, 0, VALIDATE_MODE_NO_FLD))
1525     {
1526         UBF_LOG(log_warn, "%s: arguments fail for src buf!", __func__);
1527         ndrx_Bappend_error_msg("(Bconcat: arguments fail for src buf!)");
1528         ret=EXFAIL;
1529     }
1530     else if (EXSUCCEED!=validate_entry(p_ub_dst, 0, 0, VALIDATE_MODE_NO_FLD))
1531     {
1532         UBF_LOG(log_warn, "%s: arguments fail for dst buf!", __func__);
1533         ndrx_Bappend_error_msg("(Bconcat: arguments fail for dst buf!)");
1534         ret=EXFAIL;
1535     }
1536     else
1537     {
1538         /* Call the implementation */
1539         ret=ndrx_Bconcat (p_ub_dst, p_ub_src);
1540     }
1541     UBF_LOG(log_debug, "Return %s %d", __func__, ret);
1542     return ret;
1543 }
1544 
1545 /**
1546  * CBfind API entry
1547  * @return NULL/ptr to value
1548  */
1549 expublic char * CBfind (UBFH * p_ub, 
1550                     BFLDID bfldid, BFLDOCC occ, BFLDLEN * len, int usrtype)
1551 {
1552     int bfldid_type = (bfldid>>EFFECTIVE_BITS);
1553     API_ENTRY;
1554 
1555     UBF_LOG(log_debug, "%s: bfldid: %d occ: %hd", __func__, bfldid, occ);
1556 
1557     /* Do standard validation */
1558     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
1559     {
1560         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1561         return NULL;
1562     }
1563     
1564     /* validate user specified type */
1565     VALIDATE_USER_TYPE(usrtype, return NULL);
1566     
1567     /* validate that type is not complex */
1568     if (IS_TYPE_COMPLEX(bfldid_type))
1569     {
1570         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", bfldid_type);
1571         return NULL;
1572     }
1573 
1574     /* Call the implementation */
1575     return ndrx_CBfind (p_ub, bfldid, occ, len, usrtype, CB_MODE_TEMPSPACE, 0);
1576 }
1577 
1578 /**
1579  * This almost is the same as CBfind only difference is that buffer is allocated
1580  * for user. Ant it is user's responsibility to free up memory.
1581  * @param p_ub
1582  * @param bfldid
1583  * @param occ
1584  * @param usrtype
1585  * @param extralen (IN) - extra buffer to allocate/ (OUT) - size of bufer in use.
1586  * @return NULL (failure)/ptr - in case of success
1587  */
1588 expublic char * CBgetalloc (UBFH * p_ub, BFLDID bfldid,
1589                                     BFLDOCC occ, int usrtype, BFLDLEN *extralen)
1590 {
1591     char *ret=NULL;
1592     char fn[] = "CBgetalloc";
1593     int bfldid_type = (bfldid>>EFFECTIVE_BITS);
1594     API_ENTRY;
1595     UBF_LOG(log_debug, "%s: bfldid: %d occ: %hd", fn, bfldid, occ);
1596 
1597     /* Do standard validation */
1598     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
1599     {
1600         UBF_LOG(log_warn, "CBgetalloc: arguments fail!");
1601         return NULL;
1602     }
1603     
1604     /* validate user specified type */
1605     VALIDATE_USER_TYPE(usrtype, return NULL);
1606     
1607     /* validate that type is not complex */
1608     if (IS_TYPE_COMPLEX(bfldid_type))
1609     {
1610         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", bfldid_type);
1611         return NULL;
1612     }
1613 
1614     /* Call the implementation */
1615     ret=ndrx_CBfind (p_ub, bfldid, occ, extralen, usrtype, CB_MODE_ALLOC, 
1616                     (NULL!=extralen?*extralen:0));
1617 
1618     UBF_LOG(log_debug, "%s: returns ret=%p", fn, ret);
1619 
1620     return ret;
1621 }
1622 
1623 /**
1624  * API entry for Bfindocc
1625  * @param p_ub
1626  * @param bfldid
1627  * @param buf
1628  * @param len
1629  * @return
1630  */
1631 expublic BFLDOCC Bfindocc (UBFH *p_ub, BFLDID bfldid,
1632                                         char * buf, BFLDLEN len)
1633 {
1634     char *fn = "Bfindocc";
1635     API_ENTRY;
1636 
1637     UBF_LOG(log_debug, "%s: bfldid: %d", fn, bfldid);
1638 
1639     if (NULL==buf)
1640     {
1641          ndrx_Bset_error_fmt(BEINVAL, "buf is NULL");
1642          return EXFAIL;
1643     }
1644     /* Do standard validation */
1645     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
1646     {
1647         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1648         return EXFAIL;
1649     }
1650 
1651 
1652     /* validate user type */
1653 
1654     /* Call the implementation */
1655     return ndrx_Bfindocc (p_ub, bfldid, buf, len);
1656 }
1657 
1658 /**
1659  * API entry for CBfindocc
1660  * @param p_ub
1661  * @param bfldid
1662  * @param buf
1663  * @param len
1664  * @return
1665  */
1666 expublic BFLDOCC CBfindocc (UBFH *p_ub, BFLDID bfldid,
1667                                         char * buf, BFLDLEN len, int usrtype)
1668 {
1669     char *fn = "CBfindocc";
1670     int bfldid_type = (bfldid>>EFFECTIVE_BITS);
1671     API_ENTRY;
1672 
1673     UBF_LOG(log_debug, "%s: bfldid: %d", fn, bfldid);
1674 
1675     if (NULL==buf)
1676     {
1677          ndrx_Bset_error_fmt(BEINVAL, "buf is NULL");
1678          return EXFAIL;
1679     }
1680  
1681     /* Do standard validation */
1682     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
1683     {
1684         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1685         return EXFAIL;
1686     }
1687 
1688     /* validate user specified type */
1689     VALIDATE_USER_TYPE(usrtype, return EXFAIL);
1690     
1691     /* validate that type is not complex */
1692     if (IS_TYPE_COMPLEX(bfldid_type))
1693     {
1694         ndrx_Bset_error_fmt(BEBADOP, "Unsupported bfldid type %d", bfldid_type);
1695         return EXFAIL;
1696     }
1697 
1698     /* Call the implementation */
1699     return ndrx_CBfindocc (p_ub, bfldid, buf, len, usrtype);
1700 }
1701 
1702 /**
1703  * API version of Bgetalloc
1704  * @param p_ub
1705  * @param bfldid
1706  * @param occ
1707  * @param len
1708  * @return NULL (on failure)/ ptr on success.
1709  */
1710 expublic char * Bgetalloc (UBFH * p_ub, BFLDID bfldid, BFLDOCC occ, BFLDLEN *extralen)
1711 {
1712     char *fn = "Bgetalloc";
1713     API_ENTRY;
1714 
1715     UBF_LOG(log_debug, "%s: bfldid: %d", fn, bfldid);
1716 
1717     /* Do standard validation */
1718     if (EXSUCCEED!=validate_entry(p_ub, bfldid, occ, 0))
1719     {
1720         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1721         return NULL;
1722     }
1723 
1724     /* Call the implementation */
1725     return ndrx_Bgetalloc (p_ub, bfldid, occ, extralen);
1726 }
1727 
1728 /**
1729  * Bfindlast API entry
1730  * @return NULL/ptr to value
1731  */
1732 expublic char * Bfindlast (UBFH * p_ub, BFLDID bfldid,
1733                                     BFLDOCC *occ, BFLDLEN *len)
1734 {
1735     API_ENTRY;
1736 
1737     UBF_LOG(log_debug, "%s: bfldid: %d", __func__, bfldid);
1738 
1739     /* Do standard validation */
1740     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
1741     {
1742         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1743         return NULL;
1744     }
1745 
1746     /* Call the implementation */
1747     return ndrx_Bfindlast (p_ub, bfldid, occ, len);
1748 }
1749 
1750 /**
1751  * Bfindlast API entry
1752  * @return NULL/ptr to value
1753  */
1754 expublic int Bgetlast (UBFH *p_ub, BFLDID bfldid,
1755                         BFLDOCC *occ, char *buf, BFLDLEN *len)
1756 {
1757     API_ENTRY;
1758 
1759     UBF_LOG(log_debug, "%s: bfldid: %d", __func__, bfldid);
1760 
1761     /* Do standard validation */
1762     if (EXSUCCEED!=validate_entry(p_ub, bfldid, 0, 0))
1763     {
1764         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1765         return EXFAIL;
1766     }
1767 
1768     /* Call the implementation */
1769     return ndrx_Bgetlast (p_ub, bfldid, occ, buf, len);
1770 }
1771 
1772 
1773 /**
1774  * API function for Bfprint
1775  * @param p_ub
1776  * @param outf
1777  * @return
1778  */
1779 expublic int Bfprint (UBFH *p_ub, FILE * outf)
1780 {
1781     API_ENTRY;
1782     VIEW_ENTRY3;
1783     
1784     /* Do standard validation */
1785     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1786     {
1787         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1788         return EXFAIL;
1789     }
1790     /* check output file */
1791     if (NULL==outf)
1792     {
1793         ndrx_Bset_error_msg(BEINVAL, "output file cannot be NULL!");
1794         return EXFAIL;
1795     }
1796 
1797     return ndrx_Bfprint (p_ub, outf, NULL, NULL, 0);
1798 }
1799 
1800 /**
1801  * Print UBF buffer by using callback function for data outputting
1802  * @param p_ub UBF buffer to print
1803  * @param dataptr1 user pointer passed back to callback
1804  * @param p_writef callback function for data output. Note that 'buffer' argument
1805  *  is allocated and deallocated by Bfprintcb it self. The string is zero byte
1806  *  terminated. The dataptr1 passed to function is forwarded to callback func.
1807  *  *datalen* includes the EOS byte. if do_write is set to TRUE, the data in buffer
1808  *  is written to output file.
1809  * @return EXSUCCEED/EXFAIL
1810  */
1811 expublic int Bfprintcb (UBFH *p_ub, 
1812         ndrx_plugin_tplogprintubf_hook_t p_writef, void *dataptr1)
1813 {
1814     API_ENTRY;
1815     VIEW_ENTRY3;
1816     
1817     /* Do standard validation */
1818     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1819     {
1820         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1821         return EXFAIL;
1822     }
1823     /* check output file */
1824     if (NULL==p_writef)
1825     {
1826         ndrx_Bset_error_msg(BEINVAL, "p_writef callback cannot be NULL!");
1827         return EXFAIL;
1828     }
1829 
1830     return ndrx_Bfprint (p_ub, NULL, p_writef, dataptr1, 0);
1831 }
1832 
1833 /**
1834  * API function for Bprint
1835  * uses _Bfprint in core with stdout.
1836  * @param p_ub
1837  * @param outf
1838  * @return
1839  */
1840 expublic int Bprint (UBFH *p_ub)
1841 {
1842     API_ENTRY;
1843 
1844     /* Do standard validation */
1845     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1846     {
1847         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
1848         return EXFAIL;
1849     }
1850 
1851     return ndrx_Bfprint (p_ub, stdout, NULL, NULL, 0);
1852 }
1853 
1854 /**
1855  * Print UBF buffer to logger
1856  * @param lev logging level to start print at
1857  * @param title title of the dump
1858  * @param p_ub UBF buffer
1859  */
1860 expublic void   ndrx_tplogprintubf(int lev, char *title, UBFH *p_ub)
1861 {
1862     API_ENTRY;
1863     ndrx_debug_t * dbg = debug_get_tp_ptr();
1864     
1865     if (EXSUCCEED==ndrx_view_init() && dbg->level>=lev)
1866     {
1867 
1868 #ifdef UBF_API_DEBUG
1869         UBF_header_t *buf = (UBF_header_t *)p_ub;
1870         UBF_LOG(lev, "buffer_type = [%x]", (unsigned)buf->buffer_type);
1871         UBF_LOG(lev, "version = [%x]", (unsigned)buf->buffer_type);
1872         UBF_LOG(lev, "magic = [%c%c%c%c]", buf->magic[0], buf->magic[1], buf->magic[2], buf->magic[3]);
1873         UBF_LOG(lev, "cache_long_off = [%x]", buf->cache_long_off);
1874         UBF_LOG(lev, "cache_char_off = [%x]", buf->cache_char_off);
1875         UBF_LOG(lev, "cache_float_off = [%x]", buf->cache_float_off);
1876         UBF_LOG(lev, "cache_double_off = [%x]", buf->cache_double_off);
1877         UBF_LOG(lev, "cache_string_off = [%x]", buf->cache_string_off);
1878         UBF_LOG(lev, "buf_len = [%x]", buf->buf_len);
1879         UBF_LOG(lev, "bytes_used = [%x]", buf->bytes_used);
1880         UBF_LOG(lev, "bfldid = [%x]", buf->bfldid);
1881 #endif
1882 
1883         TP_LOG(lev, "%s", title);
1884         /* Do standard validation */
1885         if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1886         {
1887             UBF_LOG(log_warn, "arguments fail - nothing to log");
1888         }
1889         else
1890         {
1891             /* use plugin callback */
1892             /* on entry... we need to perform locks */
1893             ndrx_debug_lock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
1894             ndrx_Bfprint (p_ub, ((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr)->fp, 
1895                     ndrx_G_plugins.p_ndrx_tplogprintubf_hook, NULL, 0);
1896             ndrx_debug_unlock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
1897             /* on exit we need to perform unlocks */
1898         }
1899     }
1900 }
1901 
1902 /**
1903  * API function for Btypcvt
1904  * @param to_len
1905  * @param to_type
1906  * @param from_buf
1907  * @param from_type
1908  * @param from_len
1909  * @return
1910  */
1911 expublic char * Btypcvt (BFLDLEN * to_len, int to_type,
1912                     char *from_buf, int from_type, BFLDLEN from_len)
1913 {
1914     char *fn = "Btypcvt";
1915     dtype_str_t * dtype;
1916     API_ENTRY;
1917 
1918 
1919     if (NULL==from_buf)
1920     {
1921         ndrx_Bset_error_fmt(BEINVAL, "%s:from buf cannot be NULL!", fn);
1922         return NULL; /* <<< RETURN! */
1923     }
1924 
1925     if (IS_TYPE_INVALID(from_type))
1926     {
1927         ndrx_Bset_error_fmt(BTYPERR, "%s: Invalid from_type %d", fn, from_type);
1928         return NULL; /* <<< RETURN! */
1929     }
1930     
1931     if (IS_TYPE_COMPLEX(from_type))
1932     {
1933         ndrx_Bset_error_fmt(BEBADOP, "Unsupported from_type type %d", from_type);
1934         return NULL;
1935     }
1936     
1937     if (IS_TYPE_INVALID(to_type))
1938     {
1939         ndrx_Bset_error_fmt(BTYPERR, "%s: Invalid from_type %d", fn, to_type);
1940         return NULL; /* <<< RETURN! */
1941     }
1942     
1943     if (IS_TYPE_COMPLEX(to_type))
1944     {
1945         ndrx_Bset_error_fmt(BEBADOP, "Unsupported to_type type %d", to_type);
1946         return NULL;
1947     }
1948     
1949     /*
1950      * We provide from length, it is needed for core implementation.
1951      */
1952     if (BFLD_CARRAY!=from_type)
1953     {
1954         int payload_size=0;
1955         dtype = &G_dtype_str_map[from_type];
1956         /* calculate the actual data len, required by type converter. */
1957         dtype->p_get_data_size(dtype, from_buf, from_len, &from_len);
1958     }
1959     
1960     /* Call implementation */
1961     return ndrx_Btypcvt(to_len, to_type, from_buf, from_type, from_len);
1962 }
1963 
1964 /**
1965  * API entry for Bextread
1966  * @param p_ub - UBF buffer
1967  * @param inf - file to read from 
1968  * @return SUCCEED/FAIL
1969  */
1970 expublic int Bextread (UBFH * p_ub, FILE *inf)
1971 {
1972     char *fn = "Bextread";
1973     API_ENTRY;
1974 
1975     /* Do standard validation */
1976     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
1977     {
1978         UBF_LOG(log_warn, "%s: arguments fail!", fn);
1979         return EXFAIL;
1980     }
1981     /* check output file */
1982     if (NULL==inf)
1983     {
1984         ndrx_Bset_error_msg(BEINVAL, "Input file cannot be NULL!");
1985         return EXFAIL;
1986     }
1987     return ndrx_Bextread (p_ub, inf, NULL, NULL, 0, NULL);
1988 }
1989 
1990 /**
1991  * Read UBF buffer from printed/text format UBF.
1992  * @param p_ub ptr to UBF buffer
1993  * @param p_readf callback to read function. Function shall provide back data
1994  *  to ndrx_Bextread(). The reading must be feed line by line. The input line
1995  *  must be terminated with EOS. The buffer size which accepts the input line
1996  *  is set by `bufsz'. The function receives forwarded \p dataptr1 argument.
1997  *  Once EOF is reached, the callback shall return read of 0 bytes. Otherwise
1998  *  it must return number of bytes read, including EOS.
1999  * @param dataptr1 option user pointer forwarded to \p p_readf.
2000  * @return SUCCEED/FAIL
2001  */
2002 expublic int Bextreadcb (UBFH * p_ub, 
2003         long (*p_readf)(char *buffer, long bufsz, void *dataptr1), void *dataptr1)
2004 {
2005     API_ENTRY;
2006 
2007     /* Do standard validation */
2008     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
2009     {
2010         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
2011         return EXFAIL;
2012     }
2013     /* check output file */
2014     if (NULL==p_readf)
2015     {
2016         ndrx_Bset_error_msg(BEINVAL, "Callback function cannot be NULL!");
2017         return EXFAIL;
2018     }
2019     
2020     return ndrx_Bextread (p_ub, NULL, p_readf, dataptr1, 0, NULL);
2021 }
2022 
2023 /**
2024  * API entry for Bboolpr
2025  * @param tree - compiled expression tree
2026  * @param outf - file to print to tree
2027  */
2028 expublic void Bboolpr (char * tree, FILE *outf)
2029 {
2030     API_ENTRY;
2031 
2032     /* Do standard validation */
2033     if (NULL==tree)
2034     {
2035         ndrx_Bset_error_msg(BEINVAL, "Evaluation tree cannot be NULL!");
2036         return;
2037     }
2038     /* check output file */
2039     if (NULL==outf)
2040     {
2041         ndrx_Bset_error_msg(BEINVAL, "Input file cannot be NULL!");
2042         return;
2043     }
2044 
2045     ndrx_Bboolpr (tree, outf, NULL, NULL);
2046     /* put newline at the end. */
2047     fprintf(outf, "\n");
2048 }
2049 
2050 /**
2051  * API entry for Bboolpr. Print boolean expression to callback function.
2052  * @param[in] tree compiled boolean expression tree to print
2053  * @param[in] p_writef callback function to which print the buffer. The datalen
2054  *  includes the EOS symbol.
2055  * @param[in] dataptr1 user pointer to forward to \p p_writef function
2056  */
2057 expublic void Bboolprcb (char * tree, 
2058         int (*p_writef)(char *buffer, long datalen, void *dataptr1), void *dataptr1)
2059 {
2060     API_ENTRY;
2061 
2062     /* Do standard validation */
2063     if (NULL==tree)
2064     {
2065         ndrx_Bset_error_msg(BEINVAL, "Evaluation tree cannot be NULL!");
2066         return;
2067     }
2068     /* check output file */
2069     if (NULL==p_writef)
2070     {
2071         ndrx_Bset_error_msg(BEINVAL, "Input callback function p_writef "
2072                 "cannot be NULL!");
2073         return;
2074     }
2075 
2076     ndrx_Bboolpr (tree, NULL, p_writef, dataptr1);
2077     /* put newline at the end. */
2078     p_writef("\n", 2, dataptr1);
2079 }
2080 
2081 /**
2082  * String macro for CBadd
2083  * @param p_ub
2084  * @param bfldid
2085  * @param buf
2086  * @return
2087  */
2088 expublic int Badds (UBFH *p_ub, BFLDID bfldid, char *buf)
2089 {
2090     return CBadd(p_ub, bfldid, buf, 0, BFLD_STRING);
2091 }
2092 
2093 /**
2094  * String macro for CBchg
2095  * @param p_ub
2096  * @param bfldid
2097  * @param occ
2098  * @param buf
2099  * @return
2100  */
2101 expublic int Bchgs (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ, char *buf)
2102 {
2103     return CBchg(p_ub, bfldid, occ, buf, 0, BFLD_STRING);
2104 }
2105 
2106 /**
2107  * String macro for CBgets
2108  * @param p_ub
2109  * @param bfldid
2110  * @param occ
2111  * @param buf
2112  * @return
2113  */
2114 expublic int Bgets (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ, char *buf)
2115 {
2116     return CBget(p_ub, bfldid, occ, buf, 0, BFLD_STRING);
2117 }
2118 
2119 /**
2120  * String macro for CBgetalloc
2121  * @param p_ub
2122  * @param bfldid
2123  * @param occ
2124  * @param extralen
2125  * @return
2126  */
2127 expublic char * Bgetsa (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ, BFLDLEN *extralen)
2128 {
2129     return CBgetalloc(p_ub, bfldid, occ, BFLD_STRING, extralen);
2130 }
2131 
2132 /**
2133  * String macro for CBfind
2134  * @param p_ub
2135  * @param bfldid
2136  * @param occ
2137  * @return
2138  */
2139 expublic char * Bfinds (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ)
2140 {
2141     return CBfind(p_ub, bfldid, occ, 0, BFLD_STRING);
2142 }
2143 
2144 /**
2145  * API entry for Bread. Read binary UBF buffer form input stream
2146  * @param p_ub UBF buffer
2147  * @param inf input file stream
2148  * @return EXSUCCEED(0)/EXFAIL(-1)
2149  */
2150 expublic int Bread (UBFH * p_ub, FILE * inf)
2151 {
2152     char *fn = "Bread";
2153     API_ENTRY;
2154 
2155     /* Do standard validation */
2156     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
2157     {
2158         UBF_LOG(log_warn, "%s: arguments fail!", fn);
2159         return EXFAIL;
2160     }
2161     /* check output file */
2162     if (NULL==inf)
2163     {
2164         ndrx_Bset_error_msg(BEINVAL, "Input file cannot be NULL!");
2165         return EXFAIL;
2166     }
2167 
2168     return ndrx_Bread (p_ub, inf, NULL, NULL);
2169 }
2170 
2171 /**
2172  * API entry for Bwrite. Write binary buffer to output stream.
2173  * @param p_ub UBF buffer to read from
2174  * @param outf output stream to write to
2175  * @return EXSUCCEED/EXFAIL, Berror set in case of problems.
2176  */
2177 expublic int Bwrite (UBFH *p_ub, FILE * outf)
2178 {
2179     API_ENTRY;
2180 
2181     /* Do standard validation */
2182     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
2183     {
2184         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
2185         return EXFAIL;
2186     }
2187     /* check output file */
2188     if (NULL==outf)
2189     {
2190         ndrx_Bset_error_msg(BEINVAL, "Output file cannot be NULL!");
2191         return EXFAIL;
2192     }
2193 
2194     return ndrx_Bwrite (p_ub, outf, NULL, NULL);
2195 }
2196 
2197 /**
2198  * Read UBF buffer from callback function. The format is binary, platform specific.
2199  * @param p_ub UBF buffer to write to
2200  * @param[in] p_readf is a callback function which is used to read data from.
2201  *  The special requirement of this callback is that, The number of bytes which
2202  *  must be read are specified in `bufsz', otherwise error will occur. In case of
2203  *  callback function error by it self, -1 can be returned in that case. `buffer'
2204  *  is buffer where read data must be put in. `dataptr1` is forwarded from \p
2205  *  dataptr1 argument.
2206  * @param[in] dataptr1 is value which is forwarded to \p p_writef. This is optional
2207  *  and may contain NULL.
2208  * @return EXSUCCEED/EXFAIL, Berror set in case of problems.
2209  */
2210 expublic int Breadcb (UBFH * p_ub, 
2211         long (*p_readf)(char *buffer, long bufsz, void *dataptr1), void *dataptr1)
2212 {
2213     API_ENTRY;
2214 
2215     /* Do standard validation */
2216     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
2217     {
2218         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
2219         return EXFAIL;
2220     }
2221     /* check output file */
2222     if (NULL==p_readf)
2223     {
2224         ndrx_Bset_error_msg(BEINVAL, "Read callback function must not be NULL!");
2225         return EXFAIL;
2226     }
2227 
2228     return ndrx_Bread (p_ub, NULL, p_readf, dataptr1);
2229 }
2230 
2231 /**
2232  * Write UBF buffer to callback function
2233  * @param p_ub UBF buffer to read from
2234  * @param[in] p_writef is a callback function which receives portions of UBF buffer.
2235  *  once function is called, all `bufsz' bytes must be accepted. And function
2236  *  at success must return the number of bytes written (i.e. the same `bufsz')
2237  *  other cases are considered as errro. The `buffer' is pointer where buffer
2238  *  bytes are stored. The `dataptr1' is a value forwarded from the Bwritecb()
2239  *  arguments.
2240  * @param[in] dataptr1 is value which is forwarded to \p p_writef. This is optional
2241  *  and may contain NULL.
2242  * @return EXSUCCEED/EXFAIL, Berror set in case of problems.
2243  */
2244 expublic int Bwritecb (UBFH *p_ub, 
2245         long (*p_writef)(char *buffer, long bufsz, void *dataptr1), void *dataptr1)
2246 {
2247     API_ENTRY;
2248 
2249     /* Do standard validation */
2250     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
2251     {
2252         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
2253         return EXFAIL;
2254     }
2255     /* check output file */
2256     if (NULL==p_writef)
2257     {
2258         ndrx_Bset_error_msg(BEINVAL, "Output callback function must not be NULL!");
2259         return EXFAIL;
2260     }
2261 
2262     return ndrx_Bwrite (p_ub, NULL, p_writef, dataptr1);
2263 }
2264 
2265 /**
2266  * Get the length of the field
2267  * @param p_ub
2268  * @param bfldid
2269  * @param occ
2270  * @return 
2271  */
2272 expublic int Blen (UBFH *p_ub, BFLDID bfldid, BFLDOCC occ)
2273 {
2274     API_ENTRY;
2275 
2276     if (EXSUCCEED!=validate_entry(p_ub, bfldid,occ,0))
2277     {
2278         UBF_LOG(log_warn, "Bget: arguments fail!");
2279         return EXFAIL; /* <<<< RETURN HERE! */
2280     }
2281 
2282     return ndrx_Blen (p_ub, bfldid, occ);
2283 }
2284 
2285 /**
2286  * Set callback function that can be used in expressions for long value.
2287  * @param funcname
2288  * @param functionPtr
2289  * @return SUCCEED/FAIL
2290  */
2291 expublic int Bboolsetcbf (char *funcname, 
2292             long (*functionPtr)(UBFH *p_ub, char *funcname))
2293 {
2294     API_ENTRY;
2295     {
2296 /* Lock the region */
2297     MUTEX_LOCK;
2298     {
2299         int ret;
2300         ret = ndrx_Bboolsetcbf2 (funcname, functionPtr, NDRX_CBFUNTYPE_NOARGS);
2301         MUTEX_UNLOCK;
2302         return ret;
2303     }
2304     }
2305 }
2306 
2307 /**
2308  * Set callback function that can be used in expressions for long value.
2309  * Version with one argument in callback from script
2310  * @param funcname
2311  * @param functionPtr
2312  * @return SUCCEED/FAIL
2313  */
2314 expublic int Bboolsetcbf2 (char *funcname, 
2315             long (*functionPtr)(UBFH *p_ub, char *funcname, char *arg1))
2316 {
2317     API_ENTRY;
2318     {
2319 /* Lock the region */
2320     MUTEX_LOCK;
2321     {
2322         int ret;
2323         ret = ndrx_Bboolsetcbf2 (funcname, functionPtr, NDRX_CBFUNTYPE_ARG1);
2324         MUTEX_UNLOCK;
2325         return ret;
2326     }
2327     }
2328 }
2329 
2330 
2331 /**
2332  * VIEW - test is field is NULL
2333  * @param cstruct ptr to C structure in memory
2334  * @param cname field name
2335  * @param occ occurrence of the field (array index)
2336  * @param view view name
2337  * @return EXFAIL/EXFALSE/EXTRUE
2338  */
2339 expublic int Bvnull(char *cstruct, char *cname, BFLDOCC occ, char *view)
2340 {
2341     int ret = EXSUCCEED;
2342     API_ENTRY;
2343     VIEW_ENTRY;
2344     
2345     if (NULL==cstruct)
2346     {
2347         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2348         EXFAIL_OUT(ret);
2349     }
2350     
2351     if (NULL==cname || EXEOS==cname[0])
2352     {
2353         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2354         EXFAIL_OUT(ret);
2355     }
2356     
2357     if (NULL==view || EXEOS==view[0])
2358     {
2359         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2360         EXFAIL_OUT(ret);
2361     }
2362     
2363     ret=ndrx_Bvnull(cstruct, cname, occ, view);
2364     
2365 out:
2366 
2367     return ret;
2368 }
2369 
2370 /**
2371  * Init structure element.
2372  * Count indicators and Length indicators (where appropriate) are set to zero.
2373  * @param cstruct C structure ptr in mem
2374  * @param cname field name
2375  * @param view view name
2376  * @return EXSUCCEED/EXFAIL
2377  */
2378 expublic int Bvselinit(char *cstruct, char *cname, char *view)
2379 {
2380     int ret = EXSUCCEED;
2381     API_ENTRY;
2382     VIEW_ENTRY;
2383     
2384     if (NULL==cstruct)
2385     {
2386         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2387         EXFAIL_OUT(ret);
2388     }
2389     
2390     if (NULL==cname || EXEOS==cname[0])
2391     {
2392         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2393         EXFAIL_OUT(ret);
2394     }
2395     
2396     if (NULL==view || EXEOS==view[0])
2397     {
2398         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2399         EXFAIL_OUT(ret);
2400     }
2401     
2402     ret=ndrx_Bvselinit(cstruct, cname, view);
2403     
2404 out:
2405     return ret;
2406 }
2407 
2408 /**
2409  * Initialize view fields (all)
2410  * @param cstruct memory addr
2411  * @param view view name
2412  * @return EXSUCCEED/EXFAIL
2413  */
2414 expublic int Bvsinit(char *cstruct, char *view)
2415 {
2416     int ret = EXSUCCEED;
2417     API_ENTRY;
2418     VIEW_ENTRY;
2419     
2420     if (NULL==cstruct)
2421     {
2422         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2423         EXFAIL_OUT(ret);
2424     }
2425     
2426     if (NULL==view || EXEOS==view[0])
2427     {
2428         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2429         EXFAIL_OUT(ret);
2430     }
2431     
2432     ret=ndrx_Bvsinit(cstruct, view);
2433 out:
2434     return ret;
2435 }
2436 
2437 /**
2438  * Refresh view cache not supported by Enduro/X (and not needed).
2439  */
2440 expublic void Bvrefresh(void)
2441 {
2442     UBF_LOG(log_warn, "Bvrefresh - not supported by Enduro/X");
2443 }
2444 
2445 /**
2446  * Set view option (thread safe)
2447  * @param cname field name 
2448  * @param option option (see B_FTOS, B_STOF, B_OFF, B_BOTH)
2449  * @param view view name
2450  * @return EXSUCCEED/EXFAIL
2451  */
2452 expublic int Bvopt(char *cname, int option, char *view)
2453 {
2454     int ret = EXSUCCEED;
2455     API_ENTRY;
2456     VIEW_ENTRY;
2457     
2458     if (NULL==view || EXEOS==view[0])
2459     {
2460         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2461         EXFAIL_OUT(ret);
2462     }
2463     
2464     if (NULL==cname || EXEOS==cname[0])
2465     {
2466         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2467         EXFAIL_OUT(ret);
2468     }
2469     
2470     ret=ndrx_Bvopt(cname, option, view);
2471     
2472 out:
2473     return ret;
2474 }
2475 
2476 /**
2477  * Convert UBF buffer to C struct
2478  * @param p_ub UBF buffer
2479  * @param cstruct ptr to mem block
2480  * @param view view name
2481  * @return EXSUCCEED/EXFAIL
2482  */
2483 expublic int Bvftos(UBFH *p_ub, char *cstruct, char *view)
2484 {
2485     int ret = EXSUCCEED;
2486     API_ENTRY;
2487     VIEW_ENTRY;
2488     
2489     if (NULL==view || EXEOS==view[0])
2490     {
2491         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2492         EXFAIL_OUT(ret);
2493     }
2494     
2495     if (NULL==cstruct)
2496     {
2497         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2498         EXFAIL_OUT(ret);
2499     }
2500     
2501     if (NULL==p_ub)
2502     {
2503         ndrx_Bset_error_msg(BEINVAL, "p_ub is NULL!");
2504         EXFAIL_OUT(ret);
2505     }
2506     
2507     ret=ndrx_Bvftos(p_ub, cstruct, view);
2508     
2509 out:
2510     return ret;
2511 }
2512 
2513 /**
2514  * Copy data from structure to UBF
2515  * @param p_ub ptr to UBF buffer
2516  * @param cstruct ptr to memory block
2517  * @param mode BUPDATE, BOJOIN, BJOIN, BCONCAT
2518  * @param view view name
2519  * @return EXSUCCEED/EXFAIL
2520  */
2521 expublic int Bvstof(UBFH *p_ub, char *cstruct, int mode, char *view)
2522 {
2523     int ret = EXSUCCEED;
2524     API_ENTRY;
2525     VIEW_ENTRY;
2526     
2527     if (NULL==view || EXEOS==view[0])
2528     {
2529         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2530         EXFAIL_OUT(ret);
2531     }
2532     
2533     if (NULL==cstruct)
2534     {
2535         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2536         EXFAIL_OUT(ret);
2537     }
2538     
2539     if (NULL==p_ub)
2540     {
2541         ndrx_Bset_error_msg(BEINVAL, "p_ub is NULL!");
2542         EXFAIL_OUT(ret);
2543     }
2544     
2545     ret=ndrx_Bvstof(p_ub, cstruct, mode, view);
2546     
2547 out:
2548     return ret;
2549 }
2550 /**
2551  * Join two buffers, update only existing fields in dest, remove missing fields
2552  * @param dest - dest buffer (being modified)
2553  * @param src - src buffer (not modified)
2554  * @return EXSUCCEED/EXFAIL
2555  */
2556 expublic int Bjoin(UBFH *dest, UBFH *src)
2557 {
2558     int ret=EXSUCCEED;
2559     API_ENTRY;
2560     /* Do standard validation */
2561     UBF_LOG(log_debug, "Entering %s", __func__);
2562     if (EXSUCCEED!=validate_entry(src, 0, 0, VALIDATE_MODE_NO_FLD))
2563     {
2564         UBF_LOG(log_warn, "%s: arguments fail for src buf!", __func__);
2565         ndrx_Bappend_error_msg("(Bjoin: arguments fail for src buf!)");
2566         ret=EXFAIL;
2567     }
2568     else if (EXSUCCEED!=validate_entry(dest, 0, 0, VALIDATE_MODE_NO_FLD))
2569     {
2570         UBF_LOG(log_warn, "%s: arguments fail for dest buf!", __func__);
2571         ndrx_Bappend_error_msg("(Bjoin: arguments fail for dest buf!)");
2572         ret=EXFAIL;
2573     }
2574     else
2575     {
2576         /* Call the implementation */
2577         ret=ndrx_Bjoin (dest, src);
2578     }
2579     UBF_LOG(log_debug, "Return %s %d", __func__, ret);
2580     return ret;
2581 }
2582 
2583 /**
2584  * Outer join two buffers, update existing, do not remove non-existing fields
2585  * @param dest - dest buffer (being modified)
2586  * @param src - src buffer (not modified)
2587  * @return EXSUCCEED/EXFAIL
2588  */
2589 expublic int Bojoin(UBFH *dest, UBFH *src)
2590 {
2591     int ret=EXSUCCEED;
2592     API_ENTRY;
2593     /* Do standard validation */
2594     UBF_LOG(log_debug, "Entering %s", __func__);
2595     if (EXSUCCEED!=validate_entry(src, 0, 0, VALIDATE_MODE_NO_FLD))
2596     {
2597         UBF_LOG(log_warn, "%s: arguments fail for src buf!", __func__);
2598         ndrx_Bappend_error_msg("(Bojoin: arguments fail for src buf!)");
2599         ret=EXFAIL;
2600     }
2601     else if (EXSUCCEED!=validate_entry(dest, 0, 0, VALIDATE_MODE_NO_FLD))
2602     {
2603         UBF_LOG(log_warn, "%s: arguments fail for dest buf!", __func__);
2604         ndrx_Bappend_error_msg("(Bojoin: arguments fail for dest buf!)");
2605         ret=EXFAIL;
2606     }
2607     else
2608     {
2609         /* Call the implementation */
2610         ret=ndrx_Bojoin (dest, src);
2611     }
2612     UBF_LOG(log_debug, "Return %s %d", __func__, ret);
2613     return ret;
2614 }
2615 
2616 /**
2617  * Dynamically read the 
2618  * @param cstruct view object (struct instance) from where to take the value
2619  * @param view view name
2620  * @param cname field name
2621  * @param occ array index (zero based)
2622  * @param buf buffer where to store the value
2623  * @param len buffer on input user for strings and carray. Indicates the space.
2624  * On output indicates the length of data loaded, used for carray and strings.
2625  * optional
2626  * @param usrtype User field type
2627  * @param flags 0 or BVACCESS_NOTNULL (report view 'NULL' values as BNOTPRES)
2628  * @return 0 - succeed, -1 FAIL
2629  */
2630 expublic int CBvget(char *cstruct, char *view, char *cname, BFLDOCC occ, 
2631              char *buf, BFLDLEN *len, int usrtype, long flags)
2632 {
2633     int ret = EXSUCCEED;
2634     API_ENTRY;
2635     VIEW_ENTRY;
2636 
2637     if (NULL==view || EXEOS==view[0])
2638     {
2639         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2640         EXFAIL_OUT(ret);
2641     }
2642     
2643     if (NULL==cname || EXEOS==cname[0])
2644     {
2645         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2646         EXFAIL_OUT(ret);
2647     }
2648     
2649     if (NULL==cstruct)
2650     {
2651         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2652         EXFAIL_OUT(ret);
2653     }
2654     
2655     if (NULL==buf)
2656     {
2657         ndrx_Bset_error_msg(BEINVAL, "buf is NULL or empty!");
2658         EXFAIL_OUT(ret);
2659     }
2660     
2661     ret=ndrx_CBvget(cstruct, view, cname, occ, buf, len, usrtype, flags);
2662     
2663 out:
2664     return ret;
2665 }
2666 
2667 /**
2668  * Get view field, allocate the output buffer
2669  * @param cstruct c structure from which to read the value from
2670  * @param view view name
2671  * @param cname filed name
2672  * @param occ occurrence
2673  * @param usrtype user type to cast to
2674  * @param flags BVACCESS_NOTNULL
2675  * @param extralen optional, on input len to alloc, on output len of data loaded
2676  * @return NULL on error, if ok, ptr to data
2677  */
2678 expublic char *CBvgetalloc(char *cstruct, char *view, char *cname, BFLDOCC occ, 
2679             int usrtype, long flags, BFLDLEN *extralen)
2680 {
2681     int ret = EXSUCCEED;
2682     char *retval = NULL;
2683     API_ENTRY;
2684     VIEW_ENTRY;
2685 
2686     if (NULL==view || EXEOS==view[0])
2687     {
2688         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2689         goto out;
2690     }
2691     
2692     if (NULL==cname || EXEOS==cname[0])
2693     {
2694         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2695         goto out;
2696     }
2697     
2698     if (NULL==cstruct)
2699     {
2700         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2701         goto out;
2702     }
2703     
2704     retval=ndrx_CBvgetalloc(cstruct, view, cname, occ, usrtype, flags, extralen);
2705     
2706 out:
2707     return retval;
2708 }
2709 
2710 /**
2711  * Dynamically set view value. 
2712  * 
2713  * @param cstruct user view object
2714  * @param view view name
2715  * @param cname field name
2716  * @param occ occurrence to set. If occ+1>C_<count field>, then count field 
2717  * is incremented to this occ +1
2718  * @param buf buffer to take value from
2719  * @param len buffer len (mandatory for carray)
2720  * @param usrtype User type of data see BFLD_*
2721  * @return 0 - succeed, -1 fail
2722  */
2723 expublic int CBvchg(char *cstruct, char *view, char *cname, BFLDOCC occ, 
2724              char *buf, BFLDLEN len, int usrtype)
2725 {
2726     int ret = EXSUCCEED;
2727     API_ENTRY;
2728     VIEW_ENTRY;
2729 
2730     if (NULL==view || EXEOS==view[0])
2731     {
2732         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2733         EXFAIL_OUT(ret);
2734     }
2735     
2736     if (NULL==cname || EXEOS==cname[0])
2737     {
2738         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2739         EXFAIL_OUT(ret);
2740     }
2741     
2742     if (NULL==cstruct)
2743     {
2744         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2745         EXFAIL_OUT(ret);
2746     }
2747     
2748     if (NULL==buf)
2749     {
2750         ndrx_Bset_error_msg(BEINVAL, "buf is NULL or empty!");
2751         EXFAIL_OUT(ret);
2752     }
2753     
2754     ret=ndrx_CBvchg(cstruct, view, cname, occ, buf, len, usrtype);
2755     
2756 out:
2757     return ret;
2758 
2759 }
2760 
2761 /**
2762  * Size of the view
2763  * @param view view name
2764  * @return -1 on fail, or size of the view
2765  */
2766 expublic long Bvsizeof(char *view)
2767 {
2768     long ret = EXSUCCEED;
2769     API_ENTRY;
2770     VIEW_ENTRY;
2771 
2772     if (NULL==view || EXEOS==view[0])
2773     {
2774         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2775         EXFAIL_OUT(ret);
2776     }
2777     
2778     ret = ndrx_Bvsizeof(view);
2779     
2780 out:
2781     return ret;
2782 }
2783 
2784 
2785 
2786 /**
2787  * Copy the view contents from one buffer to another
2788  * @param cstruct_dst Destination buffer
2789  * @param cstruct_src Source buffer
2790  * @param view View name
2791  * @return -1 on fail, or number of bytes copied
2792  */
2793 expublic long Bvcpy(char *cstruct_dst, char *cstruct_src, char *view)
2794 {
2795     long ret = EXSUCCEED;
2796     API_ENTRY;
2797     VIEW_ENTRY;
2798 
2799     if (NULL==view || EXEOS==view[0])
2800     {
2801         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2802         EXFAIL_OUT(ret);
2803     }
2804     
2805     if (NULL==cstruct_src)
2806     {
2807         ndrx_Bset_error_msg(BEINVAL, "cstruct_src is NULL!");
2808         EXFAIL_OUT(ret);
2809     }
2810     
2811     if (NULL==cstruct_dst)
2812     {
2813         ndrx_Bset_error_msg(BEINVAL, "cstruct_dst is NULL!");
2814         EXFAIL_OUT(ret);
2815     }
2816     
2817     
2818     ret = ndrx_Bvcpy(cstruct_dst, cstruct_src, view);
2819     
2820 out:
2821     return ret;
2822 }
2823 
2824 
2825 /**
2826  * Get field occurrences number of array elements in VIEW.
2827  * Set by 'count' column in view file.
2828  * @param cstruct view object
2829  * @param view view name
2830  * @param cname filed name
2831  * @param maxocc returns the 'count' value of the view file
2832  * @param realocc returns number of non null elements in array. Scanned from
2833  * end of the array. Once first non NULL value is found, then this is detected
2834  * as real count.
2835  * @param dim_size number of bytes for field dimension
2836  * @return count set in C_<count_filed>. If count  indicator field not used,
2837  * then 'count' value (max value) from view is returned.
2838  * In case of error -1 is returned.
2839  */
2840 expublic BFLDOCC Bvoccur(char *cstruct, char *view, char *cname, 
2841         BFLDOCC *maxocc, BFLDOCC *realocc, long *dim_size, int* fldtype)
2842 {
2843     int ret = EXSUCCEED;
2844     API_ENTRY;
2845     VIEW_ENTRY;
2846 
2847     if (NULL==view || EXEOS==view[0])
2848     {
2849         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2850         EXFAIL_OUT(ret);
2851     }
2852     
2853     if (NULL==cname || EXEOS==cname[0])
2854     {
2855         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2856         EXFAIL_OUT(ret);
2857     }
2858     
2859     if (NULL==cstruct)
2860     {
2861         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2862         EXFAIL_OUT(ret);
2863     }
2864     
2865     ret = ndrx_Bvoccur(cstruct, view, cname, maxocc, realocc, dim_size, fldtype);
2866     
2867 out:
2868     return ret;
2869 }
2870 
2871 /**
2872  * Set occurrences (C_<field>) field
2873  * @param cstruct
2874  * @param view
2875  * @param cname
2876  * @param occ
2877  * @return 
2878  */
2879 expublic int Bvsetoccur(char *cstruct, char *view, char *cname, BFLDOCC occ)
2880 {
2881     int ret = EXSUCCEED;
2882     API_ENTRY;
2883     VIEW_ENTRY;
2884 
2885     if (NULL==view || EXEOS==view[0])
2886     {
2887         ndrx_Bset_error_msg(BEINVAL, "view is NULL or empty!");
2888         EXFAIL_OUT(ret);
2889     }
2890     
2891     if (NULL==cname || EXEOS==cname[0])
2892     {
2893         ndrx_Bset_error_msg(BEINVAL, "cname is NULL or empty!");
2894         EXFAIL_OUT(ret);
2895     }
2896     
2897     if (NULL==cstruct)
2898     {
2899         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
2900         EXFAIL_OUT(ret);
2901     }
2902     
2903     ret = ndrx_Bvsetoccur(cstruct, view, cname, occ);
2904     
2905 out:
2906     return ret;
2907 }
2908 
2909 /**
2910  * Iterate dynamically over the view structure
2911  * @param state where to store the iteration state, initialised when 'view' is set
2912  * @param view view name, on start of iter, must be set
2913  * @param cname field name to return
2914  * @param fldtype type to returnd BFLD_* consts applies
2915  * @return 1 - For success (have next), 0 EOF (nothing to return), -1 FAIL
2916  */
2917 expublic int Bvnext (Bvnext_state_t *state, char *view, 
2918         char *cname, int *fldtype, BFLDOCC *maxocc, long *dim_size)
2919 {
2920     int ret = EXSUCCEED;
2921     API_ENTRY;
2922     VIEW_ENTRY;
2923 
2924     if (NULL==state)
2925     {
2926         ndrx_Bset_error_msg(BEINVAL, "state is NULL!");
2927         EXFAIL_OUT(ret);
2928     }
2929     
2930     if (NULL==view)
2931     {
2932         if (NULL == state->v)
2933         {
2934             ndrx_Bset_error_msg(BEINVAL, "view is null but state contains NULL");
2935             EXFAIL_OUT(ret);
2936         }
2937         
2938         if (NULL == state->vel)
2939         {
2940             UBF_LOG(log_debug, "View scan early EOF");
2941             ret = 0;
2942             goto out;
2943         }
2944     }
2945     
2946     if (NULL==cname)
2947     {
2948         ndrx_Bset_error_msg(BEINVAL, "cname is NULL, no where "
2949                 "to store field name");
2950         EXFAIL_OUT(ret);
2951     }
2952         
2953     ret=ndrx_Bvnext (state, view, cname, fldtype, maxocc, dim_size);
2954 
2955 out:
2956 
2957     return ret;    
2958 }
2959 
2960 /**
2961  * Compare to views
2962  * @param cstruct1 view structure 1 ptr
2963  * @param view1 view name 1
2964  * @param cstruct2 view structure 2 ptr
2965  * @param view2 view name 2
2966  * @return  0 - view name/data are equal
2967  *  -1 - first view field is less than view2/cstruct
2968  *  1 - first view is greater than view2
2969  *  -2 - there is error (view not found)
2970  */
2971 expublic int Bvcmp(char *cstruct1, char *view1, char *cstruct2, char *view2)
2972 {
2973     int ret = EXSUCCEED;
2974     API_ENTRY;
2975     VIEW_ENTRY2;
2976     
2977     if (NULL==cstruct1)
2978     {
2979         ndrx_Bset_error_msg(BEINVAL, "cstruct1 is NULL!");
2980         ret=-2;
2981         goto out;
2982     }
2983     
2984     if (NULL==view1)
2985     {
2986         ndrx_Bset_error_msg(BEINVAL, "view1 is NULL!");
2987         ret=-2;
2988         goto out;
2989     }
2990     
2991     if (NULL==cstruct2)
2992     {
2993         ndrx_Bset_error_msg(BEINVAL, "cstruct2 is NULL!");
2994         ret=-2;
2995         goto out;
2996     }
2997     
2998     if (NULL==view2)
2999     {
3000         ndrx_Bset_error_msg(BEINVAL, "view2 is NULL!");
3001         ret=-2;
3002         goto out;
3003     }
3004         
3005     ret=ndrx_Bvcmp(cstruct1, view1, cstruct2, view2);
3006 
3007 out:
3008 
3009     return ret;    
3010 }
3011 
3012 /**
3013  * Read view contents from text file.
3014  * Contents is similar to Bextread, instead of field names, view field names
3015  * are used. Unknown fields are ignored.
3016  * @param cstruct pre-allocated c view structure 
3017  * @param view view name
3018  * @param inf input stream
3019  * @return EXSUCCEED/EXFAIL
3020  */
3021 expublic int Bvextread(char *cstruct, char *view, FILE *inf)
3022 {
3023     int ret = EXSUCCEED;
3024     API_ENTRY;
3025     VIEW_ENTRY2;
3026     
3027     if (NULL==cstruct)
3028     {
3029         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
3030         EXFAIL_OUT(ret);
3031     }
3032     
3033     if (NULL==view)
3034     {
3035         ndrx_Bset_error_msg(BEINVAL, "view is NULL!");
3036         EXFAIL_OUT(ret);
3037     }
3038     
3039     if (EXEOS==view[0])
3040     {
3041         ndrx_Bset_error_msg(BEINVAL, "view is empty string!");
3042         EXFAIL_OUT(ret);
3043     }
3044     
3045     if (NULL==inf)
3046     {
3047         ndrx_Bset_error_msg(BEINVAL, "inf is NULL!");
3048         EXFAIL_OUT(ret);
3049     }
3050     
3051     ret=ndrx_Bvextread (cstruct, view, inf, NULL, NULL, 0, NULL);
3052 
3053 out:
3054 
3055     return ret;    
3056 }
3057 
3058 /**
3059  * Read view contents from callback function
3060  * Contents is similar to Bextreadcb, instead of field names, view field names
3061  * are used. Unknown fields are ignored.
3062  * @param cstruct pre-allocated c view structure 
3063  * @param view view name
3064  * @param p_readf cllback func, where `buffer' and bufsz indicates the temp
3065  *  space for putting data to read, `dataptr1' is received from Bvextreadcb() call
3066  * @param dataptr1 dat
3067  * @return EXSUCCEED/EXFAIL
3068  */
3069 expublic int Bvextreadcb(char *cstruct, char *view, 
3070         long (*p_readf)(char *buffer, long bufsz, void *dataptr1), void *dataptr1)
3071 {
3072     int ret = EXSUCCEED;
3073     API_ENTRY;
3074     VIEW_ENTRY2;
3075     
3076     if (NULL==cstruct)
3077     {
3078         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
3079         EXFAIL_OUT(ret);
3080     }
3081     
3082     if (NULL==view)
3083     {
3084         ndrx_Bset_error_msg(BEINVAL, "view is NULL!");
3085         EXFAIL_OUT(ret);
3086     }
3087     
3088     if (EXEOS==view[0])
3089     {
3090         ndrx_Bset_error_msg(BEINVAL, "view is empty string!");
3091         EXFAIL_OUT(ret);
3092     }
3093     
3094     if (NULL==p_readf)
3095     {
3096         ndrx_Bset_error_msg(BEINVAL, "p_readf callback is NULL!");
3097         EXFAIL_OUT(ret);
3098     }
3099     
3100     ret=ndrx_Bvextread (cstruct, view, NULL, p_readf, dataptr1, 0, NULL);
3101 
3102 out:
3103 
3104     return ret;
3105 }
3106 
3107 /**
3108  * Print the view to output stream
3109  * @param cstruct view blob
3110  * @param view view name
3111  * @param outf output stream
3112  * @return EXSUCCEED/EXFAIL
3113  */
3114 expublic int Bvfprint (char *cstruct, char *view, FILE * outf)
3115 {
3116     int ret = EXSUCCEED;
3117     API_ENTRY;
3118     VIEW_ENTRY2;
3119     
3120     if (NULL==cstruct)
3121     {
3122         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
3123         EXFAIL_OUT(ret);
3124     }
3125     
3126     if (NULL==view)
3127     {
3128         ndrx_Bset_error_msg(BEINVAL, "view is NULL!");
3129         EXFAIL_OUT(ret);
3130     }
3131     
3132     if (NULL==outf)
3133     {
3134         ndrx_Bset_error_msg(BEINVAL, "outf FILE ptr is NULL!");
3135         EXFAIL_OUT(ret);
3136     }
3137     
3138     ret=ndrx_Bvfprint (cstruct, view, outf, NULL, NULL, 0);
3139 
3140 out:
3141 
3142     return ret;
3143 }
3144 
3145 /**
3146  * Print VIEW buffer by using callback function for data outputting
3147  * @param cstruct C Structure according to view
3148  * @param view View name
3149  * @param dataptr1 user pointer passed back to callback
3150  * @param p_writef callback function for data output. Note that 'buffer' argument
3151  *  is allocated and deallocated by Bvfprintcb it self. The string is zero byte
3152  *  terminated. The dataptr1 passed to function is forwarded to callback func.
3153  *  *datalen* includes the EOS byte. if do_write is set to TRUE, the data in buffer
3154  *  is written to output file.
3155  * @return EXSUCCEED/EXFAIL
3156  */
3157 expublic int Bvfprintcb (char *cstruct, char *view,
3158         ndrx_plugin_tplogprintubf_hook_t p_writef, void *dataptr1)
3159 {
3160     int ret = EXSUCCEED;
3161     API_ENTRY;
3162     VIEW_ENTRY2;
3163     
3164     if (NULL==cstruct)
3165     {
3166         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
3167         EXFAIL_OUT(ret);
3168     }
3169     
3170     if (NULL==view)
3171     {
3172         ndrx_Bset_error_msg(BEINVAL, "view is NULL!");
3173         ret=-2;
3174         goto out;
3175     }
3176     
3177     if (NULL==p_writef)
3178     {
3179         ndrx_Bset_error_msg(BEINVAL, "p_writef callback is NULL!");
3180         EXFAIL_OUT(ret);
3181     }
3182     
3183     ret=ndrx_Bvfprint (cstruct, view, NULL, p_writef, dataptr1, 0);
3184 
3185 out:
3186 
3187     return ret;
3188 }
3189 
3190 /**
3191  * Print the view to stdout
3192  * @param cstruct C Structure according to view
3193  * @param view View name
3194  * @return
3195  */
3196 expublic int Bvprint (char *cstruct, char *view)
3197 {
3198     int ret = EXSUCCEED;
3199     API_ENTRY;
3200     VIEW_ENTRY2;
3201     
3202     if (NULL==cstruct)
3203     {
3204         ndrx_Bset_error_msg(BEINVAL, "cstruct is NULL!");
3205         EXFAIL_OUT(ret);
3206     }
3207     
3208     if (NULL==view)
3209     {
3210         ndrx_Bset_error_msg(BEINVAL, "view is NULL!");
3211         EXFAIL_OUT(ret);
3212     }
3213     
3214     
3215     ret=ndrx_Bvfprint (cstruct, view, stdout, NULL, NULL, 0);
3216 
3217 out:
3218 
3219     return ret;
3220 }
3221 
3222 /**
3223  * Compare buffer 1 with buffer 2
3224  * @param p_ubf1 UBF buf1
3225  * @param p_ubf2 UBF buf2
3226  * @return -1 ubf1 have less fields, id is less than ubf2 fld, value of ubf1 is less
3227  * than ubf2.
3228  * 1 - vice versa -1 (ubf1 have more fields, id greater or value greater)
3229  * 0 buffers matches
3230  * in case of error, `berror' will not be 0.
3231  */
3232 expublic int Bcmp(UBFH *p_ubf1, UBFH *p_ubf2)
3233 {
3234     int ret=EXSUCCEED;
3235     UBF_header_t *ubf1_h = (UBF_header_t *)p_ubf1;
3236     UBF_header_t *ubf2_h = (UBF_header_t *)p_ubf2;
3237     API_ENTRY;
3238 
3239     UBF_LOG(log_debug, "About to compare FB=%p to FB=%p", p_ubf1, p_ubf2);
3240 
3241     if (NULL==p_ubf1)
3242     {
3243         ndrx_Bset_error_msg(BEINVAL, "p_ubf1 is NULL!");
3244         ret=-2;
3245         goto out;
3246     }
3247 
3248     if (NULL==p_ubf2)
3249     {
3250         ndrx_Bset_error_msg(BEINVAL, "p_ubf2 is NULL!");
3251         ret=-2;
3252         goto out;
3253     }
3254 
3255     if (0!=strncmp(ubf1_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
3256     {
3257         ndrx_Bset_error_msg(BNOTFLD, "p_ubf1 magic failed!");
3258         ret=-2;
3259         goto out;
3260     }
3261 
3262     if (0!=strncmp(ubf2_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
3263     {
3264         ndrx_Bset_error_msg(BNOTFLD, "p_ubf2 magic failed!");
3265         ret=-2;
3266         goto out;
3267     }
3268 
3269     ret = ndrx_Bcmp(p_ubf1, p_ubf2);
3270     
3271 out:
3272     UBF_LOG(log_debug, "return %d", ret);
3273     
3274     return ret;
3275 }
3276 
3277 /**
3278  * Test is ubf2 a subset of ubf1 (fields and values matches)
3279  * @param p_ubf1 UBF buffer 1
3280  * @param p_ubf2 UBF buffer 2
3281  * @return EXFAIL(sys err)/EXTRUE(is subset)/EXFALSE(not a subset, fields or
3282  * values does not match)
3283  */
3284 expublic int Bsubset(UBFH *p_ubf1, UBFH *p_ubf2)
3285 {
3286     int ret=EXSUCCEED;
3287     UBF_header_t *ubf1_h = (UBF_header_t *)p_ubf1;
3288     UBF_header_t *ubf2_h = (UBF_header_t *)p_ubf2;
3289     API_ENTRY;
3290 
3291     UBF_LOG(log_debug, "%s: About to check FB2=%p as subset of to FB1=%p", __func__,
3292                                     p_ubf2, p_ubf1);
3293 
3294     if (NULL==p_ubf1)
3295     {
3296         ndrx_Bset_error_msg(BEINVAL, "p_ubf1 is NULL!");
3297         EXFAIL_OUT(ret);
3298     }
3299 
3300     if (NULL==p_ubf2)
3301     {
3302         ndrx_Bset_error_msg(BEINVAL, "p_ubf2 is NULL!");
3303         EXFAIL_OUT(ret);
3304     }
3305 
3306     if (0!=strncmp(ubf1_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
3307     {
3308         ndrx_Bset_error_msg(BNOTFLD, "p_ubf1 magic failed!");
3309         EXFAIL_OUT(ret);
3310     }
3311 
3312     if (0!=strncmp(ubf2_h->magic, UBF_MAGIC, UBF_MAGIC_SIZE))
3313     {
3314         ndrx_Bset_error_msg(BNOTFLD, "p_ubf2 magic failed!");
3315         EXFAIL_OUT(ret);
3316     }
3317 
3318     ret = ndrx_Bsubset(p_ubf1, p_ubf2, 0);
3319     
3320 out:
3321     UBF_LOG(log_debug, "%s: return %d", __func__, ret);
3322     
3323     return ret;
3324 }
3325 
3326 
3327 /**
3328  * Load LMBB database of fields (usable only if tables not loaded already)
3329  * @return EXSUCCEED/EXFAIL (B error set)
3330  */
3331 expublic int Bflddbload(void) 
3332 {
3333     int ret = EXSUCCEED;
3334     
3335     API_ENTRY;
3336     
3337     if (NULL!=ndrx_G_ubf_db)
3338     {
3339         ndrx_Bset_error_fmt(BEINVAL, "%s: field db tables already loaded (%p)",
3340                 __func__, ndrx_G_ubf_db);
3341         EXFAIL_OUT(ret);
3342     }
3343     
3344     ret = ndrx_ubfdb_Bflddbload();
3345 out:   
3346     return ret;
3347 }
3348 
3349 #define DB_API_ENTRY if (!ndrx_G_ubf_db_triedload)\
3350     {\
3351         /* error will be set here */\
3352         if (EXFAIL==ndrx_ubfdb_Bflddbload())\
3353         {\
3354             EXFAIL_OUT(ret);\
3355         }\
3356     }
3357 
3358 /**
3359  * Return LMDB database handler
3360  * @param [out] dbi_id id -> name mapping database interface
3361  * @param [out] dbi_nm name -> id database handler
3362  * @return DB Env handler or NULL (B error set)
3363  */
3364 expublic EDB_env * Bfldddbgetenv (EDB_dbi **dbi_id, EDB_dbi **dbi_nm)
3365 {
3366     int ret = EXSUCCEED;
3367     EDB_env *dbenv = NULL;
3368     
3369     API_ENTRY;
3370     DB_API_ENTRY;
3371     
3372     if (NULL==dbi_id)
3373     {
3374         ndrx_Bset_error_msg(BEINVAL, "dbi_id is NULL!");
3375         EXFAIL_OUT(ret);
3376     }
3377     
3378     if (NULL==dbi_nm)
3379     {
3380         ndrx_Bset_error_msg(BEINVAL, "dbi_nm is NULL!");
3381         EXFAIL_OUT(ret);
3382     }
3383     
3384     dbenv = ndrx_ubfdb_Bfldddbgetenv(dbi_id, dbi_nm);
3385     
3386 out:
3387                         
3388     if (EXSUCCEED!=ret)
3389     {
3390         return NULL;
3391     }
3392 
3393     return dbenv;
3394 }
3395 
3396 
3397 
3398 /**
3399  * Add field to database
3400  * @param txn LMDB transaction
3401  * @param fldtype filed type, see BFLD_*
3402  * @param bfldno field number (not compiled)
3403  * @param fldname field name
3404  * @return EXSUCCEED/EXFAIL (B error set)
3405  */
3406 expublic int Bflddbadd(EDB_txn *txn,
3407         short fldtype, BFLDID bfldno, char *fldname)
3408 {
3409     int ret=EXSUCCEED;
3410     
3411     API_ENTRY;
3412     DB_API_ENTRY;
3413     
3414     if (NULL==ndrx_G_ubf_db)
3415     {
3416         ndrx_Bset_error_fmt(BEINVAL, "%s: field db not loaded!",
3417                 __func__);
3418         EXFAIL_OUT(ret);
3419     }
3420     
3421     if (NULL==txn)
3422     {
3423         ndrx_Bset_error_msg(BEINVAL, "txn is NULL!");
3424         EXFAIL_OUT(ret);
3425     }
3426     
3427     if (bfldno <= 0)
3428     {
3429         ndrx_Bset_error_fmt(BEINVAL, "invalid bfldno = %d!", 
3430                 (int)bfldno);
3431         EXFAIL_OUT(ret);
3432     }
3433     
3434     if (fldtype < BFLD_MIN || fldtype > BFLD_MAX)
3435     {
3436         ndrx_Bset_error_fmt(BEINVAL, "invalid field type: %d", (int)fldtype);
3437         EXFAIL_OUT(ret);
3438     }
3439     
3440     if (NULL==fldname)
3441     {
3442         ndrx_Bset_error_msg(BEINVAL, "fldname is NULL!");
3443         EXFAIL_OUT(ret);
3444     }
3445     
3446     if (EXEOS==fldname[0])
3447     {
3448         ndrx_Bset_error_msg(BEINVAL, "fldname is empty (EOS)!");
3449         EXFAIL_OUT(ret);
3450     }
3451     
3452     ret=ndrx_ubfdb_Bflddbadd(txn, fldtype, bfldno, fldname);
3453     
3454  out:   
3455     return ret;
3456 }
3457 
3458 /**
3459  * Delete field from UBF db
3460  * @param txn LMDB transaction
3461  * @param bfldid Field
3462  * @return EXSUCCEED/EXFAIL (B error set)
3463  */
3464 expublic int Bflddbdel(EDB_txn *txn, BFLDID bfldid)
3465 {
3466     int ret=EXSUCCEED;
3467     
3468     API_ENTRY;
3469     DB_API_ENTRY;
3470     
3471     if (NULL==ndrx_G_ubf_db)
3472     {
3473         ndrx_Bset_error_fmt(BEINVAL, "%s: field db not loaded!",
3474                 __func__);
3475         EXFAIL_OUT(ret);
3476     }
3477     
3478     if (NULL==txn)
3479     {
3480         ndrx_Bset_error_msg(BEINVAL, "txn is NULL!");
3481         EXFAIL_OUT(ret);
3482     }
3483     
3484     if (bfldid <= 0)
3485     {
3486         ndrx_Bset_error_fmt(BEINVAL, "invalid bfldno = %d!", 
3487                 (int)bfldid);
3488         EXFAIL_OUT(ret);
3489     }
3490     
3491     ret=ndrx_ubfdb_Bflddbdel(txn, bfldid);
3492     
3493  out:   
3494     return ret;
3495 }
3496 
3497 /**
3498  * Drop database
3499  * @param txn LMDB transaction
3500  * @return EXSUCCEED/EXFAIL (B error set)
3501  */
3502 expublic int Bflddbdrop(EDB_txn *txn)
3503 {
3504     int ret=EXSUCCEED;
3505     
3506     API_ENTRY;
3507     DB_API_ENTRY;
3508     
3509     if (NULL==ndrx_G_ubf_db)
3510     {
3511         ndrx_Bset_error_fmt(BEINVAL, "%s: field db not loaded!",
3512                 __func__);
3513         EXFAIL_OUT(ret);
3514     }
3515     
3516     if (NULL==txn)
3517     {
3518         ndrx_Bset_error_msg(BEINVAL, "txn is NULL!");
3519         EXFAIL_OUT(ret);
3520     }
3521     
3522     ret=ndrx_ubfdb_Bflddbdrop(txn);
3523     
3524  out:   
3525     return ret;
3526 }
3527 
3528 /**
3529  * Unload UBF database
3530  */
3531 expublic void Bflddbunload(void)
3532 {
3533     ndrx_ubfdb_Bflddbunload();
3534 }
3535 
3536 /**
3537  * Unlink database
3538  * @return EXSUCCEED/EXFAIL (B error set)
3539  */
3540 expublic int Bflddbunlink(void)
3541 {
3542     API_ENTRY;
3543     return ndrx_ubfdb_Bflddbunlink();
3544 }
3545 
3546 /**
3547  * Get field infos from cursor data
3548  * @param[in] data UBF data record
3549  * @param[out] p_fldtype ptr field type
3550  * @param[out] p_bfldno field number (not compiled
3551  * @param[out] p_bfldid filed id (compiled)
3552  * @param[out] fldname field name to store
3553  * @param[in] fldname_bufsz size of field name variable
3554  * @return 
3555  */
3556 expublic int Bflddbget(EDB_val *data,
3557         short *p_fldtype, BFLDID *p_bfldno, BFLDID *p_bfldid, 
3558         char *fldname, int fldname_bufsz)
3559 {
3560     API_ENTRY;
3561     int ret = EXSUCCEED;
3562     
3563     if (NULL==data)
3564     {
3565         ndrx_Bset_error_msg(BEINVAL, "data is NULL!");
3566         EXFAIL_OUT(ret);
3567     }
3568     
3569     if (NULL==p_bfldno)
3570     {
3571         ndrx_Bset_error_msg(BEINVAL, "p_bfldno is NULL!");
3572         EXFAIL_OUT(ret);
3573     }
3574     
3575     if (NULL==p_bfldid)
3576     {
3577         ndrx_Bset_error_msg(BEINVAL, "p_bfldno is NULL!");
3578         EXFAIL_OUT(ret);
3579     }
3580     
3581     if (NULL==p_fldtype)
3582     {
3583         ndrx_Bset_error_msg(BEINVAL, "p_fldtype is NULL!");
3584         EXFAIL_OUT(ret);
3585     }
3586     
3587     if (NULL==fldname)
3588     {
3589         ndrx_Bset_error_msg(BEINVAL, "fldname is NULL!");
3590         EXFAIL_OUT(ret);
3591     }
3592     
3593     if (fldname_bufsz<=0)
3594     {
3595         ndrx_Bset_error_fmt(BEINVAL, "Invalid buffer size, must be >=0, got %d",
3596                 fldname_bufsz);
3597         EXFAIL_OUT(ret);
3598     }
3599     
3600     ret=ndrx_ubfdb_Bflddbget(data, p_fldtype, p_bfldno, p_bfldid,
3601             fldname, fldname_bufsz);
3602     
3603  out:   
3604     return ret;
3605 }
3606 
3607 /**
3608  * Resolve field name from id (compiled)
3609  * @param bfldid field id
3610  * @return field name (one slot stored in TLS) or NULL (B error set)
3611  */
3612 expublic char * Bflddbname (BFLDID bfldid)
3613 {
3614     int ret=EXSUCCEED;
3615     char *f = NULL;
3616     API_ENTRY;
3617     DB_API_ENTRY;
3618     
3619     if (0>=bfldid)
3620     {
3621         ndrx_Bset_error_msg(BEINVAL, "Invalid field id (<=0)");
3622         EXFAIL_OUT(ret);
3623     }
3624     
3625     f = ndrx_ubfdb_Bflddbname (bfldid);
3626     
3627  out:   
3628 
3629     if (EXSUCCEED!=ret)
3630     {
3631         return NULL;
3632     }
3633  
3634     return f;
3635 }
3636 
3637 /**
3638  * Resolve field id from field name
3639  * @param fldname field name
3640  * @return field id or BBADFLDID (B error set)
3641  */
3642 expublic BFLDID Bflddbid (char *fldname)
3643 {
3644     BFLDID ret=EXSUCCEED;
3645     API_ENTRY;
3646     DB_API_ENTRY;
3647     
3648     if (NULL==fldname || EXEOS==fldname[0])
3649     {
3650         ndrx_Bset_error_msg(BEINVAL, "Invalid field id null or empty!");
3651         EXFAIL_OUT(ret);
3652     }
3653     
3654     ret = ndrx_ubfdb_Bflddbid (fldname);
3655     
3656  out:
3657 
3658     return ret;
3659 }
3660 
3661 /**
3662  * Count all occurrences of the fields in the buffer
3663  * @param p_ub - UBF buffer
3664  * @return Number of all occurrences of the fields in buffer, -1 FAIL
3665  */
3666 expublic BFLDOCC Bnum (UBFH *p_ub)
3667 {
3668     char fn[] = "Bnum";
3669     UBF_header_t *hdr = (UBF_header_t *)p_ub;
3670 
3671     API_ENTRY;
3672 
3673     /* Do standard validation */
3674     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3675     {
3676         UBF_LOG(log_warn, "%s: arguments fail!", fn);
3677         return EXFAIL;
3678     }
3679     else
3680     {
3681         return ndrx_Bnum(p_ub);
3682     }
3683 }
3684 
3685 /**
3686  * Return number of bytes required for UBF buffer
3687  * @param nrfields number of fields
3688  * @param totsize space required for all fields (data size)
3689  * @return Space needed for UBF buffer or EXFAIL
3690  */
3691 expublic long Bneeded(BFLDOCC nrfields, BFLDLEN totsize)
3692 {
3693     long ret = EXSUCCEED;
3694     API_ENTRY;
3695     
3696     if (nrfields<=0)
3697     {
3698         ndrx_Bset_error_msg(BEINVAL, "Invalid nrfields (<=0)");
3699         EXFAIL_OUT(ret);
3700     }
3701     
3702     if (totsize<=0)
3703     {
3704         ndrx_Bset_error_msg(BEINVAL, "Invalid totsize (<=0)");
3705         EXFAIL_OUT(ret);
3706     }
3707     
3708     /* compute the total size */
3709     ret = ndrx_Bneeded(nrfields, totsize);
3710     
3711     
3712     if (ret > MAXUBFLEN)
3713     {
3714         ndrx_Bset_error_fmt(BEINVAL, "Buffer size estimated larger (%ld) than max (%ld)",
3715                 ret, (long)MAXUBFLEN);
3716         EXFAIL_OUT(ret);
3717     }
3718     
3719 out:
3720     return ret;
3721 }
3722 
3723 /**
3724  * Reallocate UBF block
3725  * @param p_Fb
3726  * @param f number of fields
3727  * @param v field length in bytes
3728  * @return reallocated UBF buffer or NULL on failure
3729  */
3730 expublic UBFH * Balloc (BFLDOCC f, BFLDLEN v)
3731 {
3732     API_ENTRY;
3733     
3734     return ndrx_Balloc (f, v, EXFAIL);
3735 }
3736 
3737 /**
3738  * Reallocate UBF block
3739  * @param p_Fb
3740  * @param f number of fields
3741  * @param v field length in bytes
3742  * @return reallocated UBF buffer or NULL on failure
3743  */
3744 expublic UBFH * Brealloc (UBFH *p_ub, BFLDOCC f, BFLDLEN v)
3745 {
3746     API_ENTRY;
3747     
3748     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3749     {
3750         UBF_LOG(log_warn, "%s: arguments fail!", __func__);
3751         p_ub=NULL;
3752     }
3753     
3754     
3755     return ndrx_Brealloc (p_ub, f, v, EXFAIL);
3756 }
3757 
3758 /**
3759  * Dummy functions. Enduro/X all buffers are 32bit
3760  * @param dest dest buffer
3761  * @param src source buffer
3762  * @return EXSUCCEED
3763  */
3764 expublic int B32to16(UBFH *dest, UBFH *src)
3765 {
3766     return EXSUCCEED;
3767 }
3768 
3769 /**
3770  * Dummy functions. Enduro/X all buffers are 32bit
3771  * @param dest dest buffer
3772  * @param src source buffer
3773  * @return EXSUCCEED
3774  */
3775 expublic int B16to32(UBFH *dest, UBFH *src)
3776 {
3777     return EXSUCCEED;
3778 }
3779 
3780 
3781 /**
3782  * Recursive buffer get
3783  * @param p_ub root UBF buffer
3784  * @param fldidocc field sequence, array of FLDID1,OCC1,FLDID2,OCC2,FLDID3,OCC3,-1
3785  *  i.e. terminator is -1
3786  * @param buf output buffer
3787  * @param buflen on input buf size, on output - bytes written
3788  * @return EXSUCCEED/EXFAIL  in case of error
3789  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
3790  *  BFLD_UBF is not found, BEINVAL for invalid sequence 
3791  */
3792 expublic int Bgetr (UBFH * p_ub, BFLDID *fldidocc, char * buf, BFLDLEN * buflen)
3793 {
3794     int ret = EXSUCCEED;
3795     API_ENTRY;
3796     
3797     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3798     {
3799         UBF_LOG(log_error, "invalid buffer passed");
3800         EXFAIL_OUT(ret);
3801     }
3802     
3803     if (NULL==fldidocc)
3804     {
3805         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3806         EXFAIL_OUT(ret);
3807     }
3808     
3809     ret=ndrx_Bgetr (p_ub, fldidocc, buf, buflen);
3810 out:
3811     return ret;
3812 }
3813 
3814 /**
3815  * Recursive Convert Buffer get
3816  * @param p_ub UBF buffer
3817  * @param fldidocc field path in array of fldid,occ,fldid,occ,...,-1
3818  * @param buf where to unload the data
3819  * @param buflen buffer length 
3820  * @param usrtype user type to convert to
3821  * @return EXSUCCEED/EXFAIL in case of error
3822  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
3823  *  BFLD_UBF is not found, BEINVAL for invalid sequence 
3824  */
3825 expublic int CBgetr (UBFH * p_ub, BFLDID *fldidocc,
3826                             char * buf, BFLDLEN * buflen, int usrtype)
3827 {
3828     int ret = EXSUCCEED;
3829     API_ENTRY;
3830     
3831     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3832     {
3833         UBF_LOG(log_error, "invalid buffer passed");
3834         EXFAIL_OUT(ret);
3835     }
3836     
3837     if (NULL==fldidocc)
3838     {
3839         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3840         EXFAIL_OUT(ret);
3841     }
3842     
3843     ret=ndrx_CBgetr (p_ub, fldidocc, buf, buflen, usrtype);
3844 out:
3845     return ret;
3846 }
3847 
3848 /**
3849  * Get field as string, allocate
3850  * @param p_ub UBF buffer
3851  * @param fldidocc fld occ path
3852  * @param usrtype user type to convert to
3853  * @param extralen extra len to alloc (or NULL) on return data len loaded
3854  * @return NULL in case of failure, allocated (malloc) data block
3855  */
3856 expublic char * CBgetallocr (UBFH *p_ub, BFLDID *fldidocc, int usrtype, BFLDLEN *extralen)
3857 {
3858     char * ret = NULL;
3859     API_ENTRY;
3860     
3861     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3862     {
3863         UBF_LOG(log_error, "invalid buffer passed");
3864         goto out;
3865     }
3866     
3867     if (NULL==fldidocc)
3868     {
3869         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3870         goto out;
3871     }
3872     
3873     ret=ndrx_CBgetallocr (p_ub, fldidocc, usrtype, extralen);
3874 out:
3875     return ret;
3876 }
3877 
3878 /**
3879  * Recursive field find
3880  * @param p_ub UBF buffer to search into
3881  * @param fldidocc fldid,occ,fldid,occ,...,BBADFLDOCC sequence
3882  * @param p_len indicates the data size in bytes
3883  * @return ptr to data found or NULL in case of error
3884  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
3885  *  BFLD_UBF is not found, BEINVAL for invalid sequence 
3886  */
3887 expublic char* Bfindr (UBFH *p_ub, BFLDID *fldidocc, BFLDLEN *p_len)
3888 {
3889     char *ret = NULL;
3890     API_ENTRY;
3891     
3892     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3893     {
3894         UBF_LOG(log_error, "invalid buffer passed");
3895         goto out;
3896     }
3897     
3898     if (NULL==fldidocc)
3899     {
3900         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3901         goto out;
3902     }
3903     
3904     ret=ndrx_Bfindr (p_ub, fldidocc, p_len);
3905     
3906 out:
3907     return ret;
3908 }
3909 
3910 /**
3911  * Recursive with Convert field find
3912  * @param p_ub buffer to start search from
3913  * @param fldidocc fldid,occ,fldid,occ,...,BBADFLDOCC sequence
3914  * @param len output ptr optional for data length indication
3915  * @param usrtype field type to convert to
3916  * @return ptr to data found or NULL in case of error
3917  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
3918  *  BFLD_UBF is not found, BEINVAL for invalid sequence
3919  */
3920 expublic char *CBfindr (UBFH *p_ub, BFLDID *fldidocc, BFLDLEN *len, int usrtype)
3921 {
3922     char *ret = NULL;
3923     API_ENTRY;
3924     
3925     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3926     {
3927         UBF_LOG(log_error, "invalid buffer passed");
3928         goto out;
3929     }
3930     
3931     if (NULL==fldidocc)
3932     {
3933         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3934         goto out;
3935     }
3936     
3937     ret=ndrx_CBfindr (p_ub, fldidocc, len, usrtype);
3938     
3939 out:
3940     return ret;
3941 }
3942 
3943 /**
3944  * Test is field present or not in recursive way
3945  * @param p_ub UBF buffer into which perform the search
3946  * @param fldidocc fldid,occ,fldid,occ,...,BBADFLDOCC
3947  * @return EXTRUE/EXFALSE (even in case of errro)
3948  */
3949 expublic int Bpresr (UBFH *p_ub, BFLDID *fldidocc)
3950 {
3951     int ret = EXSUCCEED;
3952     API_ENTRY;
3953     
3954     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3955     {
3956         UBF_LOG(log_error, "invalid buffer passed");
3957         EXFAIL_OUT(ret);
3958     }
3959     
3960     if (NULL==fldidocc)
3961     {
3962         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
3963         EXFAIL_OUT(ret);
3964     }
3965     
3966     ret=ndrx_Bpresr (p_ub, fldidocc);
3967     
3968 out:
3969     return ret;
3970 }
3971 
3972 /**
3973  * Get view field from UBF recursive buffer
3974  * @param p_ub UBF buffer
3975  * @param c
3976  * @param cname field name from view to get
3977  * @param occ occurrence from view to get
3978  * @param buf buffer where to extract the data
3979  * @param len on input it indicates buffer size, on output but bytes written to buffer
3980  * @param usrtype type to convert to the data in VIEW
3981  * @param flags BVACCESS_NOTNULL treat NULLs as field not present
3982  * @return EXSUCCEED/EXFAIL in case of error
3983  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
3984  *  BFLD_UBF is not found, BEINVAL for invalid sequence
3985  */
3986 expublic int CBvgetr(UBFH *p_ub, BFLDID *fldidocc, char *cname, BFLDOCC occ, 
3987              char *buf, BFLDLEN *len, int usrtype, long flags)
3988 {
3989     int ret = EXSUCCEED;
3990     API_ENTRY;
3991     
3992     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
3993     {
3994         UBF_LOG(log_error, "invalid buffer passed");
3995         EXFAIL_OUT(ret);
3996     }
3997     
3998     if (NULL==fldidocc)
3999     {
4000         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
4001         EXFAIL_OUT(ret);
4002     }
4003     
4004     ret=ndrx_CBvgetr (p_ub, fldidocc, cname, occ, buf, len, usrtype, flags);
4005     
4006 out:
4007     return ret;
4008 }
4009 
4010 /**
4011  * Get view field with allocation recursive from UBF
4012  * @param p_ub UBF buffer with view field present
4013  * @param fldidocc field path
4014  * @param cname field name
4015  * @param occ occurrence
4016  * @param usrtype dest type
4017  * @param flags BVACCESS_NOTNULL if any
4018  * @param extralen on input extra len to alloc, on output number of types loaded
4019  * @return NULL on error, alloct ptr ok
4020  */
4021 expublic char * CBvgetallocr(UBFH *p_ub, BFLDID *fldidocc, char *cname, BFLDOCC occ, 
4022             int usrtype, long flags, BFLDLEN *extralen)
4023 {
4024     char * ret = NULL;
4025     API_ENTRY;
4026     
4027     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
4028     {
4029         UBF_LOG(log_error, "invalid buffer passed");
4030         goto out;
4031     }
4032     
4033     if (NULL==fldidocc)
4034     {
4035         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
4036         goto out;
4037     }
4038     
4039     ret=ndrx_CBvgetallocr (p_ub, fldidocc, cname, occ, usrtype, flags, extralen);
4040     
4041 out:
4042     return ret;
4043 }
4044 
4045 /**
4046  * Test the view field for NULL value
4047  * @param p_ub UBF buffer into which search for the view
4048  * @param fldidocc fldidocc fldid,occ,fldid,occ,...,fldid (of view),occ,BBADFLDOCC
4049  * @param cname field name
4050  * @param occ field occurrence
4051  * @return EXSUCCEED/EXFALSE/EXFAIL in case of error
4052  *  combines errors from Bfind + BTYPERR in case of in middle of sequence
4053  *  BFLD_UBF is not found, BEINVAL for invalid sequence
4054  */
4055 expublic int Bvnullr(UBFH *p_ub, BFLDID *fldidocc, char *cname, BFLDOCC occ)
4056 {
4057     int ret = EXSUCCEED;
4058     API_ENTRY;
4059     
4060     if (EXSUCCEED!=validate_entry(p_ub, 0, 0, VALIDATE_MODE_NO_FLD))
4061     {
4062         UBF_LOG(log_error, "invalid buffer passed");
4063         EXFAIL_OUT(ret);
4064     }
4065     
4066     if (NULL==fldidocc)
4067     {
4068         ndrx_Bset_error_msg(BEINVAL, "fldidocc must not be NULL");
4069         EXFAIL_OUT(ret);
4070     }
4071     
4072     ret=ndrx_Bvnullr (p_ub, fldidocc, cname, occ);
4073     
4074 out:
4075     return ret;
4076 }
4077 
4078 #define NDRX_UBF_GET_FLDIDOCC(LAST_ARG) \
4079     BFLDID fldidocc[BFLDOCCMAX*2+1];\
4080     va_list ap;\
4081     int id;\
4082     int pos = 0;\
4083     \
4084     va_start(ap, LAST_ARG);\
4085     \
4086     while (BBADFLDOCC!=(id = va_arg(ap, int)))\
4087     {\
4088         fldidocc[pos]=id;\
4089         pos++;\
4090         if (pos >= sizeof(fldidocc))\
4091         {\
4092             ndrx_Bset_error_fmt(BBADFLD, "FLDID,OCC path too long, max %d", \
4093                     BFLDOCCMAX);\
4094             va_end(ap);\
4095             EXFAIL_OUT(ret);\
4096         }\
4097     }\
4098     \
4099     fldidocc[pos]=id;\
4100     pos++;\
4101     \
4102     va_end(ap);\
4103     \
4104     if ( pos % 2 == 0)\
4105     {\
4106         ndrx_Bset_error_fmt(BBADFLD, "Expected odd number FLDID,OCC,..,"\
4107                 "<terminator> arguments got: %d", pos);\
4108         EXFAIL_OUT(ret);\
4109     }\
4110     \
4111     if (1==pos)\
4112     {\
4113         ndrx_Bset_error_fmt(BBADFLD, "Expected FLDID,OCC,..,"\
4114                 "<terminator> path, got only terminator");\
4115         EXFAIL_OUT(ret);\
4116     }
4117     
4118 /**
4119  * Recursive get with var args
4120  * @param p_ub UBF buffer to get value from
4121  * @param buf where to unload the value
4122  * @param buflen output length
4123  * @param ... var args of <FLDID>,<OCC>,<FLDID>,OCC,BBADFLDOCC
4124  * @return EXSUCCEED/EXFAIL
4125  */
4126 expublic int Bgetrv (UBFH * p_ub, char * buf, BFLDLEN * buflen, ...)
4127 {
4128     int ret = EXSUCCEED;
4129     NDRX_UBF_GET_FLDIDOCC(buflen);
4130     
4131     ret=Bgetr (p_ub, fldidocc, buf, buflen);
4132     
4133 out:
4134     return ret;
4135 }
4136 
4137 /**
4138  * Recursive Change buffer get, varargs
4139  * @param p_ub UBF buffer to get value from
4140  * @param buf where to unload the value
4141  * @param buflen output length
4142  * @param usrtype user type for data unload to ubf/buflen
4143  * @param ... var args of <FLDID>,<OCC>,<FLDID>,OCC,BBADFLDOCC
4144  * @return EXSUCCEED/EXFAIL
4145  */
4146 expublic int CBgetrv (UBFH * p_ub, char * buf, BFLDLEN * buflen, int usrtype, ...)
4147 {
4148     int ret = EXSUCCEED;
4149     NDRX_UBF_GET_FLDIDOCC(usrtype);
4150     
4151     ret=CBgetr (p_ub, fldidocc, buf, buflen, usrtype);
4152     
4153 out:
4154     return ret;
4155 }
4156 
4157 /**
4158  * Get as string to allocated buffer, var-args path
4159  * @param p_ub UBF buffer
4160  * @param extralen extra len to alloc
4161  * @param usrtype user type to cast to
4162  * @param ... var args of <FLDID>,<OCC>,<FLDID>,OCC,BBADFLDOCC
4163  * @return NULL on error or allocated filed
4164  */
4165 expublic char * CBgetallocrv (UBFH *p_ub, int usrtype, BFLDLEN *extralen, ...)
4166 {
4167     int ret = EXSUCCEED;
4168     char *retval = NULL;
4169     NDRX_UBF_GET_FLDIDOCC(extralen);
4170     
4171     retval=CBgetallocr (p_ub, fldidocc, usrtype, extralen);
4172     
4173 out:
4174     return retval;
4175 }
4176 
4177 /**
4178  * Recursive convert Buffer find, var-args
4179  * @param p_ub UBF buffer where to search
4180  * @param len data len to return (optional)
4181  * @param usrtype user type to convert to found data
4182  * @param ... var args of <FLDID>,<OCC>,<FLDID>,OCC,BBADFLDOCC
4183  * @return ptr to converted value or NULL in case of error
4184  */
4185 expublic char *CBfindrv (UBFH *p_ub, BFLDLEN *len, int usrtype, ...)
4186 {
4187     char *vret = NULL;
4188     int ret = EXSUCCEED;
4189     NDRX_UBF_GET_FLDIDOCC(usrtype);
4190     
4191     vret=CBfindr (p_ub, fldidocc, len, usrtype);
4192     
4193 out:
4194     return vret;
4195 }
4196 
4197 /**
4198  * Recursive buffer find, var-args
4199  * @param p_ub UBF buffer into which search the sub-buffer
4200  * @param p_len output value
4201  * @param ... var args of <FLDID>,<OCC>,<FLDID>,OCC,BBADFLDOCC
4202  * @return Value found or NULL (with error loaded)
4203  */
4204 expublic char* Bfindrv (UBFH *p_ub, BFLDLEN *p_len, ...)
4205 {
4206     char *vret = NULL;
4207     int ret = EXSUCCEED;
4208     NDRX_UBF_GET_FLDIDOCC(p_len);
4209     
4210     vret=Bfindr (p_ub, fldidocc, p_len);
4211     
4212 out:
4213     return vret;
4214 }
4215 /**
4216  * Check is recursive field present, using var-args
4217  * @param p_ub UBF buffer
4218  * @param ... varargs to search for
4219  * @return EXSUCCEED/EXFAIL
4220  */
4221 expublic int Bpresrv (UBFH *p_ub, ...)
4222 {
4223     int ret = EXSUCCEED;
4224     NDRX_UBF_GET_FLDIDOCC(p_ub);
4225     
4226     ret=Bpresr (p_ub, fldidocc);
4227     
4228 out:
4229     return ret;
4230 }
4231 
4232 /**
4233  * Convert view get value from UBF recursive view field. Varg-args
4234  * @param p_ub UBF buffer which contains view in some of the levels
4235  * @param cname view field name
4236  * @param occ view occurrence
4237  * @param buf buffer to which unload value to
4238  * @param len optional len, on input buffer size, on output bytes copied to buf
4239  * @param usrtype user type to convert view value to
4240  * @param flags BVACCESS_NOTNULL - thread null view value as BNOTPRES error
4241  * @param ... path to view field <FLDID>,<OCC>,...,<FLDID (of view)>,OCC,BBADFLDOCC
4242  * @return EXSUCCEED/EXFAIL
4243  */
4244 expublic int CBvgetrv(UBFH *p_ub, char *cname, BFLDOCC occ,
4245             char *buf, BFLDLEN *len, int usrtype, long flags, ...)
4246 {
4247     int ret = EXSUCCEED;
4248     NDRX_UBF_GET_FLDIDOCC(flags);
4249     
4250     ret=CBvgetr (p_ub, fldidocc, cname, occ, buf, len, usrtype, flags);
4251     
4252 out:
4253     return ret;
4254 }
4255 
4256 /**
4257  * Convert view get value from UBF recursive view field. Varg-args
4258  * @param p_ub UBF buffer which contains view in some of the levels
4259  * @param cname view field name
4260  * @param occ view occurrence
4261  * @param usrtype user type to convert view value to
4262  * @param flags BVACCESS_NOTNULL - thread null view value as BNOTPRES error
4263  * @param extralen optional, on input add len, on output bytes loaded
4264  * @param ... path to view field <FLDID>,<OCC>,...,<FLDID (of view)>,OCC,BBADFLDOCC
4265  * @return NULL on error, allocd ptr
4266  */
4267 expublic char* CBvgetallocrv(UBFH *p_ub, char *cname, BFLDOCC occ,
4268             int usrtype, long flags, BFLDLEN *extralen, ...)
4269 {
4270     int ret = EXSUCCEED;
4271     char *retval = NULL;
4272     NDRX_UBF_GET_FLDIDOCC(extralen);
4273     
4274     retval=CBvgetallocr (p_ub, fldidocc, cname, occ, usrtype, flags, extralen);
4275     
4276 out:
4277     return retval;
4278 }
4279 
4280 
4281 /**
4282  * Check is view field NULL
4283  * @param p_ub UBF buffer into which search the view field in recrusive way
4284  * @param cname view field name to test
4285  * @param occ view field occurrence to test
4286  * @param ... varargs of <FLDID>,<OCC>,...,<FLDID (of view)>,OCC,BBADFLDOCC
4287  * @return 1 - field pres, 0 - field not pres, -1 error
4288  */
4289 expublic int Bvnullrv(UBFH *p_ub, char *cname, BFLDOCC occ, ...)
4290 {
4291     int ret = EXSUCCEED;
4292     NDRX_UBF_GET_FLDIDOCC(occ);
4293     
4294     ret=Bvnullr(p_ub, fldidocc, cname, occ);
4295     
4296 out:
4297     return ret;
4298 }
4299 
4300 /* vim: set ts=4 sw=4 et smartindent: */