1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: 2 * 3 * Data Differential YATL (i.e. libtest) library 4 * 5 * Copyright (C) 2012 Data Differential, http://datadifferential.com/ 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following disclaimer 16 * in the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * * The names of its contributors may not be used to endorse or 20 * promote products derived from this software without specific prior 21 * written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 */ 36 37 #pragma once 38 39 #include <iostream> 40 #include <cassert> 41 #include <sstream> 42 #include <ctime> 43 #include <ostream> 44 45 namespace libtest { 46 namespace stream { 47 48 namespace detail { 49 50 template<class Ch, class Tr, class A> 51 class channel { 52 private: 53 54 public: 55 typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer; 56 57 public: operator()58 void operator()(const stream_buffer& s, std::ostream& _out, 59 const char* filename, int line_number, const char* func) 60 { 61 if (filename) 62 { 63 _out 64 << filename 65 << ":" 66 << line_number 67 << ": in " 68 << func << "() " 69 << s.str() 70 << std::endl; 71 } 72 else 73 { 74 _out 75 << s.str() 76 << std::endl; 77 } 78 } 79 }; 80 81 template<class Ch, class Tr, class A> 82 class channelln { 83 private: 84 85 public: 86 typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer; 87 88 public: operator()89 void operator()(const stream_buffer& s, std::ostream& _out, 90 const char* filename, int line_number, const char* func) 91 { 92 if (filename) 93 { 94 _out 95 << std::endl 96 << filename 97 << ":" 98 << line_number 99 << ": in " 100 << func << "() " 101 << s.str() 102 << std::endl; 103 } 104 else 105 { 106 _out 107 << std::endl 108 << s.str() 109 << std::endl; 110 } 111 } 112 }; 113 114 template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> > 115 class log { 116 private: 117 typedef OutputPolicy<Ch, Tr, A> output_policy; 118 119 private: 120 std::ostream& _out; 121 const char *_filename; 122 int _line_number; 123 const char *_func; 124 125 public: log(std::ostream & out_arg,const char * filename,int line_number,const char * func)126 log(std::ostream& out_arg, const char* filename, int line_number, const char* func) : 127 _out(out_arg), 128 _filename(filename), 129 _line_number(line_number), 130 _func(func) 131 { } 132 ~log()133 virtual ~log() 134 { 135 output_policy()(arg, _out, _filename, _line_number, _func); 136 } 137 138 public: 139 template<class T> 140 log &operator<<(const T &x) 141 { 142 arg << x; 143 return *this; 144 } 145 146 private: 147 typename output_policy::stream_buffer arg; 148 149 private: 150 log( const log& ); 151 const log& operator=( const log& ); 152 }; 153 } // namespace detail 154 155 class make_cerr : public detail::log<detail::channelln> { 156 public: make_cerr(const char * filename,int line_number,const char * func)157 make_cerr(const char* filename, int line_number, const char* func) : 158 detail::log<detail::channelln>(std::cerr, filename, line_number, func) 159 { } 160 161 private: 162 make_cerr( const make_cerr& ); 163 const make_cerr& operator=( const make_cerr& ); 164 }; 165 166 class cerr : public detail::log<detail::channel> { 167 public: cerr(const char * filename,int line_number,const char * func)168 cerr(const char* filename, int line_number, const char* func) : 169 detail::log<detail::channel>(std::cout, filename, line_number, func) 170 { } 171 172 private: 173 cerr( const cerr& ); 174 const cerr& operator=( const cerr& ); 175 }; 176 177 class clog : public detail::log<detail::channel> { 178 public: clog(const char * filename,int line_number,const char * func)179 clog(const char* filename, int line_number, const char* func) : 180 detail::log<detail::channel>(std::clog, filename, line_number, func) 181 { } 182 183 private: 184 clog( const clog& ); 185 const clog& operator=( const clog& ); 186 }; 187 188 class make_cout : public detail::log<detail::channelln> { 189 public: make_cout(const char * filename,int line_number,const char * func)190 make_cout(const char* filename, int line_number, const char* func) : 191 detail::log<detail::channelln>(std::cout, filename, line_number, func) 192 { } 193 194 private: 195 make_cout( const make_cout& ); 196 const make_cout& operator=( const make_cout& ); 197 }; 198 199 class cout : public detail::log<detail::channel> { 200 public: cout(const char * filename,int line_number,const char * func)201 cout(const char* filename, int line_number, const char* func) : 202 detail::log<detail::channel>(std::cout, filename, line_number, func) 203 { } 204 205 private: 206 cout( const cout& ); 207 const cout& operator=( const cout& ); 208 }; 209 210 211 } // namespace stream 212 213 #define Error stream::cerr(__FILE__, __LINE__, __func__) 214 215 #define Out stream::cout(NULL, __LINE__, __func__) 216 217 #define Outn() stream::cout(NULL, __LINE__, __func__) << " " 218 219 #define Log stream::clog(NULL, __LINE__, __func__) 220 221 #define Logn() stream::clog(NULL, __LINE__, __func__) << " " 222 223 } // namespace libtest 224