Switch format.h to use Result

This commit is contained in:
apio 2022-11-19 16:13:25 +01:00
parent 31673c0ac9
commit 648bd3fb61
5 changed files with 49 additions and 58 deletions

View File

@ -19,18 +19,18 @@ namespace Serial
putchar('\n'); putchar('\n');
} }
int printf(const char* format, ...) Result<usize> printf(const char* format, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
isize rc = cstyle_format( auto rc = cstyle_format(
format, format,
[](char c, void*) -> int { [](char c, void*) -> Result<void> {
putchar(c); putchar(c);
return 0; return {};
}, },
nullptr, ap); nullptr, ap);
va_end(ap); va_end(ap);
return (int)rc; return rc;
} }
} }

View File

@ -1,12 +1,14 @@
#pragma once #pragma once
#include <Format.h> #include <FormatAttribute.h>
#include <Types.h> #include <Types.h>
template <typename T> class Result;
namespace Serial namespace Serial
{ {
void putchar(u8 c); void putchar(u8 c);
void write(const char* str, usize size); void write(const char* str, usize size);
void print(const char* str); void print(const char* str);
void println(const char* str); void println(const char* str);
int printf(const char* str, ...) _format(1, 2); Result<usize> printf(const char* str, ...) _format(1, 2);
} }

View File

@ -29,55 +29,43 @@ struct conv_state
usize precision; usize precision;
}; };
static inline int cstyle_format_putchar(char c, format_state& state) static Result<void> format_putchar(char c, format_state& state)
{ {
state.count++; state.count++;
return state.callback(c, state.arg); return state.callback(c, state.arg);
} }
static inline int cstyle_format_puts(const char* s, format_state& state) static Result<void> format_puts(const char* s, format_state& state)
{ {
while (*s) while (*s)
{ {
if (cstyle_format_putchar(*s, state)) return -1; TRY(format_putchar(*s, state));
s++; s++;
} }
return 0; return {};
} }
#define TRY_PUTCHAR(c, state) \ static Result<void> start_pad(const conv_state& vstate, format_state& state, usize start)
if (cstyle_format_putchar(c, state)) return -1;
#define TRY_PUTS(s, state) \
if (cstyle_format_puts(s, state)) return -1;
static int start_pad(const conv_state& vstate, format_state& state, usize start)
{ {
if (!(vstate.flags & FLAG_LEFT_ALIGN)) if (!(vstate.flags & FLAG_LEFT_ALIGN))
{ {
while (start++ < vstate.width) TRY_PUTCHAR(' ', state); while (start++ < vstate.width) TRY(format_putchar(' ', state));
} }
return 0; return {};
} }
#define TRY_START_PAD(vstate, state, start) \ static Result<void> end_pad(const conv_state& vstate, format_state& state, usize start)
if (start_pad(vstate, state, start)) return -1;
static int end_pad(const conv_state& vstate, format_state& state, usize start)
{ {
if (vstate.flags & FLAG_LEFT_ALIGN) if (vstate.flags & FLAG_LEFT_ALIGN)
{ {
while (start++ < vstate.width) TRY_PUTCHAR(' ', state); while (start++ < vstate.width) TRY(format_putchar(' ', state));
} }
return 0; return {};
} }
#define TRY_END_PAD(vstate, state, start) \
if (end_pad(vstate, state, start)) return -1;
static flags_t parse_flags(const char** format) static flags_t parse_flags(const char** format)
{ {
flags_t result = 0; flags_t result = 0;
@ -210,7 +198,7 @@ static usize to_string(usize value, usize base, char* buf, usize max, bool upper
return i; return i;
} }
static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) static Result<void> output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative)
{ {
usize base = 10; usize base = 10;
bool uppercase = false; bool uppercase = false;
@ -267,18 +255,18 @@ static int output_integer(char specifier, conv_state& vstate, format_state& stat
buf[buflen++] = ' '; buf[buflen++] = ' ';
} }
if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); if (!(vstate.flags & FLAG_ZERO_PAD)) TRY(start_pad(vstate, state, buflen));
usize i = buflen; usize i = buflen;
while (i--) TRY_PUTCHAR(buf[i], state); while (i--) TRY(format_putchar(buf[i], state));
TRY_END_PAD(vstate, state, buflen); TRY(end_pad(vstate, state, buflen));
return 0; return {};
} }
static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) static Result<void> va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap)
{ {
bool is_signed = false; bool is_signed = false;
bool negative = false; bool negative = false;
@ -379,7 +367,7 @@ static int va_output_integer(char specifier, conv_state& vstate, format_state& s
} }
} }
isize 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;
state.callback = callback; state.callback = callback;
@ -390,7 +378,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
{ {
if (*format != '%') if (*format != '%')
{ {
TRY_PUTCHAR(*format, state); TRY(format_putchar(*format, state));
format++; format++;
continue; continue;
} }
@ -399,7 +387,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
if (*format == '%') if (*format == '%')
{ {
TRY_PUTCHAR('%', state); TRY(format_putchar('%', state));
continue; continue;
} }
@ -417,7 +405,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
if (is_integer_format_specifier(specifier)) if (is_integer_format_specifier(specifier))
{ {
if (va_output_integer(specifier, vstate, state, ap)) return -1; TRY(va_output_integer(specifier, vstate, state, ap));
continue; continue;
} }
else if (specifier == 'p') else if (specifier == 'p')
@ -425,23 +413,23 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
void* ptr = va_arg(ap, void*); void* ptr = va_arg(ap, void*);
if (ptr == nullptr) if (ptr == nullptr)
{ {
TRY_START_PAD(vstate, state, 5); TRY(start_pad(vstate, state, 5));
TRY_PUTS("(nil)", state); TRY(format_puts("(nil)", state));
TRY_END_PAD(vstate, state, 5); TRY(end_pad(vstate, state, 5));
continue; continue;
} }
vstate.width = (sizeof(void*) * 2) + 2; vstate.width = (sizeof(void*) * 2) + 2;
vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE); vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE);
if (output_integer('p', vstate, state, (usize)ptr, false)) return -1; TRY(output_integer('p', vstate, state, (usize)ptr, false));
continue; continue;
} }
else if (specifier == 'c') else if (specifier == 'c')
{ {
const char c = (char)va_arg(ap, int); const char c = (char)va_arg(ap, int);
TRY_START_PAD(vstate, state, 1); TRY(start_pad(vstate, state, 1));
TRY_PUTCHAR(c, state); TRY(format_putchar(c, state));
TRY_END_PAD(vstate, state, 1); TRY(end_pad(vstate, state, 1));
continue; continue;
} }
@ -450,9 +438,9 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
const char* str = va_arg(ap, const char*); const char* str = va_arg(ap, const char*);
if (str == nullptr) if (str == nullptr)
{ {
TRY_START_PAD(vstate, state, 6); TRY(start_pad(vstate, state, 6));
TRY_PUTS("(null)", state); TRY(format_puts("(null)", state));
TRY_END_PAD(vstate, state, 6); TRY(end_pad(vstate, state, 6));
continue; continue;
} }
else else
@ -462,19 +450,19 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
bool use_precision = (flags & FLAG_USE_PRECISION); bool use_precision = (flags & FLAG_USE_PRECISION);
if (use_precision && len > precision) len = precision; if (use_precision && len > precision) len = precision;
TRY_START_PAD(vstate, state, len); TRY(start_pad(vstate, state, len));
while (*str && (!use_precision || precision)) while (*str && (!use_precision || precision))
{ {
TRY_PUTCHAR(*str, state); TRY(format_putchar(*str, state));
precision--; precision--;
str++; str++;
} }
TRY_END_PAD(vstate, state, len); TRY(end_pad(vstate, state, len));
continue; continue;
} }
} }
else { continue; } else { continue; }
} }
return (isize)state.count; return state.count;
} }

View File

@ -1,10 +1,9 @@
#pragma once #pragma once
#include <CType.h> #include <CType.h>
#include <Types.h> #include <FormatAttribute.h>
#include <Result.h>
#include <stdarg.h> #include <stdarg.h>
#define _format(n, m) __attribute__((format(printf, n, m))) typedef Result<void> (*callback_t)(char, void*);
typedef int (*callback_t)(char, void*); Result<usize> cstyle_format(const char* format, callback_t callback, void* arg, va_list ap);
isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap);

2
luna/FormatAttribute.h Normal file
View File

@ -0,0 +1,2 @@
#pragma once
#define _format(n, m) __attribute__((format(printf, n, m)))