#include "TypeDescription.h"
+#include <algorithm>
#include <cassert>
+#include <cstring>
+#include <ostream>
+#include <sstream>
#include <stdexcept>
+using std::endl;
+using std::invalid_argument;
+using std::make_pair;
using std::map;
using std::string;
+using std::stringstream;
using std::vector;
namespace loader {
}
}
+void TypeDescription::Construct(void *data) const {
+ if (constructor) {
+ (*constructor)(data);
+ } else {
+ std::memset(data, 0, Size());
+ }
+}
+
+void TypeDescription::Load(void *data) const {
+ if (loader) {
+ (*loader)(data);
+ }
+}
+
void TypeDescription::AddSupertype(int id, std::ptrdiff_t offset) {
supertypes[id] = offset;
}
-vector<TypeDescription> TypeDescription::typeDescriptions;
+map<int, TypeDescription> TypeDescription::typeDescriptions;
+map<string, int> TypeDescription::typeName2ID;
-TypeDescription &TypeDescription::CreateOrGet(const std::string &name) {
- for (vector<TypeDescription>::iterator i(typeDescriptions.begin()), end(typeDescriptions.end()); i != end; ++i) {
- if (i->name == name) {
- return *i;
- }
+TypeDescription &TypeDescription::Create(int id, const std::string &name) {
+ if (typeDescriptions.count(id)) {
+ std::stringstream msg;
+ msg << "duplicate type ID " << id
+ << " (have " << Get(id).TypeName() << ", got " << name << ")";
+ throw std::invalid_argument(msg.str());
+ }
+ if (typeName2ID.count(name)) {
+ std::stringstream msg;
+ msg << "duplicate type name " << name
+ << " (have " << GetTypeId(name) << ", got " << id << ")";
+ throw std::invalid_argument(msg.str());
}
- typeDescriptions.push_back(TypeDescription(typeDescriptions.size(), name));
- return typeDescriptions.back();
+ typeName2ID[name] = id;
+ return typeDescriptions.insert(make_pair(id, TypeDescription(id, name))).first->second;
}
int TypeDescription::GetTypeId(const std::string &name) {
- for (vector<TypeDescription>::size_type i(0), end(typeDescriptions.size()); i < end; ++i) {
- if (typeDescriptions[i].name == name) {
- return i;
- }
+ map<string, int>::const_iterator i(typeName2ID.find(name));
+ if (i != typeName2ID.end()) {
+ return i->second;
+ } else {
+ throw invalid_argument("unknown type name " + name);
}
- typeDescriptions.push_back(TypeDescription(typeDescriptions.size(), name));
- return typeDescriptions.size() - 1;
}
const TypeDescription &TypeDescription::Get(int id) {
- assert(id >= 0 && id < int(typeDescriptions.size()));
- return typeDescriptions[id];
+ map<int, TypeDescription>::const_iterator i(typeDescriptions.find(id));
+ if (i != typeDescriptions.end()) {
+ return i->second;
+ } else {
+ std::stringstream msg;
+ msg << "invalid type ID " << id;
+ throw invalid_argument(msg.str());
+ }
+}
+
+
+void TypeDescription::WriteSourceWiki(std::ostream &out) {
+ vector<string> types;
+ for (map<int, TypeDescription>::const_iterator i(typeDescriptions.begin()), end(typeDescriptions.end()); i != end; ++i) {
+ if (i->second.name != "Animation") {
+ types.push_back(i->second.name);
+ }
+ }
+ std::sort(types.begin(), types.end());
+
+ out << "h2. Data types" << endl << endl;
+
+ for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
+ out << "* [[LoaderSource#" << *i << "|" << *i << "]]" << endl;
+ }
+ out << endl << endl;
+
+ for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
+ const TypeDescription &td(Get(GetTypeId(*i)));
+ out << "h3. " << td.TypeName() << endl << endl;
+
+ out << "Type ID: @" << td.TypeId() << "@" << endl << endl;
+
+ if (td.Description()) {
+ out << td.Description() << endl << endl;
+ }
+
+ if (td.FieldsBegin() == td.FieldsEnd()) {
+ out << "No properties." << endl << endl;
+ } else {
+ out << "| *Property* | *Type* | *Description* |" << endl;
+ for (FieldIterator field(td.FieldsBegin()); field != td.FieldsEnd(); ++field) {
+ const FieldDescription &fd(field->second);
+ out << "| " << field->first << " | ";
+ if (fd.IsAggregate()) {
+ out << "Array<" << Get(fd.TypeId()).TypeName() << ">";
+ } else {
+ out << Get(fd.TypeId()).TypeName();
+ }
+ out << " | ";
+ if (fd.Description()) {
+ out << fd.Description();
+ }
+ out << " |" << endl;
+ }
+ out << endl;
+ }
+ }
}
}