Commit d1af88ed authored by Matthias Vallentin's avatar Matthias Vallentin

Relax streambuffer character requirements

Previously, we enforced that the stream buffer must inherit from
std::streambuf, which restricts the character type of stream buffers to
char only. With uint8_t buffers being as common, this restriction turns
out to be too tight. This change relaxes it.
parent e82c9590
......@@ -43,7 +43,9 @@ namespace caf {
template <class Streambuf>
class stream_deserializer : public deserializer {
using streambuf_type = typename std::remove_reference<Streambuf>::type;
static_assert(std::is_base_of<std::streambuf, streambuf_type>::value,
using char_type = typename streambuf_type::char_type;
using streambuf_base = std::basic_streambuf<char_type>;
static_assert(std::is_base_of<streambuf_base, streambuf_type>::value,
"Streambuf must inherit from std::streambuf");
public:
......@@ -93,7 +95,7 @@ public:
void apply_raw(size_t num_bytes, void* data) override {
range_check(num_bytes);
streambuf_.sgetn(reinterpret_cast<char*>(data), num_bytes);
streambuf_.sgetn(reinterpret_cast<char_type*>(data), num_bytes);
}
protected:
......@@ -158,7 +160,8 @@ protected:
str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a
// non-const overload.
size_t n = streambuf_.sgetn(reinterpret_cast<char*>(&str[0]), str_size);
auto data = reinterpret_cast<char_type*>(&str[0]);
size_t n = streambuf_.sgetn(data, str_size);
CAF_ASSERT(n == str_size);
end_sequence();
break;
......@@ -172,7 +175,8 @@ protected:
str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a
// non-const overload.
size_t n = streambuf_.sgetn(reinterpret_cast<char*>(&str[0]), bytes);
auto data = reinterpret_cast<char_type*>(&str[0]);
size_t n = streambuf_.sgetn(data, bytes);
CAF_ASSERT(n == bytes);
end_sequence();
break;
......@@ -186,7 +190,8 @@ protected:
str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a
// non-const overload.
size_t n = streambuf_.sgetn(reinterpret_cast<char*>(&str[0]), bytes);
auto data = reinterpret_cast<char_type*>(&str[0]);
size_t n = streambuf_.sgetn(data, bytes);
CAF_ASSERT(n == bytes);
end_sequence();
break;
......
......@@ -41,7 +41,9 @@ namespace caf {
template <class Streambuf>
class stream_serializer : public serializer {
using streambuf_type = typename std::remove_reference<Streambuf>::type;
static_assert(std::is_base_of<std::streambuf, streambuf_type>::value,
using char_type = typename streambuf_type::char_type;
using streambuf_base = std::basic_streambuf<char_type>;
static_assert(std::is_base_of<streambuf_base, streambuf_type>::value,
"Streambuf must inherit from std::streambuf");
public:
......@@ -90,7 +92,7 @@ public:
}
void apply_raw(size_t num_bytes, void* data) override {
streambuf_.sputn(reinterpret_cast<char*>(data), num_bytes);
streambuf_.sputn(reinterpret_cast<char_type*>(data), num_bytes);
}
protected:
......@@ -107,7 +109,6 @@ protected:
x >>= 7;
}
*i++ = static_cast<uint8_t>(x) & 0x7f;
using char_type = typename streambuf_type::traits_type::char_type;
return streambuf_.sputn(reinterpret_cast<char_type*>(buf), i - buf);
}
......@@ -143,16 +144,15 @@ protected:
oss << std::setprecision(std::numeric_limits<long double>::digits)
<< *reinterpret_cast<long double*>(val);
auto tmp = oss.str();
auto s = static_cast<uint32_t>(tmp.size());
apply(s);
apply_raw(tmp.size(), const_cast<char*>(tmp.c_str()));
apply(tmp);
break;
}
case string8_v: {
auto str = reinterpret_cast<std::string*>(val);
auto s = str->size();
begin_sequence(s);
apply_raw(str->size(), const_cast<char*>(str->c_str()));
auto data = const_cast<std::string::value_type*>(str->data());
apply_raw(str->size(), reinterpret_cast<char_type*>(data));
end_sequence();
break;
}
......
......@@ -438,17 +438,20 @@ CAF_TEST(streambuf_serialization) {
}
CAF_TEST(byte_sequence_optimization) {
std::vector<char> data(42);
std::fill(data.begin(), data.end(), 'a');
std::vector<char> buf;
stream_serializer<vectorbuf> bs{vectorbuf{buf}};
std::vector<uint8_t> data(42);
std::fill(data.begin(), data.end(), 0x2a);
std::vector<uint8_t> buf;
using streambuf_type = containerbuf<std::vector<uint8_t>>;
streambuf_type cb{buf};
stream_serializer<streambuf_type&> bs{cb};
bs << data;
data.clear();
stream_deserializer<charbuf> bd{charbuf{buf}};
streambuf_type cb2{buf};
stream_deserializer<streambuf_type&> bd{cb2};
bd >> data;
CAF_CHECK_EQUAL(data.size(), 42u);
CAF_CHECK(std::all_of(data.begin(), data.end(),
[](char c) { return c == 'a'; }));
[](uint8_t c) { return c == 0x2a; }));
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment