cprintf: support a configurable width and precision ("*" in printf)

This commit is contained in:
Nathan Binkert 2008-12-03 04:57:54 -08:00
parent 47e2b08893
commit 74f10be526
4 changed files with 57 additions and 8 deletions

View file

@ -40,7 +40,7 @@ using namespace std;
namespace cp { namespace cp {
Print::Print(std::ostream &stream, const std::string &format) Print::Print(std::ostream &stream, const std::string &format)
: stream(stream), format(format.c_str()), ptr(format.c_str()) : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false)
{ {
saved_flags = stream.flags(); saved_flags = stream.flags();
saved_fill = stream.fill(); saved_fill = stream.fill();
@ -48,7 +48,7 @@ Print::Print(std::ostream &stream, const std::string &format)
} }
Print::Print(std::ostream &stream, const char *format) Print::Print(std::ostream &stream, const char *format)
: stream(stream), format(format), ptr(format) : stream(stream), format(format), ptr(format), cont(false)
{ {
saved_flags = stream.flags(); saved_flags = stream.flags();
saved_fill = stream.fill(); saved_fill = stream.fill();
@ -60,8 +60,10 @@ Print::~Print()
} }
void void
Print::process(Format &fmt) Print::process()
{ {
fmt.clear();
size_t len; size_t len;
while (*ptr) { while (*ptr) {
@ -221,8 +223,15 @@ Print::process(Format &fmt)
number = number * 10 + (*ptr - '0'); number = number * 10 + (*ptr - '0');
break; break;
case '*':
if (have_precision)
fmt.get_precision = true;
else
fmt.get_width = true;
break;
case '%': case '%':
assert("we shouldn't get here"); assert(false && "we shouldn't get here");
break; break;
default: default:

View file

@ -51,24 +51,53 @@ struct Print
std::ostream &stream; std::ostream &stream;
const char *format; const char *format;
const char *ptr; const char *ptr;
bool cont;
std::ios::fmtflags saved_flags; std::ios::fmtflags saved_flags;
char saved_fill; char saved_fill;
int saved_precision; int saved_precision;
void process(Format &fmt); Format fmt;
void process();
public: public:
Print(std::ostream &stream, const std::string &format); Print(std::ostream &stream, const std::string &format);
Print(std::ostream &stream, const char *format); Print(std::ostream &stream, const char *format);
~Print(); ~Print();
int
get_number(int data)
{
return data;
}
template <typename T>
int
get_number(const T& data)
{
return 0;
}
template <typename T> template <typename T>
void void
add_arg(const T &data) add_arg(const T &data)
{ {
Format fmt; if (!cont)
process(fmt); process();
if (fmt.get_width) {
fmt.get_width = false;
cont = true;
fmt.width = get_number(data);
return;
}
if (fmt.get_precision) {
fmt.get_precision = false;
cont = true;
fmt.precision = get_number(data);
return;
}
switch (fmt.format) { switch (fmt.format) {
case Format::character: case Format::character:

View file

@ -50,6 +50,8 @@ struct Format
enum { best, fixed, scientific } float_format; enum { best, fixed, scientific } float_format;
int precision; int precision;
int width; int width;
bool get_precision;
bool get_width;
Format() { clear(); } Format() { clear(); }
@ -65,6 +67,8 @@ struct Format
format = none; format = none;
precision = -1; precision = -1;
width = 0; width = 0;
get_precision = false;
get_width = false;
} }
}; };

View file

@ -167,6 +167,13 @@ main()
cprintf("%c %c\n", 'c', 65); cprintf("%c %c\n", 'c', 65);
cout << '9'; cout << '9' << endl;
cout << endl;
cprintf("%08.4f\n", 99.99);
cprintf("%0*.*f\n", 8, 4, 99.99);
cprintf("%07.*f\n", 4, 1.234);
cprintf("%#0*x\n", 9, 123412);
return 0; return 0;
} }