* 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
This commit is contained in:
Ingo Weinhold 2009-12-30 15:17:09 +00:00
parent 3069ca963e
commit 3ce2634533
12 changed files with 199 additions and 180 deletions

View File

@ -7,6 +7,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <algorithm>
static char sTraceBuffer[256]; static char sTraceBuffer[256];
static uint32 sTraceBufferOffset = 0; static uint32 sTraceBufferOffset = 0;
@ -15,11 +17,15 @@ static uint32 sTraceBufferOffset = 0;
void void
ata_trace_printf(uint32 flags, const char *format, ...) ata_trace_printf(uint32 flags, const char *format, ...)
{ {
if (sTraceBufferOffset < sizeof(sTraceBuffer)) {
va_list arguments; va_list arguments;
va_start(arguments, format); va_start(arguments, format);
sTraceBufferOffset += vsnprintf(sTraceBuffer + sTraceBufferOffset, size_t totalBytes = vsnprintf(sTraceBuffer + sTraceBufferOffset,
sizeof(sTraceBuffer) - sTraceBufferOffset, format, arguments); sizeof(sTraceBuffer) - sTraceBufferOffset, format, arguments);
sTraceBufferOffset += std::min(totalBytes,
sizeof(sTraceBuffer) - sTraceBufferOffset - 1);
va_end(arguments); va_end(arguments);
}
if (flags & ATA_TRACE_FLUSH) { if (flags & ATA_TRACE_FLUSH) {
#if ATA_TRACING #if ATA_TRACING

View File

@ -7,9 +7,13 @@
* Niels S. Reedijk * Niels S. Reedijk
*/ */
#include "usb_p.h" #include "usb_p.h"
#include <stdio.h> #include <stdio.h>
#include <algorithm>
Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort, Hub::Hub(Object *parent, int8 hubAddress, uint8 hubPort,
usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed, 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); status_t result = Device::BuildDeviceName(string, index, bufferSize, device);
if (result < B_OK) { if (result < B_OK) {
// recursion to parent failed, we're at the root(hub) // recursion to parent failed, we're at the root(hub)
if (*index < bufferSize) {
int32 managerIndex = GetStack()->IndexOfBusManager(GetBusManager()); int32 managerIndex = GetStack()->IndexOfBusManager(GetBusManager());
*index += snprintf(string + *index, bufferSize - *index, "%ld", managerIndex); size_t totalBytes = snprintf(string + *index, bufferSize - *index,
"%ld", managerIndex);
*index += std::min(totalBytes, bufferSize - *index - 1);
}
} }
if (!device) { if (!device) {
// no device was specified - report the hub // 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 { } else {
// find out where the requested device sitts // find out where the requested device sitts
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
if (fChildren[i] == device) { 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; break;
} }
} }

View File

@ -276,6 +276,7 @@ log_writer_daemon(void *arg, int /*iteration*/)
log->team, log->timestamp, log->team_name, log->team, log->timestamp, log->team_name,
log->device, log->parent, log->launch.parent, log->device, log->parent, log->launch.parent,
log->launch.args[0]); log->launch.args[0]);
length = std::min(length, (ssize_t)sizeof(line) - 1);
for (int32 j = 1; j < log->launch.arg_count; j++) { for (int32 j = 1; j < log->launch.arg_count; j++) {
// write argument list one by one, so that we can deal // 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", length = snprintf(line, sizeof(line), "%ld: %Ld \"%s\" c%d %ld:%Ld %ld\n",
log->team, log->timestamp, log->team_name, log->type, log->team, log->timestamp, log->team_name, log->type,
log->device, log->node, log->access_type); log->device, log->node, log->access_type);
length = std::min(length, (ssize_t)sizeof(line) - 1);
break; break;
default: // open, ? default: // open, ?
length = snprintf(line, sizeof(line), "%ld: %Ld \"%s\" %c%d %ld:%Ld:%Ld:\"%s\"\n", 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->team, log->timestamp, log->team_name, log->action, log->type, log->device,
log->parent, log->node, log->file_name); log->parent, log->node, log->file_name);
length = std::min(length, (ssize_t)sizeof(line) - 1);
break; break;
} }

View File

@ -9,6 +9,8 @@
#include "RootFileSystem.h" #include "RootFileSystem.h"
#include "load_driver_settings.h" #include "load_driver_settings.h"
#include <algorithm>
#include <OS.h> #include <OS.h>
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
@ -503,8 +505,9 @@ apply_safe_mode_options(Menu *menu)
|| item->Data() == NULL || (uint32)pos > sizeof(buffer)) || item->Data() == NULL || (uint32)pos > sizeof(buffer))
continue; continue;
pos += snprintf(buffer + pos, sizeof(buffer) - pos, "%s true\n", size_t totalBytes = snprintf(buffer + pos, sizeof(buffer) - pos,
(const char *)item->Data()); "%s true\n", (const char *)item->Data());
pos += std::min(totalBytes, sizeof(buffer) - pos - 1);
} }
add_safe_mode_settings(buffer); add_safe_mode_settings(buffer);

View File

@ -11,6 +11,9 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <algorithm>
//#undef stdout //#undef stdout
//#undef stdin //#undef stdin
//extern FILE *stdout; //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... // the buffer handling could (or should) be done better...
int length = vsnprintf(buffer, sizeof(buffer), format, list); int length = vsnprintf(buffer, sizeof(buffer), format, list);
length = std::min(length, (int)sizeof(buffer) - 1);
if (length > 0) if (length > 0)
node->Write(buffer, length); node->Write(buffer, length);

View File

@ -21,7 +21,6 @@ panic(const char *format, ...)
const char greetings[] = "\n*** PANIC ***"; const char greetings[] = "\n*** PANIC ***";
char buffer[512]; char buffer[512];
va_list list; va_list list;
int length;
//platform_switch_to_text_mode(); //platform_switch_to_text_mode();
@ -31,7 +30,7 @@ panic(const char *format, ...)
nat_feat_debugprintf("\n"); nat_feat_debugprintf("\n");
va_start(list, format); va_start(list, format);
length = vsnprintf(buffer, sizeof(buffer), format, list); vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list); va_end(list);
Bconputs(DEV_CONSOLE, buffer); Bconputs(DEV_CONSOLE, buffer);
@ -52,10 +51,9 @@ dprintf(const char *format, ...)
{ {
char buffer[512]; char buffer[512];
va_list list; va_list list;
int length;
va_start(list, format); va_start(list, format);
length = vsnprintf(buffer, sizeof(buffer), format, list); vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list); va_end(list);
Bconput(DEV_AUX, buffer); Bconput(DEV_AUX, buffer);

View File

@ -46,6 +46,9 @@ dprintf(const char *format, ...)
length = vsnprintf(buffer, sizeof(buffer), format, list); length = vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list); va_end(list);
if (length >= (int)sizeof(buffer))
length = sizeof(buffer) - 1;
serial_puts(buffer, length); serial_puts(buffer, length);
if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)

View File

@ -46,6 +46,9 @@ dprintf(const char *format, ...)
length = vsnprintf(buffer, sizeof(buffer), format, list); length = vsnprintf(buffer, sizeof(buffer), format, list);
va_end(list); va_end(list);
if (length >= (int)sizeof(buffer))
length = sizeof(buffer) - 1;
serial_puts(buffer, length); serial_puts(buffer, length);
if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) if (platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT)

View File

@ -1169,7 +1169,8 @@ syslog_init(struct kernel_args* args)
length = snprintf(revisionBuffer, sizeof(revisionBuffer), length = snprintf(revisionBuffer, sizeof(revisionBuffer),
"Welcome to syslog debug output!\nHaiku revision: %lu\n", "Welcome to syslog debug output!\nHaiku revision: %lu\n",
get_haiku_revision()); 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, add_debugger_command_etc("syslog", &cmd_dump_syslog,
"Dumps the syslog buffer.", "Dumps the syslog buffer.",
@ -1267,6 +1268,7 @@ flush_pending_repeats(bool syslogOutput)
static char temp[40]; static char temp[40];
size_t length = snprintf(temp, sizeof(temp), size_t length = snprintf(temp, sizeof(temp),
"Last message repeated %ld times.\n", sMessageRepeatCount); "Last message repeated %ld times.\n", sMessageRepeatCount);
length = std::min(length, sizeof(temp) - 1);
if (sSerialDebugEnabled) if (sSerialDebugEnabled)
arch_debug_serial_puts(temp); arch_debug_serial_puts(temp);
@ -1328,8 +1330,9 @@ dprintf_args(const char* format, va_list args, bool syslogOutput)
if (are_interrupts_enabled()) { if (are_interrupts_enabled()) {
MutexLocker locker(sOutputLock); MutexLocker locker(sOutputLock);
int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, int32 length = vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, format,
format, args); args);
length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1);
InterruptsSpinLocker _(sSpinlock); InterruptsSpinLocker _(sSpinlock);
debug_output(sOutputBuffer, length, syslogOutput); 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, int32 length = vsnprintf(sInterruptOutputBuffer, OUTPUT_BUFFER_SIZE,
format, args); format, args);
length = std::min(length, (int32)OUTPUT_BUFFER_SIZE - 1);
debug_output(sInterruptOutputBuffer, length, syslogOutput); debug_output(sInterruptOutputBuffer, length, syslogOutput);
} }

View File

@ -7,12 +7,15 @@
* Distributed under the terms of the NewOS License. * Distributed under the terms of the NewOS License.
*/ */
#include "debug_commands.h" #include "debug_commands.h"
#include <setjmp.h> #include <setjmp.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <algorithm>
#include <KernelExport.h> #include <KernelExport.h>
#include <debug.h> #include <debug.h>
@ -111,8 +114,12 @@ public:
return; return;
// print directly into the buffer // print directly into the buffer
fBufferSize += vsnprintf(fBuffer + fBufferSize, if (fBufferSize < fBufferCapacity) {
size_t totalBytes = vsnprintf(fBuffer + fBufferSize,
fBufferCapacity - fBufferSize, format, args); fBufferCapacity - fBufferSize, format, args);
fBufferSize += std::min(totalBytes,
fBufferCapacity - fBufferSize - 1);
}
// execute every complete line // execute every complete line
fBuffer[fBufferSize] = '\0'; fBuffer[fBufferSize] = '\0';

View File

@ -10,6 +10,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <algorithm>
#include <arch/debug.h> #include <arch/debug.h>
#include <debug.h> #include <debug.h>
#include <elf.h> #include <elf.h>
@ -596,10 +598,14 @@ TraceOutput::Print(const char* format,...)
if (IsFull()) if (IsFull())
return; return;
if (fSize < fCapacity) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
fSize += vsnprintf(fBuffer + fSize, fCapacity - fSize, format, args); size_t length = vsnprintf(fBuffer + fSize, fCapacity - fSize, format,
args);
fSize += std::min(length, fCapacity - fSize - 1);
va_end(args); va_end(args);
}
#endif #endif
} }

View File

@ -1,4 +1,5 @@
/* /*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2003-2008, Axel Dörfler. All rights reserved. * Copyright 2003-2008, Axel Dörfler. All rights reserved.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
@ -9,10 +10,12 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <algorithm>
#define ZEROPAD 1 /* pad with zero */ #define ZEROPAD 1 /* pad with zero */
@ -26,6 +29,73 @@
#define FLOATING_SUPPORT #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 static int
skip_atoi(const char **s) 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, "<FAULT>", 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 static char
sign_symbol(int flags, bool negative) sign_symbol(int flags, bool negative)
{ {
@ -148,7 +136,7 @@ sign_symbol(int flags, bool negative)
static void 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) int precision, int flags)
{ {
const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
@ -191,31 +179,31 @@ number(char **_string, int32 *_bytesLeft, uint64 num, uint32 base, int size,
size -= precision; size -= precision;
if (!(flags & (ZEROPAD + LEFT))) { if (!(flags & (ZEROPAD + LEFT))) {
put_padding(_string, _bytesLeft, size); outBuffer.PutPadding(size);
size = 0; size = 0;
} }
if (sign) if (sign)
put_character(_string, _bytesLeft, sign); outBuffer.PutCharacter(sign);
if ((flags & SPECIAL) != 0) { if ((flags & SPECIAL) != 0) {
if (base == 8) if (base == 8)
put_character(_string, _bytesLeft, '0'); outBuffer.PutCharacter('0');
else if (base == 16) { else if (base == 16) {
put_character(_string, _bytesLeft, '0'); outBuffer.PutCharacter('0');
put_character(_string, _bytesLeft, digits[33]); outBuffer.PutCharacter(digits[33]);
} }
} }
if (!(flags & LEFT)) { if (!(flags & LEFT)) {
while (size-- > 0) while (size-- > 0)
put_character(_string, _bytesLeft, c); outBuffer.PutCharacter(c);
} }
while (i < precision--) while (i < precision--)
put_character(_string, _bytesLeft, '0'); outBuffer.PutCharacter('0');
while (i-- > 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 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. It's just here for your convenience so that you can use it for debug output.
*/ */
static bool static void
floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, floating(Buffer& outBuffer, double value, int fieldWidth, int flags)
int flags)
{ {
char buffer[66]; char buffer[66];
uint64 fraction; uint64 fraction;
@ -259,29 +246,26 @@ floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth,
// put integer part // put integer part
if (integer == 0) if (integer == 0) {
buffer[length++] = '0'; buffer[length++] = '0';
else while (integer != 0) { } else {
while (integer != 0)
buffer[length++] = '0' + do_div(&integer, 10); buffer[length++] = '0' + do_div(&integer, 10);
} }
// write back to string // write back to string
if (!(flags & LEFT) && !put_padding(_string, _bytesLeft, fieldWidth)) if (!(flags & LEFT))
return false; outBuffer.PutPadding(fieldWidth);
if (sign && !put_character(_string, _bytesLeft, sign)) if (sign)
return false; outBuffer.PutCharacter(sign);
while (length-- > 0) { while (length-- > 0)
if (!put_character(_string, _bytesLeft, buffer[length])) outBuffer.PutCharacter(buffer[length]);
return false;
}
if ((flags & LEFT) != 0 && !put_padding(_string, _bytesLeft, fieldWidth)) if ((flags & LEFT) != 0)
return false; outBuffer.PutPadding(fieldWidth);
return true;
} }
#endif // FLOATING_SUPPORT #endif // FLOATING_SUPPORT
@ -289,28 +273,19 @@ floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth,
int int
vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
{ {
int32 bytesLeft;
uint64 num; uint64 num;
int base; int base;
char *string;
int flags; /* flags to number() */ int flags; /* flags to number() */
int fieldWidth; /* width of output field */ int fieldWidth; /* width of output field */
int precision; int precision;
/* min. # of digits for integers; max number of chars for from string */ /* min. # of digits for integers; max number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */ int qualifier; /* 'h', 'l', or 'L' for integer fields */
if (bufferSize == 0) Buffer outBuffer(buffer, bufferSize);
return 0;
bytesLeft = ((int32)bufferSize - 1) & 0x7fffffff; for (; format[0]; format++) {
// make space for the terminating '\0' byte, and we
// only allow 2G characters :)
for (string = buffer; format[0] && bytesLeft > 0; format++) {
if (format[0] != '%') { if (format[0] != '%') {
if (!put_character(&string, &bytesLeft, format[0])) outBuffer.PutCharacter(format[0]);
break;
continue; continue;
} }
@ -329,8 +304,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
case '0': flags |= ZEROPAD; goto repeat; case '0': flags |= ZEROPAD; goto repeat;
case '%': case '%':
if (!put_character(&string, &bytesLeft, format[0])) outBuffer.PutCharacter(format[0]);
break;
continue; continue;
} }
@ -384,15 +358,13 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
switch (format[0]) { switch (format[0]) {
case 'c': case 'c':
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, if (!(flags & LEFT))
fieldWidth - 1)) outBuffer.PutPadding(fieldWidth - 1);
goto out;
put_character(&string, &bytesLeft, (char)va_arg(args, int)); outBuffer.PutCharacter((char)va_arg(args, int));
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, if ((flags & LEFT) != 0)
fieldWidth - 1)) outBuffer.PutPadding(fieldWidth - 1);
goto out;
continue; continue;
case 's': case 's':
@ -406,16 +378,13 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
length = strnlen(argument, precision); length = strnlen(argument, precision);
fieldWidth -= length; fieldWidth -= length;
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, if (!(flags & LEFT))
fieldWidth)) outBuffer.PutPadding(fieldWidth);
goto out;
if (!put_string(&string, &bytesLeft, argument, length)) outBuffer.PutString(argument, length);
goto out;
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, if ((flags & LEFT) != 0)
fieldWidth)) outBuffer.PutPadding(fieldWidth);
goto out;
continue; continue;
} }
@ -426,9 +395,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
case 'G': case 'G':
{ {
double value = va_arg(args, double); double value = va_arg(args, double);
if (!floating(&string, &bytesLeft, value, fieldWidth, floating(outBuffer, value, fieldWidth, flags | SIGN);
flags | SIGN))
goto out;
continue; continue;
} }
#endif // FLOATING_SUPPORT #endif // FLOATING_SUPPORT
@ -439,19 +406,18 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
flags |= ZEROPAD; flags |= ZEROPAD;
} }
if (!put_string(&string, &bytesLeft, "0x", 2)) outBuffer.PutString("0x", 2);
goto out; number(outBuffer, (uint32)va_arg(args, void *), 16, fieldWidth,
number(&string, &bytesLeft, (uint32)va_arg(args, void *), 16, precision, flags);
fieldWidth, precision, flags);
continue; continue;
case 'n': case 'n':
if (qualifier == 'l') { if (qualifier == 'l') {
long *ip = va_arg(args, long *); long *ip = va_arg(args, long *);
*ip = (string - buffer); *ip = outBuffer.BytesWritten();
} else { } else {
int *ip = va_arg(args, int *); int *ip = va_arg(args, int *);
*ip = (string - buffer); *ip = outBuffer.BytesWritten();
} }
continue; continue;
@ -474,12 +440,12 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
default: default:
if (format[0] != '%') if (format[0] != '%')
put_character(&string, &bytesLeft, '%'); outBuffer.PutCharacter('%');
if (!format[0]) if (!format[0])
goto out; goto out;
put_character(&string, &bytesLeft, format[0]); outBuffer.PutCharacter(format[0]);
continue; continue;
} }
@ -498,12 +464,12 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
else else
num = va_arg(args, unsigned int); num = va_arg(args, unsigned int);
number(&string, &bytesLeft, num, base, fieldWidth, precision, flags); number(outBuffer, num, base, fieldWidth, precision, flags);
} }
out: out:
*string = '\0'; outBuffer.NullTerminate();
return string - buffer; return outBuffer.BytesWritten();
} }