cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cmnLODMultiplexerStreambuf.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5 
6  Author(s): Ofri Sadowsky
7  Created on: 2002-05-17
8 
9  (C) Copyright 2002-2007 Johns Hopkins University (JHU), All Rights
10  Reserved.
11 
12 --- begin cisst license - do not edit ---
13 
14 This software is provided "as is" under an open source license, with
15 no warranty. The complete license can be found in license.txt and
16 http://www.cisst.org/cisst/license.txt.
17 
18 --- end cisst license ---
19 
20 */
21 
22 
26 #pragma once
27 
28 #ifndef _cmnLODMultiplexerStreambuf_h
29 #define _cmnLODMultiplexerStreambuf_h
30 
33 #include <cisstCommon/cmnLogLoD.h>
34 
35 
36 #include <list>
37 #include <algorithm>
38 #include <fstream>
39 
107 template <class _element, class _trait = std::char_traits<_element> >
108 class cmnLODMultiplexerStreambuf : public std::basic_streambuf<_element, _trait>
109 {
110  friend class cmnMultiplexerStreambufProxy<_element, _trait>;
111 
112 public:
113 
115  typedef std::basic_streambuf<_element, _trait> BaseClassType;
116  typedef std::basic_streambuf<_element, _trait> ChannelType;
117 
118  typedef std::pair<ChannelType *, cmnLogMask> ElementType;
119 
124  typedef std::list<ElementType> ChannelContainerType;
125  typedef typename ChannelContainerType::iterator IteratorType;
126  typedef typename ChannelContainerType::const_iterator ConstIteratorType;
127 
128  typedef std::list<ThisType *> MultiplexerContainerType;
129  typedef typename MultiplexerContainerType::iterator MultiplexerIteratorType;
130  typedef typename MultiplexerContainerType::const_iterator MultiplexerConstIteratorType;
131 
136  cmnLODMultiplexerStreambuf(std::ofstream & fileStream) {
137  this->AddChannel(fileStream.rdbuf(), CMN_LOG_ALLOW_ALL);
138  }
139 
144  {}
145 
146 
153  bool AddChannel(ChannelType * channel, cmnLogMask mask);
154 
155 
163  inline bool AddChannel(std::ostream & outstream, cmnLogMask mask) {
164  return AddChannel(outstream.rdbuf(), mask);
165  }
166 
167 
168  bool AddMultiplexer(ThisType * multiplexer);
169 
170 
178  void RemoveChannel(ChannelType * channel);
179 
180 
181  void RemoveMultiplexer(ThisType * multiplexer);
182 
183 
190  inline void RemoveChannel(std::ostream & outstream) {
191  RemoveChannel(outstream.rdbuf());
192  }
193 
194 
196  void RemoveAllChannels(void);
197 
198 
206  bool SetChannelMask(ChannelType * channel, cmnLogMask mask);
207 
208 
216  bool GetChannelMask(const ChannelType * channel, cmnLogMask & mask) const;
217 
226  const ChannelContainerType & GetChannels(void) const {
227  return Channels;
228  }
229 
230  // Here we provide basic_streambuf namesame methods for multiplexing.
231  // This part is declared 'protected' following the declarations of
232  // basic_streambuf. See basic_streambuf documentation for more
233  // details.
234 protected:
235  typedef typename std::basic_streambuf<_element, _trait>::int_type int_type;
236 
240  virtual std::streamsize xsputn(const _element * s, std::streamsize n, cmnLogLevel level);
241 
245  virtual int sync();
246 
252  virtual int_type overflow(int_type c, cmnLogLevel level);
253 
256  virtual std::streamsize xsputn(const _element *s, std::streamsize n);
257 
262  virtual int_type overflow(int_type c = _trait::eof());
263 
264 //private:
268 
272  IteratorType FindChannel(const ChannelType * channel);
273 
277  ConstIteratorType FindChannel(const ChannelType * channel) const;
278 
282 
286  MultiplexerIteratorType FindMultiplexer(const ThisType * multiplexer);
287 
291  MultiplexerConstIteratorType FindMultiplexer(const ThisType * multiplexer) const;
292 };
293 
294 
295 
296 //********************************
297 // Template method implementation
298 //********************************
299 
300 
301 template <class _element, class _trait>
303 {
304  IteratorType it = FindChannel(channel);
305 
306  if (it == Channels.end()) {
307  Channels.insert(it, ElementType(channel, mask));
308  return true;
309  }
310  return false;
311 }
312 
313 
314 template <class _element, class _trait>
316 {
317  MultiplexerIteratorType it = FindMultiplexer(multiplexer);
318 
319  if (it == Multiplexers.end()) {
320  Multiplexers.insert(it, multiplexer);
321  return true;
322  }
323  return false;
324 }
325 
326 
327 template <class _element, class _trait>
329 {
330  IteratorType it = FindChannel(channel);
331 
332  if (it != Channels.end()) {
333  Channels.erase(it);
334  }
335 }
336 
337 
338 template <class _element, class _trait>
340 {
341  MultiplexerIteratorType it = FindMultiplexer(multiplexer);
342 
343  if (it != Multiplexers.end()) {
344  Multiplexers.erase(it);
345  }
346 }
347 
348 
349 template <class _element, class _trait>
351 {
352  Channels.clear();
353  Multiplexers.clear();
354 }
355 
356 
357 template <class _element, class _trait>
359 {
360  IteratorType it = FindChannel(channel);
361  if (it != Channels.end()) {
362  (*it).second = mask;
363  return true;
364  }
365  return false;
366 }
367 
368 
369 template <class _element, class _trait>
371 {
372  ConstIteratorType it = FindChannel(channel);
373  if (it != Channels.end()) {
374  mask = (*it).second;
375  return true;
376  }
377  return false;
378 }
379 
380 
381 template <class _element, class _trait>
382 std::streamsize cmnLODMultiplexerStreambuf<_element, _trait>::xsputn(const _element * s, std::streamsize n, cmnLogLevel level)
383 {
384  // for channels, compare to channel's mask
385  std::streamsize ssize(0);
386  IteratorType channelIt;
387  const IteratorType channelEnd = Channels.end();
388  for (channelIt = Channels.begin();
389  channelIt != channelEnd;
390  ++channelIt) {
391  if (level & ((*channelIt).second)) {
392  ssize = ((*channelIt).first)->sputn(s, n);
393  }
394  }
395  // for multiplexers, just send message along with log level
396  MultiplexerIteratorType multiplexerIt;
397  const MultiplexerIteratorType multiplexerEnd = Multiplexers.end();
398  for (multiplexerIt = Multiplexers.begin();
399  multiplexerIt != multiplexerEnd;
400  ++multiplexerIt) {
401  ssize = (*multiplexerIt)->xsputn(s, n, level);
402  }
403  return ssize;
404 }
405 
406 
407 template <class _element, class _trait>
409 {
410  IteratorType channelIt;
411  // synchronize all channels
412  const IteratorType channelEnd = Channels.end();
413  for (channelIt = Channels.begin();
414  channelIt != channelEnd;
415  ++channelIt) {
416  ((*channelIt).first)->pubsync();
417  }
418  // synchronize all multiplexers
419  MultiplexerIteratorType multiplexerIt;
420  const MultiplexerIteratorType multiplexerEnd = Multiplexers.end();
421  for (multiplexerIt = Multiplexers.begin();
422  multiplexerIt != multiplexerEnd;
423  ++multiplexerIt) {
424  (*multiplexerIt)->sync();
425  }
426  return 0;
427 }
428 
429 
430 template <class _element, class _trait>
433 {
434  // follow the basic_streambuf standard
435  if (_trait::eq_int_type(_trait::eof(), c)) {
436  return (_trait::not_eof(c));
437  }
438 
439  // multiplexing
440  IteratorType channelIt;
441  const IteratorType channelEnd = Channels.end();
442  for (channelIt = Channels.begin();
443  channelIt != channelEnd;
444  ++channelIt) {
445  if (level & ((*channelIt).second)) {
446  ((*channelIt).first)->sputc(_trait::to_char_type(c));
447  }
448  }
449  // for multiplexers, just send message along with log level
450  MultiplexerIteratorType multiplexerIt;
451  const MultiplexerIteratorType multiplexerEnd = Multiplexers.end();
452  for (multiplexerIt = Multiplexers.begin();
453  multiplexerIt != multiplexerEnd;
454  ++multiplexerIt) {
455  (*multiplexerIt)->overflow(c, level);
456  }
457  // follow the basic_streambuf standard
458  return _trait::not_eof(c);
459 }
460 
461 
462 template <class _element, class _trait>
463 std::streamsize cmnLODMultiplexerStreambuf<_element, _trait>::xsputn(const _element *s, std::streamsize n)
464 {
465  std::streamsize ssize(0);
466  // channels
467  IteratorType channelIt;
468  const IteratorType channelEnd = Channels.end();
469  for (channelIt = Channels.begin();
470  channelIt != channelEnd;
471  ++channelIt) {
472  ssize = ((*channelIt).first)->sputn(s, n);
473  }
474  // for multiplexers, just send message along
475  MultiplexerIteratorType multiplexerIt;
476  const MultiplexerIteratorType multiplexerEnd = Multiplexers.end();
477  for (multiplexerIt = Multiplexers.begin();
478  multiplexerIt != multiplexerEnd;
479  ++multiplexerIt) {
480  ssize = (*multiplexerIt)->xsputn(s, n);
481  }
482  return ssize;
483 }
484 
485 
486 template <class _element, class _trait>
489 {
490  // follow the basic_streambuf standard
491  if (_trait::eq_int_type(_trait::eof(), c)) {
492  return (_trait::not_eof(c));
493  }
494 
495  // channels
496  IteratorType channelIt;
497  const IteratorType channelEnd = Channels.end();
498  for (channelIt = Channels.begin();
499  channelIt != channelEnd;
500  ++channelIt) {
501  ((*channelIt).first)->sputc(_trait::to_char_type(c));
502  }
503  // for multiplexers, just send message along
504  MultiplexerIteratorType multiplexerIt;
505  const MultiplexerIteratorType multiplexerEnd = Multiplexers.end();
506  for (multiplexerIt = Multiplexers.begin();
507  multiplexerIt != multiplexerEnd;
508  ++multiplexerIt) {
509  (*multiplexerIt)->overflow(c);
510  }
511 
512  // follow the basic_streambuf standard
513  return _trait::not_eof(c);
514 }
515 
516 
517 template <class _element, class _trait>
520 {
521  IteratorType it = Channels.begin();
522  while (it != Channels.end()) {
523  if ((*it).first == channel) {
524  break;
525  }
526  ++it;
527  }
528  return it;
529 }
530 
531 
532 template <class _element, class _trait>
535 {
536  ConstIteratorType it = Channels.begin();
537  while (it != Channels.end()) {
538  if ((*it).first == channel) {
539  break;
540  }
541  ++it;
542  }
543  return it;
544 }
545 
546 
547 template <class _element, class _trait>
550 {
551  MultiplexerIteratorType it = Multiplexers.begin();
552  while (it != Multiplexers.end()) {
553  if ((*it) == multiplexer) {
554  break;
555  }
556  ++it;
557  }
558  return it;
559 }
560 
561 
562 template <class _element, class _trait>
565 {
566  MultiplexerConstIteratorType it = Multiplexers.begin();
567  while (it != Multiplexers.end()) {
568  if ((*it) == multiplexer) {
569  break;
570  }
571  ++it;
572  }
573  return it;
574 }
575 
576 
577 #endif
std::basic_streambuf< _element, _trait > BaseClassType
Definition: cmnLODMultiplexerStreambuf.h:115
ChannelContainerType Channels
Definition: cmnLODMultiplexerStreambuf.h:267
Portability across compilers and operating systems tools.
Declaration of Levels of Detail for cmnLogger (human readable logging)
ChannelContainerType::const_iterator ConstIteratorType
Definition: cmnLODMultiplexerStreambuf.h:126
std::basic_streambuf< _element, _trait >::int_type int_type
Definition: cmnLODMultiplexerStreambuf.h:235
MultiplexerContainerType Multiplexers
Definition: cmnLODMultiplexerStreambuf.h:281
ChannelContainerType::iterator IteratorType
Definition: cmnLODMultiplexerStreambuf.h:125
const ChannelContainerType & GetChannels(void) const
Definition: cmnLODMultiplexerStreambuf.h:226
void RemoveChannel(ChannelType *channel)
Definition: cmnLODMultiplexerStreambuf.h:328
short cmnLogLevel
Definition: cmnLogLoD.h:55
Types for dynamic control of output messages.
Definition: cmnForwardDeclarations.h:40
std::list< ThisType * > MultiplexerContainerType
Definition: cmnLODMultiplexerStreambuf.h:128
void RemoveChannel(std::ostream &outstream)
Definition: cmnLODMultiplexerStreambuf.h:190
bool AddChannel(std::ostream &outstream, cmnLogMask mask)
Definition: cmnLODMultiplexerStreambuf.h:163
IteratorType FindChannel(const ChannelType *channel)
Definition: cmnLODMultiplexerStreambuf.h:519
bool AddMultiplexer(ThisType *multiplexer)
Definition: cmnLODMultiplexerStreambuf.h:315
bool SetChannelMask(ChannelType *channel, cmnLogMask mask)
Definition: cmnLODMultiplexerStreambuf.h:358
cmnLODMultiplexerStreambuf< _element, _trait > ThisType
Definition: cmnLODMultiplexerStreambuf.h:114
virtual int_type overflow(int_type c, cmnLogLevel level)
Definition: cmnLODMultiplexerStreambuf.h:432
std::basic_streambuf< _element, _trait > ChannelType
Definition: cmnLODMultiplexerStreambuf.h:116
std::list< ElementType > ChannelContainerType
Definition: cmnLODMultiplexerStreambuf.h:124
virtual std::streamsize xsputn(const _element *s, std::streamsize n, cmnLogLevel level)
Definition: cmnLODMultiplexerStreambuf.h:382
short cmnLogMask
Definition: cmnLogLoD.h:67
void RemoveMultiplexer(ThisType *multiplexer)
Definition: cmnLODMultiplexerStreambuf.h:339
MultiplexerContainerType::iterator MultiplexerIteratorType
Definition: cmnLODMultiplexerStreambuf.h:129
MultiplexerIteratorType FindMultiplexer(const ThisType *multiplexer)
Definition: cmnLODMultiplexerStreambuf.h:549
bool AddChannel(ChannelType *channel, cmnLogMask mask)
Definition: cmnLODMultiplexerStreambuf.h:302
void RemoveAllChannels(void)
Definition: cmnLODMultiplexerStreambuf.h:350
std::pair< ChannelType *, cmnLogMask > ElementType
Definition: cmnLODMultiplexerStreambuf.h:118
#define CMN_LOG_ALLOW_ALL
Definition: cmnLogLoD.h:75
virtual int sync()
Definition: cmnLODMultiplexerStreambuf.h:408
cmnLODMultiplexerStreambuf(std::ofstream &fileStream)
Definition: cmnLODMultiplexerStreambuf.h:136
cmnLODMultiplexerStreambuf()
Definition: cmnLODMultiplexerStreambuf.h:143
bool GetChannelMask(const ChannelType *channel, cmnLogMask &mask) const
Definition: cmnLODMultiplexerStreambuf.h:370
A Streambuffer class that allows output to multiple streambuf objects for Level of Detail information...
Definition: cmnLODMultiplexerStreambuf.h:108
MultiplexerContainerType::const_iterator MultiplexerConstIteratorType
Definition: cmnLODMultiplexerStreambuf.h:130