diff options
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c')
-rw-r--r-- | source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c | 924 |
1 files changed, 924 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c b/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c new file mode 100644 index 0000000000..2d0951acfa --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c @@ -0,0 +1,924 @@ +/** + * @file mprPrintf.c + * @brief Printf routines safe for embedded programming + * @overview This module provides safe replacements for the standard + * printf formatting routines. + * @remarks Most routines in this file are not thread-safe. It is the callers + * responsibility to perform all thread synchronization. + */ + +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + +/********************************** Includes **********************************/ +/* + * We need to use the underlying str(cpy) routines to implement our safe + * alternatives + */ +#if !DOXYGEN +#define UNSAFE_FUNCTIONS_OK 1 +#endif + +#include "mpr.h" + +/*********************************** Defines **********************************/ +/* + * Class definitions + */ +#define CLASS_NORMAL 0 /* [All other] Normal characters */ +#define CLASS_PERCENT 1 /* [%] Begin format */ +#define CLASS_MODIFIER 2 /* [-+ #,] Modifiers */ +#define CLASS_ZERO 3 /* [0] Special modifier */ +#define CLASS_STAR 4 /* [*] Width supplied by arg */ +#define CLASS_DIGIT 5 /* [1-9] Field widths */ +#define CLASS_DOT 6 /* [.] Introduce precision */ +#define CLASS_BITS 7 /* [hlL] Length bits */ +#define CLASS_TYPE 8 /* [cdfinopsSuxX] Type specifiers */ + +#define STATE_NORMAL 0 /* Normal chars in format string */ +#define STATE_PERCENT 1 /* "%" */ +#define STATE_MODIFIER 2 /* Read flag */ +#define STATE_WIDTH 3 /* Width spec */ +#define STATE_DOT 4 /* "." */ +#define STATE_PRECISION 5 /* Precision spec */ +#define STATE_BITS 6 /* Size spec */ +#define STATE_TYPE 7 /* Data type */ +#define STATE_COUNT 8 + +/* + * Format: %[modifier][width][precision][bits][type] + * + * #define CLASS_MODIFIER 2 [-+ #,] Modifiers + * #define CLASS_BITS 7 [hlL] Length bits + */ + + +/* + * Flags + */ +#define SPRINTF_LEFT 0x1 /* Left align */ +#define SPRINTF_SIGN 0x2 /* Always sign the result */ +#define SPRINTF_LEAD_SPACE 0x4 /* put leading space for +ve numbers */ +#define SPRINTF_ALTERNATE 0x8 /* Alternate format */ +#define SPRINTF_LEAD_ZERO 0x10 /* Zero pad */ +#define SPRINTF_SHORT 0x20 /* 16-bit */ +#define SPRINTF_LONG 0x40 /* 32-bit */ +#if BLD_FEATURE_INT64 +#define SPRINTF_LONGLONG 0x80 /* 64-bit */ +#endif +#define SPRINTF_COMMA 0x100 /* Thousand comma separators */ +#define SPRINTF_UPPER_CASE 0x200 /* As the name says for numbers */ + +typedef struct Format { + uchar *buf; + uchar *endbuf; + uchar *start; + uchar *end; + int growBy; + int maxsize; + + int precision; + int radix; + int width; + int flags; + int len; +} Format; + +static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt); + +#define BPUT(ctx, loc, fmt, c) \ + if (1) { \ + /* Less one to allow room for the null */ \ + if ((fmt)->end >= ((fmt)->endbuf - sizeof(char))) { \ + if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \ + *(fmt)->end++ = (c); \ + } \ + } else { \ + *(fmt)->end++ = (c); \ + } \ + } else + +#define BPUTNULL(ctx, loc, fmt) \ + if (1) { \ + if ((fmt)->end > (fmt)->endbuf) { \ + if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \ + *(fmt)->end = '\0'; \ + } \ + } else { \ + *(fmt)->end = '\0'; \ + } \ + } else + +/******************************************************************************/ + +#if BLD_FEATURE_INT64 +#define unum uint64 +#define num int64 +#else +#define unum uint +#define num int +#endif + +/***************************** Forward Declarations ***************************/ +#ifdef __cplusplus +extern "C" { +#endif + +static int getState(char c, int state); +static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **s, + int maxsize, const char *fmt, va_list arg); +static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix, + unum val); + +#if BLD_FEATURE_FLOATING_POINT +static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar, + double value); +#endif + +/******************************************************************************/ + +int mprPrintf(MprCtx ctx, const char *fmt, ...) +{ + va_list ap; + char *buf; + int len; + MprApp *app; + + /* No asserts here as this is used as part of assert reporting */ + + app = mprGetApp(ctx); + + va_start(ap, fmt); + len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap); + va_end(ap); + if (len >= 0 && app->console) { + len = mprWrite(app->console, buf, len); + } + mprFree(buf); + + return len; +} + +/******************************************************************************/ + +int mprErrorPrintf(MprCtx ctx, const char *fmt, ...) +{ + va_list ap; + char *buf; + int len; + MprApp *app; + + /* No asserts here as this is used as part of assert reporting */ + + app = mprGetApp(ctx); + + va_start(ap, fmt); + len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap); + va_end(ap); + if (len >= 0 && app->error) { + len = mprWrite(app->error, buf, len); + } + mprFree(buf); + + return len; +} + +/******************************************************************************/ + +int mprFprintf(MprFile *file, const char *fmt, ...) +{ + va_list ap; + char *buf; + int len; + + if (file == 0) { + return MPR_ERR_BAD_HANDLE; + } + + va_start(ap, fmt); + len = mprAllocVsprintf(MPR_LOC_ARGS(file), &buf, 0, fmt, ap); + va_end(ap); + + if (len >= 0) { + len = mprWrite(file, buf, len); + } + mprFree(buf); + return len; +} + +/******************************************************************************/ +/* + * Printf with a static buffer. Used internally only. WILL NOT MALLOC. + */ + +int mprStaticPrintf(MprCtx ctx, const char *fmt, ...) +{ + va_list ap; + char buf[MPR_MAX_STRING]; + char *bufp; + int len; + MprApp *app; + + app = mprGetApp(ctx); + + va_start(ap, fmt); + bufp = buf; + len = mprSprintfCore(MPR_LOC_ARGS(0), &bufp, MPR_MAX_STRING, fmt, ap); + va_end(ap); + if (len >= 0) { + len = mprWrite(app->console, buf, len); + } + return len; +} + +/******************************************************************************/ + +int mprSprintf(char *buf, int n, const char *fmt, ...) +{ + va_list ap; + int result; + + mprAssert(buf); + mprAssert(fmt); + mprAssert(n > 0); + + va_start(ap, fmt); + result = mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, ap); + va_end(ap); + return result; +} + +/******************************************************************************/ + +int mprVsprintf(char *buf, int n, const char *fmt, va_list arg) +{ + mprAssert(buf); + mprAssert(fmt); + mprAssert(n > 0); + + return mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, arg); +} + +/******************************************************************************/ + +int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, + const char *fmt, ...) +{ + va_list ap; + int result; + + mprAssert(buf); + mprAssert(fmt); + + *buf = 0; + va_start(ap, fmt); + result = mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, ap); + va_end(ap); + return result; +} + +/******************************************************************************/ + +int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, + const char *fmt, va_list arg) +{ + mprAssert(buf); + mprAssert(fmt); + + *buf = 0; + return mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, arg); +} + +/******************************************************************************/ + +static int getState(char c, int state) +{ + /* + * Declared here to remove all static / globals + * FUTURE OPT -- need to measure this. Could be slow on BREW. + */ + + char stateMap[] = { + /* STATES: Normal Percent Modifier Width Dot Prec Bits Type */ + /* CLASS 0 1 2 3 4 5 6 7 */ + /* Normal 0 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* Percent 1 */ 1, 0, 1, 1, 1, 1, 1, 1, + /* Modifier 2 */ 0, 2, 2, 0, 0, 0, 0, 0, + /* Zero 3 */ 0, 2, 2, 3, 0, 5, 0, 0, + /* Star 4 */ 0, 3, 3, 0, 5, 0, 0, 0, + /* Digit 5 */ 0, 3, 3, 3, 5, 5, 0, 0, + /* Dot 6 */ 0, 4, 4, 4, 0, 0, 0, 0, + /* Bits 7 */ 0, 6, 6, 6, 6, 6, 6, 0, + /* Types 8 */ 0, 7, 7, 7, 7, 7, 7, 0, + }; + + /* + * Format: %[modifier][width][precision][bits][type] + */ + char classMap[] = { + /* 0 ' ' ! " # $ % & ' */ + 2, 0, 0, 2, 0, 1, 0, 0, + /* 07 ( ) * + , - . / */ + 0, 0, 4, 2, 2, 2, 6, 0, + /* 10 0 1 2 3 4 5 6 7 */ + 3, 5, 5, 5, 5, 5, 5, 5, + /* 17 8 9 : ; < = > ? */ + 5, 5, 0, 0, 0, 0, 0, 0, + /* 20 @ A B C D E F G */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 27 H I J K L M N O */ + 0, 0, 0, 0, 7, 0, 0, 0, + /* 30 P Q R S T U V W */ + 0, 0, 0, 8, 0, 0, 0, 0, + /* 37 X Y Z [ \ ] ^ _ */ + 8, 0, 0, 0, 0, 0, 0, 0, + /* 40 ' a b c d e f g */ + 0, 0, 0, 8, 8, 0, 8, 0, + /* 47 h i j k l m n o */ + 7, 8, 0, 0, 7, 0, 8, 8, + /* 50 p q r s t u v w */ + 8, 0, 0, 8, 0, 8, 0, 0, + /* 57 x y z */ + 8, 0, 0, + }; + + int chrClass; + + if (c < ' ' || c > 'z') { + chrClass = CLASS_NORMAL; + } else { + mprAssert((c - ' ') < (int) sizeof(classMap)); + chrClass = classMap[(c - ' ')]; + } + mprAssert((chrClass * STATE_COUNT + state) < (int) sizeof(stateMap)); + state = stateMap[chrClass * STATE_COUNT + state]; + return state; +} + +/******************************************************************************/ + +static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **bufPtr, + int maxsize, const char *spec, va_list arg) +{ + Format fmt; + char *cp; + char c; + char *sValue; + num iValue; + unum uValue; + int count, i, len, state; + + mprAssert(bufPtr); + mprAssert(spec); + + if (*bufPtr != 0) { + mprAssert(maxsize > 0); + fmt.buf = (uchar*) *bufPtr; + fmt.endbuf = &fmt.buf[maxsize]; + fmt.growBy = 0; + } else { + if (maxsize <= 0) { + maxsize = MAXINT; + } + + len = min(MPR_DEFAULT_ALLOC, maxsize); + fmt.buf = (uchar*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); + fmt.endbuf = &fmt.buf[len]; + fmt.growBy = MPR_DEFAULT_ALLOC * 2; + } + + fmt.maxsize = maxsize; + fmt.start = fmt.buf; + fmt.end = fmt.buf; + fmt.len = 0; + *fmt.start = '\0'; + + state = STATE_NORMAL; + + while ((c = *spec++) != '\0') { + state = getState(c, state); + + switch (state) { + case STATE_NORMAL: + BPUT(ctx, loc, &fmt, c); + break; + + case STATE_PERCENT: + fmt.precision = -1; + fmt.width = 0; + fmt.flags = 0; + break; + + case STATE_MODIFIER: + switch (c) { + case '+': + fmt.flags |= SPRINTF_SIGN; + break; + case '-': + fmt.flags |= SPRINTF_LEFT; + break; + case '#': + fmt.flags |= SPRINTF_ALTERNATE; + break; + case '0': + fmt.flags |= SPRINTF_LEAD_ZERO; + break; + case ' ': + fmt.flags |= SPRINTF_LEAD_SPACE; + break; + case ',': + fmt.flags |= SPRINTF_COMMA; + break; + } + break; + + case STATE_WIDTH: + if (c == '*') { + fmt.width = va_arg(arg, int); + if (fmt.width < 0) { + fmt.width = -fmt.width; + fmt.flags |= SPRINTF_LEFT; + } + } else { + while (isdigit((int)c)) { + fmt.width = fmt.width * 10 + (c - '0'); + c = *spec++; + } + spec--; + } + break; + + case STATE_DOT: + fmt.precision = 0; + fmt.flags &= ~SPRINTF_LEAD_ZERO; + break; + + case STATE_PRECISION: + if (c == '*') { + fmt.precision = va_arg(arg, int); + } else { + while (isdigit((int) c)) { + fmt.precision = fmt.precision * 10 + (c - '0'); + c = *spec++; + } + spec--; + } + break; + + case STATE_BITS: + switch (c) { +#if BLD_FEATURE_INT64 + case 'L': + fmt.flags |= SPRINTF_LONGLONG; /* 64 bit */ + break; +#endif + + case 'l': + fmt.flags |= SPRINTF_LONG; + break; + + case 'h': + fmt.flags |= SPRINTF_SHORT; + break; + } + break; + + case STATE_TYPE: + switch (c) { +#if BLD_FEATURE_FLOATING_POINT + case 'e': + case 'g': + case 'f': + fmt.radix = 10; + outFloat(MPR_LOC_PASS(ctx, loc), &fmt, c, + (double) va_arg(arg, double)); + break; +#endif + case 'c': + BPUT(ctx, loc, &fmt, (char) va_arg(arg, int)); + break; + + case 's': + case 'S': + sValue = va_arg(arg, char*); + if (sValue == 0) { + sValue = "null"; + len = strlen(sValue); + } else if (fmt.flags & SPRINTF_ALTERNATE) { + sValue++; + len = (int) *sValue; + } else if (fmt.precision >= 0) { + /* + * Can't use strlen(), the string may not have a null + */ + cp = sValue; + for (len = 0; len < fmt.precision; len++) { + if (*cp++ == '\0') { + break; + } + } + } else { + len = strlen(sValue); + } + if (!(fmt.flags & SPRINTF_LEFT)) { + for (i = len; i < fmt.width; i++) { + BPUT(ctx, loc, &fmt, (char) ' '); + } + } + for (i = 0; i < len && *sValue; i++) { + BPUT(ctx, loc, &fmt, *sValue++); + } + if (fmt.flags & SPRINTF_LEFT) { + for (i = len; i < fmt.width; i++) { + BPUT(ctx, loc, &fmt, (char) ' '); + } + } + break; + + case 'i': + ; + case 'd': + fmt.radix = 10; + if (fmt.flags & SPRINTF_SHORT) { + iValue = (short) va_arg(arg, int); + } else if (fmt.flags & SPRINTF_LONG) { + iValue = va_arg(arg, long); +#if BLD_FEATURE_INT64 + } else if (fmt.flags & SPRINTF_LONGLONG) { + iValue = va_arg(arg, num); +#endif + } else { + iValue = va_arg(arg, int); + } + if (iValue >= 0) { + if (fmt.flags & SPRINTF_LEAD_SPACE) { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, " ", iValue); + } else if (fmt.flags & SPRINTF_SIGN) { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "+", iValue); + } else { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, iValue); + } + } else { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "-", -iValue); + } + break; + + case 'X': + fmt.flags |= SPRINTF_UPPER_CASE; + /* Fall through */ + case 'o': + case 'x': + case 'u': + if (fmt.flags & SPRINTF_SHORT) { + uValue = (ushort) va_arg(arg, uint); + } else if (fmt.flags & SPRINTF_LONG) { + uValue = va_arg(arg, ulong); +#if BLD_FEATURE_INT64 + } else if (fmt.flags & SPRINTF_LONGLONG) { + uValue = va_arg(arg, unum); +#endif + } else { + uValue = va_arg(arg, uint); + } + if (c == 'u') { + fmt.radix = 10; + outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); + } else if (c == 'o') { + fmt.radix = 8; + if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0", uValue); + } else { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); + } + } else { + fmt.radix = 16; + if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) { + if (c == 'X') { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0X", uValue); + } else { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue); + } + } else { + outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); + } + } + break; + + case 'n': /* Count of chars seen thus far */ + if (fmt.flags & SPRINTF_SHORT) { + short *count = va_arg(arg, short*); + *count = fmt.end - fmt.start; + } else if (fmt.flags & SPRINTF_LONG) { + long *count = va_arg(arg, long*); + *count = fmt.end - fmt.start; + } else { + int *count = va_arg(arg, int *); + *count = fmt.end - fmt.start; + } + break; + + case 'p': /* Pointer */ +#if __WORDSIZE == 64 && BLD_FEATURE_INT64 + uValue = (unum) va_arg(arg, void*); +#else + uValue = (uint) (int) va_arg(arg, void*); +#endif + fmt.radix = 16; + outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue); + break; + + default: + BPUT(ctx, loc, &fmt, c); + } + } + } + BPUTNULL(ctx, loc, &fmt); + + count = fmt.end - fmt.start; + if (*bufPtr == 0) { + *bufPtr = (char*) fmt.buf; + } + return count; +} + +/******************************************************************************/ +/* + * Output a number according to the given format. If BLD_FEATURE_INT64 is + * defined, then uses 64 bits universally. Slower but smaller code. + */ + +static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix, + unum value) +{ + char numBuf[64]; + char *cp; + char *endp; + char c; + int letter, len, leadingZeros, i, fill; + + endp = &numBuf[sizeof(numBuf) - 1]; + *endp = '\0'; + cp = endp; + + /* + * Convert to ascii + */ + if (fmt->radix == 16) { + do { + letter = (int) (value % fmt->radix); + if (letter > 9) { + if (fmt->flags & SPRINTF_UPPER_CASE) { + letter = 'A' + letter - 10; + } else { + letter = 'a' + letter - 10; + } + } else { + letter += '0'; + } + *--cp = letter; + value /= fmt->radix; + } while (value > 0); + + } else if (fmt->flags & SPRINTF_COMMA) { + i = 1; + do { + *--cp = '0' + (int) (value % fmt->radix); + value /= fmt->radix; + if ((i++ % 3) == 0 && value > 0) { + *--cp = ','; + } + } while (value > 0); + } else { + do { + *--cp = '0' + (int) (value % fmt->radix); + value /= fmt->radix; + } while (value > 0); + } + + len = endp - cp; + fill = fmt->width - len; + + if (prefix != 0) { + fill -= strlen(prefix); + } + leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0; + fill -= leadingZeros; + + if (!(fmt->flags & SPRINTF_LEFT)) { + c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' '; + for (i = 0; i < fill; i++) { + BPUT(ctx, loc, fmt, c); + } + } + if (prefix != 0) { + while (*prefix) { + BPUT(ctx, loc, fmt, *prefix++); + } + } + for (i = 0; i < leadingZeros; i++) { + BPUT(ctx, loc, fmt, '0'); + } + while (*cp) { + BPUT(ctx, loc, fmt, *cp); + cp++; + } + if (fmt->flags & SPRINTF_LEFT) { + for (i = 0; i < fill; i++) { + BPUT(ctx, loc, fmt, ' '); + } + } +} + +/******************************************************************************/ +#if BLD_FEATURE_FLOATING_POINT +/* + * Output a floating point number + */ + +static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar, + double value) +{ + char *cp; +#if FUTURE + char numBuf[64]; + char *endp; + char c; + int letter, len, leadingZeros, i, fill, width, precision; + + endp = &numBuf[sizeof(numBuf) - 1]; + *endp = '\0'; + + precision = fmt->precision; + if (precision < 0) { + precision = 6; + } else if (precision > (sizeof(numBuf) - 1)) { + precision = (sizeof(numBuf) - 1); + } + width = min(fmt->width, sizeof(numBuf) - 1); + + if (__isnanl(value)) { + "nan" + } else if (__isinfl(value)) { + "infinity" + } else if (value < 0) { + prefix = "-"; + } else if (fmt.flags & SPRINTF_LEAD_SPACE) { + prefix = " "; + } else if (fmt.flags & SPRINTF_SIGN) { + prefix = "+"; + } + + + /* + * Do the exponent part + */ + cp = &numBuf[sizeof(numBuf) - precision]; + for (i = 0; i < precision; i++) { + *cp++ = '0' + (int) (value % fmt->radix); + value /= fmt->radix; + } + + /* + * Do the decimal part + */ + if (fmt->flags & SPRINTF_COMMA) { + i = 1; + do { + *--cp = '0' + (int) (value % fmt->radix); + value /= fmt->radix; + if ((i++ % 3) == 0 && value > 0) { + *--cp = ','; + } + } while (value >= 1.0); + + } else { + do { + *--cp = '0' + (int) (value % fmt->radix); + value /= fmt->radix; + } while (value > 1.0); + } + + len = endp - cp; + fill = fmt->width - len; + + if (prefix != 0) { + fill -= strlen(prefix); + } + + leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0; + fill -= leadingZeros; + + if (!(fmt->flags & SPRINTF_LEFT)) { + c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' '; + for (i = 0; i < fill; i++) { + BPUT(ctx, loc, fmt, c); + } + } + if (prefix != 0) { + BPUT(ctx, loc, fmt, prefix); + } + for (i = 0; i < leadingZeros; i++) { + BPUT(ctx, loc, fmt, '0'); + } + BPUT(ctx, loc, fmt, cp); + if (fmt->flags & SPRINTF_LEFT) { + for (i = 0; i < fill; i++) { + BPUT(ctx, loc, fmt, ' '); + } + } +#else + char numBuf[64]; + if (specChar == 'f') { + sprintf(numBuf, "%*.*f", fmt->width, fmt->precision, value); + } else if (specChar == 'g') { + sprintf(numBuf, "%*.*g", fmt->width, fmt->precision, value); + } else if (specChar == 'e') { + sprintf(numBuf, "%*.*e", fmt->width, fmt->precision, value); + } + for (cp = numBuf; *cp; cp++) { + BPUT(ctx, loc, fmt, *cp); + } +#endif +} + +#endif /* BLD_FEATURE_FLOATING_POINT */ +/******************************************************************************/ +/* + * Grow the buffer to fit new data. Return 1 if the buffer can grow. + * Grow using the growBy size specified when creating the buffer. + */ + +static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt) +{ + uchar *newbuf; + int buflen; + + buflen = fmt->endbuf - fmt->buf; + if (fmt->maxsize >= 0 && buflen >= fmt->maxsize) { + return 0; + } + if (fmt->growBy < 0) { + /* + * User supplied buffer + */ + return 0; + } + + newbuf = (uchar*) mprAlloc(ctx, buflen + fmt->growBy); + if (fmt->buf) { + memcpy(newbuf, fmt->buf, buflen); + mprFree(fmt->buf); + } + + buflen += fmt->growBy; + fmt->end = newbuf + (fmt->end - fmt->buf); + fmt->start = newbuf + (fmt->start - fmt->buf); + fmt->buf = newbuf; + fmt->endbuf = &fmt->buf[buflen]; + + /* + * Increase growBy to reduce overhead + */ + if ((buflen + (fmt->growBy * 2)) < fmt->maxsize) { + fmt->growBy *= 2; + } + return 1; +} + +/******************************************************************************/ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ |