aboutsummaryrefslogtreecommitdiff
path: root/include/openvic-dataloader/detail/CallbackOStream.hpp
blob: 641d53fa8d9c3f37b8af9de0e205575e8a423c3b (plain) (blame)
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
#pragma once

#include <cstring>
#include <functional>
#include <ostream>
#include <type_traits>

namespace ovdl::detail {
   template<typename Callback, class CHAR_T, class traits = std::char_traits<CHAR_T>>
   class BasicCallbackStreamBuffer : public std::basic_streambuf<CHAR_T, traits> {
   public:
      using base_type = std::basic_streambuf<CHAR_T, traits>;
      using callback_type = Callback;
      using char_type = typename base_type::char_type;
      using int_type = typename base_type::int_type;

      BasicCallbackStreamBuffer(Callback cb, void* user_data = nullptr)
         : _callback(cb),
           _user_data(user_data) {}

   protected:
      std::streamsize xsputn(const char_type* s, std::streamsize n) override {
         if constexpr (std::is_same_v<void, typename decltype(std::function { _callback })::result_type>) {
            _callback(s, n, _user_data);
            return n;
         } else {
            return _callback(s, n, _user_data); // returns the number of characters successfully written.
         }
      };

      int_type overflow(int_type ch) override {
         if constexpr (std::is_same_v<void, typename decltype(std::function { _callback })::result_type>) {
            _callback(&ch, 1, _user_data);
            return 1;
         } else {
            return _callback(&ch, 1, _user_data); // returns the number of characters successfully written.
         }
      }

   private:
      Callback _callback;
      void* _user_data;
   };

   template<typename Callback>
   class CallbackStreamBuffer : public BasicCallbackStreamBuffer<Callback, char> {
   public:
      using base_type = BasicCallbackStreamBuffer<Callback, char>;
      using callback_type = Callback;
      using char_type = typename base_type::char_type;
      using int_type = typename base_type::int_type;

      CallbackStreamBuffer(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {}
   };

   template<typename Callback>
   class CallbackWStreamBuffer : public BasicCallbackStreamBuffer<Callback, wchar_t> {
   public:
      using base_type = BasicCallbackStreamBuffer<Callback, wchar_t>;
      using callback_type = Callback;
      using char_type = typename base_type::char_type;
      using int_type = typename base_type::int_type;

      CallbackWStreamBuffer(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {}
   };

   template<typename Callback, class CHAR_T, class traits = std::char_traits<CHAR_T>>
   class BasicCallbackStream : public std::basic_ostream<CHAR_T, traits> {
   public:
      using base_type = std::basic_ostream<CHAR_T, traits>;

      BasicCallbackStream(Callback cb, void* user_data = nullptr)
         : m_sbuf(cb, user_data),
           std::basic_ios<CHAR_T, traits>(&m_sbuf),
           std::basic_ostream<CHAR_T, traits>(&m_sbuf) {
         std::basic_ios<CHAR_T, traits>::init(&m_sbuf);
      }

   private:
      BasicCallbackStreamBuffer<Callback, CHAR_T, traits> m_sbuf;
   };

   template<typename Callback>
   class CallbackStream : public BasicCallbackStream<Callback, char> {
   public:
      using base_type = BasicCallbackStream<Callback, char>;

      CallbackStream(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {
      }
   };

   template<typename Callback>
   class CallbackWStream : public BasicCallbackStream<Callback, wchar_t> {
   public:
      using base_type = BasicCallbackStream<Callback, wchar_t>;

      CallbackWStream(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {
      }
   };
}