]> git.localhorst.tv Git - l2e.git/blobdiff - src/loader/TypeDescription.cpp
new object file format in compiler
[l2e.git] / src / loader / TypeDescription.cpp
index 8fd95d7437ef90f3744eea17d0135f4980d1aa64..1bb6c6505309117000822b92135c616cfb1d92a3 100644 (file)
@@ -1,18 +1,18 @@
-/*
- * TypeDescription.cpp
- *
- *  Created on: Sep 4, 2012
- *      Author: holy
- */
-
 #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 {
@@ -23,6 +23,9 @@ void TypeDescription::AddField(const std::string &n, const FieldDescription &f)
        } else {
                fields.insert(std::make_pair(n, f));
        }
+       if (f.IsReferenced() || f.IsAggregate()) {
+               link = true;
+       }
 }
 
 bool TypeDescription::HasField(const std::string &name) const {
@@ -66,31 +69,108 @@ std::ptrdiff_t TypeDescription::SupertypeOffset(int id) const {
 }
 
 
-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());
+       }
+}
+
+
+int TypeDescription::GetMaxSize() {
+       int max = 0;
+       for (map<int, TypeDescription>::const_iterator
+                       i(typeDescriptions.begin()),
+                       end(typeDescriptions.end());
+                       i != end; ++i) {
+               if (i->second.Size() > max) {
+                       max = i->second.Size();
+               }
+       }
+       return max;
+}
+
+
+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;
+               }
+       }
 }
 
 }