Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief UBF library
0003  *   Contains auxiliary functions
0004  *
0005  * @file utils.c
0006  */
0007 /* -----------------------------------------------------------------------------
0008  * Enduro/X Middleware Platform for Distributed Transaction Processing
0009  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0010  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0011  * This software is released under one of the following licenses:
0012  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0013  * See LICENSE file for full text.
0014  * -----------------------------------------------------------------------------
0015  * AGPL license:
0016  *
0017  * This program is free software; you can redistribute it and/or modify it under
0018  * the terms of the GNU Affero General Public License, version 3 as published
0019  * by the Free Software Foundation;
0020  *
0021  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0022  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0023  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0024  * for more details.
0025  *
0026  * You should have received a copy of the GNU Affero General Public License along 
0027  * with this program; if not, write to the Free Software Foundation, Inc.,
0028  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0029  *
0030  * -----------------------------------------------------------------------------
0031  * A commercial use license is available from Mavimax, Ltd
0032  * contact@mavimax.com
0033  * -----------------------------------------------------------------------------
0034  */
0035 
0036 /*---------------------------Includes-----------------------------------*/
0037 #include <string.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <errno.h>
0041 #include <fcntl.h>
0042 #include <ctype.h>
0043 
0044 #include <ndrstandard.h>
0045 #include <ndebug.h>
0046 #include <ubf.h>
0047 #include <ubf_int.h>
0048 #include <ubfutil.h>
0049 #include <fdatatype.h>
0050 #include <ubfview.h>
0051 #include <nstd_int.h>
0052 /*---------------------------Externs------------------------------------*/
0053 /*---------------------------Macros-------------------------------------*/
0054 #define IS_NOT_PRINTABLE(X) !(isprint(X) && !iscntrl(X))
0055 /*---------------------------Enums--------------------------------------*/
0056 /*---------------------------Typedefs-----------------------------------*/
0057 /*---------------------------Globals------------------------------------*/
0058 char HEX_TABLE[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
0059 /*---------------------------Statics------------------------------------*/
0060 /*---------------------------Prototypes---------------------------------*/
0061 
0062 /**
0063  * Returns requested space required for chracter masking.
0064  * Note that for strings we provide the string len not including EOS. Meaning
0065  * if string is ok, it should return 0 non-printable count (EOS left out!).
0066  *
0067  * @param str - string into which we should look
0068  * @param len - length of the resource.
0069  * @return count of non printable chracters
0070  */
0071 expublic int ndrx_get_nonprintable_char_tmpspace(char *str, int len)
0072 {
0073     int ret=0;
0074     int i;
0075 
0076     for (i=0; i<len; i++)
0077     {
0078         if (IS_NOT_PRINTABLE(str[i]))
0079         {
0080             ret+=3;
0081         }
0082         else if ('\\'==str[i])
0083         {
0084             ret+=2;
0085         }
0086         else
0087         {
0088             ret++;
0089         }
0090     }
0091     return ret;
0092 }
0093 /**
0094  * Builds printable version out 
0095  */
0096 expublic void ndrx_build_printable_string(char *out, int out_len, char *in, int in_len)
0097 {
0098     int i;
0099     int cur = 0;
0100     
0101     for (i=0; i<in_len; i++)
0102     {
0103         if (IS_NOT_PRINTABLE(in[i]))
0104         {
0105             /* we shall leave space for EOS, thus having not >= but > and same
0106              * bellow.
0107              */
0108             if (out_len - cur > 3)
0109             {
0110                 /* make int hexy */
0111                 out[cur++] = '\\';
0112                 out[cur++] = HEX_TABLE[(in[i]>>4)&0x0f];
0113                 out[cur++] = HEX_TABLE[in[i]&0x0f];
0114             }
0115             else
0116             {
0117                 break;
0118             }
0119         }
0120         else if ('\\'==in[i])
0121         {
0122             /* Convert \ to two \\ */
0123             if (out_len - cur > 2)
0124             {
0125                 out[cur++] = '\\';
0126                 out[cur++] = '\\';
0127             }
0128             else
0129             {
0130                 break;
0131             }
0132         }
0133         else if (out_len - cur > 1)
0134         {
0135             /* copy off printable char */
0136             out[cur++] = in[i];
0137         }
0138         else
0139         {
0140             break;
0141         }
0142     }
0143     
0144     if (cur<out_len)
0145     {
0146         out[cur] = EXEOS;
0147     }
0148 }
0149 
0150 /**
0151  * Returns decimal number out from hex digit
0152  * @param c - hex digit 0..f
0153  * @return -1 (on FAIL)/decimal number
0154  */
0155 expublic int ndrx_get_num_from_hex(char c)
0156 {
0157     int ret=EXFAIL;
0158     int i;
0159 
0160     for (i=0; i< sizeof(HEX_TABLE); i++)
0161     {
0162         if (toupper(HEX_TABLE[i])==toupper(c))
0163         {
0164             ret=i;
0165             break;
0166         }
0167     }
0168 
0169     return ret;
0170 }
0171 
0172 
0173 /**
0174  * Function builds string back from value built by build_printable_string
0175  * We will re-use the same string, because by the case normalized version is shorter
0176  * that printable version
0177  * @param str - coded string with build_printable_string function
0178  */
0179 expublic int ndrx_normalize_string(char *str, int *out_len)
0180 {
0181     int ret=EXSUCCEED;
0182     int real=0;
0183     int data=0;
0184     int len = strlen(str);
0185     int high, low;
0186     while (data<len)
0187     {
0188         if (str[data]=='\\')
0189         {
0190             if (data+1>=len)
0191             {
0192                 UBF_LOG(log_error, "String terminates after prefix \\");
0193                 return EXFAIL; /* << RETURN! */
0194             }
0195             else if (str[data+1]=='\\') /* this is simply \ */
0196             {
0197                 str[real] = str[data];
0198                 data+=2;
0199                 real++;
0200             } 
0201             else if (data+2>=len)
0202             {
0203                 UBF_LOG(log_error, "Hex code does not follow at the"
0204                                                 " end of string for \\");
0205                 return EXFAIL; /* << RETURN! */
0206             }
0207             else
0208             {
0209                 /* get high, low parts */
0210                 high = ndrx_get_num_from_hex(str[data+1]);
0211                 low = ndrx_get_num_from_hex(str[data+2]);
0212                 if (EXFAIL==high||EXFAIL==low)
0213                 {
0214                     UBF_LOG(log_error, "Invalid hex number 0x%c%c",
0215                                                     str[data+1], str[data+2]);
0216                     return EXFAIL; /* << RETURN! */
0217                 }
0218                 else
0219                 {
0220                     /* Construct the value back */
0221                     str[real]= high<<4 | low;
0222                     real++;
0223                     data+=3;
0224                 }
0225             }
0226         }
0227         else /* nothing special about this */
0228         {
0229             str[real] = str[data];
0230             real++;
0231             data++;
0232         }
0233     }
0234     /* Finish up the string with EOS! 
0235     str[real] = EOS;*/
0236     *out_len = real;
0237     
0238     return ret;
0239 }
0240 
0241 /**
0242  * Dump the UBF buffer to log file
0243  * @param lev - debug level
0244  * @param title - debug title
0245  * @param p_ub - pointer to UBF buffer
0246  */
0247 expublic void ndrx_debug_dump_UBF(int lev, char *title, UBFH *p_ub)
0248 {
0249     ndrx_debug_t * dbg = debug_get_ndrx_ptr();
0250     if (dbg->level>=lev)
0251     {
0252         /* This is as is it is meant ndrx topic: */
0253         NDRX_LOG(lev, "%s", title);
0254         
0255         ndrx_debug_lock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
0256         Bfprint(p_ub, ((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr)->fp);
0257         ndrx_debug_unlock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
0258     }
0259 }
0260 
0261 /**
0262  * Dump the UBF buffer to log file, UBF logger
0263  * @param lev - debug level
0264  * @param title - debug title
0265  * @param p_ub - pointer to UBF buffer
0266  */
0267 expublic void ndrx_debug_dump_UBF_ubflogger(int lev, char *title, UBFH *p_ub)
0268 {
0269     ndrx_debug_t * dbg = debug_get_ubf_ptr();
0270     if (dbg->level>=lev)
0271     {
0272         UBF_LOG(lev, "%s", title);
0273         
0274         ndrx_debug_lock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
0275         Bfprint(p_ub,((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr)->fp);
0276         ndrx_debug_unlock((ndrx_debug_file_sink_t*)dbg->dbg_f_ptr);
0277     }
0278 }
0279 
0280 /**
0281  * Print UBF header to UBF log
0282  * @param p_ub UBF buffer to dump
0283  */
0284 expublic void ndrx_debug_dump_UBF_hdr_ubflogger(int lev, char *title, UBFH *p_ub)
0285 {
0286     UBF_header_t *hdr = (UBF_header_t*)p_ub;
0287     ndrx_debug_t * dbg = debug_get_ubf_ptr();
0288     
0289     if (dbg->level>=lev)
0290     {
0291         UBF_LOG(lev, "****************** START OF %p UBF HEADER ******************", p_ub);
0292         UBF_LOG(lev, "%s: UBF_header_t.buffer_type=[%c] offset=%d", title,
0293                 hdr->buffer_type, EXOFFSET(UBF_header_t, buffer_type));
0294         UBF_LOG(lev, "%s: UBF_header_t.version=[%d]  offset=%d", title,
0295                 (unsigned int)hdr->version, EXOFFSET(UBF_header_t, version));
0296         UBF_LOG(lev, "%s: UBF_header_t.magic=[%x%x%x%x]  offset=%d", title,
0297                 (unsigned int)hdr->magic[0], (unsigned int)hdr->magic[1], 
0298                 (unsigned int)hdr->magic[2], (unsigned int)hdr->magic[3],
0299                 EXOFFSET(UBF_header_t, magic));
0300         UBF_LOG(lev, "%s: UBF_header_t.cache_long_off=[%d] offset=%d", title,
0301                 hdr->cache_long_off, EXOFFSET(UBF_header_t, cache_long_off));
0302         UBF_LOG(lev, "%s: UBF_header_t.cache_char_off=[%d] offset=%d", title,
0303                 hdr->cache_char_off, EXOFFSET(UBF_header_t, cache_char_off));
0304         UBF_LOG(lev, "%s: UBF_header_t.cache_float_off=[%d] offset=%d", title,
0305                 hdr->cache_float_off, EXOFFSET(UBF_header_t, cache_float_off));
0306         UBF_LOG(lev, "%s: UBF_header_t.cache_double_off=[%d] offset=%d", title,
0307                 hdr->cache_double_off, EXOFFSET(UBF_header_t, cache_double_off));
0308         UBF_LOG(lev, "%s: UBF_header_t.cache_string_off=[%d] offset=%d", title,
0309                 hdr->cache_string_off, EXOFFSET(UBF_header_t, cache_string_off));
0310         UBF_LOG(lev, "%s: UBF_header_t.cache_carray_off=[%d] offset=%d", title,
0311                 hdr->cache_carray_off, EXOFFSET(UBF_header_t, cache_carray_off));
0312         UBF_LOG(lev, "%s: UBF_header_t.cache_ptr_off=[%d] offset=%d", title,
0313                 hdr->cache_ptr_off, EXOFFSET(UBF_header_t, cache_ptr_off));
0314         UBF_LOG(lev, "%s: UBF_header_t.cache_ubf_off=[%d] offset=%d", title,
0315                 hdr->cache_ubf_off, EXOFFSET(UBF_header_t, cache_ubf_off));
0316         UBF_LOG(lev, "%s: UBF_header_t.cache_view_off=[%d] offset=%d", title,
0317                 hdr->cache_view_off, EXOFFSET(UBF_header_t, cache_view_off));
0318         UBF_LOG(lev, "%s: UBF_header_t.buf_len=[%d] offset=%d", title,
0319                 hdr->buf_len, EXOFFSET(UBF_header_t, buf_len));
0320         UBF_LOG(lev, "%s: UBF_header_t.opts=[%d] offset=%d", title,
0321                 hdr->opts, EXOFFSET(UBF_header_t, opts));
0322         UBF_LOG(lev, "%s: UBF_header_t.bytes_used=[%d] offset=%d", title,
0323                 hdr->bytes_used, EXOFFSET(UBF_header_t, bytes_used));
0324 #if EX_ALIGNMENT_BYTES == 8
0325         UBF_LOG(lev, "%s: UBF_header_t.padding1=[%ld] offset=%d", title,
0326                 hdr->padding1, EXOFFSET(UBF_header_t, padding1));
0327 #endif
0328         UBF_LOG(lev, "%s: UBF_header_t.bfldid=[%d] offset=%d", title,
0329                 hdr->bfldid, EXOFFSET(UBF_header_t, buffer_type));
0330 #if EX_ALIGNMENT_BYTES == 8
0331         UBF_LOG(lev, "%s: UBF_header_t.passing2=[%d] offset=%d", title,
0332                 hdr->passing2, EXOFFSET(UBF_header_t, passing2));
0333 #endif
0334         UBF_LOG(lev, "******************** END OF %p UBF HEADER ******************", p_ub);
0335     }
0336 }
0337 
0338 /**
0339  * Dump the VIEW buffer to log file, UBF logger
0340  * @param lev debug level
0341  * @param title debug title
0342  * @param cstruct blob to print
0343  * @param view View name
0344  */
0345 expublic void ndrx_debug_dump_VIEW_ubflogger(int lev, char *title, char *cstruct, char *view)
0346 {
0347     ndrx_debug_t * dbg = debug_get_ubf_ptr();
0348     
0349     if (EXSUCCEED==ndrx_view_init() && dbg->level>=lev)
0350     {
0351         UBF_LOG(lev, "%s: VIEW [%s]", title, view);
0352         Bvfprint(cstruct, view, dbg->dbg_f_ptr);
0353     }
0354 }
0355 
0356 /**
0357  * Compute size of UBF buffer
0358  * @param nrfields number of fields
0359  * @param totsize total space required for data (bytes of all fields)
0360  * @return EXSUCCEED/EXFAIL
0361  */
0362 expublic long ndrx_Bneeded(BFLDOCC nrfields, BFLDLEN totsize)
0363 {
0364     /* the biggest field we have is string, for which we have also len stored.. and EOS */
0365     return sizeof(UBF_header_t) + totsize 
0366             + nrfields*(EX_ALIGNMENT_BYTES+sizeof(UBF_string_t));
0367 }
0368 
0369 /* vim: set ts=4 sw=4 et smartindent: */