diff --git a/luna/Format.h b/luna/Format.h index c683d882..b2b47506 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -217,14 +217,12 @@ template static usize to_string(T value, T base, char* buf, usize m return i; } -static int output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +template +static int output_integer(char specifier, const conv_state& vstate, format_state& state, T value, bool negative) { usize base = 10; - bool is_signed = false; bool uppercase = false; - bool negative = false; - if (specifier == 'd' || specifier == 'i') is_signed = true; switch (specifier) { case 'x': @@ -236,97 +234,7 @@ static int output_integer(char specifier, const conv_state& vstate, format_state if (specifier == 'X') uppercase = true; char buf[1024]; - usize buflen; - if (vstate.flags & FLAG_CHAR) - { - if (is_signed) - { - char v = (char)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (char)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned char v = (unsigned char)va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned char)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_SHORT) - { - if (is_signed) - { - short v = (short)va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (short)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned short v = (unsigned short)va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned short)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_LONG_LONG) - { - if (is_signed) - { - long long v = va_arg(ap, long long); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (long long)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned long long v = va_arg(ap, unsigned long long); - buflen = to_string(v, (unsigned long long)base, buf, sizeof(buf), uppercase); - } - } - else if (vstate.flags & FLAG_LONG) - { - if (is_signed) - { - long v = va_arg(ap, long); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (long)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned long v = va_arg(ap, unsigned long); - buflen = to_string(v, (unsigned long)base, buf, sizeof(buf), uppercase); - } - } - else - { - if (is_signed) - { - int v = va_arg(ap, int); - if (v < 0) - { - v = -v; - negative = true; - } - buflen = to_string(v, (int)base, buf, sizeof(buf), uppercase); - } - else - { - unsigned int v = va_arg(ap, unsigned int); - buflen = to_string(v, (unsigned int)base, buf, sizeof(buf), uppercase); - } - } + usize buflen = to_string(value, (T)base, buf, sizeof(buf), uppercase); // FIXME: Start padding and alternate forms. @@ -348,6 +256,105 @@ static int output_integer(char specifier, const conv_state& vstate, format_state return 0; } +static int va_output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +{ + bool is_signed = false; + bool negative = false; + + if (specifier == 'd' || specifier == 'i') is_signed = true; + + if (vstate.flags & FLAG_CHAR) + { + if (is_signed) + { + char v = (char)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned char v = (unsigned char)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_SHORT) + { + if (is_signed) + { + short v = (short)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned short v = (unsigned short)va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG_LONG) + { + if (is_signed) + { + long long v = va_arg(ap, long long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long long v = va_arg(ap, unsigned long long); + return output_integer(specifier, vstate, state, v, false); + } + } + else if (vstate.flags & FLAG_LONG) + { + if (is_signed) + { + long v = va_arg(ap, long); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned long v = va_arg(ap, unsigned long); + return output_integer(specifier, vstate, state, v, false); + } + } + else + { + if (is_signed) + { + int v = va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + return output_integer(specifier, vstate, state, v, negative); + } + else + { + unsigned int v = va_arg(ap, unsigned int); + return output_integer(specifier, vstate, state, v, false); + } + } +} + #endif isize cstyle_format(const char* format, callback_t callback, void* arg, va_list ap) @@ -383,7 +390,7 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list if (is_integer_format_specifier(specifier)) { - if (output_integer(specifier, vstate, state, ap)) return -1; + if (va_output_integer(specifier, vstate, state, ap)) return -1; } else if (specifier == 'c') {