Get rid of the gross operator,()/variadic macro hack
that made ccprintf and friends work, turn it into a normal function (though it still has a slightly strange implementation.) All instances of variadic macros are not yet removed, but I know how, and it will happen. One side effect of this new implementation is that a cprintf statement can now only have 16 parameters, though it's easy enough to raise this number if needed. --HG-- extra : convert_revision : 85cb3c17f8e2ecf9cd2f31ea80a760a28ea127a7
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* Copyright (c) 2002-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,142 +29,135 @@
|
||||
* Steve Reinhardt
|
||||
*/
|
||||
|
||||
#ifndef __CPRINTF_HH__
|
||||
#define __CPRINTF_HH__
|
||||
#ifndef __BASE_CPRINTF_HH__
|
||||
#define __BASE_CPRINTF_HH__
|
||||
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "base/varargs.hh"
|
||||
#include "base/cprintf_formats.hh"
|
||||
|
||||
namespace cp {
|
||||
|
||||
class ArgList
|
||||
#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print)
|
||||
#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print)
|
||||
|
||||
struct Print
|
||||
{
|
||||
private:
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
virtual ~Base() {}
|
||||
virtual void process(std::ostream &out, Format &fmt) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Node : public Base
|
||||
{
|
||||
public:
|
||||
const T &data;
|
||||
|
||||
public:
|
||||
Node(const T &d) : data(d) {}
|
||||
virtual void process(std::ostream &out, Format &fmt) {
|
||||
switch (fmt.format) {
|
||||
case Format::character:
|
||||
format_char(out, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::integer:
|
||||
format_integer(out, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::floating:
|
||||
format_float(out, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::string:
|
||||
format_string(out, data, fmt);
|
||||
break;
|
||||
|
||||
default:
|
||||
out << "<bad format>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::list<Base *> list_t;
|
||||
|
||||
protected:
|
||||
list_t objects;
|
||||
std::ostream *stream;
|
||||
std::ostream &stream;
|
||||
const char *format;
|
||||
const char *ptr;
|
||||
|
||||
std::ios::fmtflags saved_flags;
|
||||
char saved_fill;
|
||||
int saved_precision;
|
||||
|
||||
void process(Format &fmt);
|
||||
|
||||
public:
|
||||
ArgList() : stream(&std::cout) {}
|
||||
~ArgList();
|
||||
Print(std::ostream &stream, const std::string &format);
|
||||
Print(std::ostream &stream, const char *format);
|
||||
~Print();
|
||||
|
||||
template<class T>
|
||||
void append(const T &data) {
|
||||
Base *obj = new ArgList::Node<T>(data);
|
||||
objects.push_back(obj);
|
||||
template <typename T>
|
||||
void
|
||||
add_arg(const T &data)
|
||||
{
|
||||
Format fmt;
|
||||
process(fmt);
|
||||
|
||||
switch (fmt.format) {
|
||||
case Format::character:
|
||||
format_char(stream, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::integer:
|
||||
format_integer(stream, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::floating:
|
||||
format_float(stream, data, fmt);
|
||||
break;
|
||||
|
||||
case Format::string:
|
||||
format_string(stream, data, fmt);
|
||||
break;
|
||||
|
||||
default:
|
||||
stream << "<bad format>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void prepend(const T &data) {
|
||||
Base *obj = new ArgList::Node<T>(data);
|
||||
objects.push_front(obj);
|
||||
}
|
||||
|
||||
void dump(const std::string &format);
|
||||
void dump(std::ostream &strm, const std::string &fmt)
|
||||
{ stream = &strm; dump(fmt); }
|
||||
|
||||
std::string dumpToString(const std::string &format);
|
||||
|
||||
friend ArgList &operator<<(std::ostream &str, ArgList &list);
|
||||
void end_args();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline ArgList &
|
||||
operator,(ArgList &alist, const T &data)
|
||||
/* end namespace cp */ }
|
||||
|
||||
typedef VarArgs::List<cp::Print> CPrintfArgsList;
|
||||
|
||||
inline void
|
||||
ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
|
||||
{
|
||||
alist.append(data);
|
||||
return alist;
|
||||
cp::Print print(stream, format);
|
||||
args.add_args(print);
|
||||
}
|
||||
|
||||
class ArgListNull {
|
||||
};
|
||||
|
||||
inline ArgList &
|
||||
operator,(ArgList &alist, ArgListNull)
|
||||
{ return alist; }
|
||||
|
||||
//
|
||||
// cprintf(format, args, ...) prints to cout
|
||||
// (analogous to printf())
|
||||
//
|
||||
inline void
|
||||
__cprintf(const std::string &format, ArgList &args)
|
||||
{ args.dump(format); delete &args; }
|
||||
#define __cprintf__(format, ...) \
|
||||
cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__))
|
||||
#define cprintf(...) \
|
||||
__cprintf__(__VA_ARGS__, cp::ArgListNull())
|
||||
ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
|
||||
{
|
||||
cp::Print print(stream, format);
|
||||
VARARGS_ADDARGS(print);
|
||||
}
|
||||
|
||||
//
|
||||
// ccprintf(stream, format, args, ...) prints to the specified stream
|
||||
// (analogous to fprintf())
|
||||
//
|
||||
inline void
|
||||
__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
|
||||
{ args.dump(stream, format); delete &args; }
|
||||
#define __ccprintf__(stream, format, ...) \
|
||||
cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__))
|
||||
#define ccprintf(stream, ...) \
|
||||
__ccprintf__(stream, __VA_ARGS__, cp::ArgListNull())
|
||||
cprintf(const char *format, CPRINTF_DECLARATION)
|
||||
{
|
||||
ccprintf(std::cout, format, VARARGS_ALLARGS);
|
||||
}
|
||||
|
||||
//
|
||||
// csprintf(format, args, ...) returns a string
|
||||
// (roughly analogous to sprintf())
|
||||
//
|
||||
inline std::string
|
||||
__csprintf(const std::string &format, ArgList &args)
|
||||
{ std::string s = args.dumpToString(format); delete &args; return s; }
|
||||
#define __csprintf__(format, ...) \
|
||||
cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__))
|
||||
#define csprintf(...) \
|
||||
__csprintf__(__VA_ARGS__, cp::ArgListNull())
|
||||
csprintf(const char *format, CPRINTF_DECLARATION)
|
||||
{
|
||||
std::stringstream stream;
|
||||
ccprintf(stream, format, VARARGS_ALLARGS);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* functions again with std::string. We have both so we don't waste
|
||||
* time converting const char * to std::string since we don't take
|
||||
* advantage of it.
|
||||
*/
|
||||
inline void
|
||||
ccprintf(std::ostream &stream, const std::string &format,
|
||||
const CPrintfArgsList &args)
|
||||
{
|
||||
ccprintf(stream, format.c_str(), args);
|
||||
}
|
||||
|
||||
inline void
|
||||
ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION)
|
||||
{
|
||||
ccprintf(stream, format, VARARGS_ALLARGS);
|
||||
}
|
||||
|
||||
inline void
|
||||
cprintf(const std::string &format, CPRINTF_DECLARATION)
|
||||
{
|
||||
ccprintf(std::cout, format, VARARGS_ALLARGS);
|
||||
}
|
||||
|
||||
inline std::string
|
||||
csprintf(const std::string &format, CPRINTF_DECLARATION)
|
||||
{
|
||||
std::stringstream stream;
|
||||
ccprintf(stream, format, VARARGS_ALLARGS);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
#endif // __CPRINTF_HH__
|
||||
|
||||
Reference in New Issue
Block a user