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 { ...@@ -43,7 +43,9 @@ namespace caf {
template <class Streambuf> template <class Streambuf>
class stream_deserializer : public deserializer { class stream_deserializer : public deserializer {
using streambuf_type = typename std::remove_reference<Streambuf>::type; 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"); "Streambuf must inherit from std::streambuf");
public: public:
...@@ -93,7 +95,7 @@ public: ...@@ -93,7 +95,7 @@ public:
void apply_raw(size_t num_bytes, void* data) override { void apply_raw(size_t num_bytes, void* data) override {
range_check(num_bytes); range_check(num_bytes);
streambuf_.sgetn(reinterpret_cast<char*>(data), num_bytes); streambuf_.sgetn(reinterpret_cast<char_type*>(data), num_bytes);
} }
protected: protected:
...@@ -158,7 +160,8 @@ protected: ...@@ -158,7 +160,8 @@ protected:
str.resize(str_size); str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a // TODO: When using C++14, switch to str.data(), which then has a
// non-const overload. // 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); CAF_ASSERT(n == str_size);
end_sequence(); end_sequence();
break; break;
...@@ -172,7 +175,8 @@ protected: ...@@ -172,7 +175,8 @@ protected:
str.resize(str_size); str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a // TODO: When using C++14, switch to str.data(), which then has a
// non-const overload. // 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); CAF_ASSERT(n == bytes);
end_sequence(); end_sequence();
break; break;
...@@ -186,7 +190,8 @@ protected: ...@@ -186,7 +190,8 @@ protected:
str.resize(str_size); str.resize(str_size);
// TODO: When using C++14, switch to str.data(), which then has a // TODO: When using C++14, switch to str.data(), which then has a
// non-const overload. // 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); CAF_ASSERT(n == bytes);
end_sequence(); end_sequence();
break; break;
......
...@@ -41,7 +41,9 @@ namespace caf { ...@@ -41,7 +41,9 @@ namespace caf {
template <class Streambuf> template <class Streambuf>
class stream_serializer : public serializer { class stream_serializer : public serializer {
using streambuf_type = typename std::remove_reference<Streambuf>::type; 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"); "Streambuf must inherit from std::streambuf");
public: public:
...@@ -90,7 +92,7 @@ public: ...@@ -90,7 +92,7 @@ public:
} }
void apply_raw(size_t num_bytes, void* data) override { 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: protected:
...@@ -107,7 +109,6 @@ protected: ...@@ -107,7 +109,6 @@ protected:
x >>= 7; x >>= 7;
} }
*i++ = static_cast<uint8_t>(x) & 0x7f; *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); return streambuf_.sputn(reinterpret_cast<char_type*>(buf), i - buf);
} }
...@@ -143,16 +144,15 @@ protected: ...@@ -143,16 +144,15 @@ protected:
oss << std::setprecision(std::numeric_limits<long double>::digits) oss << std::setprecision(std::numeric_limits<long double>::digits)
<< *reinterpret_cast<long double*>(val); << *reinterpret_cast<long double*>(val);
auto tmp = oss.str(); auto tmp = oss.str();
auto s = static_cast<uint32_t>(tmp.size()); apply(tmp);
apply(s);
apply_raw(tmp.size(), const_cast<char*>(tmp.c_str()));
break; break;
} }
case string8_v: { case string8_v: {
auto str = reinterpret_cast<std::string*>(val); auto str = reinterpret_cast<std::string*>(val);
auto s = str->size(); auto s = str->size();
begin_sequence(s); 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(); end_sequence();
break; break;
} }
......
...@@ -438,17 +438,20 @@ CAF_TEST(streambuf_serialization) { ...@@ -438,17 +438,20 @@ CAF_TEST(streambuf_serialization) {
} }
CAF_TEST(byte_sequence_optimization) { CAF_TEST(byte_sequence_optimization) {
std::vector<char> data(42); std::vector<uint8_t> data(42);
std::fill(data.begin(), data.end(), 'a'); std::fill(data.begin(), data.end(), 0x2a);
std::vector<char> buf; std::vector<uint8_t> buf;
stream_serializer<vectorbuf> bs{vectorbuf{buf}}; using streambuf_type = containerbuf<std::vector<uint8_t>>;
streambuf_type cb{buf};
stream_serializer<streambuf_type&> bs{cb};
bs << data; bs << data;
data.clear(); data.clear();
stream_deserializer<charbuf> bd{charbuf{buf}}; streambuf_type cb2{buf};
stream_deserializer<streambuf_type&> bd{cb2};
bd >> data; bd >> data;
CAF_CHECK_EQUAL(data.size(), 42u); CAF_CHECK_EQUAL(data.size(), 42u);
CAF_CHECK(std::all_of(data.begin(), data.end(), 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() 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