081c2bf04ef26685677d58af17a448f95071025d
[awesomized/libmemcached] / libtest / stream.h
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:
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:
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:
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
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:
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:
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:
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:
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:
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