diff options
Diffstat (limited to 'src/base/cprintf.hh')
-rw-r--r-- | src/base/cprintf.hh | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh new file mode 100644 index 000000000..c468c375f --- /dev/null +++ b/src/base/cprintf.hh @@ -0,0 +1,197 @@ +/* + * 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. + */ + +#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__ |