From 3ce26345338e484601eb0a6598414d22cb73c9cc Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 30 Dec 2009 15:17:09 +0000 Subject: [PATCH] * Fixed the semantics of [v]snprintf(): If the buffer is not large enough, the function shall nevertheless return the length of the string that would be written, if the buffer were large enough. Added a touch of C++ while doing that. :-) * Fixed the instances in boot loader, kernel, and kernel modules where the wrong semantics were expected. The majority of uses actually. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34826 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/bus_managers/ata/ATATracing.cpp | 16 +- src/add-ons/kernel/bus_managers/usb/Hub.cpp | 24 +- src/add-ons/kernel/file_cache/log.cpp | 3 + src/system/boot/loader/menu.cpp | 7 +- src/system/boot/loader/stdio.cpp | 6 +- src/system/boot/platform/atari_m68k/debug.c | 6 +- src/system/boot/platform/bios_ia32/debug.c | 3 + src/system/boot/platform/u-boot/debug.c | 3 + src/system/kernel/debug/debug.cpp | 10 +- src/system/kernel/debug/debug_commands.cpp | 11 +- src/system/kernel/debug/tracing.cpp | 14 +- src/system/kernel/lib/kernel_vsprintf.cpp | 276 ++++++++---------- 12 files changed, 199 insertions(+), 180 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ata/ATATracing.cpp b/src/add-ons/kernel/bus_managers/ata/ATATracing.cpp index b01e41ff99..1f2d53f374 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATATracing.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATATracing.cpp @@ -7,6 +7,8 @@ #include +#include + static char sTraceBuffer[256]; static uint32 sTraceBufferOffset = 0; @@ -15,11 +17,15 @@ static uint32 sTraceBufferOffset = 0; void ata_trace_printf(uint32 flags, const char *format, ...) { - va_list arguments; - va_start(arguments, format); - sTraceBufferOffset += vsnprintf(sTraceBuffer + sTraceBufferOffset, - sizeof(sTraceBuffer) - sTraceBufferOffset, format, arguments); - va_end(arguments); + if (sTraceBufferOffset < sizeof(sTraceBuffer)) { + va_list arguments; + va_start(arguments, format); + size_t totalBytes = vsnprintf(sTraceBuffer + sTraceBufferOffset, + sizeof(sTraceBuffer) - sTraceBufferOffset, format, arguments); + sTraceBufferOffset += std::min(totalBytes, + sizeof(sTraceBuffer) - sTraceBufferOffset - 1); + va_end(arguments); + } if (flags & ATA_TRACE_FLUSH) { #if ATA_TRACING diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index d8cc9c2887..cf5474e989 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -7,9 +7,13 @@ * Niels S. Reedijk */ + #include "usb_p.h" + #include +#include + Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort, usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed, @@ -386,18 +390,30 @@ Hub::BuildDeviceName(char *string, uint32 *index, size_t bufferSize, status_t result = Device::BuildDeviceName(string, index, bufferSize, device); if (result < B_OK) { // recursion to parent failed, we're at the root(hub) - int32 managerIndex = GetStack()->IndexOfBusManager(GetBusManager()); - *index += snprintf(string + *index, bufferSize - *index, "%ld", managerIndex); + if (*index < bufferSize) { + int32 managerIndex = GetStack()->IndexOfBusManager(GetBusManager()); + size_t totalBytes = snprintf(string + *index, bufferSize - *index, + "%ld", managerIndex); + *index += std::min(totalBytes, bufferSize - *index - 1); + } } if (!device) { // no device was specified - report the hub - *index += snprintf(string + *index, bufferSize - *index, "/hub"); + if (*index < bufferSize) { + size_t totalBytes = snprintf(string + *index, bufferSize - *index, + "/hub"); + *index += std::min(totalBytes, bufferSize - *index - 1); + } } else { // find out where the requested device sitts for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { if (fChildren[i] == device) { - *index += snprintf(string + *index, bufferSize - *index, "/%ld", i); + if (*index < bufferSize) { + size_t totalBytes = snprintf(string + *index, + bufferSize - *index, "/%ld", i); + *index += std::min(totalBytes, bufferSize - *index - 1); + } break; } } diff --git a/src/add-ons/kernel/file_cache/log.cpp b/src/add-ons/kernel/file_cache/log.cpp index c426f1f47a..6fe1b7b3e0 100644 --- a/src/add-ons/kernel/file_cache/log.cpp +++ b/src/add-ons/kernel/file_cache/log.cpp @@ -276,6 +276,7 @@ log_writer_daemon(void *arg, int /*iteration*/) log->team, log->timestamp, log->team_name, log->device, log->parent, log->launch.parent, log->launch.args[0]); + length = std::min(length, (ssize_t)sizeof(line) - 1); for (int32 j = 1; j < log->launch.arg_count; j++) { // write argument list one by one, so that we can deal @@ -302,12 +303,14 @@ log_writer_daemon(void *arg, int /*iteration*/) length = snprintf(line, sizeof(line), "%ld: %Ld \"%s\" c%d %ld:%Ld %ld\n", log->team, log->timestamp, log->team_name, log->type, log->device, log->node, log->access_type); + length = std::min(length, (ssize_t)sizeof(line) - 1); break; default: // open, ? length = snprintf(line, sizeof(line), "%ld: %Ld \"%s\" %c%d %ld:%Ld:%Ld:\"%s\"\n", log->team, log->timestamp, log->team_name, log->action, log->type, log->device, log->parent, log->node, log->file_name); + length = std::min(length, (ssize_t)sizeof(line) - 1); break; } diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index 4fafb751df..6f8d45b630 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -9,6 +9,8 @@ #include "RootFileSystem.h" #include "load_driver_settings.h" +#include + #include #include @@ -503,8 +505,9 @@ apply_safe_mode_options(Menu *menu) || item->Data() == NULL || (uint32)pos > sizeof(buffer)) continue; - pos += snprintf(buffer + pos, sizeof(buffer) - pos, "%s true\n", - (const char *)item->Data()); + size_t totalBytes = snprintf(buffer + pos, sizeof(buffer) - pos, + "%s true\n", (const char *)item->Data()); + pos += std::min(totalBytes, sizeof(buffer) - pos - 1); } add_safe_mode_settings(buffer); diff --git a/src/system/boot/loader/stdio.cpp b/src/system/boot/loader/stdio.cpp index 48676d6e15..c6d8efbc46 100644 --- a/src/system/boot/loader/stdio.cpp +++ b/src/system/boot/loader/stdio.cpp @@ -11,6 +11,9 @@ #include #include +#include + + //#undef stdout //#undef stdin //extern FILE *stdout; @@ -28,6 +31,7 @@ vfprintf(FILE *file, const char *format, va_list list) // the buffer handling could (or should) be done better... int length = vsnprintf(buffer, sizeof(buffer), format, list); + length = std::min(length, (int)sizeof(buffer) - 1); if (length > 0) node->Write(buffer, length); @@ -77,7 +81,7 @@ fputc(int c, FILE *file) status_t status; char character = (char)c; - // we only support direct console output right now... + // we only support direct console output right now... status = ((ConsoleNode *)file)->Write(&character, 1); if (status > 0) diff --git a/src/system/boot/platform/atari_m68k/debug.c b/src/system/boot/platform/atari_m68k/debug.c index 35861e96d9..3defe36cdd 100644 --- a/src/system/boot/platform/atari_m68k/debug.c +++ b/src/system/boot/platform/atari_m68k/debug.c @@ -21,7 +21,6 @@ panic(const char *format, ...) const char greetings[] = "\n*** PANIC ***"; char buffer[512]; va_list list; - int length; //platform_switch_to_text_mode(); @@ -31,7 +30,7 @@ panic(const char *format, ...) nat_feat_debugprintf("\n"); va_start(list, format); - length = vsnprintf(buffer, sizeof(buffer), format, list); + vsnprintf(buffer, sizeof(buffer), format, list); va_end(list); Bconputs(DEV_CONSOLE, buffer); @@ -52,10 +51,9 @@ dprintf(const char *format, ...) { char buffer[512]; va_list list; - int length; va_start(list, format); - length = vsnprintf(buffer, sizeof(buffer), format, list); + vsnprintf(buffer, sizeof(buffer), format, list); va_end(list); Bconput(DEV_AUX, buffer); diff --git a/src/system/boot/platform/bios_ia32/debug.c b/src/system/boot/platform/bios_ia32/debug.c index 79c8cc3e8c..23094c0009 100644 --- a/src/system/boot/platform/bios_ia32/debug.c +++ b/src/system/boot/platform/bios_ia32/debug.c @@ -46,6 +46,9 @@ dprintf(const char *format, ...) length = vsnprintf(buffer, sizeof(buffer), format, list); va_end(list); + if (length >= (int)sizeof(buffer)) + length = sizeof(buffer) - 1; + serial_puts(buffer, length); if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) diff --git a/src/system/boot/platform/u-boot/debug.c b/src/system/boot/platform/u-boot/debug.c index 79c8cc3e8c..23094c0009 100644 --- a/src/system/boot/platform/u-boot/debug.c +++ b/src/system/boot/platform/u-boot/debug.c @@ -46,6 +46,9 @@ dprintf(const char *format, ...) length = vsnprintf(buffer, sizeof(buffer), format, list); va_end(list); + if (length >= (int)sizeof(buffer)) + length = sizeof(buffer) - 1; + serial_puts(buffer, length); if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 5493166ebe..7c6fd916e3 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1169,7 +1169,8 @@ syslog_init(struct kernel_args* args) length = snprintf(revisionBuffer, sizeof(revisionBuffer), "Welcome to syslog debug output!\nHaiku revision: %lu\n", get_haiku_revision()); - syslog_write(revisionBuffer, length); + syslog_write(revisionBuffer, + std::min(length, (ssize_t)sizeof(revisionBuffer) - 1)); add_debugger_command_etc("syslog", &cmd_dump_syslog, "Dumps the syslog buffer.", @@ -1267,6 +1268,7 @@ flush_pending_repeats(bool syslogOutput) static char temp[40]; size_t length = snprintf(temp, sizeof(temp), "Last message repeated %ld times.\n", sMessageRepeatCount); + length = std::min(length, sizeof(temp) - 1); if (sSerialDebugEnabled) arch_debug_serial_puts(temp); @@ -1328,8 +1330,9 @@ dprintf_args(const char* format, va_list args, bool syslogOutput) if (are_interrupts_enabled()) { MutexLocker locker(sOutputLock); - int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, - format, args); + int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, format, + args); + length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); InterruptsSpinLocker _(sSpinlock); debug_output(sOutputBuffer, length, syslogOutput); @@ -1338,6 +1341,7 @@ dprintf_args(const char* format, va_list args, bool syslogOutput) int32 length = vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE, format, args); + length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1); debug_output(sInterruptOutputBuffer, length, syslogOutput); } diff --git a/src/system/kernel/debug/debug_commands.cpp b/src/system/kernel/debug/debug_commands.cpp index a31ae6a85e..8e5a7ebf1b 100644 --- a/src/system/kernel/debug/debug_commands.cpp +++ b/src/system/kernel/debug/debug_commands.cpp @@ -7,12 +7,15 @@ * Distributed under the terms of the NewOS License. */ + #include "debug_commands.h" #include #include #include +#include + #include #include @@ -111,8 +114,12 @@ public: return; // print directly into the buffer - fBufferSize += vsnprintf(fBuffer + fBufferSize, - fBufferCapacity - fBufferSize, format, args); + if (fBufferSize < fBufferCapacity) { + size_t totalBytes = vsnprintf(fBuffer + fBufferSize, + fBufferCapacity - fBufferSize, format, args); + fBufferSize += std::min(totalBytes, + fBufferCapacity - fBufferSize - 1); + } // execute every complete line fBuffer[fBufferSize] = '\0'; diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index 90164cc699..de528f6d0f 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include #include @@ -596,10 +598,14 @@ TraceOutput::Print(const char* format,...) if (IsFull()) return; - va_list args; - va_start(args, format); - fSize += vsnprintf(fBuffer + fSize, fCapacity - fSize, format, args); - va_end(args); + if (fSize < fCapacity) { + va_list args; + va_start(args, format); + size_t length = vsnprintf(fBuffer + fSize, fCapacity - fSize, format, + args); + fSize += std::min(length, fCapacity - fSize - 1); + va_end(args); + } #endif } diff --git a/src/system/kernel/lib/kernel_vsprintf.cpp b/src/system/kernel/lib/kernel_vsprintf.cpp index 7afee6f8d7..ee3d5c9e4f 100644 --- a/src/system/kernel/lib/kernel_vsprintf.cpp +++ b/src/system/kernel/lib/kernel_vsprintf.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2003-2008, Axel Dörfler. All rights reserved. * Distributed under the terms of the MIT license. * @@ -9,10 +10,12 @@ #include -#include -#include #include +#include #include +#include + +#include #define ZEROPAD 1 /* pad with zero */ @@ -26,6 +29,73 @@ #define FLOATING_SUPPORT +struct Buffer { + Buffer(char* buffer, size_t size) + : + fCurrent(buffer), + fSize(size), + fBytesWritten(0) + { + } + + size_t BytesWritten() const + { + return fBytesWritten; + } + + void PutCharacter(char c) + { + if (fBytesWritten < fSize) { + *fCurrent = c; + fCurrent++; + } + + fBytesWritten++; + } + + void PutPadding(int32 count) + { + if (count <= 0) + return; + + if (fBytesWritten < fSize) { + int32 toWrite = std::min(fSize - fBytesWritten, (size_t)count); + while (--toWrite >= 0) + *fCurrent++ = ' '; + } + + fBytesWritten += count; + } + + void PutString(const char *source, int32 length) + { + if (length <= 0) + return; + + if (fBytesWritten < fSize) { + int32 toWrite = std::min(fSize - fBytesWritten, (size_t)length); + memcpy(fCurrent, source, toWrite); + fCurrent += toWrite; + } + + fBytesWritten += length; + } + + void NullTerminate() + { + if (fBytesWritten < fSize) + *fCurrent = '\0'; + else if (fSize > 0) + fCurrent[-1] = '\0'; + } + +private: + char* fCurrent; + size_t fSize; + size_t fBytesWritten; +}; + + static int skip_atoi(const char **s) { @@ -48,88 +118,6 @@ do_div(uint64 *_number, uint32 base) } -static bool -put_padding(char **_buffer, int32 *_bytesLeft, int32 count) -{ - int32 left = *_bytesLeft; - char *string = *_buffer; - int32 written; - bool allWritten; - - if (count <= 0) - return true; - if (left == 0) - return false; - - if (left < count) { - count = left; - allWritten = false; - } else - allWritten = true; - - written = count; - - while (count-- > 0) - *string++ = ' '; - - *_buffer = string; - *_bytesLeft = left - written; - - return allWritten; -} - - -static inline bool -put_string(char **_buffer, int32 *_bytesLeft, const char *source, int32 length) -{ - int32 left = *_bytesLeft; - char *target = *_buffer; - bool allWritten; - - if (length == 0) - return true; - if (left == 0) - return false; - - if (left < length) { - length = left; - allWritten = false; - } else - allWritten = true; - -#if 0 - // take care of string arguments in user space - if (CHECK_USER_ADDRESS(source)) { - if (user_memcpy(target, source, length) < B_OK) - return put_string(_buffer, _bytesLeft, "", 7); - } else -#endif - memcpy(target, source, length); - - *_bytesLeft = left - length; - *_buffer = target + length; - - return allWritten; -} - - -static inline bool -put_character(char **_buffer, int32 *_bytesLeft, char c) -{ - int32 left = *_bytesLeft; - char *string = *_buffer; - - if (left > 0) { - *string++ = c; - *_buffer = string; - *_bytesLeft = left - 1; - return true; - } - - return false; -} - - static char sign_symbol(int flags, bool negative) { @@ -148,7 +136,7 @@ sign_symbol(int flags, bool negative) static void -number(char **_string, int32 *_bytesLeft, uint64 num, uint32 base, int size, +number(Buffer& outBuffer, uint64 num, uint32 base, int size, int precision, int flags) { const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; @@ -191,31 +179,31 @@ number(char **_string, int32 *_bytesLeft, uint64 num, uint32 base, int size, size -= precision; if (!(flags & (ZEROPAD + LEFT))) { - put_padding(_string, _bytesLeft, size); + outBuffer.PutPadding(size); size = 0; } if (sign) - put_character(_string, _bytesLeft, sign); + outBuffer.PutCharacter(sign); if ((flags & SPECIAL) != 0) { if (base == 8) - put_character(_string, _bytesLeft, '0'); + outBuffer.PutCharacter('0'); else if (base == 16) { - put_character(_string, _bytesLeft, '0'); - put_character(_string, _bytesLeft, digits[33]); + outBuffer.PutCharacter('0'); + outBuffer.PutCharacter(digits[33]); } } if (!(flags & LEFT)) { while (size-- > 0) - put_character(_string, _bytesLeft, c); + outBuffer.PutCharacter(c); } while (i < precision--) - put_character(_string, _bytesLeft, '0'); + outBuffer.PutCharacter('0'); while (i-- > 0) - put_character(_string, _bytesLeft, tmp[i]); + outBuffer.PutCharacter(tmp[i]); - put_padding(_string, _bytesLeft, size); + outBuffer.PutPadding(size); } @@ -225,9 +213,8 @@ number(char **_string, int32 *_bytesLeft, uint64 num, uint32 base, int size, It prints up to 3 fraction digits, and doesn't support any precision arguments. It's just here for your convenience so that you can use it for debug output. */ -static bool -floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, - int flags) +static void +floating(Buffer& outBuffer, double value, int fieldWidth, int flags) { char buffer[66]; uint64 fraction; @@ -259,29 +246,26 @@ floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, // put integer part - if (integer == 0) + if (integer == 0) { buffer[length++] = '0'; - else while (integer != 0) { - buffer[length++] = '0' + do_div(&integer, 10); + } else { + while (integer != 0) + buffer[length++] = '0' + do_div(&integer, 10); } // write back to string - if (!(flags & LEFT) && !put_padding(_string, _bytesLeft, fieldWidth)) - return false; + if (!(flags & LEFT)) + outBuffer.PutPadding(fieldWidth); - if (sign && !put_character(_string, _bytesLeft, sign)) - return false; + if (sign) + outBuffer.PutCharacter(sign); - while (length-- > 0) { - if (!put_character(_string, _bytesLeft, buffer[length])) - return false; - } + while (length-- > 0) + outBuffer.PutCharacter(buffer[length]); - if ((flags & LEFT) != 0 && !put_padding(_string, _bytesLeft, fieldWidth)) - return false; - - return true; + if ((flags & LEFT) != 0) + outBuffer.PutPadding(fieldWidth); } #endif // FLOATING_SUPPORT @@ -289,28 +273,19 @@ floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, int vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) { - int32 bytesLeft; uint64 num; int base; - char *string; int flags; /* flags to number() */ int fieldWidth; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ - if (bufferSize == 0) - return 0; + Buffer outBuffer(buffer, bufferSize); - bytesLeft = ((int32)bufferSize - 1) & 0x7fffffff; - // make space for the terminating '\0' byte, and we - // only allow 2G characters :) - - for (string = buffer; format[0] && bytesLeft > 0; format++) { + for (; format[0]; format++) { if (format[0] != '%') { - if (!put_character(&string, &bytesLeft, format[0])) - break; - + outBuffer.PutCharacter(format[0]); continue; } @@ -329,8 +304,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) case '0': flags |= ZEROPAD; goto repeat; case '%': - if (!put_character(&string, &bytesLeft, format[0])) - break; + outBuffer.PutCharacter(format[0]); continue; } @@ -384,15 +358,13 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) switch (format[0]) { case 'c': - if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, - fieldWidth - 1)) - goto out; + if (!(flags & LEFT)) + outBuffer.PutPadding(fieldWidth - 1); - put_character(&string, &bytesLeft, (char)va_arg(args, int)); + outBuffer.PutCharacter((char)va_arg(args, int)); - if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, - fieldWidth - 1)) - goto out; + if ((flags & LEFT) != 0) + outBuffer.PutPadding(fieldWidth - 1); continue; case 's': @@ -406,16 +378,13 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) length = strnlen(argument, precision); fieldWidth -= length; - if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, - fieldWidth)) - goto out; + if (!(flags & LEFT)) + outBuffer.PutPadding(fieldWidth); - if (!put_string(&string, &bytesLeft, argument, length)) - goto out; + outBuffer.PutString(argument, length); - if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, - fieldWidth)) - goto out; + if ((flags & LEFT) != 0) + outBuffer.PutPadding(fieldWidth); continue; } @@ -426,9 +395,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) case 'G': { double value = va_arg(args, double); - if (!floating(&string, &bytesLeft, value, fieldWidth, - flags | SIGN)) - goto out; + floating(outBuffer, value, fieldWidth, flags | SIGN); continue; } #endif // FLOATING_SUPPORT @@ -439,19 +406,18 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) flags |= ZEROPAD; } - if (!put_string(&string, &bytesLeft, "0x", 2)) - goto out; - number(&string, &bytesLeft, (uint32)va_arg(args, void *), 16, - fieldWidth, precision, flags); + outBuffer.PutString("0x", 2); + number(outBuffer, (uint32)va_arg(args, void *), 16, fieldWidth, + precision, flags); continue; case 'n': if (qualifier == 'l') { long *ip = va_arg(args, long *); - *ip = (string - buffer); + *ip = outBuffer.BytesWritten(); } else { int *ip = va_arg(args, int *); - *ip = (string - buffer); + *ip = outBuffer.BytesWritten(); } continue; @@ -474,12 +440,12 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) default: if (format[0] != '%') - put_character(&string, &bytesLeft, '%'); + outBuffer.PutCharacter('%'); if (!format[0]) goto out; - put_character(&string, &bytesLeft, format[0]); + outBuffer.PutCharacter(format[0]); continue; } @@ -498,12 +464,12 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) else num = va_arg(args, unsigned int); - number(&string, &bytesLeft, num, base, fieldWidth, precision, flags); + number(outBuffer, num, base, fieldWidth, precision, flags); } out: - *string = '\0'; - return string - buffer; + outBuffer.NullTerminate(); + return outBuffer.BytesWritten(); }