forked from Bananymous/banan-os
LibC: fix bugs with printf
This commit is contained in:
parent
632b699475
commit
d82c6c2337
|
@ -26,17 +26,14 @@ struct format_options_t
|
||||||
};
|
};
|
||||||
|
|
||||||
template<BAN::integral T>
|
template<BAN::integral T>
|
||||||
static void integer_to_string(char* buffer, T value, int base, bool upper, const format_options_t options)
|
static void integer_to_string(char* buffer, T value, int base, bool upper, format_options_t options)
|
||||||
{
|
{
|
||||||
int width = 1;
|
int digits = 1;
|
||||||
bool zero_padded = options.zero_padded;
|
|
||||||
if (options.percision != -1)
|
if (options.percision != -1)
|
||||||
{
|
{
|
||||||
width = options.percision;
|
digits = options.percision;
|
||||||
zero_padded = false;
|
options.zero_padded = false;
|
||||||
}
|
}
|
||||||
else if (options.width != -1)
|
|
||||||
width = options.width;
|
|
||||||
|
|
||||||
auto digit_char = [](int digit, bool upper)
|
auto digit_char = [](int digit, bool upper)
|
||||||
{
|
{
|
||||||
|
@ -45,51 +42,57 @@ static void integer_to_string(char* buffer, T value, int base, bool upper, const
|
||||||
return (upper ? 'A' : 'a') + (digit - 10);
|
return (upper ? 'A' : 'a') + (digit - 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool sign = false;
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
|
int prefix_length = 0;
|
||||||
|
char prefix[2] {};
|
||||||
|
if constexpr(BAN::is_signed_v<T>)
|
||||||
|
{
|
||||||
|
prefix_length = 1;
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
{
|
{
|
||||||
sign = true;
|
prefix[0] = '-';
|
||||||
buffer[offset++] = digit_char(-(value % base), upper);
|
buffer[offset++] = digit_char(-(value % base), upper);
|
||||||
value = -(value / base);
|
value = -(value / base);
|
||||||
}
|
}
|
||||||
|
else if (options.show_plus_sign)
|
||||||
|
prefix[0] = '+';
|
||||||
|
else if (options.show_plus_sign_as_space)
|
||||||
|
prefix[0] = ' ';
|
||||||
|
else
|
||||||
|
prefix_length = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (options.alternate_form && base == 8)
|
||||||
|
{
|
||||||
|
prefix_length = 1;
|
||||||
|
prefix[0] = '0';
|
||||||
|
}
|
||||||
|
else if (options.alternate_form && base == 16)
|
||||||
|
{
|
||||||
|
prefix_length = 2;
|
||||||
|
prefix[0] = '0';
|
||||||
|
prefix[1] = 'x';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (value == 0 && width > 0)
|
while (value || offset < digits)
|
||||||
buffer[offset++] = '0';
|
|
||||||
|
|
||||||
while (value)
|
|
||||||
{
|
{
|
||||||
buffer[offset++] = digit_char(value % base, upper);
|
buffer[offset++] = digit_char(value % base, upper);
|
||||||
value /= base;
|
value /= base;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prefix_length = 0;
|
if (options.zero_padded)
|
||||||
|
|
||||||
if (sign || options.show_plus_sign || options.show_plus_sign_as_space)
|
|
||||||
prefix_length++;
|
|
||||||
if (base == 8 && options.alternate_form)
|
|
||||||
prefix_length++;
|
|
||||||
if (base == 16 && options.alternate_form)
|
|
||||||
prefix_length += 2;
|
|
||||||
|
|
||||||
while (offset < width - prefix_length)
|
|
||||||
buffer[offset++] = (zero_padded ? '0' : ' ');
|
|
||||||
|
|
||||||
if (sign)
|
|
||||||
buffer[offset++] = '-';
|
|
||||||
else if (options.show_plus_sign)
|
|
||||||
buffer[offset++] = '+';
|
|
||||||
else if (options.show_plus_sign_as_space)
|
|
||||||
buffer[offset++] = ' ';
|
|
||||||
|
|
||||||
if (base == 8 && options.alternate_form)
|
|
||||||
buffer[offset++] = '0';
|
|
||||||
if (base == 16 && options.alternate_form)
|
|
||||||
{
|
{
|
||||||
buffer[offset++] = 'x';
|
int zeroes = options.width - prefix_length;
|
||||||
|
for (int i = offset; i < zeroes; i++)
|
||||||
buffer[offset++] = '0';
|
buffer[offset++] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prefix[1]) buffer[offset++] = prefix[1];
|
||||||
|
if (prefix[0]) buffer[offset++] = prefix[0];
|
||||||
|
|
||||||
for (int i = 0; i < offset / 2; i++)
|
for (int i = 0; i < offset / 2; i++)
|
||||||
{
|
{
|
||||||
char temp = buffer[i];
|
char temp = buffer[i];
|
||||||
|
@ -273,6 +276,13 @@ extern "C" int printf_impl(const char* format, va_list arguments, int (*putc_fun
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (*format == '-')
|
||||||
|
{
|
||||||
|
percision = -1;
|
||||||
|
format++;
|
||||||
|
while (isdigit(*format))
|
||||||
|
format++;
|
||||||
|
}
|
||||||
else if (*format == '*')
|
else if (*format == '*')
|
||||||
{
|
{
|
||||||
percision = va_arg(arguments, int);
|
percision = va_arg(arguments, int);
|
||||||
|
|
|
@ -476,7 +476,6 @@ int vprintf(const char* format, va_list arguments)
|
||||||
// TODO
|
// TODO
|
||||||
int vscanf(const char*, va_list);
|
int vscanf(const char*, va_list);
|
||||||
|
|
||||||
// TODO
|
|
||||||
int vsnprintf(char* buffer, size_t max_size, const char* format, va_list arguments)
|
int vsnprintf(char* buffer, size_t max_size, const char* format, va_list arguments)
|
||||||
{
|
{
|
||||||
if (buffer == nullptr)
|
if (buffer == nullptr)
|
||||||
|
@ -489,34 +488,44 @@ int vsnprintf(char* buffer, size_t max_size, const char* format, va_list argumen
|
||||||
};
|
};
|
||||||
print_info info { buffer, max_size };
|
print_info info { buffer, max_size };
|
||||||
|
|
||||||
return printf_impl(format, arguments,
|
int ret = printf_impl(format, arguments,
|
||||||
[](int c, void* _info)
|
[](int c, void* _info)
|
||||||
{
|
{
|
||||||
print_info* info = (print_info*)_info;
|
print_info* info = (print_info*)_info;
|
||||||
if (info->remaining)
|
if (info->remaining == 1)
|
||||||
{
|
{
|
||||||
*info->buffer = (info->remaining == 1 ? '\0' : c);
|
*info->buffer = '\0';
|
||||||
|
info->remaining = 0;
|
||||||
|
}
|
||||||
|
else if (info->remaining)
|
||||||
|
{
|
||||||
|
*info->buffer = c;
|
||||||
info->buffer++;
|
info->buffer++;
|
||||||
info->remaining--;
|
info->remaining--;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}, &info
|
}, &info
|
||||||
);
|
);
|
||||||
|
|
||||||
|
*info.buffer = '\0';
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
int vsprintf(char* buffer, const char* format, va_list arguments)
|
int vsprintf(char* buffer, const char* format, va_list arguments)
|
||||||
{
|
{
|
||||||
if (buffer == nullptr)
|
if (buffer == nullptr)
|
||||||
return printf_impl(format, arguments, [](int, void*) { return 0; }, nullptr);
|
return printf_impl(format, arguments, [](int, void*) { return 0; }, nullptr);
|
||||||
|
|
||||||
return printf_impl(format, arguments,
|
int ret = printf_impl(format, arguments,
|
||||||
[](int c, void* _buffer)
|
[](int c, void* _buffer)
|
||||||
{
|
{
|
||||||
*(*(char**)_buffer)++ = c;
|
*(*(char**)_buffer)++ = c;
|
||||||
return 0;
|
return 0;
|
||||||
}, &buffer
|
}, &buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
*buffer = '\0';
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
Loading…
Reference in New Issue