Interface Documentation
Version: invalid
types.hh
Go to the documentation of this file.
1 /*
2  @@@@@@@@ @@ @@@@@@ @@@@@@@@ @@
3  /@@///// /@@ @@////@@ @@////// /@@
4  /@@ /@@ @@@@@ @@ // /@@ /@@
5  /@@@@@@@ /@@ @@///@@/@@ /@@@@@@@@@/@@
6  /@@//// /@@/@@@@@@@/@@ ////////@@/@@
7  /@@ /@@/@@//// //@@ @@ /@@/@@
8  /@@ @@@//@@@@@@ //@@@@@@ @@@@@@@@ /@@
9  // /// ////// ////// //////// //
10 
11  Copyright (c) 2016, Triad National Security, LLC
12  All rights reserved.
13  */
14 #pragma once
15 
18 #include <flecsi-config.h>
19 
20 #if defined(FLECSI_ENABLE_FLOG)
21 
22 #include "flecsi/log/packet.hh"
23 #include "flecsi/log/utils.hh"
24 
25 #include <cassert>
26 #include <unordered_map>
27 
28 namespace flecsi {
29 namespace log {
30 
38 class tee_buffer_t : public std::streambuf
39 {
40 public:
46  struct buffer_data_t {
47  bool enabled;
48  bool colorized;
49  std::streambuf * buffer;
50  }; // struct buffer_data_t
51 
58  void add_buffer(std::string key, std::streambuf * sb, bool colorized) {
59  if(buffers_.find(key) == buffers_.end()) {
60  buffers_[key].enabled = true;
61  buffers_[key].buffer = sb;
62  buffers_[key].colorized = colorized;
63  } // if
64  } // add_buffer
65 
71  bool enable_buffer(std::string key) {
72  assert(buffers_.find(key) != buffers_.end());
73  buffers_[key].enabled = true;
74  return buffers_[key].enabled;
75  } // enable_buffer
76 
81  bool disable_buffer(std::string key) {
82  assert(buffers_.find(key) != buffers_.end());
83  buffers_[key].enabled = false;
84  return buffers_[key].enabled;
85  } // disable_buffer
86 
87 protected:
99  virtual int overflow(int c) {
100  if(c == EOF) {
101  return !EOF;
102  }
103  else {
104  // Get the size before we add the current character
105  const size_t tbsize = test_buffer_.size();
106 
107  // Buffer the output for now...
108  test_buffer_.append(1, char(c)); // takes char
109 
110  switch(tbsize) {
111 
112  case 0:
113  if(c == '\033') {
114  // This could be a color string, start buffering
115  return c;
116  }
117  else {
118  // No match, go ahead and write the character
119  return flush_buffer(all_buffers);
120  } // if
121 
122  case 1:
123  if(c == '[') {
124  // This still looks like a color string, keep buffering
125  return c;
126  }
127  else {
128  // This is some other kind of escape. Write the
129  // buffered output to all buffers.
130  return flush_buffer(all_buffers);
131  } // if
132 
133  case 2:
134  if(c == '0' || c == '1') {
135  // This still looks like a color string, keep buffering
136  return c;
137  }
138  else {
139  // This is some other kind of escape. Write the
140  // buffered output to all buffers.
141  return flush_buffer(all_buffers);
142  } // if
143 
144  case 3:
145  if(c == ';') {
146  // This still looks like a color string, keep buffering
147  return c;
148  }
149  else if(c == 'm') {
150  // This is a plain color termination. Write the
151  // buffered output to the color buffers.
152  return flush_buffer(color_buffers);
153  }
154  else {
155  // This is some other kind of escape. Write the
156  // buffered output to all buffers.
157  return flush_buffer(all_buffers);
158  } // if
159 
160  case 4:
161  if(c == '3') {
162  // This still looks like a color string, keep buffering
163  return c;
164  }
165  else {
166  // This is some other kind of escape. Write the
167  // buffered output to all buffers.
168  return flush_buffer(all_buffers);
169  } // if
170 
171  case 5:
172  if(isdigit(c) && (c - '0') < 8) {
173  // This still looks like a color string, keep buffering
174  return c;
175  }
176  else {
177  // This is some other kind of escape. Write the
178  // buffered output to all buffers.
179  return flush_buffer(all_buffers);
180  } // if
181 
182  case 6:
183  if(c == 'm') {
184  // This is a color string termination. Write the
185  // buffered output to the color buffers.
186  return flush_buffer(color_buffers);
187  }
188  else {
189  // This is some other kind of escape. Write the
190  // buffered output to all buffers.
191  return flush_buffer(all_buffers);
192  } // if
193  } // switch
194 
195  return c;
196  } // if
197  } // overflow
198 
203  virtual int sync() {
204  int state = 0;
205 
206  for(auto b : buffers_) {
207  const int s = b.second.buffer->pubsync();
208  state = (state != 0) ? state : s;
209  } // for
210 
211  // Return -1 if one of the buffers had an error
212  return (state == 0) ? 0 : -1;
213  } // sync
214 
215 private:
216  // Predicate to select all buffers.
217  static bool all_buffers(const buffer_data_t & bd) {
218  return bd.enabled;
219  } // any_buffer
220 
221  // Predicate to select color buffers.
222  static bool color_buffers(const buffer_data_t & bd) {
223  return bd.enabled && bd.colorized;
224  } // any_buffer
225 
226  // Flush buffered output to buffers that satisfy the predicate function.
227  template<typename P>
228  int flush_buffer(P && predicate = all_buffers) {
229  int eof = !EOF;
230 
231  // Put test buffer characters to each buffer
232  for(auto b : buffers_) {
233  if(predicate(b.second)) {
234  for(auto bc : test_buffer_) {
235  const int w = b.second.buffer->sputc(bc);
236  eof = (eof == EOF) ? eof : w;
237  } // for
238  } // if
239  } // for
240 
241  // Clear the test buffer
242  test_buffer_.clear();
243 
244  // Return EOF if one of the buffers hit the end
245  return eof == EOF ? EOF : !EOF;
246  } // flush_buffer
247 
248  std::unordered_map<std::string, buffer_data_t> buffers_;
249  std::string test_buffer_;
250 
251 }; // class tee_buffer_t
252 
258 struct tee_stream_t : public std::ostream {
259 
260  tee_stream_t() : std::ostream(&tee_) {
261  // Allow users to turn std::clog output on and off from
262  // their environment.
263  if(std::getenv("FLOG_ENABLE_STDLOG")) {
264  tee_.add_buffer("flog", std::clog.rdbuf(), true);
265  } // if
266  } // tee_stream_t
267 
268  tee_stream_t & operator*() {
269  return *this;
270  } // operator *
271 
276  void add_buffer(std::string const & key,
277  std::ostream & s,
278  bool colorized = false) {
279  tee_.add_buffer(key, s.rdbuf(), colorized);
280  } // add_buffer
281 
288  bool enable_buffer(std::string const & key) {
289  tee_.enable_buffer(key);
290  return true;
291  } // enable_buffer
292 
299  bool disable_buffer(std::string const & key) {
300  tee_.disable_buffer(key);
301  return false;
302  } // disable_buffer
303 
304 private:
305  tee_buffer_t tee_;
306 
307 }; // struct tee_stream_t
308 
309 } // namespace log
310 } // namespace flecsi
311 
312 #endif // FLECSI_ENABLE_FLOG
void add_buffer(std::string const &key, std::ostream &s, bool colorized=false)
Definition: types.hh:276
bool disable_buffer(std::string const &key)
Definition: types.hh:299
virtual int overflow(int c)
Definition: types.hh:99
Definition: types.hh:258
bool enable_buffer(std::string const &key)
Definition: types.hh:288
bool enable_buffer(std::string key)
Definition: types.hh:71
Definition: types.hh:38
bool disable_buffer(std::string key)
Definition: types.hh:81
virtual int sync()
Definition: types.hh:203
void add_buffer(std::string key, std::streambuf *sb, bool colorized)
Definition: types.hh:58
Definition: control.hh:31