/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2014 ARM Limited
+ * 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
*
* Authors: Nathan Binkert
* Steve Reinhardt
+ * Andreas Sandberg
*/
-#ifndef __CPRINTF_HH__
-#define __CPRINTF_HH__
+#ifndef __BASE_CPRINTF_HH__
+#define __BASE_CPRINTF_HH__
+#include <ios>
#include <iostream>
#include <list>
#include <string>
namespace cp {
-class ArgList
+struct Print
{
- private:
- class Base
+ protected:
+ std::ostream &stream;
+ const char *format;
+ const char *ptr;
+ bool cont;
+
+ std::ios::fmtflags saved_flags;
+ char saved_fill;
+ int saved_precision;
+
+ Format fmt;
+ void process();
+ void process_flag();
+
+ public:
+ Print(std::ostream &stream, const std::string &format);
+ Print(std::ostream &stream, const char *format);
+ ~Print();
+
+ int
+ get_number(int data)
{
- public:
- virtual ~Base() {}
- virtual void process(std::ostream &out, Format &fmt) = 0;
- };
+ return data;
+ }
+
+ template <typename T>
+ int
+ get_number(const T& data)
+ {
+ return 0;
+ }
template <typename T>
- class Node : public Base
+ void
+ add_arg(const T &data)
{
- 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;
- }
+ if (!cont)
+ 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;
}
- };
- typedef std::list<Base *> list_t;
+ switch (fmt.format) {
+ case Format::character:
+ format_char(stream, data, fmt);
+ break;
- protected:
- list_t objects;
- std::ostream *stream;
+ case Format::integer:
+ format_integer(stream, data, fmt);
+ break;
- public:
- ArgList() : stream(&std::cout) {}
- ~ArgList();
+ case Format::floating:
+ format_float(stream, data, fmt);
+ break;
- template<class T>
- void append(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_back(obj);
- }
+ case Format::string:
+ format_string(stream, data, fmt);
+ break;
- template<class T>
- void prepend(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_front(obj);
+ default:
+ stream << "<bad format>";
+ break;
+ }
}
- 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)
+} // namespace cp
+
+inline void
+ccprintf(cp::Print &print)
{
- alist.append(data);
- return alist;
+ print.end_args();
}
-class ArgListNull {
-};
-inline ArgList &
-operator,(ArgList &alist, ArgListNull)
-{ return alist; }
+template<typename T, typename ...Args> void
+ccprintf(cp::Print &print, const T &value, const Args &...args)
+{
+ print.add_arg(value);
-//
-// 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, args...) \
- cp::__cprintf(format, (*(new cp::ArgList), args))
-#define cprintf(args...) \
- __cprintf__(args, cp::ArgListNull())
-
-//
-// 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, args...) \
- cp::__ccprintf(stream, format, (*(new cp::ArgList), args))
-#define ccprintf(stream, args...) \
- __ccprintf__(stream, args, cp::ArgListNull())
-
-//
-// 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, args...) \
- cp::__csprintf(format, (*(new cp::ArgList), args))
-#define csprintf(args...) \
- __csprintf__(args, cp::ArgListNull())
-
-template<class T>
-inline ArgList &
-operator<<(ArgList &list, const T &data)
+ ccprintf(print, args...);
+}
+
+
+template<typename ...Args> void
+ccprintf(std::ostream &stream, const char *format, const Args &...args)
{
- list.append(data);
- return list;
+ cp::Print print(stream, format);
+
+ ccprintf(print, args...);
}
-inline ArgList &
-operator<<(std::ostream &str, ArgList &list)
+
+template<typename ...Args> void
+cprintf(const char *format, const Args &...args)
{
- list.stream = &str;
- return list;
+ ccprintf(std::cout, format, args...);
}
-class ArgListTemp
+template<typename ...Args> std::string
+csprintf(const char *format, const Args &...args)
{
- private:
- std::string format;
- ArgList *args;
+ std::stringstream stream;
+ ccprintf(stream, format, args...);
+ return stream.str();
+}
- public:
- ArgListTemp(const std::string &f) : format(f) { args = new ArgList; }
- ~ArgListTemp() { args->dump(format); delete args; }
+/*
+ * 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.
+ */
+template<typename ...Args> void
+ccprintf(std::ostream &stream, const std::string &format, const Args &...args)
+{
+ ccprintf(stream, format.c_str(), args...);
+}
- operator ArgList *() { return args; }
-};
+template<typename ...Args> void
+cprintf(const std::string &format, const Args &...args)
+{
+ ccprintf(std::cout, format.c_str(), args...);
+}
-#define cformat(format) \
- (*((cp::ArgList *)cp::ArgListTemp(format)))
+template<typename ...Args> std::string
+csprintf(const std::string &format, const Args &...args)
+{
+ return csprintf(format.c_str(), args...);
}
#endif // __CPRINTF_HH__