Update Console::printFormat to new style

This commit is contained in:
Eryn Wells 2016-03-20 12:56:28 -04:00
parent d2d7fac4df
commit b3d47319a9

View file

@ -10,48 +10,54 @@
#include "Console.hh" #include "Console.hh"
#include "kstd/ASCII.hh" #include "kstd/ASCII.hh"
#include "kstd/CString.hh" #include "kstd/CString.hh"
#include "kstd/Types.hh"
namespace { namespace {
void itoa(int value, char* buffer, int base); void itoa(int value, char* buffer, int base);
struct PrintfSpec struct Spec {
{ enum class Size {
enum Size { Normal,
SizeNormal, DoubleShort,
SizeDoubleShort, Short,
SizeShort, Long,
SizeLong, DoubleLong,
SizeDoubleLong,
}; };
enum Type { enum class Type {
TypeInt, Int,
TypeHex, Unsigned,
TypeChar, Hex,
TypeString Char,
String
}; };
union Value { bool zeroPadded;
int d; bool capitalized;
char hhd;
short int hd;
long int ld;
long long int lld;
unsigned int x;
unsigned char hhx;
unsigned short int hx;
unsigned long int lx;
unsigned long long int llx;
char c;
char* s;
};
bool zero;
int width; int width;
Size size; Size size;
Type type; Type type;
Value value;
union Value {
i8 hhd;
i16 hd;
i32 d;
i64 ld;
i64 lld;
u8 hhu;
u16 hu;
u32 u;
u64 lu;
u64 llu;
u8 hhx;
u16 hx;
u32 x;
u64 lx;
u64 llx;
char c;
char* s;
} value;
void clear(); void clear();
int print(kernel::Console& console); int print(kernel::Console& console);
@ -59,17 +65,19 @@ struct PrintfSpec
void void
PrintfSpec::clear() Spec::clear()
{ {
zero = false; zeroPadded = false;
capitalized = false;
width = 0; width = 0;
size = PrintfSpec::SizeNormal; size = Size::Normal;
type = PrintfSpec::TypeInt; type = Type::Int;
value.llx = 0;
} }
int int
PrintfSpec::print(kernel::Console& console) Spec::print(kernel::Console& console)
{ {
int nchars = 0; int nchars = 0;
int length = 0; int length = 0;
@ -81,7 +89,7 @@ PrintfSpec::print(kernel::Console& console)
* TypeChar is a special case because it will always be a single character * TypeChar is a special case because it will always be a single character
* in length and there is no \0 to terminate it. * in length and there is no \0 to terminate it.
*/ */
if (type == TypeChar) { if (type == Type::Char) {
if (width == 0) { if (width == 0) {
width = 1; width = 1;
} }
@ -92,53 +100,53 @@ PrintfSpec::print(kernel::Console& console)
return width; return width;
} }
if (type == TypeInt || type == TypeHex) { if (type == Type::Int || type == Type::Hex) {
if (zero) { if (zeroPadded) {
pad = '0'; pad = '0';
} }
if (type == TypeInt) { if (type == Type::Int) {
switch (size) { switch (size) {
case SizeNormal: case Size::Normal:
itoa(value.d, buf, 10); itoa(value.d, buf, 10);
break; break;
case SizeDoubleShort: case Size::DoubleShort:
itoa(value.hhd, buf, 10); itoa(value.hhd, buf, 10);
break; break;
case SizeShort: case Size::Short:
itoa(value.hd, buf, 10); itoa(value.hd, buf, 10);
break; break;
case SizeLong: case Size::Long:
itoa(value.ld, buf, 10); itoa(value.ld, buf, 10);
break; break;
case SizeDoubleLong: case Size::DoubleLong:
itoa(value.lld, buf, 10); itoa(value.lld, buf, 10);
break; break;
} }
} else { } else {
switch (size) { switch (size) {
case SizeNormal: case Size::Normal:
itoa(value.x, buf, 16); kstd::CString::fromUnsignedInteger(value.x, buf, 16, capitalized);
break; break;
case SizeDoubleShort: case Size::DoubleShort:
itoa(value.hhx, buf, 16); kstd::CString::fromUnsignedInteger(value.hhx, buf, 16, capitalized);
break; break;
case SizeShort: case Size::Short:
itoa(value.hx, buf, 16); kstd::CString::fromUnsignedInteger(value.hx, buf, 16, capitalized);
break; break;
case SizeLong: case Size::Long:
itoa(value.lx, buf, 16); kstd::CString::fromUnsignedLongInteger(value.lx, buf, 16, capitalized);
break; break;
case SizeDoubleLong: case Size::DoubleLong:
itoa(value.llx, buf, 16); kstd::CString::fromUnsignedLongInteger(value.llx, buf, 16, capitalized);
break; break;
} }
} }
length = kstd::CString::length(buf); length = kstd::CString::length(buf, 32);
if (width < length) { if (width < length) {
width = length; width = length;
} }
str = buf; str = buf;
} else if (type == TypeString) { } else if (type == Type::String) {
length = kstd::CString::length(value.s); length = kstd::CString::length(value.s);
if (width < length) { if (width < length) {
width = length; width = length;
@ -172,14 +180,15 @@ itoa(int value,
if (neg) { if (neg) {
value *= -1; value *= -1;
} }
unsigned int v = (unsigned int)value;
char* p = buffer; char* p = buffer;
int place; int place;
do { do {
place = value % base; place = v % base;
value /= base; v /= base;
*p++ = place < 10 ? place + '0' : (place - 10) + 'a'; *p++ = place < 10 ? place + '0' : (place - 10) + 'a';
} while (value != 0); } while (v != 0);
if (neg) { if (neg) {
*p++ = '-'; *p++ = '-';
@ -220,39 +229,39 @@ Console::printFormat(const char* fmt,
...) ...)
{ {
enum { enum {
StateDefault = 0, Default = 0,
StatePercent, Percent,
StateWidth, Width,
StateSize Size
} state = StateDefault; } state = Default;
va_list vl; va_list vl;
va_start(vl, fmt); va_start(vl, fmt);
int nchars = 0; int nchars = 0;
PrintfSpec spec; Spec spec;
for (const char* p = fmt; *p != 0; p++) { for (const char* p = fmt; *p != 0; p++) {
switch (state) { switch (state) {
case StateDefault: case Default:
if (*p == '%') { if (*p == '%') {
state = StatePercent; state = Percent;
spec.clear(); spec.clear();
} else { } else {
printChar(*p); printChar(*p);
nchars++; nchars++;
} }
break; break;
case StatePercent: case Percent:
if (*p == '%') { if (*p == '%') {
state = StateDefault; state = Default;
printChar(*p); printChar(*p);
nchars++; nchars++;
} else if (kstd::Char::isDigit(*p)) { } else if (kstd::Char::isDigit(*p)) {
if (*p == '0' && !spec.zero) { if (*p == '0' && !spec.zeroPadded) {
spec.zero = true; spec.zeroPadded = true;
} else { } else {
state = StateWidth; state = Width;
spec.width = *p - '0'; spec.width = *p - '0';
} }
} else if (is_size(*p)) { } else if (is_size(*p)) {
@ -261,17 +270,17 @@ Console::printFormat(const char* fmt,
goto state_specifier; goto state_specifier;
} }
break; break;
case StateWidth: case Width:
if (kstd::Char::isDigit(*p)) { if (kstd::Char::isDigit(*p)) {
spec.width = 10 * spec.width + (*p - '0'); spec.width = 10 * spec.width + (*p - '0');
} else if (is_size(*p)) { } else if (is_size(*p)) {
state = StateSize; state = Size;
goto state_size; goto state_size;
} else if (is_specifier(*p)) { } else if (is_specifier(*p)) {
goto state_specifier; goto state_specifier;
} }
break; break;
case StateSize: case Size:
if (is_size(*p)) { if (is_size(*p)) {
goto state_size; goto state_size;
} else if (is_specifier(*p)) { } else if (is_specifier(*p)) {
@ -287,68 +296,68 @@ Console::printFormat(const char* fmt,
state_size: state_size:
if (*p == 'h') { if (*p == 'h') {
spec.size = (spec.size == PrintfSpec::SizeShort) spec.size = (spec.size == Spec::Size::Short)
? PrintfSpec::SizeDoubleShort ? Spec::Size::DoubleShort
: PrintfSpec::SizeShort; : Spec::Size::Short;
} else if (*p == 'l') { } else if (*p == 'l') {
spec.size = (spec.size == PrintfSpec::SizeLong) spec.size = (spec.size == Spec::Size::Long)
? PrintfSpec::SizeDoubleLong ? Spec::Size::DoubleLong
: PrintfSpec::SizeLong; : Spec::Size::Long;
} }
continue; continue;
state_specifier: state_specifier:
state = StateDefault; state = Default;
switch (*p) { switch (*p) {
case 'd': case 'd':
case 'i': case 'i':
switch (spec.size) { switch (spec.size) {
case PrintfSpec::SizeNormal: case Spec::Size::Normal:
spec.value.d = va_arg(vl, int); spec.value.d = va_arg(vl, int);
break; break;
case PrintfSpec::SizeDoubleShort: case Spec::Size::DoubleShort:
spec.value.hhd = (signed char)va_arg(vl, int); spec.value.hhd = (signed char)va_arg(vl, int);
break; break;
case PrintfSpec::SizeShort: case Spec::Size::Short:
spec.value.hd = (short int)va_arg(vl, int); spec.value.hd = (short int)va_arg(vl, int);
break; break;
case PrintfSpec::SizeLong: case Spec::Size::Long:
spec.value.ld = va_arg(vl, long int); spec.value.ld = va_arg(vl, long int);
break; break;
case PrintfSpec::SizeDoubleLong: case Spec::Size::DoubleLong:
spec.value.lld = va_arg(vl, long long int); spec.value.lld = va_arg(vl, long long int);
break; break;
} }
spec.type = PrintfSpec::TypeInt; spec.type = Spec::Type::Int;
break; break;
case 'x': case 'x':
case 'X': case 'X':
switch (spec.size) { switch (spec.size) {
case PrintfSpec::SizeNormal: case Spec::Size::Normal:
spec.value.x = va_arg(vl, unsigned int); spec.value.x = va_arg(vl, unsigned int);
break; break;
case PrintfSpec::SizeDoubleShort: case Spec::Size::DoubleShort:
spec.value.hhx = (unsigned char)va_arg(vl, unsigned int); spec.value.hhx = (unsigned char)va_arg(vl, unsigned int);
break; break;
case PrintfSpec::SizeShort: case Spec::Size::Short:
spec.value.hx = (unsigned short int)va_arg(vl, unsigned int); spec.value.hx = (unsigned short int)va_arg(vl, unsigned int);
break; break;
case PrintfSpec::SizeLong: case Spec::Size::Long:
spec.value.lx = va_arg(vl, unsigned long int); spec.value.lx = va_arg(vl, unsigned long int);
break; break;
case PrintfSpec::SizeDoubleLong: case Spec::Size::DoubleLong:
spec.value.llx = va_arg(vl, unsigned long long int); spec.value.llx = va_arg(vl, unsigned long long int);
break; break;
} }
spec.type = PrintfSpec::TypeHex; spec.type = Spec::Type::Hex;
break; break;
case 'c': case 'c':
spec.value.c = va_arg(vl, int); spec.value.c = va_arg(vl, int);
spec.type = PrintfSpec::TypeChar; spec.type = Spec::Type::Char;
break; break;
case 's': case 's':
spec.value.s = va_arg(vl, char*); spec.value.s = va_arg(vl, char*);
spec.type = PrintfSpec::TypeString; spec.type = Spec::Type::String;
break; break;
} }
nchars += spec.print(*this); nchars += spec.print(*this);