string.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. /*
  2. ** Copyright (c) 2011 D. Richard Hipp
  3. **
  4. ** This program is free software; you can redistribute it and/or
  5. ** modify it under the terms of the Simplified BSD License (also
  6. ** known as the "2-Clause License" or "FreeBSD License".)
  7. **
  8. ** This program is distributed in the hope that it will be useful,
  9. ** but without any warranty; without even the implied warranty of
  10. ** merchantability or fitness for a particular purpose.
  11. **
  12. ** Author contact information:
  13. ** [email protected]
  14. ** http://www.hwaci.com/drh/
  15. **
  16. *************************************************************************
  17. ** String manipulation routines.
  18. */
  19. #include "xjd1Int.h"
  20. /*
  21. ** Compute a string length that is limited to what can be stored in
  22. ** lower 30 bits of a 32-bit signed integer.
  23. **
  24. ** The value returned will never be negative. Nor will it ever be greater
  25. ** than the actual length of the string. For very long strings (greater
  26. ** than 1GiB) the value returned might be less than the true string length.
  27. */
  28. PRIVATE int xjd1Strlen30(const char *z){
  29. const char *z2 = z;
  30. if( z==0 ) return 0;
  31. while( *z2 ){ z2++; }
  32. return 0x3fffffff & (int)(z2 - z);
  33. }
  34. /*
  35. ** Change the allocation size for a string to newSize bytes. Return
  36. ** 1 if an OOM error occurs or 0 on success.
  37. */
  38. static int resizeString(String *pStr, int newSize){
  39. char *zNew;
  40. if( pStr->pPool ){
  41. zNew = xjd1PoolMalloc(pStr->pPool, newSize);
  42. if( zNew==0 ) return 1;
  43. memcpy(zNew, pStr->zBuf, pStr->nUsed);
  44. }else{
  45. zNew = xjd1_realloc(pStr->zBuf, newSize);
  46. if( zNew==0 ) return 1;
  47. }
  48. pStr->nAlloc = newSize;
  49. pStr->zBuf = zNew;
  50. return 0;
  51. }
  52. /*
  53. ** Truncate a string to zero length
  54. */
  55. void xjd1StringTruncate(String *pStr){
  56. if( pStr ){
  57. pStr->nUsed = 0;
  58. if( pStr->zBuf ) pStr->zBuf[0] = 0;
  59. }
  60. }
  61. /*
  62. ** Return the value of a string.
  63. */
  64. char *xjd1StringGet(String *pStr){
  65. char *z;
  66. if( pStr==0 ) return 0;
  67. z = pStr->zBuf;
  68. memset(pStr, 0, sizeof(*pStr));
  69. return z;
  70. }
  71. /*
  72. ** Append text in z to a string. If n>=0 then append exactly
  73. ** n bytes. If n<0 then append all of z[] up to the zero terminator.
  74. **
  75. ** Return the number of bytes appended. 0 is returned on an OOM
  76. ** error.
  77. */
  78. PRIVATE int xjd1StringAppend(String *pStr, const char *z, int n){
  79. if( n<0 ) n = xjd1Strlen30(z);
  80. if( pStr->nUsed + n + 1 >= pStr->nAlloc ){
  81. if( resizeString(pStr, pStr->nAlloc*2 + n + 100) ) return 0;
  82. }
  83. if( z ){
  84. memcpy(&pStr->zBuf[pStr->nUsed], z, n);
  85. pStr->nUsed += n;
  86. pStr->zBuf[pStr->nUsed] = 0;
  87. }
  88. return n;
  89. }
  90. /*
  91. ** Initialize a string object that has been previously allocated.
  92. ** In other words, turn bulk memory into a string object.
  93. */
  94. PRIVATE void xjd1StringInit(String *pStr, Pool *pPool, int initSize){
  95. memset(pStr, 0, sizeof(*pStr));
  96. pStr->pPool = pPool;
  97. if( initSize>0 ){
  98. resizeString(pStr, initSize);
  99. }
  100. }
  101. /*
  102. ** Allocate a new string object. Initialize the string buffer to
  103. ** initSize bytes. initSize can be zero.
  104. **
  105. ** If pPool is not NULL then all string memory allocations including
  106. ** the allocation of the String object itself, come from the identified
  107. ** memory pool. If pPool is NULL, then xjd1_malloc()/xjd1_free() are used.
  108. */
  109. PRIVATE String *xjd1StringNew(Pool *pPool, int initSize){
  110. String *pStr;
  111. if( pPool ){
  112. pStr = xjd1PoolMalloc(pPool, sizeof(*pStr));
  113. }else{
  114. pStr = xjd1_malloc( sizeof(*pStr) );
  115. }
  116. if( pStr) xjd1StringInit(pStr, pPool, initSize);
  117. return pStr;
  118. }
  119. /*
  120. ** Free the content of a string but not the String object itself.
  121. */
  122. PRIVATE void xjd1StringClear(String *pStr){
  123. if( pStr ){
  124. if( pStr->pPool==0 ) xjd1_free(pStr->zBuf);
  125. memset(pStr, 0, sizeof(*pStr));
  126. }
  127. }
  128. /*
  129. ** Free a string previously allocated using xjd1StringNew().
  130. */
  131. PRIVATE void xjd1StringDelete(String *pStr){
  132. if( pStr && pStr->pPool==0 ){
  133. xjd1_free(pStr->zBuf);
  134. xjd1_free(pStr);
  135. }
  136. }
  137. /*
  138. ** Consume the first N characters from the front of the string.
  139. */
  140. PRIVATE void xjd1StringRemovePrefix(String *pStr, int N){
  141. if( pStr==0 ) return;
  142. if( pStr->nUsed<=N ){
  143. xjd1StringTruncate(pStr);
  144. }else{
  145. memmove(pStr->zBuf, &pStr->zBuf[N], (pStr->nUsed+1)-N);
  146. pStr->nUsed -= N;
  147. }
  148. }
  149. /*
  150. ** Conversion types fall into various categories as defined by the
  151. ** following enumeration.
  152. */
  153. #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
  154. #define etFLOAT 2 /* Floating point. %f */
  155. #define etEXP 3 /* Exponentional notation. %e and %E */
  156. #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
  157. #define etSIZE 5 /* Return number of characters processed so far. %n */
  158. #define etSTRING 6 /* Strings. %s */
  159. #define etDYNSTRING 7 /* Dynamically allocated strings. %z */
  160. #define etPERCENT 8 /* Percent symbol. %% */
  161. #define etCHARX 9 /* Characters. %c */
  162. #define etERROR 10 /* Used to indicate no such conversion type */
  163. #define etPOINTER 11 /* Pointer value. %p */
  164. /* The rest are extensions, not normally found in printf() */
  165. #define etSTRESCAPE 12 /* Strings with escapes. %q */
  166. /*
  167. ** An "etByte" is an 8-bit unsigned value.
  168. */
  169. typedef unsigned char etByte;
  170. typedef long long int i64;
  171. typedef unsigned long long int u64;
  172. /*
  173. ** Each builtin conversion character (ex: the 'd' in "%d") is described
  174. ** by an instance of the following structure
  175. */
  176. typedef struct et_info { /* Information about each format field */
  177. char fmttype; /* The format field code letter */
  178. etByte base; /* The base for radix conversion */
  179. etByte flags; /* One or more of FLAG_ constants below */
  180. etByte type; /* Conversion paradigm */
  181. etByte charset; /* Offset into aDigits[] of the digits string */
  182. etByte prefix; /* Offset into aPrefix[] of the prefix string */
  183. } et_info;
  184. /*
  185. ** Allowed values for et_info.flags
  186. */
  187. #define FLAG_SIGNED 1 /* True if the value to convert is signed */
  188. #define FLAG_INTERN 2 /* True if for internal use only */
  189. #define FLAG_STRING 4 /* Allow infinity precision */
  190. /*
  191. ** The following table is searched linearly, so it is good to put the
  192. ** most frequently used conversion types first.
  193. */
  194. static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
  195. static const char aPrefix[] = "-x0\000X0";
  196. static const et_info fmtinfo[] = {
  197. { 'd', 10, 1, etRADIX, 0, 0 },
  198. { 's', 0, 4, etSTRING, 0, 0 },
  199. { 'g', 0, 1, etGENERIC, 30, 0 },
  200. { 'q', 0, 4, etSTRESCAPE, 0, 0 },
  201. { 'c', 0, 0, etCHARX, 0, 0 },
  202. { 'o', 8, 0, etRADIX, 0, 2 },
  203. { 'u', 10, 0, etRADIX, 0, 0 },
  204. { 'x', 16, 0, etRADIX, 16, 1 },
  205. { 'X', 16, 0, etRADIX, 0, 4 },
  206. { 'f', 0, 1, etFLOAT, 0, 0 },
  207. { 'e', 0, 1, etEXP, 30, 0 },
  208. { 'E', 0, 1, etEXP, 14, 0 },
  209. { 'G', 0, 1, etGENERIC, 14, 0 },
  210. { 'i', 10, 1, etRADIX, 0, 0 },
  211. { 'n', 0, 0, etSIZE, 0, 0 },
  212. { '%', 0, 0, etPERCENT, 0, 0 },
  213. { 'p', 16, 0, etPOINTER, 0, 1 },
  214. };
  215. #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
  216. /*
  217. ** "*val" is a double such that 0.1 <= *val < 10.0
  218. ** Return the ascii code for the leading digit of *val, then
  219. ** multiply "*val" by 10.0 to renormalize.
  220. **
  221. ** Example:
  222. ** input: *val = 3.14159
  223. ** output: *val = 1.4159 function return = '3'
  224. **
  225. ** The counter *cnt is incremented each time. After counter exceeds
  226. ** 16 (the number of significant digits in a 64-bit float) '0' is
  227. ** always returned.
  228. */
  229. static int et_getdigit(long double *val, int *cnt){
  230. int digit;
  231. long double d;
  232. if( (*cnt)++ >= 16 ) return '0';
  233. digit = (int)*val;
  234. d = digit;
  235. digit += '0';
  236. *val = (*val - d)*10.0;
  237. return digit;
  238. }
  239. /*
  240. ** Size of temporary conversion buffer.
  241. */
  242. #define etBUFSIZE 500
  243. /*
  244. ** Find the length of a string as long as that length does not
  245. ** exceed N bytes. If no zero terminator is seen in the first
  246. ** N bytes then return N. If N is negative, then this routine
  247. ** is an alias for strlen().
  248. */
  249. static int StrNLen32(const char *z, int N){
  250. int n = 0;
  251. while( (N-- != 0) && *(z++)!=0 ){ n++; }
  252. return n;
  253. }
  254. /*
  255. ** INPUTS:
  256. ** pStr Append output to this string.
  257. **
  258. ** fmt This is the format string, as in the usual print.
  259. **
  260. ** ap This is a pointer to a list of arguments. Same as in
  261. ** vfprint.
  262. **
  263. ** OUTPUTS:
  264. ** The return value is the total number of characters appended.
  265. ** Returns -1 on a error.
  266. **
  267. ** Note that the order in which automatic variables are declared below
  268. ** seems to make a big difference in determining how fast this beast
  269. ** will run.
  270. */
  271. PRIVATE int xjd1StringVAppendF(
  272. String *pStr, /* Append output to this string */
  273. const char *fmt, /* Format string */
  274. va_list ap /* arguments */
  275. ){
  276. int c; /* Next character in the format string */
  277. char *bufpt; /* Pointer to the conversion buffer */
  278. int precision; /* Precision of the current field */
  279. int length; /* Length of the field */
  280. int idx; /* A general purpose loop counter */
  281. int count; /* Total number of characters output */
  282. int width; /* Width of the current field */
  283. etByte flag_leftjustify; /* True if "-" flag is present */
  284. etByte flag_plussign; /* True if "+" flag is present */
  285. etByte flag_blanksign; /* True if " " flag is present */
  286. etByte flag_alternateform; /* True if "#" flag is present */
  287. etByte flag_altform2; /* True if "!" flag is present */
  288. etByte flag_zeropad; /* True if field width constant starts with zero */
  289. etByte flag_long; /* True if "l" flag is present */
  290. etByte flag_longlong; /* True if the "ll" flag is present */
  291. etByte done; /* Loop termination flag */
  292. u64 longvalue; /* Value for integer types */
  293. long double realvalue; /* Value for real types */
  294. const et_info *infop; /* Pointer to the appropriate info structure */
  295. char buf[etBUFSIZE]; /* Conversion buffer */
  296. char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
  297. etByte errorflag = 0; /* True if an error is encountered */
  298. etByte xtype; /* Conversion paradigm */
  299. char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
  300. static const char spaces[] =
  301. " ";
  302. #define etSPACESIZE (sizeof(spaces)-1)
  303. int exp, e2; /* exponent of real numbers */
  304. double rounder; /* Used for rounding floating point values */
  305. etByte flag_dp; /* True if decimal point should be shown */
  306. etByte flag_rtz; /* True if trailing zeros should be removed */
  307. etByte flag_exp; /* True to force display of the exponent */
  308. int nsd; /* Number of significant digits returned */
  309. count = length = 0;
  310. bufpt = 0;
  311. for(; (c=(*fmt))!=0; ++fmt){
  312. if( c!='%' ){
  313. int amt;
  314. bufpt = (char *)fmt;
  315. amt = 1;
  316. while( (c=(*++fmt))!='%' && c!=0 ) amt++;
  317. xjd1StringAppend(pStr,bufpt,amt);
  318. count += amt;
  319. if( c==0 ) break;
  320. }
  321. if( (c=(*++fmt))==0 ){
  322. errorflag = 1;
  323. xjd1StringAppend(pStr,"%",1);
  324. count++;
  325. break;
  326. }
  327. /* Find out what flags are present */
  328. flag_leftjustify = flag_plussign = flag_blanksign =
  329. flag_alternateform = flag_altform2 = flag_zeropad = 0;
  330. done = 0;
  331. do{
  332. switch( c ){
  333. case '-': flag_leftjustify = 1; break;
  334. case '+': flag_plussign = 1; break;
  335. case ' ': flag_blanksign = 1; break;
  336. case '#': flag_alternateform = 1; break;
  337. case '!': flag_altform2 = 1; break;
  338. case '0': flag_zeropad = 1; break;
  339. default: done = 1; break;
  340. }
  341. }while( !done && (c=(*++fmt))!=0 );
  342. /* Get the field width */
  343. width = 0;
  344. if( c=='*' ){
  345. width = va_arg(ap,int);
  346. if( width<0 ){
  347. flag_leftjustify = 1;
  348. width = -width;
  349. }
  350. c = *++fmt;
  351. }else{
  352. while( c>='0' && c<='9' ){
  353. width = width*10 + c - '0';
  354. c = *++fmt;
  355. }
  356. }
  357. if( width > etBUFSIZE-10 ){
  358. width = etBUFSIZE-10;
  359. }
  360. /* Get the precision */
  361. if( c=='.' ){
  362. precision = 0;
  363. c = *++fmt;
  364. if( c=='*' ){
  365. precision = va_arg(ap,int);
  366. if( precision<0 ) precision = -precision;
  367. c = *++fmt;
  368. }else{
  369. while( c>='0' && c<='9' ){
  370. precision = precision*10 + c - '0';
  371. c = *++fmt;
  372. }
  373. }
  374. }else{
  375. precision = -1;
  376. }
  377. /* Get the conversion type modifier */
  378. if( c=='l' ){
  379. flag_long = 1;
  380. c = *++fmt;
  381. if( c=='l' ){
  382. flag_longlong = 1;
  383. c = *++fmt;
  384. }else{
  385. flag_longlong = 0;
  386. }
  387. }else{
  388. flag_long = flag_longlong = 0;
  389. }
  390. /* Fetch the info entry for the field */
  391. infop = 0;
  392. xtype = etERROR;
  393. for(idx=0; idx<etNINFO; idx++){
  394. if( c==fmtinfo[idx].fmttype ){
  395. infop = &fmtinfo[idx];
  396. xtype = infop->type;
  397. break;
  398. }
  399. }
  400. zExtra = 0;
  401. /* Limit the precision to prevent overflowing buf[] during conversion */
  402. if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
  403. precision = etBUFSIZE-40;
  404. }
  405. /*
  406. ** At this point, variables are initialized as follows:
  407. **
  408. ** flag_alternateform TRUE if a '#' is present.
  409. ** flag_altform2 TRUE if a '!' is present.
  410. ** flag_plussign TRUE if a '+' is present.
  411. ** flag_leftjustify TRUE if a '-' is present or if the
  412. ** field width was negative.
  413. ** flag_zeropad TRUE if the width began with 0.
  414. ** flag_long TRUE if the letter 'l' (ell) prefixed
  415. ** the conversion character.
  416. ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
  417. ** the conversion character.
  418. ** flag_blanksign TRUE if a ' ' is present.
  419. ** width The specified field width. This is
  420. ** always non-negative. Zero is the default.
  421. ** precision The specified precision. The default
  422. ** is -1.
  423. ** xtype The class of the conversion.
  424. ** infop Pointer to the appropriate info struct.
  425. */
  426. switch( xtype ){
  427. case etPOINTER:
  428. flag_longlong = sizeof(char*)==sizeof(i64);
  429. flag_long = sizeof(char*)==sizeof(long int);
  430. /* Fall through into the next case */
  431. case etRADIX:
  432. if( infop->flags & FLAG_SIGNED ){
  433. i64 v;
  434. if( flag_longlong ) v = va_arg(ap,i64);
  435. else if( flag_long ) v = va_arg(ap,long int);
  436. else v = va_arg(ap,int);
  437. if( v<0 ){
  438. longvalue = -v;
  439. prefix = '-';
  440. }else{
  441. longvalue = v;
  442. if( flag_plussign ) prefix = '+';
  443. else if( flag_blanksign ) prefix = ' ';
  444. else prefix = 0;
  445. }
  446. }else{
  447. if( flag_longlong ) longvalue = va_arg(ap,u64);
  448. else if( flag_long ) longvalue = va_arg(ap,unsigned long int);
  449. else longvalue = va_arg(ap,unsigned int);
  450. prefix = 0;
  451. }
  452. if( longvalue==0 ) flag_alternateform = 0;
  453. if( flag_zeropad && precision<width-(prefix!=0) ){
  454. precision = width-(prefix!=0);
  455. }
  456. bufpt = &buf[etBUFSIZE-1];
  457. {
  458. register const char *cset; /* Use registers for speed */
  459. register int base;
  460. cset = &aDigits[infop->charset];
  461. base = infop->base;
  462. do{ /* Convert to ascii */
  463. *(--bufpt) = cset[longvalue%base];
  464. longvalue = longvalue/base;
  465. }while( longvalue>0 );
  466. }
  467. length = &buf[etBUFSIZE-1]-bufpt;
  468. for(idx=precision-length; idx>0; idx--){
  469. *(--bufpt) = '0'; /* Zero pad */
  470. }
  471. if( prefix ) *(--bufpt) = prefix; /* Add sign */
  472. if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
  473. const char *pre;
  474. char x;
  475. pre = &aPrefix[infop->prefix];
  476. if( *bufpt!=pre[0] ){
  477. for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
  478. }
  479. }
  480. length = &buf[etBUFSIZE-1]-bufpt;
  481. break;
  482. case etFLOAT:
  483. case etEXP:
  484. case etGENERIC:
  485. realvalue = va_arg(ap,double);
  486. if( precision<0 ) precision = 6; /* Set default precision */
  487. if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
  488. if( realvalue<0.0 ){
  489. realvalue = -realvalue;
  490. prefix = '-';
  491. }else{
  492. if( flag_plussign ) prefix = '+';
  493. else if( flag_blanksign ) prefix = ' ';
  494. else prefix = 0;
  495. }
  496. if( xtype==etGENERIC && precision>0 ) precision--;
  497. #if 0
  498. /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
  499. for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
  500. #else
  501. /* It makes more sense to use 0.5 */
  502. for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
  503. #endif
  504. if( xtype==etFLOAT ) realvalue += rounder;
  505. /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
  506. exp = 0;
  507. if( realvalue>0.0 ){
  508. while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
  509. while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
  510. while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
  511. while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
  512. while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
  513. if( exp>350 || exp<-350 ){
  514. bufpt = "NaN";
  515. length = 3;
  516. break;
  517. }
  518. }
  519. bufpt = buf;
  520. /*
  521. ** If the field type is etGENERIC, then convert to either etEXP
  522. ** or etFLOAT, as appropriate.
  523. */
  524. flag_exp = xtype==etEXP;
  525. if( xtype!=etFLOAT ){
  526. realvalue += rounder;
  527. if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
  528. }
  529. if( xtype==etGENERIC ){
  530. flag_rtz = !flag_alternateform;
  531. if( exp<-4 || exp>precision ){
  532. xtype = etEXP;
  533. }else{
  534. precision = precision - exp;
  535. xtype = etFLOAT;
  536. }
  537. }else{
  538. flag_rtz = 0;
  539. }
  540. if( xtype==etEXP ){
  541. e2 = 0;
  542. }else{
  543. e2 = exp;
  544. }
  545. nsd = 0;
  546. flag_dp = (precision>0) | flag_alternateform | flag_altform2;
  547. /* The sign in front of the number */
  548. if( prefix ){
  549. *(bufpt++) = prefix;
  550. }
  551. /* Digits prior to the decimal point */
  552. if( e2<0 ){
  553. *(bufpt++) = '0';
  554. }else{
  555. for(; e2>=0; e2--){
  556. *(bufpt++) = et_getdigit(&realvalue,&nsd);
  557. }
  558. }
  559. /* The decimal point */
  560. if( flag_dp ){
  561. *(bufpt++) = '.';
  562. }
  563. /* "0" digits after the decimal point but before the first
  564. ** significant digit of the number */
  565. for(e2++; e2<0 && precision>0; precision--, e2++){
  566. *(bufpt++) = '0';
  567. }
  568. /* Significant digits after the decimal point */
  569. while( (precision--)>0 ){
  570. *(bufpt++) = et_getdigit(&realvalue,&nsd);
  571. }
  572. /* Remove trailing zeros and the "." if no digits follow the "." */
  573. if( flag_rtz && flag_dp ){
  574. while( bufpt[-1]=='0' ) *(--bufpt) = 0;
  575. assert( bufpt>buf );
  576. if( bufpt[-1]=='.' ){
  577. if( flag_altform2 ){
  578. *(bufpt++) = '0';
  579. }else{
  580. *(--bufpt) = 0;
  581. }
  582. }
  583. }
  584. /* Add the "eNNN" suffix */
  585. if( flag_exp || (xtype==etEXP && exp) ){
  586. *(bufpt++) = aDigits[infop->charset];
  587. if( exp<0 ){
  588. *(bufpt++) = '-'; exp = -exp;
  589. }else{
  590. *(bufpt++) = '+';
  591. }
  592. if( exp>=100 ){
  593. *(bufpt++) = (exp/100)+'0'; /* 100's digit */
  594. exp %= 100;
  595. }
  596. *(bufpt++) = exp/10+'0'; /* 10's digit */
  597. *(bufpt++) = exp%10+'0'; /* 1's digit */
  598. }
  599. *bufpt = 0;
  600. /* The converted number is in buf[] and zero terminated. Output it.
  601. ** Note that the number is in the usual order, not reversed as with
  602. ** integer conversions. */
  603. length = bufpt-buf;
  604. bufpt = buf;
  605. /* Special case: Add leading zeros if the flag_zeropad flag is
  606. ** set and we are not left justified */
  607. if( flag_zeropad && !flag_leftjustify && length < width){
  608. int i;
  609. int nPad = width - length;
  610. for(i=width; i>=nPad; i--){
  611. bufpt[i] = bufpt[i-nPad];
  612. }
  613. i = prefix!=0;
  614. while( nPad-- ) bufpt[i++] = '0';
  615. length = width;
  616. }
  617. break;
  618. case etSIZE:
  619. *(va_arg(ap,int*)) = count;
  620. length = width = 0;
  621. break;
  622. case etPERCENT:
  623. buf[0] = '%';
  624. bufpt = buf;
  625. length = 1;
  626. break;
  627. case etCHARX:
  628. c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
  629. if( precision>=0 ){
  630. for(idx=1; idx<precision; idx++) buf[idx] = c;
  631. length = precision;
  632. }else{
  633. length =1;
  634. }
  635. bufpt = buf;
  636. break;
  637. case etSTRING: {
  638. int limit = flag_alternateform ? va_arg(ap,int) : -1;
  639. bufpt = va_arg(ap,char*);
  640. if( bufpt==0 ){
  641. bufpt = "";
  642. }else if( xtype==etDYNSTRING ){
  643. zExtra = bufpt;
  644. }
  645. length = StrNLen32(bufpt, limit);
  646. if( precision>=0 && precision<length ) length = precision;
  647. break;
  648. }
  649. case etSTRESCAPE: {
  650. int i, j, n, ch, isnull;
  651. int limit = flag_alternateform ? va_arg(ap,int) : -1;
  652. char *escarg = va_arg(ap,char*);
  653. isnull = escarg==0;
  654. if( isnull ) escarg = "(NULL)";
  655. if( limit<0 ) limit = strlen(escarg);
  656. for(i=n=0; i<limit; i++){
  657. if( escarg[i]=='"' || escarg[i]=='\\' ) n++;
  658. }
  659. n += i + 1;
  660. if( n>etBUFSIZE ){
  661. bufpt = zExtra = xjd1_malloc( n );
  662. }else{
  663. bufpt = buf;
  664. }
  665. j = 0;
  666. for(i=0; i<limit; i++){
  667. ch = escarg[i];
  668. if( ch=='"' || ch=='\\' ) bufpt[j++] = '\\';
  669. bufpt[j++] = ch;
  670. }
  671. bufpt[j] = 0;
  672. length = j;
  673. if( precision>=0 && precision<length ) length = precision;
  674. break;
  675. }
  676. case etERROR:
  677. buf[0] = '%';
  678. buf[1] = c;
  679. errorflag = 0;
  680. idx = 1+(c!=0);
  681. xjd1StringAppend(pStr,"%",idx);
  682. count += idx;
  683. if( c==0 ) fmt--;
  684. break;
  685. }/* End switch over the format type */
  686. /*
  687. ** The text of the conversion is pointed to by "bufpt" and is
  688. ** "length" characters long. The field width is "width". Do
  689. ** the output.
  690. */
  691. if( !flag_leftjustify ){
  692. register int nspace;
  693. nspace = width-length;
  694. if( nspace>0 ){
  695. count += nspace;
  696. while( nspace>=etSPACESIZE ){
  697. xjd1StringAppend(pStr,spaces,etSPACESIZE);
  698. nspace -= etSPACESIZE;
  699. }
  700. if( nspace>0 ) xjd1StringAppend(pStr,spaces,nspace);
  701. }
  702. }
  703. if( length>0 ){
  704. xjd1StringAppend(pStr,bufpt,length);
  705. count += length;
  706. }
  707. if( flag_leftjustify ){
  708. register int nspace;
  709. nspace = width-length;
  710. if( nspace>0 ){
  711. count += nspace;
  712. while( nspace>=etSPACESIZE ){
  713. xjd1StringAppend(pStr,spaces,etSPACESIZE);
  714. nspace -= etSPACESIZE;
  715. }
  716. if( nspace>0 ) xjd1StringAppend(pStr,spaces,nspace);
  717. }
  718. }
  719. if( zExtra ){
  720. xjd1_free(zExtra);
  721. }
  722. }/* End for loop over the format string */
  723. return errorflag ? -1 : count;
  724. } /* End of function */
  725. /*
  726. ** Append formatted text to a string. Return the number of bytes appended.
  727. */
  728. PRIVATE int xjd1StringAppendF(String *pStr, const char *zFormat, ...){
  729. va_list ap;
  730. int rc;
  731. va_start(ap, zFormat);
  732. rc = xjd1StringVAppendF(pStr, zFormat, ap);
  733. va_end(ap);
  734. return rc;
  735. }