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