--- /dev/null
+#include "struct.h"
+#include <algorithm>
+#include <msp/core/maputils.h>
+#include <msp/io/print.h>
+#include "setupgen.h"
+
+using namespace std;
+using namespace Msp;
+
+class Struct::Field::Loader: public Msp::DataFile::ObjectLoader<Struct::Field>
+{
+public:
+ Loader(Struct::Field &);
+
+private:
+ void init_actions() override;
+};
+
+
+Struct::Struct(const string &n, Kind k):
+ name(n),
+ kind(k)
+{ }
+
+void Struct::define_type(IO::Base &out) const
+{
+ IO::print(out, "struct %s\n{\n", name);
+ IO::print(out, "\tclass Loader;\n\n");
+
+ for(const Field &f: fields)
+ {
+ IO::print(out, "\t%s %s", f.type->get_cpp_type(), f.name);
+ if(!f.default_value.empty())
+ {
+ if(const string &c = f.type->get_conversion(); !c.empty())
+ IO::print(out, " = %s(%s)", f.type->get_conversion(), f.default_value);
+ else if(f.type->get_kind() == Type::AGGREGATE)
+ IO::print(out, " = { %s }", f.default_value);
+ else if(f.type->get_kind() == Type::ENUM)
+ IO::print(out, " = %s::%s", f.type->get_name(), f.default_value);
+ else
+ IO::print(out, " = %s", f.default_value);
+ }
+ IO::print(out, ";\n");
+ }
+
+ IO::print(out, "};\n");
+}
+
+void Struct::define_loader(IO::Base &out) const
+{
+ IO::print(out, "class %s::Loader: public Msp::DataFile::ObjectLoader<%s>\n{\n", name, name);
+ IO::print(out, "public:\n");
+ IO::print(out, "\tLoader(%s &);\n", name);
+ IO::print(out, "\nprivate:\n");
+ IO::print(out, "\tvoid init_actions() override;\n");
+ for(const Field &f: fields)
+ if(f.type->needs_loader_function())
+ IO::print(out, "\tvoid %s(%s);\n", f.name, f.type->create_loader_params(false));
+ IO::print(out, "};\n");
+}
+
+void Struct::define_functions(IO::Base &out) const
+{
+ IO::print(out, "%s::Loader::Loader(%s &o):\n", name, name);
+ IO::print(out, "\tObjectLoader<%s>(o)\n{\n", name);
+ IO::print(out, "\tstatic ActionMap shared_actions;\n");
+ IO::print(out, "\tset_actions(shared_actions);\n}\n");
+
+ IO::print(out, "\nvoid %s::Loader::init_actions()\n{\n", name);
+ for(const Field &f: fields)
+ {
+ IO::print(out, "\tadd(\"%s\", ", f.name);
+ if(f.type->needs_loader_function())
+ IO::print(out, "&Loader::%s", f.name);
+ else
+ IO::print(out, "&%s::%s", name, f.name);
+ IO::print(out, ");\n");
+ }
+ IO::print(out, "}\n");
+
+ for(const Field &f: fields)
+ if(f.type->needs_loader_function())
+ {
+ IO::print(out, "\nvoid %s::Loader::%s(%s)\n{\n", name, f.name, f.type->create_loader_params(true));
+ IO::print(out, "\tauto &_v = obj.%s;\n", f.name);
+ IO::print(out, "\t%s\n", f.type->create_loader_statement());
+ IO::print(out, "}\n");
+ }
+}
+
+
+Struct::Loader::Loader(Struct &s, const SetupGen &g):
+ ObjectLoader<Struct>(s),
+ gen(g)
+{
+ static ActionMap shared_actions;
+ set_actions(shared_actions);
+}
+
+void Struct::Loader::init_actions()
+{
+ add("field", &Loader::field);
+}
+
+void Struct::Loader::field(const DataFile::Symbol &n, const DataFile::Symbol &t)
+{
+ if(ranges::any_of(obj.fields, [&n](const Field &f){ return f.name==n.name; }))
+ throw key_error(n.name);
+ Field fld;
+ fld.name=n.name;
+ fld.type=&gen.get_type(t.name);
+ load_sub(fld);
+ obj.fields.emplace_back(move(fld));
+}
+
+
+Struct::Field::Loader::Loader(Field &f):
+ ObjectLoader<Field>(f)
+{
+ static ActionMap shared_actions;
+ set_actions(shared_actions);
+}
+
+void Struct::Field::Loader::init_actions()
+{
+ add("default", &Field::default_value);
+}