// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once #include "ISerializer.h" #include #include #include #include #include #include #include #include #include #include #include namespace CryptoNote { template typename std::enable_if::value>::type serializeAsBinary(std::vector& value, Common::StringView name, CryptoNote::ISerializer& serializer) { std::string blob; if (serializer.type() == ISerializer::INPUT) { serializer.binary(blob, name); value.resize(blob.size() / sizeof(T)); if (blob.size()) { memcpy(&value[0], blob.data(), blob.size()); } } else { if (!value.empty()) { blob.assign(reinterpret_cast(&value[0]), value.size() * sizeof(T)); } serializer.binary(blob, name); } } template typename std::enable_if::value>::type serializeAsBinary(std::list& value, Common::StringView name, CryptoNote::ISerializer& serializer) { std::string blob; if (serializer.type() == ISerializer::INPUT) { serializer.binary(blob, name); size_t count = blob.size() / sizeof(T); const T* ptr = reinterpret_cast(blob.data()); while (count--) { value.push_back(*ptr++); } } else { if (!value.empty()) { blob.resize(value.size() * sizeof(T)); T* ptr = reinterpret_cast(&blob[0]); for (const auto& item : value) { *ptr++ = item; } } serializer.binary(blob, name); } } template bool serializeContainer(Cont& value, Common::StringView name, CryptoNote::ISerializer& serializer) { size_t size = value.size(); if (!serializer.beginArray(size, name)) { value.clear(); return false; } value.resize(size); for (auto& item : value) { serializer(const_cast(item), ""); } serializer.endArray(); return true; } template bool serializeEnumClass(E& value, Common::StringView name, CryptoNote::ISerializer& serializer) { static_assert(std::is_enum::value, "E must be an enum class"); typedef typename std::underlying_type::type EType; if (serializer.type() == CryptoNote::ISerializer::INPUT) { EType numericValue; serializer(numericValue, name); value = static_cast(numericValue); } else { auto numericValue = static_cast(value); serializer(numericValue, name); } return true; } template bool serialize(std::vector& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeContainer(value, name, serializer); } template bool serialize(std::list& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeContainer(value, name, serializer); } template bool serializeMap(MapT& value, Common::StringView name, CryptoNote::ISerializer& serializer, ReserveOp reserve) { size_t size = value.size(); if (!serializer.beginArray(size, name)) { value.clear(); return false; } if (serializer.type() == CryptoNote::ISerializer::INPUT) { reserve(size); for (size_t i = 0; i < size; ++i) { typename MapT::key_type key; typename MapT::mapped_type v; serializer.beginObject(""); serializer(key, "key"); serializer(v, "value"); serializer.endObject(); value.insert(std::make_pair(std::move(key), std::move(v))); } } else { for (auto& kv : value) { serializer.beginObject(""); serializer(const_cast(kv.first), "key"); serializer(kv.second, "value"); serializer.endObject(); } } serializer.endArray(); return true; } template bool serializeSet(SetT& value, Common::StringView name, CryptoNote::ISerializer& serializer) { size_t size = value.size(); if (!serializer.beginArray(size, name)) { value.clear(); return false; } if (serializer.type() == CryptoNote::ISerializer::INPUT) { for (size_t i = 0; i < size; ++i) { typename SetT::value_type key; serializer(key, ""); value.insert(std::move(key)); } } else { for (auto& key : value) { serializer(const_cast(key), ""); } } serializer.endArray(); return true; } template bool serialize(std::unordered_set& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeSet(value, name, serializer); } template bool serialize(std::set& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeSet(value, name, serializer); } template bool serialize(std::unordered_map& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeMap(value, name, serializer, [&value](size_t size) { value.reserve(size); }); } template bool serialize(std::unordered_multimap& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeMap(value, name, serializer, [&value](size_t size) { value.reserve(size); }); } template bool serialize(std::map& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeMap(value, name, serializer, [](size_t size) {}); } template bool serialize(std::multimap& value, Common::StringView name, CryptoNote::ISerializer& serializer) { return serializeMap(value, name, serializer, [](size_t size) {}); } template bool serialize(std::array& value, Common::StringView name, CryptoNote::ISerializer& s) { return s.binary(value.data(), value.size(), name); } template void serialize(std::pair& value, ISerializer& s) { s(value.first, "first"); s(value.second, "second"); } template void writeSequence(Iterator begin, Iterator end, Common::StringView name, ISerializer& s) { size_t size = std::distance(begin, end); s.beginArray(size, name); for (Iterator i = begin; i != end; ++i) { s(const_cast(*i), ""); } s.endArray(); } template void readSequence(Iterator outputIterator, Common::StringView name, ISerializer& s) { size_t size = 0; s.beginArray(size, name); while (size--) { Element e; s(e, ""); *outputIterator++ = std::move(e); } s.endArray(); } //convinience function since we change block height type void serializeBlockHeight(ISerializer& s, uint32_t& blockHeight, Common::StringView name); //convinience function since we change global output index type void serializeGlobalOutputIndex(ISerializer& s, uint32_t& globalOutputIndex, Common::StringView name); }