]> git.tdb.fi Git - libs/game.git/blob - tools/setupgen/type.cpp
Add a tool for generating setup structs and loaders for them
[libs/game.git] / tools / setupgen / type.cpp
1 #include "type.h"
2 #include <msp/core/except.h>
3 #include <msp/strings/format.h>
4 #include <msp/strings/utils.h>
5
6 using namespace std;
7 using namespace Msp;
8
9 Type::Type(const string &n, Kind k):
10         name(n),
11         kind(k)
12 {
13         if(kind==VALUE || kind==ENUM)
14                 cpp_type = name;
15         if(kind==STRUCT)
16                 cpp_type = name+"Setup";
17 }
18
19 Type &Type::set_cpp_type(const string &t, const string &h)
20 {
21         cpp_type = t;
22         header = h;
23         return *this;
24 }
25
26 Type &Type::set_elements(const Type &t, unsigned c)
27 {
28         if(kind!=AGGREGATE && kind!=POINTER && kind!=DYN_ARRAY)
29                 throw invalid_state("wrong kind");
30         if((kind==POINTER && c>1) || (kind==DYN_ARRAY && c>0))
31                 throw invalid_argument("Type::set_elements");
32
33         element_type = &t;
34         element_count = (kind==POINTER ? 1 : c);
35         if(cpp_type.empty())
36         {
37                 if(kind==POINTER)
38                         cpp_type = format("%s *", t.get_cpp_type());
39                 else if(kind==DYN_ARRAY)
40                         cpp_type = format("std::vector<%s>", t.get_cpp_type());
41         }
42
43         return *this;
44 }
45
46 Type &Type::set_struct(const Struct &s)
47 {
48         if(kind!=STRUCT)
49                 throw invalid_state("wrong kind");
50         struct_def = &s;
51         return *this;
52 }
53
54 Type &Type::set_enum(const Enum &e)
55 {
56         if(kind!=ENUM)
57                 throw invalid_state("wrong kind");
58         enum_def = &e;
59         return *this;
60 }
61
62 Type &Type::set_load(const string &l, const string &c)
63 {
64         if(kind!=VALUE)
65                 throw invalid_state("wrong kind");
66         load_type = l;
67         conversion = c;
68         return *this;
69 }
70
71 const Type &Type::get_element_type() const
72 {
73         if(kind!=AGGREGATE && kind!=POINTER && kind!=DYN_ARRAY)
74                 throw invalid_state("wrong kind");
75         if(!element_type)
76                 throw invalid_state("no element type");
77         return *element_type;
78 }
79
80 const Struct &Type::get_struct() const
81 {
82         if(kind!=STRUCT)
83                 throw invalid_state("wrong kind");
84         if(!struct_def)
85                 throw invalid_state("no struct");
86         return *struct_def;
87 }
88
89 const Enum &Type::get_enum() const
90 {
91         if(kind!=ENUM)
92                 throw invalid_state("wrong kind");
93         if(!enum_def)
94                 throw invalid_state("no enum");
95         return *enum_def;
96 }
97
98 bool Type::needs_loader_function() const
99 {
100         switch(kind)
101         {
102         case VALUE: return !load_type.empty();
103         case POINTER:
104         case ENUM: return false;
105         case AGGREGATE:
106         case DYN_ARRAY:
107         case STRUCT: return true;
108         default: throw invalid_state("bad kind");
109         }
110 }
111
112 string Type::create_loader_params(bool with_names) const
113 {
114         if(kind==AGGREGATE)
115         {
116                 string result;
117                 for(unsigned i=0; i<element_count; ++i)
118                 {
119                         if(with_names)
120                                 append(result, ", ", format("%s _a%d", element_type->get_cpp_type(), i));
121                         else
122                                 append(result, ", ", element_type->get_cpp_type());
123                 }
124                 return result;
125         }
126         else if(kind==VALUE)
127         {
128                 const string &type = (load_type.empty() ? cpp_type : load_type);
129                 return (with_names ? format("%s _a", type) : type);
130         }
131         else if(kind==DYN_ARRAY)
132         {
133                 Kind elem_kind = element_type->get_kind();
134                 if(elem_kind==VALUE || elem_kind==ENUM)
135                 {
136                         string type = format("std::vector<%s>", element_type->get_cpp_type());
137                         return (with_names ? format("%s _a", type) : type);
138                 }
139                 else
140                         return string();
141         }
142         else if(kind==STRUCT)
143                 return string();
144         else
145                 throw invalid_state("wrong kind");
146 }
147
148 string Type::create_loader_statement() const
149 {
150         if(kind==AGGREGATE)
151         {
152                 string init;
153                 for(unsigned i=0; i<element_count; ++i)
154                         append(init, ", ", format("_a%d", i));
155                 return format("_v = { %s };", init);
156         }
157         else if(kind==VALUE)
158                 return format("_v = %s(_a);", (conversion.empty() ? cpp_type : conversion));
159         else if(kind==STRUCT)
160                 return "load_sub(_v);";
161         else if(kind==DYN_ARRAY)
162         {
163                 Kind elem_kind = element_type->get_kind();
164                 if(elem_kind==VALUE || elem_kind==ENUM)
165                         return "_v.insert(_v.end(), _a.begin(), _a.end());";
166                 else
167                         return format("%s _e; load_sub(_e); _v.emplace_back(move(_e));", cpp_type);
168         }
169         else
170                 throw invalid_state("wrong kind");
171 }