FreeSWITCH API Documentation  1.7.0
Data Structures | Macros | Typedefs | Functions | Variables
switch_mprintf.c File Reference
#include <switch.h>
+ Include dependency graph for switch_mprintf.c:

Go to the source code of this file.

Data Structures

struct  et_info
 
struct  sgMprintf
 

Macros

#define LONGDOUBLE_TYPE   long double
 
#define etRADIX   1 /* Integer types. %d, %x, %o, and so forth */
 
#define etFLOAT   2 /* Floating point. %f */
 
#define etEXP   3 /* Exponentional notation. %e and %E */
 
#define etGENERIC   4 /* Floating or exponential, depending on exponent. %g */
 
#define etSIZE   5 /* Return number of characters processed so far. %n */
 
#define etSTRING   6 /* Strings. %s */
 
#define etDYNSTRING   7 /* Dynamically allocated strings. %z */
 
#define etPERCENT   8 /* Percent symbol. %% */
 
#define etCHARX   9 /* Characters. %c */
 
#define etCHARLIT   10 /* Literal characters. %' */
 
#define etSQLESCAPE   11 /* Strings with '\'' doubled. %q */
 
#define etSQLESCAPE2
 
#define etPOINTER   15 /* The %p conversion */
 
#define etSQLESCAPE3   16
 
#define etSQLESCAPE4   17
 
#define FLAG_SIGNED   1 /* True if the value to convert is signed */
 
#define FLAG_INTERN   2 /* True if for internal use only */
 
#define FLAG_STRING   4 /* Allow infinity precision */
 
#define etNINFO   (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
 
#define SWITCH_PRINT_BUF_SIZE   350
 
#define etBUFSIZE   SWITCH_PRINT_BUF_SIZE /* Size of the output buffer */
 
#define etSPACESIZE   (sizeof(spaces)-1)
 

Typedefs

typedef unsigned char etByte
 
typedef struct et_info et_info
 

Functions

static int et_getdigit (LONGDOUBLE_TYPE *val, int *cnt)
 
static int vxprintf (void(*func)(void *, const char *, int), void *arg, int useExtended, const char *fmt, va_list ap)
 
static void mout (void *arg, const char *zNewText, int nNewChar)
 
static char * base_vprintf (void *(*xRealloc)(void *, int), int useInternal, char *zInitBuf, int nInitBuf, const char *zFormat, va_list ap)
 
static void * printf_realloc (void *old, int size)
 
char * switch_vmprintf (const char *zFormat, va_list ap)
 
char * switch_mprintf (const char *zFormat,...)
 
char * switch_snprintfv (char *zBuf, int n, const char *zFormat,...)
 

Variables

static const char aDigits [] = "0123456789ABCDEF0123456789abcdef"
 
static const char aPrefix [] = "-x0\000X0"
 
static const et_info fmtinfo []
 

Macro Definition Documentation

#define etBUFSIZE   SWITCH_PRINT_BUF_SIZE /* Size of the output buffer */

Definition at line 195 of file switch_mprintf.c.

Referenced by vxprintf().

#define etCHARLIT   10 /* Literal characters. %' */

Definition at line 79 of file switch_mprintf.c.

Referenced by vxprintf().

#define etCHARX   9 /* Characters. %c */

Definition at line 77 of file switch_mprintf.c.

Referenced by vxprintf().

#define etDYNSTRING   7 /* Dynamically allocated strings. %z */

Definition at line 75 of file switch_mprintf.c.

Referenced by vxprintf().

#define etEXP   3 /* Exponentional notation. %e and %E */

Definition at line 71 of file switch_mprintf.c.

Referenced by vxprintf().

#define etFLOAT   2 /* Floating point. %f */

Definition at line 70 of file switch_mprintf.c.

Referenced by vxprintf().

#define etGENERIC   4 /* Floating or exponential, depending on exponent. %g */

Definition at line 72 of file switch_mprintf.c.

Referenced by vxprintf().

#define etNINFO   (sizeof(fmtinfo)/sizeof(fmtinfo[0]))

Definition at line 153 of file switch_mprintf.c.

Referenced by vxprintf().

#define etPERCENT   8 /* Percent symbol. %% */

Definition at line 76 of file switch_mprintf.c.

Referenced by vxprintf().

#define etPOINTER   15 /* The %p conversion */

Definition at line 87 of file switch_mprintf.c.

Referenced by vxprintf().

#define etRADIX   1 /* Integer types. %d, %x, %o, and so forth */

Definition at line 69 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSIZE   5 /* Return number of characters processed so far. %n */

Definition at line 73 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSPACESIZE   (sizeof(spaces)-1)

Referenced by vxprintf().

#define etSQLESCAPE   11 /* Strings with '\'' doubled. %q */

Definition at line 80 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSQLESCAPE2
Value:
12 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */

Definition at line 81 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSQLESCAPE3   16

Definition at line 88 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSQLESCAPE4   17

Definition at line 89 of file switch_mprintf.c.

Referenced by vxprintf().

#define etSTRING   6 /* Strings. %s */

Definition at line 74 of file switch_mprintf.c.

Referenced by vxprintf().

#define FLAG_INTERN   2 /* True if for internal use only */

Definition at line 113 of file switch_mprintf.c.

Referenced by vxprintf().

#define FLAG_SIGNED   1 /* True if the value to convert is signed */

Definition at line 112 of file switch_mprintf.c.

Referenced by vxprintf().

#define FLAG_STRING   4 /* Allow infinity precision */

Definition at line 114 of file switch_mprintf.c.

Referenced by vxprintf().

#define LONGDOUBLE_TYPE   long double

Definition at line 63 of file switch_mprintf.c.

Referenced by et_getdigit(), and vxprintf().

#define SWITCH_PRINT_BUF_SIZE   350

Definition at line 193 of file switch_mprintf.c.

Referenced by switch_mprintf(), and switch_vmprintf().

Typedef Documentation

typedef struct et_info et_info
typedef unsigned char etByte

Definition at line 94 of file switch_mprintf.c.

Function Documentation

static char* base_vprintf ( void *(*)(void *, int)  xRealloc,
int  useInternal,
char *  zInitBuf,
int  nInitBuf,
const char *  zFormat,
va_list  ap 
)
static

Definition at line 847 of file switch_mprintf.c.

References mout(), sgMprintf::nAlloc, sgMprintf::nChar, sgMprintf::nTotal, vxprintf(), sgMprintf::xRealloc, sgMprintf::zBase, and sgMprintf::zText.

Referenced by switch_mprintf(), switch_snprintfv(), and switch_vmprintf().

854 {
855  struct sgMprintf sM;
856  sM.zBase = sM.zText = zInitBuf;
857  sM.nChar = sM.nTotal = 0;
858  sM.nAlloc = nInitBuf;
859  sM.xRealloc = xRealloc;
860  vxprintf(mout, &sM, useInternal, zFormat, ap);
861  if (xRealloc) {
862  if (sM.zText == sM.zBase) {
863  sM.zText = xRealloc(0, sM.nChar + 1);
864  if (sM.zText) {
865  memcpy(sM.zText, sM.zBase, sM.nChar + 1);
866  }
867  } else if (sM.nAlloc > sM.nChar + 10) {
868  char *zNew = xRealloc(sM.zText, sM.nChar + 1);
869  if (zNew) {
870  sM.zText = zNew;
871  }
872  }
873  }
874  return sM.zText;
875 }
char * zBase
static void mout(void *arg, const char *zNewText, int nNewChar)
static int vxprintf(void(*func)(void *, const char *, int), void *arg, int useExtended, const char *fmt, va_list ap)
void *(* xRealloc)(void *, int)
static int et_getdigit ( LONGDOUBLE_TYPE val,
int *  cnt 
)
static

Definition at line 173 of file switch_mprintf.c.

References LONGDOUBLE_TYPE.

Referenced by vxprintf().

174 {
175  int digit;
176  LONGDOUBLE_TYPE d;
177  if ((*cnt)++ >= 16)
178  return '0';
179  digit = (int) *val;
180  d = digit;
181  digit += '0';
182  *val = (*val - d) * 10.0;
183  return digit;
184 }
#define LONGDOUBLE_TYPE
static void mout ( void *  arg,
const char *  zNewText,
int  nNewChar 
)
static

Definition at line 811 of file switch_mprintf.c.

References sgMprintf::nAlloc, sgMprintf::nChar, sgMprintf::nTotal, sgMprintf::xRealloc, sgMprintf::zBase, and sgMprintf::zText.

Referenced by base_vprintf().

812 {
813  struct sgMprintf *pM = (struct sgMprintf *) arg;
814  pM->nTotal += nNewChar;
815  if (pM->nChar + nNewChar + 1 > pM->nAlloc) {
816  if (pM->xRealloc == 0) {
817  nNewChar = pM->nAlloc - pM->nChar - 1;
818  } else {
819  pM->nAlloc = pM->nChar + nNewChar * 2 + 1;
820  if (pM->zText == pM->zBase) {
821  pM->zText = pM->xRealloc(0, pM->nAlloc);
822  if (pM->zText && pM->nChar) {
823  memcpy(pM->zText, pM->zBase, pM->nChar);
824  }
825  } else {
826  char *zNew;
827  zNew = pM->xRealloc(pM->zText, pM->nAlloc);
828  if (zNew) {
829  pM->zText = zNew;
830  }
831  }
832  }
833  }
834  if (pM->zText) {
835  if (nNewChar > 0) {
836  memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
837  pM->nChar += nNewChar;
838  }
839  pM->zText[pM->nChar] = 0;
840  }
841 }
char * zBase
char * zText
void *(* xRealloc)(void *, int)
static void* printf_realloc ( void *  old,
int  size 
)
static

Definition at line 880 of file switch_mprintf.c.

Referenced by switch_mprintf(), and switch_vmprintf().

881 {
882  return realloc(old, size);
883 }
char* switch_mprintf ( const char *  zFormat,
  ... 
)

This routine is a variant of the "sprintf()" from the standard C library. The resulting string is written into memory obtained from malloc() so that there is never a possiblity of buffer overflow. This routine also implement some additional formatting options that are useful for constructing SQL statements.

The strings returned by this routine should be freed by calling free().

All of the usual printf formatting options apply. In addition, there is a "%q" option. q works like s in that it substitutes a null-terminated string from the argument list. But q also doubles every '\'' character. q is designed for use inside a string literal. By doubling each '\'' character it escapes that character and allows it to be inserted into the string.

For example, so some string variable contains text as follows:

 char *zText = "It's a happy day!";

We can use this text in an SQL statement as follows:

 char *z = switch_mprintf("INSERT INTO TABLES('%q')", zText);
 switch_core_db_exec(db, z, callback1, 0, 0);
 free(z);

Because the q format string is used, the '\'' character in zText is escaped and the SQL generated is as follows:

 INSERT INTO table1 VALUES('It''s a happy day!')

This is correct. Had we used s instead of q, the generated SQL would have looked like this:

 INSERT INTO table1 VALUES('It's a happy day!');

This second example is an SQL syntax error. As a general rule you should always use q instead of s when inserting text into a string literal.

Definition at line 897 of file switch_mprintf.c.

References base_vprintf(), printf_realloc(), SWITCH_PRINT_BUF_SIZE, and sgMprintf::zBase.

Referenced by core_event_handler(), load_mime_types(), preprocess_glob(), Event::serialize(), setup_ringback(), switch_channel_export_variable_var_check(), switch_console_complete(), switch_console_expand_alias(), switch_console_list_uuid(), switch_console_set_alias(), switch_core_add_registration(), switch_core_cert_gen_fingerprint(), switch_core_del_registration(), switch_core_expire_registration(), switch_core_file_close(), switch_core_gen_certs(), switch_core_recovery_flush(), switch_core_recovery_recover(), switch_core_recovery_track(), switch_core_recovery_untrack(), switch_core_session_exec(), switch_format_number(), switch_ivr_wait_for_answer(), switch_load_network_lists(), switch_loadable_module_enumerate_available(), switch_loadable_module_load_file(), switch_odbc_handle_get_error(), switch_play_and_get_digits(), switch_process_import(), switch_simple_email(), switch_stream_write_file_contents(), switch_xml_parse_file(), and tone_detect_set_total_time().

898 {
899  va_list ap;
900  char *z;
902  va_start(ap, zFormat);
903  z = base_vprintf(printf_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
904  va_end(ap);
905  return z;
906 }
#define SWITCH_PRINT_BUF_SIZE
static char * base_vprintf(void *(*xRealloc)(void *, int), int useInternal, char *zInitBuf, int nInitBuf, const char *zFormat, va_list ap)
char * zBase
static void * printf_realloc(void *old, int size)
char* switch_snprintfv ( char *  zBuf,
int  n,
const char *  zFormat,
  ... 
)

Definition at line 914 of file switch_mprintf.c.

References base_vprintf().

Referenced by do_trans(), parse_presence_data_cols(), switch_cache_db_persistant_execute_trans_full(), and switch_core_sqldb_start().

915 {
916  char *z;
917  va_list ap;
918 
919  va_start(ap, zFormat);
920  z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
921  va_end(ap);
922  return z;
923 }
static char * base_vprintf(void *(*xRealloc)(void *, int), int useInternal, char *zInitBuf, int nInitBuf, const char *zFormat, va_list ap)
char* switch_vmprintf ( const char *  zFormat,
va_list  ap 
)

Definition at line 888 of file switch_mprintf.c.

References base_vprintf(), printf_realloc(), SWITCH_PRINT_BUF_SIZE, and sgMprintf::zBase.

Referenced by cJSON_CreateStringPrintf(), and switch_console_stream_write().

889 {
891  return base_vprintf(printf_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
892 }
#define SWITCH_PRINT_BUF_SIZE
static char * base_vprintf(void *(*xRealloc)(void *, int), int useInternal, char *zInitBuf, int nInitBuf, const char *zFormat, va_list ap)
char * zBase
static void * printf_realloc(void *old, int size)
static int vxprintf ( void(*)(void *, const char *, int)  func,
void *  arg,
int  useExtended,
const char *  fmt,
va_list  ap 
)
static

Definition at line 224 of file switch_mprintf.c.

References aDigits, aPrefix, et_info::base, buf, et_info::charset, et_getdigit(), etBUFSIZE, etCHARLIT, etCHARX, etDYNSTRING, etEXP, etFLOAT, etGENERIC, etNINFO, etPERCENT, etPOINTER, etRADIX, etSIZE, etSPACESIZE, etSQLESCAPE, etSQLESCAPE2, etSQLESCAPE3, etSQLESCAPE4, etSTRING, FLAG_INTERN, FLAG_SIGNED, FLAG_STRING, et_info::flags, if(), LONGDOUBLE_TYPE, et_info::prefix, and et_info::type.

Referenced by base_vprintf().

230 {
231  int c; /* Next character in the format string */
232  char *bufpt; /* Pointer to the conversion buffer */
233  int precision; /* Precision of the current field */
234  int length; /* Length of the field */
235  int idx; /* A general purpose loop counter */
236  int count; /* Total number of characters output */
237  int width; /* Width of the current field */
238  etByte flag_leftjustify; /* True if "-" flag is present */
239  etByte flag_plussign; /* True if "+" flag is present */
240  etByte flag_blanksign; /* True if " " flag is present */
241  etByte flag_alternateform; /* True if "#" flag is present */
242  etByte flag_altform2; /* True if "!" flag is present */
243  etByte flag_zeropad; /* True if field width constant starts with zero */
244  etByte flag_long; /* True if "l" flag is present */
245  etByte flag_longlong; /* True if the "ll" flag is present */
246  etByte done; /* Loop termination flag */
247  uint64_t longvalue; /* Value for integer types */
248  LONGDOUBLE_TYPE realvalue; /* Value for real types */
249  const et_info *infop; /* Pointer to the appropriate info structure */
250  char buf[etBUFSIZE]; /* Conversion buffer */
251  char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
252  etByte errorflag = 0; /* True if an error is encountered */
253  etByte xtype = 0; /* Conversion paradigm */
254  char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
255  static const char spaces[] = " ";
256 #define etSPACESIZE (sizeof(spaces)-1)
257 #ifndef SWITCH_OMIT_FLOATING_POINT
258  int exp, e2; /* exponent of real numbers */
259  double rounder; /* Used for rounding floating point values */
260  etByte flag_dp; /* True if decimal point should be shown */
261  etByte flag_rtz; /* True if trailing zeros should be removed */
262  etByte flag_exp; /* True to force display of the exponent */
263  int nsd; /* Number of significant digits returned */
264 #endif
265 
266  func(arg, "", 0);
267  count = length = 0;
268  bufpt = 0;
269  for (; (c = (*fmt)) != 0; ++fmt) {
270  if (c != '%') {
271  int amt;
272  bufpt = (char *) fmt;
273  amt = 1;
274  while ((c = (*++fmt)) != '%' && c != 0)
275  amt++;
276  (*func) (arg, bufpt, amt);
277  count += amt;
278  if (c == 0)
279  break;
280  }
281  if ((c = (*++fmt)) == 0) {
282  errorflag = 1;
283  (*func) (arg, "%", 1);
284  count++;
285  break;
286  }
287  /* Find out what flags are present */
288  flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_altform2 = flag_zeropad = 0;
289  done = 0;
290  do {
291  switch (c) {
292  case '-':
293  flag_leftjustify = 1;
294  break;
295  case '+':
296  flag_plussign = 1;
297  break;
298  case ' ':
299  flag_blanksign = 1;
300  break;
301  case '#':
302  flag_alternateform = 1;
303  break;
304  case '!':
305  flag_altform2 = 1;
306  break;
307  case '0':
308  flag_zeropad = 1;
309  break;
310  default:
311  done = 1;
312  break;
313  }
314  } while (!done && (c = (*++fmt)) != 0);
315  /* Get the field width */
316  width = 0;
317  if (c == '*') {
318  width = va_arg(ap, int);
319  if (width < 0) {
320  flag_leftjustify = 1;
321  width = -width;
322  }
323  c = *++fmt;
324  } else {
325  while (c >= '0' && c <= '9') {
326  width = width * 10 + c - '0';
327  c = *++fmt;
328  }
329  }
330  if (width > etBUFSIZE - 10) {
331  width = etBUFSIZE - 10;
332  }
333  /* Get the precision */
334  if (c == '.') {
335  precision = 0;
336  c = *++fmt;
337  if (c == '*') {
338  precision = va_arg(ap, int);
339  if (precision < 0)
340  precision = -precision;
341  c = *++fmt;
342  } else {
343  while (c >= '0' && c <= '9') {
344  precision = precision * 10 + c - '0';
345  c = *++fmt;
346  }
347  }
348  } else {
349  precision = -1;
350  }
351  /* Get the conversion type modifier */
352  if (c == 'l') {
353  flag_long = 1;
354  c = *++fmt;
355  if (c == 'l') {
356  flag_longlong = 1;
357  c = *++fmt;
358  } else {
359  flag_longlong = 0;
360  }
361  } else {
362  flag_long = flag_longlong = 0;
363  }
364  /* Fetch the info entry for the field */
365  infop = 0;
366  for (idx = 0; idx < etNINFO; idx++) {
367  if (c == fmtinfo[idx].fmttype) {
368  infop = &fmtinfo[idx];
369  if (useExtended || (infop->flags & FLAG_INTERN) == 0) {
370  xtype = infop->type;
371  } else {
372  return -1;
373  }
374  break;
375  }
376  }
377  zExtra = 0;
378  if (infop == 0) {
379  return -1;
380  }
381 
382 
383  /* Limit the precision to prevent overflowing buf[] during conversion */
384  if (precision > etBUFSIZE - 40 && (infop->flags & FLAG_STRING) == 0) {
385  precision = etBUFSIZE - 40;
386  }
387 
388  /*
389  ** At this point, variables are initialized as follows:
390  **
391  ** flag_alternateform TRUE if a '#' is present.
392  ** flag_altform2 TRUE if a '!' is present.
393  ** flag_plussign TRUE if a '+' is present.
394  ** flag_leftjustify TRUE if a '-' is present or if the
395  ** field width was negative.
396  ** flag_zeropad TRUE if the width began with 0.
397  ** flag_long TRUE if the letter 'l' (ell) prefixed
398  ** the conversion character.
399  ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
400  ** the conversion character.
401  ** flag_blanksign TRUE if a ' ' is present.
402  ** width The specified field width. This is
403  ** always non-negative. Zero is the default.
404  ** precision The specified precision. The default
405  ** is -1.
406  ** xtype The class of the conversion.
407  ** infop Pointer to the appropriate info struct.
408  */
409  switch (xtype) {
410  case etPOINTER:
411  flag_longlong = sizeof(char *) == sizeof(int64_t);
412  flag_long = sizeof(char *) == sizeof(long int);
413  /* Fall through into the next case */
414  case etRADIX:
415  if (infop->flags & FLAG_SIGNED) {
416  int64_t v;
417  if (flag_longlong)
418  v = va_arg(ap, int64_t);
419  else if (flag_long)
420  v = va_arg(ap, long int);
421  else
422  v = va_arg(ap, int);
423  if (v < 0) {
424  longvalue = -v;
425  prefix = '-';
426  } else {
427  longvalue = v;
428  if (flag_plussign)
429  prefix = '+';
430  else if (flag_blanksign)
431  prefix = ' ';
432  else
433  prefix = 0;
434  }
435  } else {
436  if (flag_longlong)
437  longvalue = va_arg(ap, uint64_t);
438  else if (flag_long)
439  longvalue = va_arg(ap, unsigned long int);
440  else
441  longvalue = va_arg(ap, unsigned int);
442  prefix = 0;
443  }
444  if (longvalue == 0)
445  flag_alternateform = 0;
446  if (flag_zeropad && precision < width - (prefix != 0)) {
447  precision = width - (prefix != 0);
448  }
449  bufpt = &buf[etBUFSIZE - 1];
450  {
451  register const char *cset; /* Use registers for speed */
452  register int base;
453  cset = &aDigits[infop->charset];
454  base = infop->base;
455  do { /* Convert to ascii */
456  *(--bufpt) = cset[longvalue % base];
457  longvalue = longvalue / base;
458  } while (longvalue > 0);
459  }
460  length = (int)(&buf[etBUFSIZE - 1] - bufpt);
461  for (idx = precision - length; idx > 0; idx--) {
462  *(--bufpt) = '0'; /* Zero pad */
463  }
464  if (prefix)
465  *(--bufpt) = prefix; /* Add sign */
466  if (flag_alternateform && infop->prefix) { /* Add "0" or "0x" */
467  const char *pre;
468  char x;
469  pre = &aPrefix[infop->prefix];
470  if (*bufpt != pre[0]) {
471  for (; (x = (*pre)) != 0; pre++)
472  *(--bufpt) = x;
473  }
474  }
475  length = (int)(&buf[etBUFSIZE - 1] - bufpt);
476  break;
477  case etFLOAT:
478  case etEXP:
479  case etGENERIC:
480  realvalue = va_arg(ap, double);
481 #ifndef SWITCH_OMIT_FLOATING_POINT
482  if (precision < 0)
483  precision = 6; /* Set default precision */
484  if (precision > etBUFSIZE / 2 - 10)
485  precision = etBUFSIZE / 2 - 10;
486  if (realvalue < 0.0) {
487  realvalue = -realvalue;
488  prefix = '-';
489  } else {
490  if (flag_plussign)
491  prefix = '+';
492  else if (flag_blanksign)
493  prefix = ' ';
494  else
495  prefix = 0;
496  }
497  if (xtype == etGENERIC && precision > 0)
498  precision--;
499 #if 0
500  /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
501  for (idx = precision, rounder = 0.4999; idx > 0; idx--, rounder *= 0.1);
502 #else
503  /* It makes more sense to use 0.5 */
504  for (idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1) {
505  }
506 #endif
507  if (xtype == etFLOAT)
508  realvalue += rounder;
509  /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
510  exp = 0;
511  if (realvalue > 0.0) {
512  while (realvalue >= 1e32 && exp <= 350) {
513  realvalue *= 1e-32;
514  exp += 32;
515  }
516  while (realvalue >= 1e8 && exp <= 350) {
517  realvalue *= 1e-8;
518  exp += 8;
519  }
520  while (realvalue >= 10.0 && exp <= 350) {
521  realvalue *= 0.1;
522  exp++;
523  }
524  while (realvalue < 1e-8 && exp >= -350) {
525  realvalue *= 1e8;
526  exp -= 8;
527  }
528  while (realvalue < 1.0 && exp >= -350) {
529  realvalue *= 10.0;
530  exp--;
531  }
532  if (exp > 350 || exp < -350) {
533  bufpt = "NaN";
534  length = 3;
535  break;
536  }
537  }
538  bufpt = buf;
539  /*
540  ** If the field type is etGENERIC, then convert to either etEXP
541  ** or etFLOAT, as appropriate.
542  */
543  flag_exp = xtype == etEXP;
544  if (xtype != etFLOAT) {
545  realvalue += rounder;
546  if (realvalue >= 10.0) {
547  realvalue *= 0.1;
548  exp++;
549  }
550  }
551  if (xtype == etGENERIC) {
552  flag_rtz = !flag_alternateform;
553  if (exp < -4 || exp > precision) {
554  xtype = etEXP;
555  } else {
556  precision = precision - exp;
557  xtype = etFLOAT;
558  }
559  } else {
560  flag_rtz = 0;
561  }
562  if (xtype == etEXP) {
563  e2 = 0;
564  } else {
565  e2 = exp;
566  }
567  nsd = 0;
568  flag_dp = (precision > 0) | flag_alternateform | flag_altform2;
569  /* The sign in front of the number */
570  if (prefix) {
571  *(bufpt++) = prefix;
572  }
573  /* Digits prior to the decimal point */
574  if (e2 < 0) {
575  *(bufpt++) = '0';
576  } else {
577  for (; e2 >= 0; e2--) {
578  *(bufpt++) = (char) et_getdigit(&realvalue, &nsd);
579  }
580  }
581  /* The decimal point */
582  if (flag_dp) {
583  *(bufpt++) = '.';
584  }
585  /* "0" digits after the decimal point but before the first
586  ** significant digit of the number */
587  for (e2++; e2 < 0 && precision > 0; precision--, e2++) {
588  *(bufpt++) = '0';
589  }
590  /* Significant digits after the decimal point */
591  while ((precision--) > 0) {
592  *(bufpt++) = (char) et_getdigit(&realvalue, &nsd);
593  }
594  /* Remove trailing zeros and the "." if no digits follow the "." */
595  if (flag_rtz && flag_dp) {
596  while (bufpt[-1] == '0')
597  *(--bufpt) = 0;
598  assert(bufpt > buf);
599  if (bufpt[-1] == '.') {
600  if (flag_altform2) {
601  *(bufpt++) = '0';
602  } else {
603  *(--bufpt) = 0;
604  }
605  }
606  }
607  /* Add the "eNNN" suffix */
608  if (flag_exp || (xtype == etEXP && exp)) {
609  *(bufpt++) = aDigits[infop->charset];
610  if (exp < 0) {
611  *(bufpt++) = '-';
612  exp = -exp;
613  } else {
614  *(bufpt++) = '+';
615  }
616  if (exp >= 100) {
617  *(bufpt++) = (char) (exp / 100) + '0'; /* 100's digit */
618  exp %= 100;
619  }
620  *(bufpt++) = (char) exp / 10 + '0'; /* 10's digit */
621  *(bufpt++) = exp % 10 + '0'; /* 1's digit */
622  }
623  *bufpt = 0;
624 
625  /* The converted number is in buf[] and zero terminated. Output it.
626  ** Note that the number is in the usual order, not reversed as with
627  ** integer conversions. */
628  length = (int)(bufpt - buf);
629  bufpt = buf;
630 
631  /* Special case: Add leading zeros if the flag_zeropad flag is
632  ** set and we are not left justified */
633  if (flag_zeropad && !flag_leftjustify && length < width) {
634  int i;
635  int nPad = width - length;
636  for (i = width; i >= nPad; i--) {
637  bufpt[i] = bufpt[i - nPad];
638  }
639  i = prefix != 0;
640  while (nPad--)
641  bufpt[i++] = '0';
642  length = width;
643  }
644 #endif
645  break;
646  case etSIZE:
647  *(va_arg(ap, int *)) = count;
648  length = width = 0;
649  break;
650  case etPERCENT:
651  buf[0] = '%';
652  bufpt = buf;
653  length = 1;
654  break;
655  case etCHARLIT:
656  case etCHARX:
657  c = buf[0] = (char) (xtype == etCHARX ? va_arg(ap, int) : *++fmt);
658  if (precision >= 0) {
659  for (idx = 1; idx < precision; idx++)
660  buf[idx] = (char) c;
661  length = precision;
662  } else {
663  length = 1;
664  }
665  bufpt = buf;
666  break;
667  case etSTRING:
668  case etDYNSTRING:
669  bufpt = va_arg(ap, char *);
670  if (bufpt == 0) {
671  bufpt = "";
672  } else if (xtype == etDYNSTRING) {
673  zExtra = bufpt;
674  }
675  length = (int)strlen(bufpt);
676  if (precision >= 0 && precision < length)
677  length = precision;
678  break;
679  case etSQLESCAPE:
680  case etSQLESCAPE2:
681  case etSQLESCAPE4:
682  case etSQLESCAPE3:{
683  int i, j, n, ch, isnull;
684  int needQuote;
685  char *escarg = va_arg(ap, char *);
686  isnull = escarg == 0;
687  if (isnull)
688  escarg = (xtype == etSQLESCAPE2 ? "NULL" : "(NULL)");
689  for (i = n = 0; (ch = escarg[i]) != 0; i++) {
690  if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\'))
691  n++;
692  }
693  needQuote = !isnull && xtype == etSQLESCAPE2;
694  n += i + 1 + needQuote * 2;
695  if (n > etBUFSIZE) {
696  bufpt = zExtra = malloc(n);
697  if (bufpt == 0)
698  return -1;
699  } else {
700  bufpt = buf;
701  }
702  j = 0;
703  if (needQuote)
704  bufpt[j++] = '\'';
705  for (i = 0; (ch = escarg[i]) != 0; i++) {
706  bufpt[j++] = (char) ch;
707  if (xtype == etSQLESCAPE4) {
708  if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\')) {
709  bufpt[j] = (char) ch;
710  bufpt[j-1] = (char) '\\';
711  j++;
712  }
713  } else {
714  if (ch == '\'' || (xtype == etSQLESCAPE3 && ch == '\\'))
715  bufpt[j++] = (char) ch;
716  }
717  }
718  if (needQuote)
719  bufpt[j++] = '\'';
720  bufpt[j] = 0;
721  length = j;
722  /* The precision is ignored on %q and %Q */
723  /* if ( precision>=0 && precision<length ) length = precision; */
724  break;
725  }
726 #ifdef __UNSUPPORTED__
727  case etTOKEN:{
728  Token *pToken = va_arg(ap, Token *);
729  if (pToken && pToken->z) {
730  (*func) (arg, (char *) pToken->z, pToken->n);
731  }
732  length = width = 0;
733  break;
734  }
735  case etSRCLIST:{
736  SrcList *pSrc = va_arg(ap, SrcList *);
737  int k = va_arg(ap, int);
738  struct SrcList_item *pItem = &pSrc->a[k];
739  assert(k >= 0 && k < pSrc->nSrc);
740  if (pItem->zDatabase && pItem->zDatabase[0]) {
741  (*func) (arg, pItem->zDatabase, strlen(pItem->zDatabase));
742  (*func) (arg, ".", 1);
743  }
744  (*func) (arg, pItem->zName, strlen(pItem->zName));
745  length = width = 0;
746  break;
747  }
748 #endif
749  } /* End switch over the format type */
750  /*
751  ** The text of the conversion is pointed to by "bufpt" and is
752  ** "length" characters long. The field width is "width". Do
753  ** the output.
754  */
755  if (!flag_leftjustify) {
756  register int nspace;
757  nspace = width - length;
758  if (nspace > 0) {
759  count += nspace;
760  while (nspace >= etSPACESIZE) {
761  (*func) (arg, spaces, etSPACESIZE);
762  nspace -= etSPACESIZE;
763  }
764  if (nspace > 0)
765  (*func) (arg, spaces, nspace);
766  }
767  }
768  if (length > 0) {
769  (*func) (arg, bufpt, length);
770  count += length;
771  }
772  if (flag_leftjustify) {
773  register int nspace;
774  nspace = width - length;
775  if (nspace > 0) {
776  count += nspace;
777  while (nspace >= etSPACESIZE) {
778  (*func) (arg, spaces, etSPACESIZE);
779  nspace -= etSPACESIZE;
780  }
781  if (nspace > 0)
782  (*func) (arg, spaces, nspace);
783  }
784  }
785  if (zExtra) {
786  free(zExtra);
787  }
788  } /* End for loop over the format string */
789  return errorflag ? -1 : count;
790 } /* End of function */
etByte charset
static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt)
#define etSQLESCAPE4
static const et_info fmtinfo[]
#define etBUFSIZE
#define etRADIX
#define etEXP
etByte type
static const char aPrefix[]
#define etSTRING
#define FLAG_STRING
unsigned char etByte
etByte prefix
#define etSIZE
static const char aDigits[]
if((uint32_t)(unpack->cur-unpack->buf) > unpack->buflen)
switch_byte_t switch_byte_t * buf
#define etSPACESIZE
#define etNINFO
etByte flags
#define etCHARLIT
#define LONGDOUBLE_TYPE
#define FLAG_INTERN
#define etSQLESCAPE
#define etFLOAT
#define etPERCENT
#define etGENERIC
#define etPOINTER
#define etCHARX
#define etSQLESCAPE3
etByte base
#define etDYNSTRING
#define etSQLESCAPE2
#define FLAG_SIGNED

Variable Documentation

const char aDigits[] = "0123456789ABCDEF0123456789abcdef"
static

Definition at line 121 of file switch_mprintf.c.

Referenced by vxprintf().

const char aPrefix[] = "-x0\000X0"
static

Definition at line 122 of file switch_mprintf.c.

Referenced by vxprintf().

const et_info fmtinfo[]
static
Initial value:
= {
{'d', 10, 1, etRADIX, 0, 0},
{'s', 0, 4, etSTRING, 0, 0},
{'g', 0, 1, etGENERIC, 30, 0},
{'z', 0, 6, etDYNSTRING, 0, 0},
{'q', 0, 4, etSQLESCAPE, 0, 0},
{'Q', 0, 4, etSQLESCAPE2, 0, 0},
{'w', 0, 4, etSQLESCAPE3, 0, 0},
{'y', 0, 4, etSQLESCAPE4, 0, 0},
{'c', 0, 0, etCHARX, 0, 0},
{'o', 8, 0, etRADIX, 0, 2},
{'u', 10, 0, etRADIX, 0, 0},
{'x', 16, 0, etRADIX, 16, 1},
{'X', 16, 0, etRADIX, 0, 4},
{'f', 0, 1, etFLOAT, 0, 0},
{'e', 0, 1, etEXP, 30, 0},
{'E', 0, 1, etEXP, 14, 0},
{'G', 0, 1, etGENERIC, 14, 0},
{'i', 10, 1, etRADIX, 0, 0},
{'n', 0, 0, etSIZE, 0, 0},
{'%', 0, 0, etPERCENT, 0, 0},
{'p', 16, 0, etPOINTER, 0, 1},
}
#define etSQLESCAPE4
#define etRADIX
#define etEXP
#define etSTRING
#define etSIZE
#define etSQLESCAPE
#define etFLOAT
#define etPERCENT
#define etGENERIC
#define etPOINTER
#define etCHARX
#define etSQLESCAPE3
#define etDYNSTRING
#define etSQLESCAPE2

Definition at line 123 of file switch_mprintf.c.