/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #ifndef INCLUDED_SERIALIZED_TYPES #define INCLUDED_SERIALIZED_TYPES /** * @file * Provide specializations for some generic types and containers. */ #include "simulation2/serialization/SerializeTemplates.h" #include "lib/types.h" #include #include #include #include #include #include template struct SerializeHelper> { void operator()(ISerializer& serialize, const char* name, std::array& value) { for (size_t i = 0; i < N; ++i) Serializer(serialize, name, value[i]); } void operator()(IDeserializer& deserialize, const char* name, std::array& value) { for (size_t i = 0; i < N; ++i) Serializer(deserialize, name, value[i]); } }; template struct SerializeHelper> { void operator()(ISerializer& serialize, const char* name, std::vector& value) { size_t len = value.size(); serialize.NumberU32_Unbounded("length", (u32)len); for (size_t i = 0; i < len; ++i) Serializer(serialize, name, value[i]); } void operator()(IDeserializer& deserialize, const char* name, std::vector& value) { value.clear(); u32 len; deserialize.NumberU32_Unbounded("length", len); value.reserve(len); // TODO: watch out for out-of-memory for (size_t i = 0; i < len; ++i) { T el; Serializer(deserialize, name, el); value.emplace_back(el); } } }; template struct SerializeHelper> { void operator()(ISerializer& serialize, const char* name, const std::set& value) { serialize.NumberU32_Unbounded("size", static_cast(value.size())); for (const T& elem : value) Serializer(serialize, name, elem); } void operator()(IDeserializer& deserialize, const char* name, std::set& value) { value.clear(); u32 size; deserialize.NumberU32_Unbounded("size", size); for (size_t i = 0; i < size; ++i) { T el; Serializer(deserialize, name, el); value.emplace(std::move(el)); } } }; template struct SerializeHelper> { template void operator()(ISerializer& serialize, const char* UNUSED(name), std::map& value, Args&&... args) { size_t len = value.size(); serialize.NumberU32_Unbounded("length", (u32)len); for (typename std::map::iterator it = value.begin(); it != value.end(); ++it) { Serializer(serialize, "key", it->first, std::forward(args)...); Serializer(serialize, "value", it->second, std::forward(args)...); } } template void operator()(IDeserializer& deserialize, const char* UNUSED(name), std::map& value, Args&&... args) { value.clear(); u32 len; deserialize.NumberU32_Unbounded("length", len); for (size_t i = 0; i < len; ++i) { K k; V v; Serializer(deserialize, "key", k, std::forward(args)...); Serializer(deserialize, "value", v, std::forward(args)...); value.emplace(std::move(k), std::move(v)); } } }; // We have to order the map before serializing to make things consistent template struct SerializeHelper> { void operator()(ISerializer& serialize, const char* name, std::unordered_map& value) { std::map ordered_value(value.begin(), value.end()); Serializer(serialize, name, ordered_value); } void operator()(IDeserializer& deserialize, const char* name, std::unordered_map& value) { Serializer(deserialize, name, value); } }; template<> struct SerializeHelper { void operator()(ISerializer& serialize, const char* name, u8 value) { serialize.NumberU8_Unbounded(name, value); } void operator()(IDeserializer& deserialize, const char* name, u8& value) { deserialize.NumberU8_Unbounded(name, value); } }; template struct SerializeHelper>> { void operator()(ISerializer& serialize, const char* name, Enum value, Enum&& max) { serialize.NumberU8(name, static_cast(value), 0, static_cast(max)); } void operator()(IDeserializer& deserialize, const char* name, Enum& value, Enum&& max) { u8 val; deserialize.NumberU8(name, val, 0, static_cast(max)); value = static_cast(val); } }; template<> struct SerializeHelper { void operator()(ISerializer& serialize, const char* name, u16 value) { serialize.NumberU16_Unbounded(name, value); } void operator()(IDeserializer& deserialize, const char* name, u16& value) { deserialize.NumberU16_Unbounded(name, value); } }; template<> struct SerializeHelper { template void operator()(ISerializer& serialize, const char* name, u32 value, Args&&...) { serialize.NumberU32_Unbounded(name, value); } template void operator()(IDeserializer& deserialize, const char* name, u32& value, Args&&...) { deserialize.NumberU32_Unbounded(name, value); } }; template<> struct SerializeHelper { void operator()(ISerializer& serialize, const char* name, i32 value) { serialize.NumberI32_Unbounded(name, value); } void operator()(IDeserializer& deserialize, const char* name, i32& value) { deserialize.NumberI32_Unbounded(name, value); } }; template<> struct SerializeHelper { void operator()(ISerializer& serialize, const char* name, bool value) { serialize.Bool(name, value); } void operator()(IDeserializer& deserialize, const char* name, bool& value) { deserialize.Bool(name, value); } }; template struct SerializeHelper>> { template void operator()(ISerializer& serialize, const char* name, T&& value) { serialize.StringASCII(name, value, 0, UINT32_MAX); } template void operator()(IDeserializer& deserialize, const char* name, T& value) { deserialize.StringASCII(name, value, 0, UINT32_MAX); } }; #endif // INCLUDED_SERIALIZED_TYPES