Update all licenses to BSD.
[m6w6/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 cerr {
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)
59 {
60 std::cerr << s.str() << std::endl;
61 }
62 };
63
64 template<class Ch, class Tr, class A>
65 class make_cerr {
66 private:
67
68 public:
69 typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
70
71 public:
72 void operator()(const stream_buffer &s)
73 {
74 std::cerr << std::endl << s.str() << std::endl;
75 }
76 };
77
78 template<class Ch, class Tr, class A>
79 class cout {
80 private:
81
82 public:
83 typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
84
85 public:
86 void operator()(const stream_buffer &s)
87 {
88 std::cout << s.str() << std::endl;
89 }
90 };
91
92 template<class Ch, class Tr, class A>
93 class clog {
94 private:
95
96 public:
97 typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
98
99 public:
100 void operator()(const stream_buffer &s)
101 {
102 std::cerr<< s.str() << std::endl;
103 }
104 };
105
106 template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
107 class log {
108 private:
109 typedef OutputPolicy<Ch, Tr, A> output_policy;
110 const char *_filename;
111 int _line_number;
112 const char *_func;
113
114 public:
115 log() :
116 _filename(NULL),
117 _line_number(0)
118 { }
119
120 void set_filename(const char *filename, int line_number, const char *func)
121 {
122 _filename= filename;
123 _line_number= line_number;
124 _func= func;
125 }
126
127 ~log()
128 {
129 output_policy()(arg);
130 }
131
132 public:
133 template<class T>
134 log &operator<<(const T &x)
135 {
136 if (_filename)
137 {
138 arg << _filename << ":" << _line_number << ": in " << _func << "() ";
139 _filename= NULL;
140 }
141 arg << x;
142 return *this;
143 }
144
145 private:
146 typename output_policy::stream_buffer arg;
147 };
148 }
149
150 class make_cerr : public detail::log<detail::make_cerr> {
151 public:
152 make_cerr(const char *filename, int line_number, const char *func)
153 {
154 set_filename(filename, line_number, func);
155 }
156 };
157
158 class cerr : public detail::log<detail::cerr> {
159 public:
160 cerr(const char *filename, int line_number, const char *func)
161 {
162 set_filename(filename, line_number, func);
163 }
164 };
165
166 class clog : public detail::log<detail::clog> {
167 public:
168 clog(const char *, int, const char*)
169 { }
170 };
171
172 class cout : public detail::log<detail::cout> {
173 public:
174 cout(const char *, int, const char *)
175 { }
176 };
177
178
179 } // namespace stream
180
181 #define Error stream::cerr(__FILE__, __LINE__, __func__)
182
183 #define Out stream::cout(NULL, __LINE__, __func__)
184
185 #define Outn() stream::cout(NULL, __LINE__, __func__) << " "
186
187 #define Log stream::clog(NULL, __LINE__, __func__)
188
189 #define Logn() stream::clog(NULL, __LINE__, __func__) << " "
190
191 } // namespace libtest