Index: ps/trunk/source/simulation2/serialization/SerializeTemplates.h
===================================================================
--- ps/trunk/source/simulation2/serialization/SerializeTemplates.h (revision 23043)
+++ ps/trunk/source/simulation2/serialization/SerializeTemplates.h (revision 23044)
@@ -1,312 +1,343 @@
-/* Copyright (C) 2016 Wildfire Games.
+/* Copyright (C) 2019 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_SERIALIZETEMPLATES
#define INCLUDED_SERIALIZETEMPLATES
/**
* @file
* Helper templates for serializing/deserializing common objects.
*/
#include "simulation2/components/ICmpPathfinder.h"
+#include "simulation2/serialization/IDeserializer.h"
+#include "simulation2/serialization/ISerializer.h"
+
+#include
+#include
template
struct SerializeVector
{
template
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)
ELEM()(serialize, name, value[i]);
}
template
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;
ELEM()(deserialize, name, el);
value.push_back(el);
}
}
};
template
struct SerializeRepetitiveVector
{
template
void operator()(ISerializer& serialize, const char* name, std::vector& value)
{
size_t len = value.size();
serialize.NumberU32_Unbounded("length", (u32)len);
if (len == 0)
return;
u32 count = 1;
T prevVal = value[0];
for (size_t i = 1; i < len; ++i)
{
if (prevVal == value[i])
{
count++;
continue;
}
serialize.NumberU32_Unbounded("#", count);
ELEM()(serialize, name, prevVal);
count = 1;
prevVal = value[i];
}
serialize.NumberU32_Unbounded("#", count);
ELEM()(serialize, name, prevVal);
}
template
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;)
{
u32 count;
deserialize.NumberU32_Unbounded("#", count);
T el;
ELEM()(deserialize, name, el);
i += count;
value.insert(value.end(), count, el);
}
}
};
+template
+struct SerializeSet
+{
+ template
+ void operator()(ISerializer& serialize, const char* name, const std::set& value)
+ {
+ serialize.NumberU32_Unbounded("size", static_cast(value.size()));
+ for (const T& elem : value)
+ ELEM()(serialize, name, elem);
+ }
+
+ template
+ 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;
+ ELEM()(deserialize, name, el);
+ value.emplace(std::move(el));
+ }
+ }
+};
+
template
struct SerializeMap
{
template
void operator()(ISerializer& serialize, const char* UNUSED(name), std::map& value)
{
size_t len = value.size();
serialize.NumberU32_Unbounded("length", (u32)len);
for (typename std::map::iterator it = value.begin(); it != value.end(); ++it)
{
KS()(serialize, "key", it->first);
VS()(serialize, "value", it->second);
}
}
template
void operator()(ISerializer& serialize, const char* UNUSED(name), std::map& value, C& context)
{
size_t len = value.size();
serialize.NumberU32_Unbounded("length", (u32)len);
for (typename std::map::iterator it = value.begin(); it != value.end(); ++it)
{
KS()(serialize, "key", it->first);
VS()(serialize, "value", it->second, context);
}
}
template
void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value)
{
typedef typename M::key_type K;
typedef typename M::value_type::second_type V; // M::data_type gives errors with gcc
value.clear();
u32 len;
deserialize.NumberU32_Unbounded("length", len);
for (size_t i = 0; i < len; ++i)
{
K k;
V v;
KS()(deserialize, "key", k);
VS()(deserialize, "value", v);
- value.insert(std::make_pair(k, v));
+ value.emplace(std::move(k), std::move(v));
}
}
template
void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value, C& context)
{
typedef typename M::key_type K;
typedef typename M::value_type::second_type V; // M::data_type gives errors with gcc
value.clear();
u32 len;
deserialize.NumberU32_Unbounded("length", len);
for (size_t i = 0; i < len; ++i)
{
K k;
V v;
KS()(deserialize, "key", k);
VS()(deserialize, "value", v, context);
- value.insert(std::make_pair(k, v));
+ value.emplace(std::move(k), std::move(v));
}
}
};
// We have to order the map before serializing to make things consistent
template
struct SerializeUnorderedMap
{
template
void operator()(ISerializer& serialize, const char* name, boost::unordered_map& value)
{
std::map ordered_value(value.begin(), value.end());
SerializeMap()(serialize, name, ordered_value);
}
template
void operator()(IDeserializer& deserialize, const char* name, boost::unordered_map& value)
{
SerializeMap()(deserialize, name, value);
}
};
template
struct SerializeU8_Enum
{
void operator()(ISerializer& serialize, const char* name, T value)
{
serialize.NumberU8(name, value, 0, max);
}
void operator()(IDeserializer& deserialize, const char* name, T& value)
{
u8 val;
deserialize.NumberU8(name, val, 0, max);
- value = (T)val;
+ value = static_cast(val);
}
};
struct SerializeU8_Unbounded
{
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);
}
};
struct SerializeU16_Unbounded
{
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);
}
};
struct SerializeU32_Unbounded
{
void operator()(ISerializer& serialize, const char* name, u32 value)
{
serialize.NumberU32_Unbounded(name, value);
}
void operator()(IDeserializer& deserialize, const char* name, u32& value)
{
deserialize.NumberU32_Unbounded(name, value);
}
};
struct SerializeI32_Unbounded
{
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);
}
};
struct SerializeBool
{
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);
}
};
struct SerializeString
{
void operator()(ISerializer& serialize, const char* name, const std::string& value)
{
serialize.StringASCII(name, value, 0, UINT32_MAX);
}
void operator()(IDeserializer& deserialize, const char* name, std::string& value)
{
deserialize.StringASCII(name, value, 0, UINT32_MAX);
}
};
struct SerializeWaypoint
{
void operator()(ISerializer& serialize, const char* UNUSED(name), const Waypoint& value)
{
serialize.NumberFixed_Unbounded("waypoint x", value.x);
serialize.NumberFixed_Unbounded("waypoint z", value.z);
}
void operator()(IDeserializer& deserialize, const char* UNUSED(name), Waypoint& value)
{
deserialize.NumberFixed_Unbounded("waypoint x", value.x);
deserialize.NumberFixed_Unbounded("waypoint z", value.z);
}
};
struct SerializeGoal
{
template
void operator()(S& serialize, const char* UNUSED(name), PathGoal& value)
{
SerializeU8_Enum()(serialize, "type", value.type);
serialize.NumberFixed_Unbounded("goal x", value.x);
serialize.NumberFixed_Unbounded("goal z", value.z);
serialize.NumberFixed_Unbounded("goal u x", value.u.X);
serialize.NumberFixed_Unbounded("goal u z", value.u.Y);
serialize.NumberFixed_Unbounded("goal v x", value.v.X);
serialize.NumberFixed_Unbounded("goal v z", value.v.Y);
serialize.NumberFixed_Unbounded("goal hw", value.hw);
serialize.NumberFixed_Unbounded("goal hh", value.hh);
serialize.NumberFixed_Unbounded("maxdist", value.maxdist);
}
};
#endif // INCLUDED_SERIALIZETEMPLATES
Index: ps/trunk/source/simulation2/tests/test_SerializeTemplates.h
===================================================================
--- ps/trunk/source/simulation2/tests/test_SerializeTemplates.h (nonexistent)
+++ ps/trunk/source/simulation2/tests/test_SerializeTemplates.h (revision 23044)
@@ -0,0 +1,56 @@
+/* Copyright (C) 2019 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 .
+ */
+
+#include "lib/self_test.h"
+
+#include "scriptinterface/ScriptInterface.h"
+#include "simulation2/serialization/DebugSerializer.h"
+#include "simulation2/serialization/SerializeTemplates.h"
+
+#include
+#include
+#include
+
+class TestSerializeTemplates : public CxxTest::TestSuite
+{
+public:
+ void test_Debug_vector()
+ {
+ ScriptInterface script("Test", "Test", g_ScriptRuntime);
+ std::stringstream stream;
+
+ CDebugSerializer serialize(script, stream);
+ std::vector value = {
+ 3, 0, 1, 4, 1, 5
+ };
+ SerializeVector()(serialize, "E", value);
+ TS_ASSERT_STR_EQUALS(stream.str(), "length: 6\nE: 3\nE: 0\nE: 1\nE: 4\nE: 1\nE: 5\n");
+ }
+
+ void test_Debug_set()
+ {
+ ScriptInterface script("Test", "Test", g_ScriptRuntime);
+ std::stringstream stream;
+
+ CDebugSerializer serialize(script, stream);
+ std::set value = {
+ 3, 0, 1, 4, 1, 5
+ };
+ SerializeSet()(serialize, "E", value);
+ TS_ASSERT_STR_EQUALS(stream.str(), "size: 5\nE: 0\nE: 1\nE: 3\nE: 4\nE: 5\n");
+ }
+};