luna: Remove pure_cstyle_format
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
It was causing a lot of code duplication. If someone doesn't have errors, just return {} from the callback and unwrap the Result.
This commit is contained in:
parent
a595a77421
commit
de38eb6877
@ -38,8 +38,14 @@ static void log_serial(LogLevel level, const char* format, va_list origin)
|
|||||||
Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000));
|
Serial::printf("%4zu.%.3zu ", Timer::ticks(), Timer::ticks_ms() - (Timer::ticks() * 1000));
|
||||||
|
|
||||||
// NOTE: We do this manually because of a lack of vprintf() in both Serial and TextConsole.
|
// NOTE: We do this manually because of a lack of vprintf() in both Serial and TextConsole.
|
||||||
pure_cstyle_format(
|
cstyle_format(
|
||||||
format, [](char c, void*) { Serial::putchar((u8)c); }, nullptr, ap);
|
format,
|
||||||
|
[](char c, void*) -> Result<void> {
|
||||||
|
Serial::putchar((u8)c);
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
nullptr, ap)
|
||||||
|
.value();
|
||||||
|
|
||||||
Serial::putchar('\n');
|
Serial::putchar('\n');
|
||||||
|
|
||||||
|
@ -25,8 +25,14 @@ namespace Serial
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
auto rc = pure_cstyle_format(
|
auto rc = cstyle_format(
|
||||||
format, [](char c, void*) { putchar((u8)c); }, nullptr, ap);
|
format,
|
||||||
|
[](char c, void*) -> Result<void> {
|
||||||
|
putchar((u8)c);
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
nullptr, ap)
|
||||||
|
.value();
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,14 @@ extern "C"
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
|
|
||||||
int rc = (int)pure_cstyle_format(
|
int rc = (int)cstyle_format(
|
||||||
format, [](char c, void*) { console_write(&c, 1); }, nullptr, ap);
|
format,
|
||||||
|
[](char c, void*) -> Result<void> {
|
||||||
|
console_write(&c, 1);
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
nullptr, ap)
|
||||||
|
.value();
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
@ -82,7 +88,13 @@ extern "C"
|
|||||||
|
|
||||||
void debug_log_impl(const char* format, va_list ap)
|
void debug_log_impl(const char* format, va_list ap)
|
||||||
{
|
{
|
||||||
pure_cstyle_format(
|
cstyle_format(
|
||||||
format, [](char c, void*) { console_write(&c, 1); }, nullptr, ap);
|
format,
|
||||||
|
[](char c, void*) -> Result<void> {
|
||||||
|
console_write(&c, 1);
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
nullptr, ap)
|
||||||
|
.value();
|
||||||
console_write("\n", 1);
|
console_write("\n", 1);
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,10 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
typedef Result<void> (*callback_t)(char, void*);
|
typedef Result<void> (*callback_t)(char, void*);
|
||||||
typedef void (*pure_callback_t)(char, void*);
|
|
||||||
|
|
||||||
// Used to format anything that can fail (writing to C FILEs, etc...)
|
// Used to format anything that can fail (writing to C FILEs, etc...)
|
||||||
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap);
|
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap);
|
||||||
|
|
||||||
// Used to format anything that cannot fail (formatting to a string, writing to the serial port (kernel-only))
|
|
||||||
usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg, va_list ap);
|
|
||||||
|
|
||||||
// Convenience function which outputs into a fixed-size buffer (not unlike vsnprintf)
|
// Convenience function which outputs into a fixed-size buffer (not unlike vsnprintf)
|
||||||
usize vstring_format(char* buf, usize max, const char* format, va_list ap);
|
usize vstring_format(char* buf, usize max, const char* format, va_list ap);
|
||||||
|
|
||||||
|
@ -26,13 +26,6 @@ struct format_state
|
|||||||
void* arg;
|
void* arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pure_format_state
|
|
||||||
{
|
|
||||||
usize count;
|
|
||||||
pure_callback_t callback;
|
|
||||||
void* arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct conv_state
|
struct conv_state
|
||||||
{
|
{
|
||||||
flags_t flags;
|
flags_t flags;
|
||||||
@ -46,12 +39,6 @@ static Result<void> format_putchar(char c, format_state& state)
|
|||||||
return state.callback(c, state.arg);
|
return state.callback(c, state.arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pure_format_putchar(char c, pure_format_state& state)
|
|
||||||
{
|
|
||||||
state.count++;
|
|
||||||
return state.callback(c, state.arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<void> format_puts(const char* s, format_state& state)
|
static Result<void> format_puts(const char* s, format_state& state)
|
||||||
{
|
{
|
||||||
while (*s)
|
while (*s)
|
||||||
@ -63,15 +50,6 @@ static Result<void> format_puts(const char* s, format_state& state)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pure_format_puts(const char* s, pure_format_state& state)
|
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
{
|
|
||||||
pure_format_putchar(*s, state);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<void> start_pad(const conv_state& vstate, format_state& state, usize start)
|
static Result<void> start_pad(const conv_state& vstate, format_state& state, usize start)
|
||||||
{
|
{
|
||||||
if (!(vstate.flags & FLAG_LEFT_ALIGN))
|
if (!(vstate.flags & FLAG_LEFT_ALIGN))
|
||||||
@ -82,14 +60,6 @@ static Result<void> start_pad(const conv_state& vstate, format_state& state, usi
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pure_start_pad(const conv_state& vstate, pure_format_state& state, usize start)
|
|
||||||
{
|
|
||||||
if (!(vstate.flags & FLAG_LEFT_ALIGN))
|
|
||||||
{
|
|
||||||
while (start++ < vstate.width) pure_format_putchar(' ', state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<void> end_pad(const conv_state& vstate, format_state& state, usize start)
|
static Result<void> end_pad(const conv_state& vstate, format_state& state, usize start)
|
||||||
{
|
{
|
||||||
if (vstate.flags & FLAG_LEFT_ALIGN)
|
if (vstate.flags & FLAG_LEFT_ALIGN)
|
||||||
@ -100,14 +70,6 @@ static Result<void> end_pad(const conv_state& vstate, format_state& state, usize
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pure_end_pad(const conv_state& vstate, pure_format_state& state, usize start)
|
|
||||||
{
|
|
||||||
if (vstate.flags & FLAG_LEFT_ALIGN)
|
|
||||||
{
|
|
||||||
while (start++ < vstate.width) pure_format_putchar(' ', state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static flags_t parse_flags(const char** format)
|
static flags_t parse_flags(const char** format)
|
||||||
{
|
{
|
||||||
flags_t result = 0;
|
flags_t result = 0;
|
||||||
@ -254,21 +216,7 @@ static Result<void> output_integer_data(const conv_state& vstate, format_state&
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_pure_integer_data(const conv_state& vstate, pure_format_state& state, char* buf, usize len)
|
static Result<void> output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative)
|
||||||
{
|
|
||||||
if (!(vstate.flags & FLAG_ZERO_PAD)) pure_start_pad(vstate, state, len);
|
|
||||||
|
|
||||||
usize i = len;
|
|
||||||
|
|
||||||
while (i--) pure_format_putchar(buf[i], state);
|
|
||||||
|
|
||||||
pure_end_pad(vstate, state, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ReturnType, typename FormatStateType>
|
|
||||||
static ReturnType output_integer_generic(char specifier, conv_state& vstate, FormatStateType& state, usize value,
|
|
||||||
bool negative,
|
|
||||||
ReturnType (*output_data)(const conv_state&, FormatStateType&, char*, usize))
|
|
||||||
{
|
{
|
||||||
usize base = 10;
|
usize base = 10;
|
||||||
bool uppercase = false;
|
bool uppercase = false;
|
||||||
@ -325,27 +273,10 @@ static ReturnType output_integer_generic(char specifier, conv_state& vstate, For
|
|||||||
buf[buflen++] = ' ';
|
buf[buflen++] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return output_data(vstate, state, buf, buflen);
|
return output_integer_data(vstate, state, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<void> output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative)
|
static Result<void> va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap)
|
||||||
{
|
|
||||||
return output_integer_generic<Result<void>, format_state>(specifier, vstate, state, value, negative,
|
|
||||||
output_integer_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pure_output_integer(char specifier, conv_state& vstate, pure_format_state& state, usize value,
|
|
||||||
bool negative)
|
|
||||||
{
|
|
||||||
return output_integer_generic<void, pure_format_state>(specifier, vstate, state, value, negative,
|
|
||||||
output_pure_integer_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ReturnType, typename FormatStateType>
|
|
||||||
static ReturnType va_generic_output_integer(char specifier, conv_state& vstate, FormatStateType& state,
|
|
||||||
ReturnType (*integer_output)(char, conv_state&, FormatStateType&, usize,
|
|
||||||
bool),
|
|
||||||
va_list ap)
|
|
||||||
{
|
{
|
||||||
bool is_signed = false;
|
bool is_signed = false;
|
||||||
bool negative = false;
|
bool negative = false;
|
||||||
@ -364,12 +295,12 @@ static ReturnType va_generic_output_integer(char specifier, conv_state& vstate,
|
|||||||
v = -v;
|
v = -v;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
return integer_output(specifier, vstate, state, (unsigned char)v, negative);
|
return output_integer(specifier, vstate, state, (unsigned char)v, negative);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const unsigned char v = (unsigned char)va_arg(ap, unsigned int);
|
const unsigned char v = (unsigned char)va_arg(ap, unsigned int);
|
||||||
return integer_output(specifier, vstate, state, v, false);
|
return output_integer(specifier, vstate, state, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vstate.flags & FLAG_SHORT)
|
else if (vstate.flags & FLAG_SHORT)
|
||||||
@ -382,12 +313,12 @@ static ReturnType va_generic_output_integer(char specifier, conv_state& vstate,
|
|||||||
v = -v;
|
v = -v;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
return integer_output(specifier, vstate, state, (unsigned short)v, negative);
|
return output_integer(specifier, vstate, state, (unsigned short)v, negative);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const unsigned short v = (unsigned short)va_arg(ap, unsigned int);
|
const unsigned short v = (unsigned short)va_arg(ap, unsigned int);
|
||||||
return integer_output(specifier, vstate, state, v, false);
|
return output_integer(specifier, vstate, state, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vstate.flags & FLAG_LONG_LONG)
|
else if (vstate.flags & FLAG_LONG_LONG)
|
||||||
@ -400,12 +331,12 @@ static ReturnType va_generic_output_integer(char specifier, conv_state& vstate,
|
|||||||
v = -v;
|
v = -v;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
return integer_output(specifier, vstate, state, (unsigned long long)v, negative);
|
return output_integer(specifier, vstate, state, (unsigned long long)v, negative);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const unsigned long long v = va_arg(ap, unsigned long long);
|
const unsigned long long v = va_arg(ap, unsigned long long);
|
||||||
return integer_output(specifier, vstate, state, v, false);
|
return output_integer(specifier, vstate, state, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vstate.flags & FLAG_LONG)
|
else if (vstate.flags & FLAG_LONG)
|
||||||
@ -418,12 +349,12 @@ static ReturnType va_generic_output_integer(char specifier, conv_state& vstate,
|
|||||||
v = -v;
|
v = -v;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
return integer_output(specifier, vstate, state, (unsigned long)v, negative);
|
return output_integer(specifier, vstate, state, (unsigned long)v, negative);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const unsigned long v = va_arg(ap, unsigned long);
|
const unsigned long v = va_arg(ap, unsigned long);
|
||||||
return integer_output(specifier, vstate, state, v, false);
|
return output_integer(specifier, vstate, state, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -436,26 +367,16 @@ static ReturnType va_generic_output_integer(char specifier, conv_state& vstate,
|
|||||||
v = -v;
|
v = -v;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
return integer_output(specifier, vstate, state, (unsigned int)v, negative);
|
return output_integer(specifier, vstate, state, (unsigned int)v, negative);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const unsigned int v = va_arg(ap, unsigned int);
|
const unsigned int v = va_arg(ap, unsigned int);
|
||||||
return integer_output(specifier, vstate, state, v, false);
|
return output_integer(specifier, vstate, state, v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<void> va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap)
|
|
||||||
{
|
|
||||||
return va_generic_output_integer<Result<void>, format_state>(specifier, vstate, state, output_integer, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void va_pure_output_integer(char specifier, conv_state& vstate, pure_format_state& state, va_list ap)
|
|
||||||
{
|
|
||||||
return va_generic_output_integer<void, pure_format_state>(specifier, vstate, state, pure_output_integer, ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap)
|
Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap)
|
||||||
{
|
{
|
||||||
format_state state;
|
format_state state;
|
||||||
@ -557,106 +478,6 @@ Result<usize> cstyle_format(const char* format, callback_t callback, void* arg,
|
|||||||
return state.count;
|
return state.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize pure_cstyle_format(const char* format, pure_callback_t callback, void* arg, va_list ap)
|
|
||||||
{
|
|
||||||
pure_format_state state;
|
|
||||||
state.callback = callback;
|
|
||||||
state.arg = arg;
|
|
||||||
state.count = 0;
|
|
||||||
|
|
||||||
while (*format)
|
|
||||||
{
|
|
||||||
if (*format != '%')
|
|
||||||
{
|
|
||||||
pure_format_putchar(*format, state);
|
|
||||||
format++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
format++;
|
|
||||||
|
|
||||||
if (*format == '%')
|
|
||||||
{
|
|
||||||
pure_format_putchar('%', state);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// %[flags][width][.precision][length]conversion
|
|
||||||
|
|
||||||
flags_t flags = parse_flags(&format);
|
|
||||||
const usize width = parse_width(&format, flags, ap);
|
|
||||||
usize precision = parse_precision(&format, flags, ap);
|
|
||||||
parse_length(&format, flags);
|
|
||||||
|
|
||||||
conv_state vstate = { flags, width, precision };
|
|
||||||
|
|
||||||
const char specifier = *format;
|
|
||||||
format++;
|
|
||||||
|
|
||||||
if (is_integer_format_specifier(specifier))
|
|
||||||
{
|
|
||||||
va_pure_output_integer(specifier, vstate, state, ap);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (specifier == 'p')
|
|
||||||
{
|
|
||||||
const void* ptr = va_arg(ap, void*);
|
|
||||||
if (ptr == nullptr)
|
|
||||||
{
|
|
||||||
pure_start_pad(vstate, state, 5);
|
|
||||||
pure_format_puts("(nil)", state);
|
|
||||||
pure_end_pad(vstate, state, 5);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
vstate.width = (sizeof(void*) * 2) + 2;
|
|
||||||
vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE);
|
|
||||||
pure_output_integer('p', vstate, state, (usize)ptr, false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (specifier == 'c')
|
|
||||||
{
|
|
||||||
const char c = (char)va_arg(ap, int);
|
|
||||||
|
|
||||||
pure_start_pad(vstate, state, 1);
|
|
||||||
pure_format_putchar(c, state);
|
|
||||||
pure_end_pad(vstate, state, 1);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (specifier == 's')
|
|
||||||
{
|
|
||||||
const char* str = va_arg(ap, const char*);
|
|
||||||
if (str == nullptr)
|
|
||||||
{
|
|
||||||
pure_start_pad(vstate, state, 6);
|
|
||||||
pure_format_puts("(null)", state);
|
|
||||||
pure_end_pad(vstate, state, 6);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usize len = strlen(str);
|
|
||||||
|
|
||||||
bool use_precision = (flags & FLAG_USE_PRECISION);
|
|
||||||
if (use_precision && len > precision) len = precision;
|
|
||||||
|
|
||||||
pure_start_pad(vstate, state, len);
|
|
||||||
while (*str && (!use_precision || precision))
|
|
||||||
{
|
|
||||||
pure_format_putchar(*str, state);
|
|
||||||
precision--;
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
pure_end_pad(vstate, state, len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { continue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StringFormatInfo
|
struct StringFormatInfo
|
||||||
{
|
{
|
||||||
char* buffer;
|
char* buffer;
|
||||||
@ -667,17 +488,18 @@ usize vstring_format(char* buf, usize max, const char* format, va_list ap)
|
|||||||
{
|
{
|
||||||
StringFormatInfo info = { .buffer = buf, .remaining = max - 1 };
|
StringFormatInfo info = { .buffer = buf, .remaining = max - 1 };
|
||||||
|
|
||||||
usize result = pure_cstyle_format(
|
usize result = cstyle_format(
|
||||||
format,
|
format,
|
||||||
[](char c, void* arg) {
|
[](char c, void* arg) -> Result<void> {
|
||||||
StringFormatInfo* info_arg = (StringFormatInfo*)arg;
|
StringFormatInfo* info_arg = (StringFormatInfo*)arg;
|
||||||
if (!info_arg->remaining) return;
|
if (!info_arg->remaining) return {};
|
||||||
*(info_arg->buffer) = c;
|
*(info_arg->buffer) = c;
|
||||||
info_arg->buffer++;
|
info_arg->buffer++;
|
||||||
info_arg->remaining--;
|
info_arg->remaining--;
|
||||||
return;
|
return {};
|
||||||
},
|
},
|
||||||
&info, ap);
|
&info, ap)
|
||||||
|
.value();
|
||||||
|
|
||||||
*(info.buffer) = 0;
|
*(info.buffer) = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user