00001 #ifndef UTIL_FAKE_OSTREAM_H
00002 #define UTIL_FAKE_OSTREAM_H
00003
00004 #include "util/float_to_string.hh"
00005 #include "util/integer_to_string.hh"
00006 #include "util/string_piece.hh"
00007
00008 #include <cassert>
00009 #include <limits>
00010
00011 #include <stdint.h>
00012
00013 namespace util {
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 template <class Derived> class FakeOStream {
00037 public:
00038 FakeOStream() {}
00039
00040
00041 Derived &operator<<(StringPiece str) {
00042 return C().write(str.data(), str.size());
00043 }
00044
00045
00046 private:
00047 template <class Arg> struct EnableIfKludge {
00048 typedef Derived type;
00049 };
00050 template <class From, unsigned Length = sizeof(From), bool Signed = std::numeric_limits<From>::is_signed, bool IsInteger = std::numeric_limits<From>::is_integer> struct Coerce {};
00051
00052 template <class From> struct Coerce<From, 2, false, true> { typedef uint16_t To; };
00053 template <class From> struct Coerce<From, 4, false, true> { typedef uint32_t To; };
00054 template <class From> struct Coerce<From, 8, false, true> { typedef uint64_t To; };
00055
00056 template <class From> struct Coerce<From, 2, true, true> { typedef int16_t To; };
00057 template <class From> struct Coerce<From, 4, true, true> { typedef int32_t To; };
00058 template <class From> struct Coerce<From, 8, true, true> { typedef int64_t To; };
00059 public:
00060 template <class From> typename EnableIfKludge<typename Coerce<From>::To>::type &operator<<(const From value) {
00061 return CallToString(static_cast<typename Coerce<From>::To>(value));
00062 }
00063
00064
00065 Derived &operator<<(char val) { return put(val); }
00066 Derived &operator<<(signed char val) { return put(static_cast<char>(val)); }
00067 Derived &operator<<(unsigned char val) { return put(static_cast<char>(val)); }
00068
00069 Derived &operator<<(bool val) { return put(val + '0'); }
00070
00071 Derived &operator<<(int val) { return CallToString(static_cast<typename Coerce<int>::To>(val)); }
00072
00073 Derived &operator<<(float val) { return CallToString(val); }
00074 Derived &operator<<(double val) { return CallToString(val); }
00075
00076
00077 Derived &operator<<(const void *value) { return CallToString(value); }
00078
00079 Derived &operator<<(const char *value) { return *this << StringPiece(value); }
00080 Derived &operator<<(char *value) { return *this << StringPiece(value); }
00081
00082 Derived &put(char val) {
00083 char *c = C().Ensure(1);
00084 *c = val;
00085 C().AdvanceTo(++c);
00086 return C();
00087 }
00088
00089 char widen(char val) const { return val; }
00090
00091 private:
00092
00093 Derived &C() {
00094 return *static_cast<Derived*>(this);
00095 }
00096
00097 const Derived &C() const {
00098 return *static_cast<const Derived*>(this);
00099 }
00100
00101
00102
00103 template <class T> Derived &CallToString(const T value) {
00104 C().AdvanceTo(ToString(value, C().Ensure(ToStringBuf<T>::kBytes)));
00105 return C();
00106 }
00107 };
00108
00109 }
00110
00111 #endif // UTIL_FAKE_OSTREAM_H