-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathtri_logger.cpp
307 lines (257 loc) · 7.4 KB
/
tri_logger.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
//
// Copyright (c) 2005 - 2010
// Seweryn Habdank-Wojewodzki
//
// Distributed under the Boost Software License, Version 1.0.
// ( copy at http://www.boost.org/LICENSE_1_0.txt )
#include "tri_logger.hpp"
#include <memory>
#if !defined(CLEANTLOG)
#if defined (FTLOG)
#include <fstream>
#include <cctype>
#else
#include <iostream>
#include "nullstream.hpp"
#endif
namespace trivial_logger
{
namespace detail
{
class tri_logger_impl
{
public:
// true if logger is activated
static bool is_activated_;
// auto pointer helps manage resources;
static ::std::auto_ptr < ::std::ostream > outstream_helper_ptr_;
// pointer to the output stream of the logger
static ::std::ostream * outstream_;
};
// activate logger by default
bool tri_logger_impl::is_activated_ = true;
void init_tri_logger_impl();
}
std::auto_ptr<detail::tri_logger_impl>
tri_logger_t::tl_impl ( std::auto_ptr<detail::tri_logger_impl> ( new detail::tri_logger_impl ) );
tri_logger_t::tri_logger_t()
{
if (tl_impl.get() == NULL)
{
tri_logger_t::tl_impl.reset ( new detail::tri_logger_impl );
}
detail::init_tri_logger_impl();
}
tri_logger_t::~tri_logger_t()
{
}
bool tri_logger_t::is_activated()
{
return tl_impl->is_activated_;
}
void tri_logger_t::activate ( bool const activate )
{
tl_impl->is_activated_ = activate;
}
::std::ostream *& tri_logger_t::ostream_ptr()
{
return tl_impl->outstream_;
}
#if defined(TLOG)
// set auto pointer to the null stream
// reason: ::std::cout can not be created in runtime, so
// the auto pointer has nothing to do with its resources
::std::auto_ptr < ::std::ostream >
detail::tri_logger_impl::outstream_helper_ptr_
= ::std::auto_ptr < ::std::ostream > ( new null_stream );
::std::ostream * detail::tri_logger_impl::outstream_ = &::std::cout;
void detail::init_tri_logger_impl()
{
detail::tri_logger_impl::outstream_helper_ptr_.reset ( new null_stream );
detail::tri_logger_impl::outstream_ = &::std::cout;
}
#elif defined (ETLOG)
// look to the TLOG comments
::std::auto_ptr < ::std::ostream >
detail::tri_logger_impl::outstream_helper_ptr_
= ::std::auto_ptr < ::std::ostream > ( new null_stream );
::std::ostream * detail::tri_logger_impl::outstream_ = &::std::cerr;
void detail::init_tri_logger_impl()
{
detail::tri_logger_impl::outstream_helper_ptr_.reset ( new null_stream );
detail::tri_logger_impl::outstream_ = &::std::cerr;
}
#elif defined (FTLOG)
#define XSTR(s) STR(s)
#define STR(s) #s
#define MAX(x,y) ( (x) < (y) ? (y) : (x) )
namespace detail
{
/// Function paste rhs C string to the lhs C string.
/// lhs should be long enough for that operation.
/// Additionally coping is stared from the point which
/// points lhs.
template < typename Char_type >
size_t const str_cat ( Char_type *& lhs, Char_type const * rhs )
{
size_t len = 0;
while ( *rhs != '\0' )
{
*lhs = *rhs;
++rhs;
++lhs;
++len;
}
return len;
}
/// Function calculates length of C string
/// It can be used with wide characters
template < typename Char_type >
size_t const str_len ( Char_type const * str )
{
size_t len = 0;
while ( *str != '\0' )
{
++str;
++len;
}
return len;
}
/// Function copy rhs C string in to the lhs.
/// It do not check size of target C string
/// It starts to copy from the beginning of the C string,
/// but it begins put characters at the point where lhs points,
/// so there can be a problem when lhs points on the end of lhs
/// C string.
template < typename Char_type >
size_t const str_cpy ( Char_type *& lhs, Char_type const * rhs )
{
size_t len = 0;
while ( *rhs != '\0' )
{
*lhs = *rhs;
++rhs;
++lhs;
++len;
}
*lhs = '\0';
return len+1;
}
/// Function converts existing file name to the file name
/// which has no non-printable signs and
/// at the end is added extension.
/// The space sign in file name is converted to the underscore.
/// Lengths of C strings has to be proper.
template < typename Char_type >
size_t const
createfilename ( Char_type * result,
Char_type const * filename,
Char_type const * ext,
Char_type const * helper )
{
size_t len = 0;
if ( str_len ( filename ) > 1 )
{
while ( *filename != '\0' )
{
// check if characters have grapnical
// reprasentation
if ( 0 != ::std::isgraph( *filename ) )
{
*result = *filename;
++result;
++len;
}
else
{
// convert space to underscore
if ( *filename == ' ' )
{
*result = '_';
++result;
++len;
}
}
++filename;
}
// add extension
str_cat ( result, ext );
*result = '\0';
}
else
{
result = &result[0];
len = str_cpy ( result, helper );
}
return len;
}
template < typename T >
T const max ( T const x, T const y )
{
return ( x < y ? y : x );
}
char_type* const get_xstr()
{
return XSTR(FTLOG);
}
// extension C string
char_type* const get_ext()
{
return ".log";
}
char_type* const get_logger_file_name()
{
return "_logger.log";
}
} // namespace detail
typedef char char_type;
// convert definition of the TLOGFILE
// to the C string
char_type* const tlogfilename = detail::get_xstr();
// extension C string
char_type* const ext = detail::get_ext();
char_type* const helper_name = detail::get_logger_file_name();
// container for final file name
char_type filename[(MAX(sizeof(tlogfilename),sizeof(helper_name))+sizeof(ext))/sizeof(char_type)];
// create file name
size_t const len = detail::createfilename ( filename, detail::get_xstr(), detail::get_ext(), detail::get_logger_file_name() );
#undef MAX
#undef STR
#undef XSTR
// new file is opened and its destruction is managed by auto_ptr
::std::auto_ptr < ::std::ostream >
detail::tri_logger_impl::outstream_helper_ptr_
= ::std::auto_ptr < ::std::ostream >
( new ::std::ofstream ( filename ));
// set pointer output stream
::std::ostream * detail::tri_logger_impl::outstream_ = outstream_helper_ptr_.get();
void detail::init_tri_logger_impl()
{
detail::tri_logger_impl::outstream_helper_ptr_.reset( new ::std::ofstream ( filename ));
// set pointer output stream
detail::tri_logger_impl::outstream_ = detail::tri_logger_impl::outstream_helper_ptr_.get();
}
// here is a place for user defined output stream and flag
// ...
#else
::std::auto_ptr < ::std::ostream >
detail::tri_logger_impl::outstream_helper_ptr_
= ::std::auto_ptr < ::std::ostream > ( new null_stream );
::std::ostream * detail::tri_logger_impl::outstream_ = outstream_helper_ptr_.get();
void detail::init_tri_logger_impl()
{
detail::tri_logger_impl::outstream_helper_ptr_ .reset ( new null_stream );
detail::tri_logger_impl::outstream_ = outstream_helper_ptr_.get();
}
#endif
::std::auto_ptr<tri_logger_t> detail::tri_logger_out_ptr ( new tri_logger_t() );
tri_logger_t& tri_logger()
{
if (detail::tri_logger_out_ptr.get() == NULL)
{
detail::tri_logger_out_ptr.reset ( new tri_logger_t() );
}
return *detail::tri_logger_out_ptr;
}
} // namespace trivial_logger
#endif // !CLEANTLOG