You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

63 lines
2.0 KiB

  1. #ifndef APT_HELPER_TEESTREAM_H
  2. #define APT_HELPER_TEESTREAM_H
  3. /* 'basic' implementation of a streambuf which passes the output
  4. to two 'real' streambufs emulating '| tee' on the shell
  5. The main use is streaming debug output to std::clog as well as
  6. a logfile easily, so don't expect that to be a bulletproof
  7. implementation. */
  8. #include <iostream>
  9. #include <apt-pkg/macros.h>
  10. template <typename CharT, typename Traits = std::char_traits<CharT>
  11. > class basic_teebuf: public std::basic_streambuf<CharT, Traits>
  12. {
  13. public:
  14. basic_teebuf(std::basic_streambuf<CharT, Traits> * const sb1,
  15. std::basic_streambuf<CharT, Traits> * const sb2)
  16. : s1(sb1), s2(sb2) {}
  17. protected:
  18. virtual std::streamsize xsputn(const CharT* s, std::streamsize c) APT_OVERRIDE
  19. {
  20. return s2->sputn(s, s1->sputn(s, c));
  21. }
  22. // overflow is the fallback of sputc which is non-virtual
  23. typedef typename Traits::int_type int_type;
  24. virtual int_type overflow(int_type ch = Traits::eof()) APT_OVERRIDE
  25. {
  26. auto const eof = Traits::eof();
  27. if (Traits::eq_int_type(ch, Traits::eof()) == true)
  28. return eof;
  29. auto const r1 = s1->sputc(Traits::to_char_type(ch));
  30. auto const r2 = s2->sputc(Traits::to_char_type(ch));
  31. return Traits::eq_int_type(r1, eof) ? r1: r2;
  32. }
  33. virtual void imbue(const std::locale& loc) APT_OVERRIDE
  34. {
  35. s1->pubimbue(loc);
  36. s2->pubimbue(loc);
  37. }
  38. virtual int sync() APT_OVERRIDE
  39. {
  40. auto const r1 = s1->pubsync();
  41. auto const r2 = s2->pubsync();
  42. return r1 == 0 ? r2 : r1;
  43. }
  44. private:
  45. std::basic_streambuf<CharT, Traits> * const s1;
  46. std::basic_streambuf<CharT, Traits> * const s2;
  47. };
  48. template <typename CharT, typename Traits = std::char_traits<CharT>
  49. > class basic_teeostream: public std::basic_ostream<CharT, Traits>
  50. {
  51. public:
  52. basic_teeostream(std::basic_ostream<CharT, Traits> &o1, std::basic_ostream<CharT, Traits> &o2) :
  53. std::basic_ostream<CharT, Traits>(&tbuf), tbuf(o1.rdbuf(), o2.rdbuf()) {}
  54. private:
  55. basic_teebuf<CharT, Traits> tbuf;
  56. };
  57. #endif