]> git.tdb.fi Git - libs/game.git/blob - tools/setupgen/struct.cpp
Add a tool for generating setup structs and loaders for them
[libs/game.git] / tools / setupgen / struct.cpp
1 #include "struct.h"
2 #include <algorithm>
3 #include <msp/core/maputils.h>
4 #include <msp/io/print.h>
5 #include "setupgen.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 class Struct::Field::Loader: public Msp::DataFile::ObjectLoader<Struct::Field>
11 {
12 public:
13         Loader(Struct::Field &);
14
15 private:
16         void init_actions() override;
17 };
18
19
20 Struct::Struct(const string &n, Kind k):
21         name(n),
22         kind(k)
23 { }
24
25 void Struct::define_type(IO::Base &out) const
26 {
27         IO::print(out, "struct %s\n{\n", name);
28         IO::print(out, "\tclass Loader;\n\n");
29
30         for(const Field &f: fields)
31         {
32                 IO::print(out, "\t%s %s", f.type->get_cpp_type(), f.name);
33                 if(!f.default_value.empty())
34                 {
35                         if(const string &c = f.type->get_conversion(); !c.empty())
36                                 IO::print(out, " = %s(%s)", f.type->get_conversion(), f.default_value);
37                         else if(f.type->get_kind() == Type::AGGREGATE)
38                                 IO::print(out, " = { %s }", f.default_value);
39                         else if(f.type->get_kind() == Type::ENUM)
40                                 IO::print(out, " = %s::%s", f.type->get_name(), f.default_value);
41                         else
42                                 IO::print(out, " = %s", f.default_value);
43                 }
44                 IO::print(out, ";\n");
45         }
46
47         IO::print(out, "};\n");
48 }
49
50 void Struct::define_loader(IO::Base &out) const
51 {
52         IO::print(out, "class %s::Loader: public Msp::DataFile::ObjectLoader<%s>\n{\n", name, name);
53         IO::print(out, "public:\n");
54         IO::print(out, "\tLoader(%s &);\n", name);
55         IO::print(out, "\nprivate:\n");
56         IO::print(out, "\tvoid init_actions() override;\n");
57         for(const Field &f: fields)
58                 if(f.type->needs_loader_function())
59                         IO::print(out, "\tvoid %s(%s);\n", f.name, f.type->create_loader_params(false));
60         IO::print(out, "};\n");
61 }
62
63 void Struct::define_functions(IO::Base &out) const
64 {
65         IO::print(out, "%s::Loader::Loader(%s &o):\n", name, name);
66         IO::print(out, "\tObjectLoader<%s>(o)\n{\n", name);
67         IO::print(out, "\tstatic ActionMap shared_actions;\n");
68         IO::print(out, "\tset_actions(shared_actions);\n}\n");
69
70         IO::print(out, "\nvoid %s::Loader::init_actions()\n{\n", name);
71         for(const Field &f: fields)
72         {
73                 IO::print(out, "\tadd(\"%s\", ", f.name);
74                 if(f.type->needs_loader_function())
75                         IO::print(out, "&Loader::%s", f.name);
76                 else
77                         IO::print(out, "&%s::%s", name, f.name);
78                 IO::print(out, ");\n");
79         }
80         IO::print(out, "}\n");
81
82         for(const Field &f: fields)
83                 if(f.type->needs_loader_function())
84                 {
85                         IO::print(out, "\nvoid %s::Loader::%s(%s)\n{\n", name, f.name, f.type->create_loader_params(true));
86                         IO::print(out, "\tauto &_v = obj.%s;\n", f.name);
87                         IO::print(out, "\t%s\n", f.type->create_loader_statement());
88                         IO::print(out, "}\n");
89                 }
90 }
91
92
93 Struct::Loader::Loader(Struct &s, const SetupGen &g):
94         ObjectLoader<Struct>(s),
95         gen(g)
96 {
97         static ActionMap shared_actions;
98         set_actions(shared_actions);
99 }
100
101 void Struct::Loader::init_actions()
102 {
103         add("field", &Loader::field);
104 }
105
106 void Struct::Loader::field(const DataFile::Symbol &n, const DataFile::Symbol &t)
107 {
108         if(ranges::any_of(obj.fields, [&n](const Field &f){ return f.name==n.name; }))
109                 throw key_error(n.name);
110         Field fld;
111         fld.name=n.name;
112         fld.type=&gen.get_type(t.name);
113         load_sub(fld);
114         obj.fields.emplace_back(move(fld));
115 }
116
117
118 Struct::Field::Loader::Loader(Field &f):
119         ObjectLoader<Field>(f)
120 {
121         static ActionMap shared_actions;
122         set_actions(shared_actions);
123 }
124
125 void Struct::Field::Loader::init_actions()
126 {
127         add("default", &Field::default_value);
128 }