1bd185b41SIngo Weinhold /* 2*3ce26345SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3bd185b41SIngo Weinhold * Copyright 2003-2008, Axel Dörfler. All rights reserved. 4bd185b41SIngo Weinhold * Distributed under the terms of the MIT license. 5bd185b41SIngo Weinhold * 6bd185b41SIngo Weinhold * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7bd185b41SIngo Weinhold * Distributed under the terms of the NewOS License. 8bd185b41SIngo Weinhold */ 9bd185b41SIngo Weinhold 10bd185b41SIngo Weinhold 11bd185b41SIngo Weinhold #include <SupportDefs.h> 12bd185b41SIngo Weinhold 13bd185b41SIngo Weinhold #include <ctype.h> 14*3ce26345SIngo Weinhold #include <stdarg.h> 15bd185b41SIngo Weinhold #include <stdio.h> 16*3ce26345SIngo Weinhold #include <string.h> 17*3ce26345SIngo Weinhold 18*3ce26345SIngo Weinhold #include <algorithm> 19bd185b41SIngo Weinhold 20bd185b41SIngo Weinhold 21bd185b41SIngo Weinhold #define ZEROPAD 1 /* pad with zero */ 22bd185b41SIngo Weinhold #define SIGN 2 /* unsigned/signed long */ 23bd185b41SIngo Weinhold #define PLUS 4 /* show plus */ 24bd185b41SIngo Weinhold #define SPACE 8 /* space if plus */ 25bd185b41SIngo Weinhold #define LEFT 16 /* left justified */ 26bd185b41SIngo Weinhold #define SPECIAL 32 /* 0x */ 27bd185b41SIngo Weinhold #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ 28bd185b41SIngo Weinhold 29bd185b41SIngo Weinhold #define FLOATING_SUPPORT 30bd185b41SIngo Weinhold 31bd185b41SIngo Weinhold 32*3ce26345SIngo Weinhold struct Buffer { 33*3ce26345SIngo Weinhold Buffer(char* buffer, size_t size) 34*3ce26345SIngo Weinhold : 35*3ce26345SIngo Weinhold fCurrent(buffer), 36*3ce26345SIngo Weinhold fSize(size), 37*3ce26345SIngo Weinhold fBytesWritten(0) 38*3ce26345SIngo Weinhold { 39*3ce26345SIngo Weinhold } 40*3ce26345SIngo Weinhold 41*3ce26345SIngo Weinhold size_t BytesWritten() const 42*3ce26345SIngo Weinhold { 43*3ce26345SIngo Weinhold return fBytesWritten; 44*3ce26345SIngo Weinhold } 45*3ce26345SIngo Weinhold 46*3ce26345SIngo Weinhold void PutCharacter(char c) 47*3ce26345SIngo Weinhold { 48*3ce26345SIngo Weinhold if (fBytesWritten < fSize) { 49*3ce26345SIngo Weinhold *fCurrent = c; 50*3ce26345SIngo Weinhold fCurrent++; 51*3ce26345SIngo Weinhold } 52*3ce26345SIngo Weinhold 53*3ce26345SIngo Weinhold fBytesWritten++; 54*3ce26345SIngo Weinhold } 55*3ce26345SIngo Weinhold 56*3ce26345SIngo Weinhold void PutPadding(int32 count) 57*3ce26345SIngo Weinhold { 58*3ce26345SIngo Weinhold if (count <= 0) 59*3ce26345SIngo Weinhold return; 60*3ce26345SIngo Weinhold 61*3ce26345SIngo Weinhold if (fBytesWritten < fSize) { 62*3ce26345SIngo Weinhold int32 toWrite = std::min(fSize - fBytesWritten, (size_t)count); 63*3ce26345SIngo Weinhold while (--toWrite >= 0) 64*3ce26345SIngo Weinhold *fCurrent++ = ' '; 65*3ce26345SIngo Weinhold } 66*3ce26345SIngo Weinhold 67*3ce26345SIngo Weinhold fBytesWritten += count; 68*3ce26345SIngo Weinhold } 69*3ce26345SIngo Weinhold 70*3ce26345SIngo Weinhold void PutString(const char *source, int32 length) 71*3ce26345SIngo Weinhold { 72*3ce26345SIngo Weinhold if (length <= 0) 73*3ce26345SIngo Weinhold return; 74*3ce26345SIngo Weinhold 75*3ce26345SIngo Weinhold if (fBytesWritten < fSize) { 76*3ce26345SIngo Weinhold int32 toWrite = std::min(fSize - fBytesWritten, (size_t)length); 77*3ce26345SIngo Weinhold memcpy(fCurrent, source, toWrite); 78*3ce26345SIngo Weinhold fCurrent += toWrite; 79*3ce26345SIngo Weinhold } 80*3ce26345SIngo Weinhold 81*3ce26345SIngo Weinhold fBytesWritten += length; 82*3ce26345SIngo Weinhold } 83*3ce26345SIngo Weinhold 84*3ce26345SIngo Weinhold void NullTerminate() 85*3ce26345SIngo Weinhold { 86*3ce26345SIngo Weinhold if (fBytesWritten < fSize) 87*3ce26345SIngo Weinhold *fCurrent = '\0'; 88*3ce26345SIngo Weinhold else if (fSize > 0) 89*3ce26345SIngo Weinhold fCurrent[-1] = '\0'; 90*3ce26345SIngo Weinhold } 91*3ce26345SIngo Weinhold 92*3ce26345SIngo Weinhold private: 93*3ce26345SIngo Weinhold char* fCurrent; 94*3ce26345SIngo Weinhold size_t fSize; 95*3ce26345SIngo Weinhold size_t fBytesWritten; 96*3ce26345SIngo Weinhold }; 97*3ce26345SIngo Weinhold 98*3ce26345SIngo Weinhold 99bd185b41SIngo Weinhold static int 100bd185b41SIngo Weinhold skip_atoi(const char **s) 101bd185b41SIngo Weinhold { 102bd185b41SIngo Weinhold int i = 0; 103bd185b41SIngo Weinhold 104bd185b41SIngo Weinhold while (isdigit(**s)) 105bd185b41SIngo Weinhold i = i*10 + *((*s)++) - '0'; 106bd185b41SIngo Weinhold 107bd185b41SIngo Weinhold return i; 108bd185b41SIngo Weinhold } 109bd185b41SIngo Weinhold 110bd185b41SIngo Weinhold 111bd185b41SIngo Weinhold static uint64 112bd185b41SIngo Weinhold do_div(uint64 *_number, uint32 base) 113bd185b41SIngo Weinhold { 114bd185b41SIngo Weinhold uint64 result = *_number % (uint64)base; 115bd185b41SIngo Weinhold *_number = *_number / (uint64)base; 116bd185b41SIngo Weinhold 117bd185b41SIngo Weinhold return result; 118bd185b41SIngo Weinhold } 119bd185b41SIngo Weinhold 120bd185b41SIngo Weinhold 121bd185b41SIngo Weinhold static char 122bd185b41SIngo Weinhold sign_symbol(int flags, bool negative) 123bd185b41SIngo Weinhold { 124bd185b41SIngo Weinhold if ((flags & SIGN) == 0) 125bd185b41SIngo Weinhold return '\0'; 126bd185b41SIngo Weinhold 127bd185b41SIngo Weinhold if (negative) 128bd185b41SIngo Weinhold return '-'; 129bd185b41SIngo Weinhold else if ((flags & PLUS) != 0) 130bd185b41SIngo Weinhold return '+'; 131bd185b41SIngo Weinhold else if ((flags & SPACE) != 0) 132bd185b41SIngo Weinhold return ' '; 133bd185b41SIngo Weinhold 134bd185b41SIngo Weinhold return '\0'; 135bd185b41SIngo Weinhold } 136bd185b41SIngo Weinhold 137bd185b41SIngo Weinhold 138bd185b41SIngo Weinhold static void 139*3ce26345SIngo Weinhold number(Buffer& outBuffer, uint64 num, uint32 base, int size, 140bd185b41SIngo Weinhold int precision, int flags) 141bd185b41SIngo Weinhold { 142bd185b41SIngo Weinhold const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 143bd185b41SIngo Weinhold char c, sign, tmp[66]; 144bd185b41SIngo Weinhold int i; 145bd185b41SIngo Weinhold 146bd185b41SIngo Weinhold if (flags & LARGE) 147bd185b41SIngo Weinhold digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 148bd185b41SIngo Weinhold if (flags & LEFT) 149bd185b41SIngo Weinhold flags &= ~ZEROPAD; 150bd185b41SIngo Weinhold if (base < 2 || base > 36) 151bd185b41SIngo Weinhold return; 152bd185b41SIngo Weinhold 153bd185b41SIngo Weinhold c = (flags & ZEROPAD) ? '0' : ' '; 154bd185b41SIngo Weinhold 155bd185b41SIngo Weinhold if (flags & SIGN) { 156bd185b41SIngo Weinhold sign = sign_symbol(flags, (int64)num < 0); 157bd185b41SIngo Weinhold if ((int64)num < 0) 158bd185b41SIngo Weinhold num = -(int64)num; 159bd185b41SIngo Weinhold if (sign) 160bd185b41SIngo Weinhold size--; 161bd185b41SIngo Weinhold } else 162bd185b41SIngo Weinhold sign = 0; 163bd185b41SIngo Weinhold 164bd185b41SIngo Weinhold if ((flags & SPECIAL) != 0) { 165bd185b41SIngo Weinhold if (base == 16) 166bd185b41SIngo Weinhold size -= 2; 167bd185b41SIngo Weinhold else if (base == 8) 168bd185b41SIngo Weinhold size--; 169bd185b41SIngo Weinhold } 170bd185b41SIngo Weinhold 171bd185b41SIngo Weinhold i = 0; 172bd185b41SIngo Weinhold if (num == 0) 173bd185b41SIngo Weinhold tmp[i++] = '0'; 174bd185b41SIngo Weinhold else while (num != 0) 175bd185b41SIngo Weinhold tmp[i++] = digits[do_div(&num, base)]; 176bd185b41SIngo Weinhold 177bd185b41SIngo Weinhold if (i > precision) 178bd185b41SIngo Weinhold precision = i; 179bd185b41SIngo Weinhold size -= precision; 180bd185b41SIngo Weinhold 181bd185b41SIngo Weinhold if (!(flags & (ZEROPAD + LEFT))) { 182*3ce26345SIngo Weinhold outBuffer.PutPadding(size); 183bd185b41SIngo Weinhold size = 0; 184bd185b41SIngo Weinhold } 185bd185b41SIngo Weinhold if (sign) 186*3ce26345SIngo Weinhold outBuffer.PutCharacter(sign); 187bd185b41SIngo Weinhold 188bd185b41SIngo Weinhold if ((flags & SPECIAL) != 0) { 189bd185b41SIngo Weinhold if (base == 8) 190*3ce26345SIngo Weinhold outBuffer.PutCharacter('0'); 191bd185b41SIngo Weinhold else if (base == 16) { 192*3ce26345SIngo Weinhold outBuffer.PutCharacter('0'); 193*3ce26345SIngo Weinhold outBuffer.PutCharacter(digits[33]); 194bd185b41SIngo Weinhold } 195bd185b41SIngo Weinhold } 196bd185b41SIngo Weinhold 197bd185b41SIngo Weinhold if (!(flags & LEFT)) { 198bd185b41SIngo Weinhold while (size-- > 0) 199*3ce26345SIngo Weinhold outBuffer.PutCharacter(c); 200bd185b41SIngo Weinhold } 201bd185b41SIngo Weinhold while (i < precision--) 202*3ce26345SIngo Weinhold outBuffer.PutCharacter('0'); 203bd185b41SIngo Weinhold while (i-- > 0) 204*3ce26345SIngo Weinhold outBuffer.PutCharacter(tmp[i]); 205bd185b41SIngo Weinhold 206*3ce26345SIngo Weinhold outBuffer.PutPadding(size); 207bd185b41SIngo Weinhold } 208bd185b41SIngo Weinhold 209bd185b41SIngo Weinhold 210bd185b41SIngo Weinhold #ifdef FLOATING_SUPPORT 211bd185b41SIngo Weinhold /*! 212bd185b41SIngo Weinhold This is a very basic floating point to string conversion routine. 213bd185b41SIngo Weinhold It prints up to 3 fraction digits, and doesn't support any precision arguments. 214bd185b41SIngo Weinhold It's just here for your convenience so that you can use it for debug output. 215bd185b41SIngo Weinhold */ 216*3ce26345SIngo Weinhold static void 217*3ce26345SIngo Weinhold floating(Buffer& outBuffer, double value, int fieldWidth, int flags) 218bd185b41SIngo Weinhold { 219bd185b41SIngo Weinhold char buffer[66]; 220bd185b41SIngo Weinhold uint64 fraction; 221bd185b41SIngo Weinhold uint64 integer; 222bd185b41SIngo Weinhold int32 length = 0; 223bd185b41SIngo Weinhold char sign; 224bd185b41SIngo Weinhold 225bd185b41SIngo Weinhold sign = sign_symbol(flags, value < 0.0); 226bd185b41SIngo Weinhold if (value < 0.0) 227bd185b41SIngo Weinhold value = -value; 228bd185b41SIngo Weinhold 229bd185b41SIngo Weinhold fraction = (uint64)(value * 1000) % 1000; 230bd185b41SIngo Weinhold integer = (uint64)value; 231bd185b41SIngo Weinhold 232bd185b41SIngo Weinhold // put fraction part, if any 233bd185b41SIngo Weinhold 234bd185b41SIngo Weinhold if (fraction != 0) { 235bd185b41SIngo Weinhold bool first = true; 236bd185b41SIngo Weinhold while (fraction != 0) { 237bd185b41SIngo Weinhold int digit = do_div(&fraction, 10); 238bd185b41SIngo Weinhold if (!first || digit > 0) { 239bd185b41SIngo Weinhold buffer[length++] = '0' + digit; 240bd185b41SIngo Weinhold first = false; 241bd185b41SIngo Weinhold } 242bd185b41SIngo Weinhold } 243bd185b41SIngo Weinhold 244bd185b41SIngo Weinhold buffer[length++] = '.'; 245bd185b41SIngo Weinhold } 246bd185b41SIngo Weinhold 247bd185b41SIngo Weinhold // put integer part 248bd185b41SIngo Weinhold 249*3ce26345SIngo Weinhold if (integer == 0) { 250bd185b41SIngo Weinhold buffer[length++] = '0'; 251*3ce26345SIngo Weinhold } else { 252*3ce26345SIngo Weinhold while (integer != 0) 253bd185b41SIngo Weinhold buffer[length++] = '0' + do_div(&integer, 10); 254bd185b41SIngo Weinhold } 255bd185b41SIngo Weinhold 256bd185b41SIngo Weinhold // write back to string 257bd185b41SIngo Weinhold 258*3ce26345SIngo Weinhold if (!(flags & LEFT)) 259*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth); 260bd185b41SIngo Weinhold 261*3ce26345SIngo Weinhold if (sign) 262*3ce26345SIngo Weinhold outBuffer.PutCharacter(sign); 263bd185b41SIngo Weinhold 264*3ce26345SIngo Weinhold while (length-- > 0) 265*3ce26345SIngo Weinhold outBuffer.PutCharacter(buffer[length]); 266bd185b41SIngo Weinhold 267*3ce26345SIngo Weinhold if ((flags & LEFT) != 0) 268*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth); 269bd185b41SIngo Weinhold } 270bd185b41SIngo Weinhold #endif // FLOATING_SUPPORT 271bd185b41SIngo Weinhold 272bd185b41SIngo Weinhold 273bd185b41SIngo Weinhold int 274bd185b41SIngo Weinhold vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) 275bd185b41SIngo Weinhold { 276bd185b41SIngo Weinhold uint64 num; 277bd185b41SIngo Weinhold int base; 278bd185b41SIngo Weinhold int flags; /* flags to number() */ 279bd185b41SIngo Weinhold int fieldWidth; /* width of output field */ 280bd185b41SIngo Weinhold int precision; 281bd185b41SIngo Weinhold /* min. # of digits for integers; max number of chars for from string */ 282bd185b41SIngo Weinhold int qualifier; /* 'h', 'l', or 'L' for integer fields */ 283bd185b41SIngo Weinhold 284*3ce26345SIngo Weinhold Buffer outBuffer(buffer, bufferSize); 285bd185b41SIngo Weinhold 286*3ce26345SIngo Weinhold for (; format[0]; format++) { 287bd185b41SIngo Weinhold if (format[0] != '%') { 288*3ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]); 289bd185b41SIngo Weinhold continue; 290bd185b41SIngo Weinhold } 291bd185b41SIngo Weinhold 292bd185b41SIngo Weinhold /* process flags */ 293bd185b41SIngo Weinhold 294bd185b41SIngo Weinhold flags = 0; 295bd185b41SIngo Weinhold 296bd185b41SIngo Weinhold repeat: 297bd185b41SIngo Weinhold format++; 298bd185b41SIngo Weinhold /* this also skips first '%' */ 299bd185b41SIngo Weinhold switch (format[0]) { 300bd185b41SIngo Weinhold case '-': flags |= LEFT; goto repeat; 301bd185b41SIngo Weinhold case '+': flags |= PLUS; goto repeat; 302bd185b41SIngo Weinhold case ' ': flags |= SPACE; goto repeat; 303bd185b41SIngo Weinhold case '#': flags |= SPECIAL; goto repeat; 304bd185b41SIngo Weinhold case '0': flags |= ZEROPAD; goto repeat; 305bd185b41SIngo Weinhold 306bd185b41SIngo Weinhold case '%': 307*3ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]); 308bd185b41SIngo Weinhold continue; 309bd185b41SIngo Weinhold } 310bd185b41SIngo Weinhold 311bd185b41SIngo Weinhold /* get field width */ 312bd185b41SIngo Weinhold 313bd185b41SIngo Weinhold fieldWidth = -1; 314bd185b41SIngo Weinhold if (isdigit(*format)) 315bd185b41SIngo Weinhold fieldWidth = skip_atoi(&format); 316bd185b41SIngo Weinhold else if (format[0] == '*') { 317bd185b41SIngo Weinhold format++; 318bd185b41SIngo Weinhold /* it's the next argument */ 319bd185b41SIngo Weinhold fieldWidth = va_arg(args, int); 320bd185b41SIngo Weinhold if (fieldWidth < 0) { 321bd185b41SIngo Weinhold fieldWidth = -fieldWidth; 322bd185b41SIngo Weinhold flags |= LEFT; 323bd185b41SIngo Weinhold } 324bd185b41SIngo Weinhold } 325bd185b41SIngo Weinhold 326bd185b41SIngo Weinhold /* get the precision */ 327bd185b41SIngo Weinhold 328bd185b41SIngo Weinhold precision = -1; 329bd185b41SIngo Weinhold if (format[0] == '.') { 330bd185b41SIngo Weinhold format++; 331bd185b41SIngo Weinhold if (isdigit(*format)) 332bd185b41SIngo Weinhold precision = skip_atoi(&format); 333bd185b41SIngo Weinhold else if (format[0] == '*') { 334bd185b41SIngo Weinhold format++; 335bd185b41SIngo Weinhold /* it's the next argument */ 336bd185b41SIngo Weinhold precision = va_arg(args, int); 337bd185b41SIngo Weinhold } 338bd185b41SIngo Weinhold if (precision < 0) 339bd185b41SIngo Weinhold precision = 0; 340bd185b41SIngo Weinhold } 341bd185b41SIngo Weinhold 342bd185b41SIngo Weinhold /* get the conversion qualifier */ 343bd185b41SIngo Weinhold 344bd185b41SIngo Weinhold qualifier = -1; 345bd185b41SIngo Weinhold if (format[0] == 'h' || format[0] == 'L') { 346bd185b41SIngo Weinhold qualifier = *format++; 347bd185b41SIngo Weinhold } else if (format[0] == 'l') { 348bd185b41SIngo Weinhold format++; 349bd185b41SIngo Weinhold if (format[0] == 'l') { 350bd185b41SIngo Weinhold qualifier = 'L'; 351bd185b41SIngo Weinhold format++; 352bd185b41SIngo Weinhold } else 353bd185b41SIngo Weinhold qualifier = 'l'; 354bd185b41SIngo Weinhold } 355bd185b41SIngo Weinhold 356bd185b41SIngo Weinhold /* default base */ 357bd185b41SIngo Weinhold base = 10; 358bd185b41SIngo Weinhold 359bd185b41SIngo Weinhold switch (format[0]) { 360bd185b41SIngo Weinhold case 'c': 361*3ce26345SIngo Weinhold if (!(flags & LEFT)) 362*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth - 1); 363bd185b41SIngo Weinhold 364*3ce26345SIngo Weinhold outBuffer.PutCharacter((char)va_arg(args, int)); 365bd185b41SIngo Weinhold 366*3ce26345SIngo Weinhold if ((flags & LEFT) != 0) 367*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth - 1); 368bd185b41SIngo Weinhold continue; 369bd185b41SIngo Weinhold 370bd185b41SIngo Weinhold case 's': 371bd185b41SIngo Weinhold { 372bd185b41SIngo Weinhold const char *argument = va_arg(args, char *); 373bd185b41SIngo Weinhold int32 length; 374bd185b41SIngo Weinhold 375bd185b41SIngo Weinhold if (argument == NULL) 376bd185b41SIngo Weinhold argument = "<NULL>"; 377bd185b41SIngo Weinhold 378bd185b41SIngo Weinhold length = strnlen(argument, precision); 379bd185b41SIngo Weinhold fieldWidth -= length; 380bd185b41SIngo Weinhold 381*3ce26345SIngo Weinhold if (!(flags & LEFT)) 382*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth); 383bd185b41SIngo Weinhold 384*3ce26345SIngo Weinhold outBuffer.PutString(argument, length); 385bd185b41SIngo Weinhold 386*3ce26345SIngo Weinhold if ((flags & LEFT) != 0) 387*3ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth); 388bd185b41SIngo Weinhold continue; 389bd185b41SIngo Weinhold } 390bd185b41SIngo Weinhold 391bd185b41SIngo Weinhold #ifdef FLOATING_SUPPORT 392bd185b41SIngo Weinhold case 'f': 393bd185b41SIngo Weinhold case 'F': 394bd185b41SIngo Weinhold case 'g': 395bd185b41SIngo Weinhold case 'G': 396bd185b41SIngo Weinhold { 397bd185b41SIngo Weinhold double value = va_arg(args, double); 398*3ce26345SIngo Weinhold floating(outBuffer, value, fieldWidth, flags | SIGN); 399bd185b41SIngo Weinhold continue; 400bd185b41SIngo Weinhold } 401bd185b41SIngo Weinhold #endif // FLOATING_SUPPORT 402bd185b41SIngo Weinhold 403bd185b41SIngo Weinhold case 'p': 404bd185b41SIngo Weinhold if (fieldWidth == -1) { 405bd185b41SIngo Weinhold fieldWidth = 2*sizeof(void *); 406bd185b41SIngo Weinhold flags |= ZEROPAD; 407bd185b41SIngo Weinhold } 408bd185b41SIngo Weinhold 409*3ce26345SIngo Weinhold outBuffer.PutString("0x", 2); 410*3ce26345SIngo Weinhold number(outBuffer, (uint32)va_arg(args, void *), 16, fieldWidth, 411*3ce26345SIngo Weinhold precision, flags); 412bd185b41SIngo Weinhold continue; 413bd185b41SIngo Weinhold 414bd185b41SIngo Weinhold case 'n': 415bd185b41SIngo Weinhold if (qualifier == 'l') { 416bd185b41SIngo Weinhold long *ip = va_arg(args, long *); 417*3ce26345SIngo Weinhold *ip = outBuffer.BytesWritten(); 418bd185b41SIngo Weinhold } else { 419bd185b41SIngo Weinhold int *ip = va_arg(args, int *); 420*3ce26345SIngo Weinhold *ip = outBuffer.BytesWritten(); 421bd185b41SIngo Weinhold } 422bd185b41SIngo Weinhold continue; 423bd185b41SIngo Weinhold 424bd185b41SIngo Weinhold /* integer number formats - set up the flags and "break" */ 425bd185b41SIngo Weinhold case 'o': 426bd185b41SIngo Weinhold base = 8; 427bd185b41SIngo Weinhold break; 428bd185b41SIngo Weinhold 429bd185b41SIngo Weinhold case 'X': 430bd185b41SIngo Weinhold flags |= LARGE; 431bd185b41SIngo Weinhold case 'x': 432bd185b41SIngo Weinhold base = 16; 433bd185b41SIngo Weinhold break; 434bd185b41SIngo Weinhold 435bd185b41SIngo Weinhold case 'd': 436bd185b41SIngo Weinhold case 'i': 437bd185b41SIngo Weinhold flags |= SIGN; 438bd185b41SIngo Weinhold case 'u': 439bd185b41SIngo Weinhold break; 440bd185b41SIngo Weinhold 441bd185b41SIngo Weinhold default: 442bd185b41SIngo Weinhold if (format[0] != '%') 443*3ce26345SIngo Weinhold outBuffer.PutCharacter('%'); 444bd185b41SIngo Weinhold 445bd185b41SIngo Weinhold if (!format[0]) 446bd185b41SIngo Weinhold goto out; 447bd185b41SIngo Weinhold 448*3ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]); 449bd185b41SIngo Weinhold continue; 450bd185b41SIngo Weinhold } 451bd185b41SIngo Weinhold 452bd185b41SIngo Weinhold if (qualifier == 'L') 453bd185b41SIngo Weinhold num = va_arg(args, uint64); 454bd185b41SIngo Weinhold else if (qualifier == 'l') { 455bd185b41SIngo Weinhold num = va_arg(args, uint32); 456bd185b41SIngo Weinhold if (flags & SIGN) 457bd185b41SIngo Weinhold num = (long)num; 458bd185b41SIngo Weinhold } else if (qualifier == 'h') { 459bd185b41SIngo Weinhold num = (unsigned short)va_arg(args, int); 460bd185b41SIngo Weinhold if (flags & SIGN) 461bd185b41SIngo Weinhold num = (short)num; 462bd185b41SIngo Weinhold } else if (flags & SIGN) 463bd185b41SIngo Weinhold num = va_arg(args, int); 464bd185b41SIngo Weinhold else 465bd185b41SIngo Weinhold num = va_arg(args, unsigned int); 466bd185b41SIngo Weinhold 467*3ce26345SIngo Weinhold number(outBuffer, num, base, fieldWidth, precision, flags); 468bd185b41SIngo Weinhold } 469bd185b41SIngo Weinhold 470bd185b41SIngo Weinhold out: 471*3ce26345SIngo Weinhold outBuffer.NullTerminate(); 472*3ce26345SIngo Weinhold return outBuffer.BytesWritten(); 473bd185b41SIngo Weinhold } 474bd185b41SIngo Weinhold 475bd185b41SIngo Weinhold 476bd185b41SIngo Weinhold int 477bd185b41SIngo Weinhold vsprintf(char *buffer, const char *format, va_list args) 478bd185b41SIngo Weinhold { 479bd185b41SIngo Weinhold return vsnprintf(buffer, ~0UL, format, args); 480bd185b41SIngo Weinhold } 481bd185b41SIngo Weinhold 482bd185b41SIngo Weinhold 483bd185b41SIngo Weinhold int 484bd185b41SIngo Weinhold snprintf(char *buffer, size_t bufferSize, const char *format, ...) 485bd185b41SIngo Weinhold { 486bd185b41SIngo Weinhold va_list args; 487bd185b41SIngo Weinhold int i; 488bd185b41SIngo Weinhold 489bd185b41SIngo Weinhold va_start(args, format); 490bd185b41SIngo Weinhold i = vsnprintf(buffer, bufferSize, format, args); 491bd185b41SIngo Weinhold va_end(args); 492bd185b41SIngo Weinhold 493bd185b41SIngo Weinhold return i; 494bd185b41SIngo Weinhold } 495bd185b41SIngo Weinhold 496bd185b41SIngo Weinhold 497bd185b41SIngo Weinhold int 498bd185b41SIngo Weinhold sprintf(char *buffer, const char *format, ...) 499bd185b41SIngo Weinhold { 500bd185b41SIngo Weinhold va_list args; 501bd185b41SIngo Weinhold int i; 502bd185b41SIngo Weinhold 503bd185b41SIngo Weinhold va_start(args, format); 504bd185b41SIngo Weinhold i = vsnprintf(buffer, ~0UL, format, args); 505bd185b41SIngo Weinhold va_end(args); 506bd185b41SIngo Weinhold 507bd185b41SIngo Weinhold return i; 508bd185b41SIngo Weinhold } 509bd185b41SIngo Weinhold 510