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
|
#pragma once
#include <cstring>
#include <functional>
#include <ostream>
#include <type_traits>
namespace ovdl::detail {
template<typename Callback, class CharT, class traits = std::char_traits<CharT>>
class BasicCallbackStreamBuffer : public std::basic_streambuf<CharT, traits> {
public:
using base_type = std::basic_streambuf<CharT, 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 {
auto c = static_cast<char_type>(ch);
if constexpr (std::is_same_v<void, typename decltype(std::function { _callback })::result_type>) {
_callback(&c, 1, _user_data);
return 1;
} else {
return _callback(&c, 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<class CharT, typename Callback, class traits = std::char_traits<CharT>>
class BasicCallbackStream : public std::basic_ostream<CharT, traits> {
public:
using base_type = std::basic_ostream<CharT, traits>;
BasicCallbackStream(Callback cb, void* user_data = nullptr)
: m_sbuf(cb, user_data),
std::basic_ios<CharT, traits>(&m_sbuf),
std::basic_ostream<CharT, traits>(&m_sbuf) {
std::basic_ios<CharT, traits>::init(&m_sbuf);
}
private:
BasicCallbackStreamBuffer<Callback, CharT, traits> m_sbuf;
};
template<typename CharT>
auto make_callback_stream(auto&& cb, void* user_data = nullptr) {
using Callback = std::decay_t<decltype(cb)>;
return BasicCallbackStream<CharT, Callback> { std::forward<Callback>(cb), user_data };
}
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) {
}
};
}
|