Switch format.h to use Result
This commit is contained in:
parent
31673c0ac9
commit
648bd3fb61
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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
2
luna/FormatAttribute.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#define _format(n, m) __attribute__((format(printf, n, m)))
|
Loading…
Reference in New Issue
Block a user