Update for OSX build issues.
[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 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 ~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 } // namespace detail
150
151 class make_cerr : public detail::log<detail::channelln> {
152 public:
153 make_cerr(const char* filename, int line_number, const char* func) :
154 detail::log<detail::channelln>(std::cerr, filename, line_number, func)
155 { }
156 };
157
158 class cerr : public detail::log<detail::channel> {
159 public:
160 cerr(const char* filename, int line_number, const char* func) :
161 detail::log<detail::channel>(std::cout, filename, line_number, func)
162 { }
163 };
164
165 class clog : public detail::log<detail::channel> {
166 public:
167 clog(const char* filename, int line_number, const char* func) :
168 detail::log<detail::channel>(std::clog, filename, line_number, func)
169 { }
170 };
171
172 class cout : public detail::log<detail::channel> {
173 public:
174 cout(const char* filename, int line_number, const char* func) :
175 detail::log<detail::channel>(std::cout, filename, line_number, func)
176 { }
177 };
178
179
180 } // namespace stream
181
182 #define Error stream::cerr(__FILE__, __LINE__, __func__)
183
184 #define Out stream::cout(NULL, __LINE__, __func__)
185
186 #define Outn() stream::cout(NULL, __LINE__, __func__) << " "
187
188 #define Log stream::clog(NULL, __LINE__, __func__)
189
190 #define Logn() stream::clog(NULL, __LINE__, __func__) << " "
191
192 } // namespace libtest