]> git.localhorst.tv Git - l2e.git/blob - src/loader/TypeDescription.cpp
1bb6c6505309117000822b92135c616cfb1d92a3
[l2e.git] / src / loader / TypeDescription.cpp
1 #include "TypeDescription.h"
2
3 #include <algorithm>
4 #include <cassert>
5 #include <cstring>
6 #include <ostream>
7 #include <sstream>
8 #include <stdexcept>
9
10 using std::endl;
11 using std::invalid_argument;
12 using std::make_pair;
13 using std::map;
14 using std::string;
15 using std::stringstream;
16 using std::vector;
17
18 namespace loader {
19
20 void TypeDescription::AddField(const std::string &n, const FieldDescription &f) {
21         if (HasField(n)) {
22                 throw std::invalid_argument("duplicate definition of field " + n + " of type " + name);
23         } else {
24                 fields.insert(std::make_pair(n, f));
25         }
26         if (f.IsReferenced() || f.IsAggregate()) {
27                 link = true;
28         }
29 }
30
31 bool TypeDescription::HasField(const std::string &name) const {
32         return fields.count(name);
33 }
34
35 const FieldDescription &TypeDescription::GetField(const std::string &n) const {
36         map<string, FieldDescription>::const_iterator result(fields.find(n));
37         if (result != fields.end()) {
38                 return result->second;
39         } else {
40                 throw std::invalid_argument("undefined field " + n + " of type " + name);
41         }
42 }
43
44 void TypeDescription::Construct(void *data) const {
45         if (constructor) {
46                 (*constructor)(data);
47         } else {
48                 std::memset(data, 0, Size());
49         }
50 }
51
52 void TypeDescription::Load(void *data) const {
53         if (loader) {
54                 (*loader)(data);
55         }
56 }
57
58
59 void TypeDescription::AddSupertype(int id, std::ptrdiff_t offset) {
60         supertypes[id] = offset;
61 }
62
63 bool TypeDescription::IsSubtypeOf(int id) const {
64         return supertypes.count(id);
65 }
66
67 std::ptrdiff_t TypeDescription::SupertypeOffset(int id) const {
68         return supertypes.at(id);
69 }
70
71
72 map<int, TypeDescription> TypeDescription::typeDescriptions;
73 map<string, int> TypeDescription::typeName2ID;
74
75 TypeDescription &TypeDescription::Create(int id, const std::string &name) {
76         if (typeDescriptions.count(id)) {
77                 std::stringstream msg;
78                 msg << "duplicate type ID " << id
79                                 << " (have " << Get(id).TypeName() << ", got " << name << ")";
80                 throw std::invalid_argument(msg.str());
81         }
82         if (typeName2ID.count(name)) {
83                 std::stringstream msg;
84                 msg << "duplicate type name " << name
85                                 << " (have " << GetTypeId(name) << ", got " << id << ")";
86                 throw std::invalid_argument(msg.str());
87         }
88         typeName2ID[name] = id;
89         return typeDescriptions.insert(make_pair(id, TypeDescription(id, name))).first->second;
90 }
91
92 int TypeDescription::GetTypeId(const std::string &name) {
93         map<string, int>::const_iterator i(typeName2ID.find(name));
94         if (i != typeName2ID.end()) {
95                 return i->second;
96         } else {
97                 throw invalid_argument("unknown type name " + name);
98         }
99 }
100
101 const TypeDescription &TypeDescription::Get(int id) {
102         map<int, TypeDescription>::const_iterator i(typeDescriptions.find(id));
103         if (i != typeDescriptions.end()) {
104                 return i->second;
105         } else {
106                 std::stringstream msg;
107                 msg << "invalid type ID " << id;
108                 throw invalid_argument(msg.str());
109         }
110 }
111
112
113 int TypeDescription::GetMaxSize() {
114         int max = 0;
115         for (map<int, TypeDescription>::const_iterator
116                         i(typeDescriptions.begin()),
117                         end(typeDescriptions.end());
118                         i != end; ++i) {
119                 if (i->second.Size() > max) {
120                         max = i->second.Size();
121                 }
122         }
123         return max;
124 }
125
126
127 void TypeDescription::WriteSourceWiki(std::ostream &out) {
128         vector<string> types;
129         for (map<int, TypeDescription>::const_iterator i(typeDescriptions.begin()), end(typeDescriptions.end()); i != end; ++i) {
130                 if (i->second.name != "Animation") {
131                         types.push_back(i->second.name);
132                 }
133         }
134         std::sort(types.begin(), types.end());
135
136         out << "h2. Data types" << endl << endl;
137
138         for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
139                 out << "* [[LoaderSource#" << *i << "|" << *i << "]]" << endl;
140         }
141         out << endl << endl;
142
143         for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
144                 const TypeDescription &td(Get(GetTypeId(*i)));
145                 out << "h3. " << td.TypeName() << endl << endl;
146
147                 out << "Type ID: @" << td.TypeId() << "@" << endl << endl;
148
149                 if (td.Description()) {
150                         out << td.Description() << endl << endl;
151                 }
152
153                 if (td.FieldsBegin() == td.FieldsEnd()) {
154                         out << "No properties." << endl << endl;
155                 } else {
156                         out << "| *Property* | *Type* | *Description* |" << endl;
157                         for (FieldIterator field(td.FieldsBegin()); field != td.FieldsEnd(); ++field) {
158                                 const FieldDescription &fd(field->second);
159                                 out << "| " << field->first << " | ";
160                                 if (fd.IsAggregate()) {
161                                         out << "Array<" << Get(fd.TypeId()).TypeName() << ">";
162                                 } else {
163                                         out << Get(fd.TypeId()).TypeName();
164                                 }
165                                 out << " | ";
166                                 if (fd.Description()) {
167                                         out << fd.Description();
168                                 }
169                                 out << " |" << endl;
170                         }
171                         out << endl;
172                 }
173         }
174 }
175
176 }