]> git.tdb.fi Git - libs/game.git/blobdiff - tools/setupgen/type.cpp
Add a tool for generating setup structs and loaders for them
[libs/game.git] / tools / setupgen / type.cpp
diff --git a/tools/setupgen/type.cpp b/tools/setupgen/type.cpp
new file mode 100644 (file)
index 0000000..4eb19da
--- /dev/null
@@ -0,0 +1,171 @@
+#include "type.h"
+#include <msp/core/except.h>
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
+
+using namespace std;
+using namespace Msp;
+
+Type::Type(const string &n, Kind k):
+       name(n),
+       kind(k)
+{
+       if(kind==VALUE || kind==ENUM)
+               cpp_type = name;
+       if(kind==STRUCT)
+               cpp_type = name+"Setup";
+}
+
+Type &Type::set_cpp_type(const string &t, const string &h)
+{
+       cpp_type = t;
+       header = h;
+       return *this;
+}
+
+Type &Type::set_elements(const Type &t, unsigned c)
+{
+       if(kind!=AGGREGATE && kind!=POINTER && kind!=DYN_ARRAY)
+               throw invalid_state("wrong kind");
+       if((kind==POINTER && c>1) || (kind==DYN_ARRAY && c>0))
+               throw invalid_argument("Type::set_elements");
+
+       element_type = &t;
+       element_count = (kind==POINTER ? 1 : c);
+       if(cpp_type.empty())
+       {
+               if(kind==POINTER)
+                       cpp_type = format("%s *", t.get_cpp_type());
+               else if(kind==DYN_ARRAY)
+                       cpp_type = format("std::vector<%s>", t.get_cpp_type());
+       }
+
+       return *this;
+}
+
+Type &Type::set_struct(const Struct &s)
+{
+       if(kind!=STRUCT)
+               throw invalid_state("wrong kind");
+       struct_def = &s;
+       return *this;
+}
+
+Type &Type::set_enum(const Enum &e)
+{
+       if(kind!=ENUM)
+               throw invalid_state("wrong kind");
+       enum_def = &e;
+       return *this;
+}
+
+Type &Type::set_load(const string &l, const string &c)
+{
+       if(kind!=VALUE)
+               throw invalid_state("wrong kind");
+       load_type = l;
+       conversion = c;
+       return *this;
+}
+
+const Type &Type::get_element_type() const
+{
+       if(kind!=AGGREGATE && kind!=POINTER && kind!=DYN_ARRAY)
+               throw invalid_state("wrong kind");
+       if(!element_type)
+               throw invalid_state("no element type");
+       return *element_type;
+}
+
+const Struct &Type::get_struct() const
+{
+       if(kind!=STRUCT)
+               throw invalid_state("wrong kind");
+       if(!struct_def)
+               throw invalid_state("no struct");
+       return *struct_def;
+}
+
+const Enum &Type::get_enum() const
+{
+       if(kind!=ENUM)
+               throw invalid_state("wrong kind");
+       if(!enum_def)
+               throw invalid_state("no enum");
+       return *enum_def;
+}
+
+bool Type::needs_loader_function() const
+{
+       switch(kind)
+       {
+       case VALUE: return !load_type.empty();
+       case POINTER:
+       case ENUM: return false;
+       case AGGREGATE:
+       case DYN_ARRAY:
+       case STRUCT: return true;
+       default: throw invalid_state("bad kind");
+       }
+}
+
+string Type::create_loader_params(bool with_names) const
+{
+       if(kind==AGGREGATE)
+       {
+               string result;
+               for(unsigned i=0; i<element_count; ++i)
+               {
+                       if(with_names)
+                               append(result, ", ", format("%s _a%d", element_type->get_cpp_type(), i));
+                       else
+                               append(result, ", ", element_type->get_cpp_type());
+               }
+               return result;
+       }
+       else if(kind==VALUE)
+       {
+               const string &type = (load_type.empty() ? cpp_type : load_type);
+               return (with_names ? format("%s _a", type) : type);
+       }
+       else if(kind==DYN_ARRAY)
+       {
+               Kind elem_kind = element_type->get_kind();
+               if(elem_kind==VALUE || elem_kind==ENUM)
+               {
+                       string type = format("std::vector<%s>", element_type->get_cpp_type());
+                       return (with_names ? format("%s _a", type) : type);
+               }
+               else
+                       return string();
+       }
+       else if(kind==STRUCT)
+               return string();
+       else
+               throw invalid_state("wrong kind");
+}
+
+string Type::create_loader_statement() const
+{
+       if(kind==AGGREGATE)
+       {
+               string init;
+               for(unsigned i=0; i<element_count; ++i)
+                       append(init, ", ", format("_a%d", i));
+               return format("_v = { %s };", init);
+       }
+       else if(kind==VALUE)
+               return format("_v = %s(_a);", (conversion.empty() ? cpp_type : conversion));
+       else if(kind==STRUCT)
+               return "load_sub(_v);";
+       else if(kind==DYN_ARRAY)
+       {
+               Kind elem_kind = element_type->get_kind();
+               if(elem_kind==VALUE || elem_kind==ENUM)
+                       return "_v.insert(_v.end(), _a.begin(), _a.end());";
+               else
+                       return format("%s _e; load_sub(_e); _v.emplace_back(move(_e));", cpp_type);
+       }
+       else
+               throw invalid_state("wrong kind");
+}