diff options
Diffstat (limited to 'src/serialization/binary_archive.h')
-rw-r--r-- | src/serialization/binary_archive.h | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h new file mode 100644 index 000000000..f28e45c0c --- /dev/null +++ b/src/serialization/binary_archive.h @@ -0,0 +1,169 @@ +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/* binary_archive.h + * + * Portable (low-endian) binary archive */ +#pragma once + +#include <cassert> +#include <iostream> +#include <iterator> +#include <boost/type_traits/make_unsigned.hpp> + +#include "common/varint.h" +#include "warnings.h" + +PUSH_WARNINGS +DISABLE_VS_WARNINGS(4244) + +//TODO: fix size_t warning in x32 platform + +template <class Stream, bool IsSaving> +struct binary_archive_base +{ + typedef Stream stream_type; + typedef binary_archive_base<Stream, IsSaving> base_type; + typedef boost::mpl::bool_<IsSaving> is_saving; + + typedef uint8_t variant_tag_type; + + explicit binary_archive_base(stream_type &s) : stream_(s) { } + + void tag(const char *) { } + void begin_object() { } + void end_object() { } + void begin_variant() { } + void end_variant() { } + stream_type &stream() { return stream_; } +protected: + stream_type &stream_; +}; + +template <bool W> +struct binary_archive; + +template <> +struct binary_archive<false> : public binary_archive_base<std::istream, false> +{ + explicit binary_archive(stream_type &s) : base_type(s) { + stream_type::streampos pos = stream_.tellg(); + stream_.seekg(0, std::ios_base::end); + eof_pos_ = stream_.tellg(); + stream_.seekg(pos); + } + + template <class T> + void serialize_int(T &v) + { + serialize_uint(*(typename boost::make_unsigned<T>::type *)&v); + } + + template <class T> + void serialize_uint(T &v, size_t width = sizeof(T)) + { + T ret = 0; + unsigned shift = 0; + for (size_t i = 0; i < width; i++) { + //std::cerr << "tell: " << stream_.tellg() << " value: " << ret << std::endl; + char c; + stream_.get(c); + T b = (unsigned char)c; + ret += (b << shift); + shift += 8; + } + v = ret; + } + void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.read((char *)buf, len); } + + template <class T> + void serialize_varint(T &v) + { + serialize_uvarint(*(typename boost::make_unsigned<T>::type *)(&v)); + } + + template <class T> + void serialize_uvarint(T &v) + { + typedef std::istreambuf_iterator<char> it; + tools::read_varint(it(stream_), it(), v); // XXX handle failure + } + void begin_array(size_t &s) + { + serialize_varint(s); + } + void begin_array() { } + + void delimit_array() { } + void end_array() { } + + void begin_string(const char *delimiter="\"") { } + void end_string(const char *delimiter="\"") { } + + void read_variant_tag(variant_tag_type &t) { + serialize_int(t); + } + + size_t remaining_bytes() { + if (!stream_.good()) + return 0; + //std::cerr << "tell: " << stream_.tellg() << std::endl; + assert(stream_.tellg() <= eof_pos_); + return eof_pos_ - stream_.tellg(); + } +protected: + std::streamoff eof_pos_; +}; + +template <> +struct binary_archive<true> : public binary_archive_base<std::ostream, true> +{ + explicit binary_archive(stream_type &s) : base_type(s) { } + + template <class T> + void serialize_int(T v) + { + serialize_uint(static_cast<typename boost::make_unsigned<T>::type>(v)); + } + template <class T> + void serialize_uint(T v) + { + for (size_t i = 0; i < sizeof(T); i++) { + stream_.put((char)(v & 0xff)); + if (1 < sizeof(T)) { + v >>= 8; + } + } + } + void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.write((char *)buf, len); } + + template <class T> + void serialize_varint(T &v) + { + serialize_uvarint(*(typename boost::make_unsigned<T>::type *)(&v)); + } + + template <class T> + void serialize_uvarint(T &v) + { + typedef std::ostreambuf_iterator<char> it; + tools::write_varint(it(stream_), v); + } + void begin_array(size_t s) + { + serialize_varint(s); + } + void begin_array() { } + void delimit_array() { } + void end_array() { } + + void begin_string(const char *delimiter="\"") { } + void end_string(const char *delimiter="\"") { } + + void write_variant_tag(variant_tag_type t) { + serialize_int(t); + } +}; + +POP_WARNINGS |