Update Console::printFormat to new style
This commit is contained in:
parent
d2d7fac4df
commit
b3d47319a9
1 changed files with 105 additions and 96 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue