]> git.tdb.fi Git - libs/game.git/blobdiff - tools/setupgen/struct.cpp
Add a tool for generating setup structs and loaders for them
[libs/game.git] / tools / setupgen / struct.cpp
diff --git a/tools/setupgen/struct.cpp b/tools/setupgen/struct.cpp
new file mode 100644 (file)
index 0000000..b93b5be
--- /dev/null
@@ -0,0 +1,128 @@
+#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);
+}