0%

Wrapper std::vector for serialization / deserialization

C++ 的Serialization / Deserialization已經很成熟了
有了Boost 和 Cereal可以選,不過它們需要ifstreamofstream做參數傳入
如果我們需要用於網路傳輸跟Database該怎麼辦
Boost ASIO幫我們解決了這個問題

Output Wrapper

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
template <typename Container, typename SinkType, typename CharType>
class container_sink
{
public:
typedef CharType char_type;
typedef boost::iostreams::sink_tag category;

container_sink(Container& container)
: container_(container)
{
static_assert(sizeof(SinkType) == sizeof(CharType), "invalid size");
}

std::streamsize write(const char_type* buffer, std::streamsize size)
{
const auto safe_sink = reinterpret_cast<const SinkType*>(buffer);
container_.insert(container_.end(), safe_sink, safe_sink + size);
return size;
}

private:
Container& container_;
};

template <typename Container>
using byte_sink = container_sink<Container, uint8_t, char>;
using data_sink = boost::iostreams::stream<byte_sink<data_chunk>>;

如何使用

1
2
3
4
5
6
7
data_chunk data;
data_sink ostream(data);
boost::archive::binary_oarchive oa(ostream);
const gps_position g(35, 59, 24.567f);
oa << g;
ostream.flush();
return ostream;

Input Wrapper

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
template <typename Container, typename SourceType, typename CharType>
class container_source
{
public:
typedef CharType char_type;
typedef boost::iostreams::source_tag category;

container_source(const Container& container)
: container_(container), position_(0)
{
static_assert(sizeof(SourceType) == sizeof(CharType), "invalid size");
}

std::streamsize read(char_type* buffer, std::streamsize size)
{
const auto amount = container_.size() - position_;
const auto result = std::min(size,
static_cast<std::streamsize>(amount));

// TODO: use ios eof symbol (template-based).
if (result <= 0)
return -1;

const auto value = static_cast<typename Container::size_type>(result);
const auto limit = position_ + value;
const auto start = container_.begin() + position_;

const auto end = container_.begin() + limit;
std::copy(start, end, buffer);
position_ = limit;
return result;
}

private:
const Container& container_;
typename Container::size_type position_;
};

template <typename Container>
using byte_source = container_source<Container, uint8_t, char>;
using data_source = boost::iostreams::stream<byte_source<data_chunk>>;

如何使用

1
2
3
4
data_chunk data;
data_source istream(data);
boost::archive::binary_iarchive ia(istream);
istream >> g;