/* * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Nathan Binkert * Steve Reinhardt */ #ifndef __CPRINTF_HH__ #define __CPRINTF_HH__ #include <iostream> #include <list> #include <string> #include "base/cprintf_formats.hh" namespace cp { class ArgList { 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; public: ArgList() : stream(&std::cout) {} ~ArgList(); template<class T> void append(const T &data) { Base *obj = new ArgList::Node<T>(data); objects.push_back(obj); } 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); }; template<class T> inline ArgList & operator,(ArgList &alist, const T &data) { alist.append(data); return alist; } 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, 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) { list.append(data); return list; } inline ArgList & operator<<(std::ostream &str, ArgList &list) { list.stream = &str; return list; } class ArgListTemp { private: std::string format; ArgList *args; public: ArgListTemp(const std::string &f) : format(f) { args = new ArgList; } ~ArgListTemp() { args->dump(format); delete args; } operator ArgList *() { return args; } }; #define cformat(format) \ (*((cp::ArgList *)cp::ArgListTemp(format))) } #endif // __CPRINTF_HH__