2 #include <msp/core/getopt.h>
3 #include <msp/core/maputils.h>
4 #include <msp/fs/utils.h>
5 #include <msp/io/console.h>
6 #include <msp/io/print.h>
7 #include <msp/strings/utils.h>
12 SetupGen::SetupGen(int argc, char **argv)
15 getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG);
16 getopt.add_argument("input_file", in_fn, GetOpt::REQUIRED_ARG);
22 create_standard_types();
29 generate_header(IO::cout);
30 generate_code(IO::cout);
34 string out_base = FS::basename(out_fn);
35 string out_ext = FS::extpart(out_base);
36 if(out_ext==".cpp" || out_ext==".h")
38 FS::Path out_dir = FS::dirname(out_fn);
39 out_base = FS::basepart(out_base);
40 IO::BufferedFile header_out((out_dir/(out_base+".h")).str(), IO::M_WRITE);
41 generate_header(header_out);
42 IO::BufferedFile code_out((out_dir/(out_base+".cpp")).str(), IO::M_WRITE);
43 IO::print(code_out, "#include \"%s.h\"\n", out_base);
45 IO::print(code_out, "#include <msp/strings/format.h>\n");
46 generate_code(code_out);
50 IO::BufferedFile out(out_fn, IO::M_WRITE);
60 void SetupGen::create_standard_types()
62 add_type("bool", Type::VALUE);
63 add_type("int", Type::VALUE);
64 add_type("uint", Type::VALUE).set_cpp_type("unsigned");
65 const Type &float_type = add_type("float", Type::VALUE);
66 add_type("string", Type::VALUE).set_cpp_type("std::string", "string");
67 add_type("angle", Type::VALUE).set_cpp_type("Msp::Geometry::Angle<float>", "msp/geometry/angle.h")
68 .set_load("float", "Msp::Geometry::Angle<float>::from_degrees");
69 add_type("vector2", Type::AGGREGATE).set_cpp_type("Msp::LinAl::Vector<float, 2>", "msp/linal/vector.h")
70 .set_elements(float_type, 2);
71 add_type("vector3", Type::AGGREGATE).set_cpp_type("Msp::LinAl::Vector<float, 3>", "msp/linal/vector.h")
72 .set_elements(float_type, 3);
75 Type &SetupGen::add_type(const string &n, Type::Kind k)
77 auto result = types.try_emplace(n, n, k);
80 return result.first->second;
83 const Type &SetupGen::get_type(const string &n) const
85 return get_item(types, n);
90 IO::BufferedFile in_file(in_fn);
91 DataFile::Parser parser(in_file, in_fn);
96 void SetupGen::collect_headers()
98 headers.insert("msp/datafile/objectloader.h");
99 headers.insert("msp/strings/lexicalcast.h");
100 for(const unique_ptr<Struct> &s: structs)
101 for(const Struct::Field &f: s->get_fields())
102 if(const string &h = f.type->get_header(); !h.empty())
106 void SetupGen::generate_header(IO::Base &out) const
108 string guard = toupper(FS::basepart(FS::basename(out_fn.empty() ? in_fn : out_fn)))+"_H_";
109 if(!name_space.empty())
111 vector<string> parts = split(name_space, "::");
112 parts.emplace_back(move(guard));
113 guard = join(parts.begin(), parts.end(), "_");
115 IO::print(out, "#ifndef %s\n", guard);
116 IO::print(out, "#define %s\n", guard);
121 for(const string &h: headers)
122 IO::print(out, "#include <%s>\n", h);
125 if(!name_space.empty())
126 IO::print(out, "\nnamespace %s {\n", name_space);
128 for(const unique_ptr<Enum> &e: enums)
134 for(const unique_ptr<Struct> &s: structs)
140 for(const unique_ptr<Struct> &s: structs)
143 s->define_loader(out);
146 for(const unique_ptr<Enum> &e: enums)
149 e->declare_conversions(out);
152 if(!name_space.empty())
153 IO::print(out, "\n} // namespace %s\n", name_space);
155 IO::print(out, "\n#endif\n");
158 void SetupGen::generate_code(IO::Base &out) const
160 if(!name_space.empty())
161 IO::print(out, "\nnamespace %s {\n", name_space);
163 for(const unique_ptr<Struct> &s: structs)
166 s->define_functions(out);
169 for(const unique_ptr<Enum> &e: enums)
172 e->define_conversions(out);
175 if(!name_space.empty())
176 IO::print(out, "\n} // namespace %s\n", name_space);
180 SetupGen::Loader::Loader(SetupGen &s):
181 ObjectLoader<SetupGen>(s)
183 static ActionMap shared_actions;
184 set_actions(shared_actions);
187 void SetupGen::Loader::init_actions()
189 add("component", &Loader::struct_def, Struct::COMPONENT);
190 add("entity", &Loader::struct_def, Struct::ENTITY);
191 add("enum", &Loader::enum_def);
192 add("namespace", &Loader::name_space);
195 void SetupGen::Loader::enum_def(const DataFile::Symbol &n)
199 Type &type = obj.add_type(n.name, Type::ENUM);
200 type.set_enum(*obj.enums.emplace_back(make_unique<Enum>(move(en))));
203 void SetupGen::Loader::name_space(const string &ns)
208 void SetupGen::Loader::struct_def(Struct::Kind kind, const DataFile::Symbol &n)
210 Struct sct(n.name+"Setup", kind);
212 Type &type = obj.add_type(n.name, Type::STRUCT);
213 type.set_struct(*obj.structs.emplace_back(make_unique<Struct>(move(sct))));