diff --git a/lib/base/reflectionobject.cpp b/lib/base/reflectionobject.cpp index ab990fcda..b39eabe39 100644 --- a/lib/base/reflectionobject.cpp +++ b/lib/base/reflectionobject.cpp @@ -24,10 +24,12 @@ using namespace icinga; Dictionary::Ptr ReflectionObject::Serialize(int attributeTypes) const { + const ReflectionType *type = GetReflectionType(); + Dictionary::Ptr update = boost::make_shared(); - for (int i = 0; i < GetFieldCount(); i++) { - ReflectionField field = GetFieldInfo(i); + for (int i = 0; i < type->GetFieldCount(); i++) { + ReflectionField field = type->GetFieldInfo(i); if ((field.Attributes & attributeTypes) == 0) continue; @@ -40,8 +42,10 @@ Dictionary::Ptr ReflectionObject::Serialize(int attributeTypes) const void ReflectionObject::Deserialize(const Dictionary::Ptr& update, int attributeTypes) { - for (int i = 0; i < GetFieldCount(); i++) { - ReflectionField field = GetFieldInfo(i); + const ReflectionType *type = GetReflectionType(); + + for (int i = 0; i < type->GetFieldCount(); i++) { + ReflectionField field = type->GetFieldInfo(i); if ((field.Attributes & attributeTypes) == 0) continue; diff --git a/lib/base/reflectionobject.h b/lib/base/reflectionobject.h index 842aa3a78..7429a6ff9 100644 --- a/lib/base/reflectionobject.h +++ b/lib/base/reflectionobject.h @@ -38,10 +38,9 @@ struct ReflectionField int ID; String Name; int Attributes; - Value DefaultValue; - ReflectionField(int id, const String& name, int attributes, const Value& default_value = Empty) - : ID(id), Name(name), Attributes(attributes), DefaultValue(default_value) + ReflectionField(int id, const String& name, int attributes) + : ID(id), Name(name), Attributes(attributes) { } }; @@ -51,14 +50,20 @@ enum InvokationType ITSet }; +class I2_BASE_API ReflectionType +{ +public: + virtual int GetFieldId(const String& name) const = 0; + virtual ReflectionField GetFieldInfo(int id) const = 0; + virtual int GetFieldCount(void) const = 0; +}; + class I2_BASE_API ReflectionObject : public Object { public: DECLARE_PTR_TYPEDEFS(ReflectionObject); - virtual int GetFieldId(const String& name) const = 0; - virtual ReflectionField GetFieldInfo(int id) const = 0; - virtual int GetFieldCount(void) const = 0; + virtual const ReflectionType *GetReflectionType(void) const = 0; virtual void SetField(int id, const Value& value) = 0; virtual Value GetField(int id) const = 0; @@ -66,6 +71,11 @@ public: void Deserialize(const Dictionary::Ptr& update, int attributeTypes); }; +template +class ReflectionTypeImpl +{ +}; + template class ReflectionObjectImpl { diff --git a/lib/base/singleton.h b/lib/base/singleton.h index 85fef1082..1e882e58a 100644 --- a/lib/base/singleton.h +++ b/lib/base/singleton.h @@ -48,9 +48,8 @@ public: return instance; } -private: - friend T *T::GetInstance(void); +private: static T *m_Instance; }; diff --git a/tools/mkclass/classcompiler.cpp b/tools/mkclass/classcompiler.cpp index 106d47d9f..24ddd4f72 100644 --- a/tools/mkclass/classcompiler.cpp +++ b/tools/mkclass/classcompiler.cpp @@ -81,15 +81,121 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp) { std::vector::const_iterator it; + /* forward declaration */ if (klass.Name.find_first_of(':') == std::string::npos) std::cout << "class " << klass.Name << ";" << std::endl << std::endl; + /* ReflectionTypeImpl */ + std::cout << "template<>" << std::endl + << "class ReflectionTypeImpl<" << klass.Name << ">" + << " : public ReflectionType, public Singleton >" << std::endl + << "{" << std::endl + << "public:" << std::endl; + + /* GetFieldId */ + std::cout << "\t" << "virtual int GetFieldId(const String& name) const" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return StaticGetFieldId(name);" << std::endl + << "\t" << "}" << std::endl << std::endl; + + /* StaticGetFieldId */ + std::cout << "\t" << "static int StaticGetFieldId(const String& name)" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "int offset = "; + + if (!klass.Parent.empty()) + std::cout << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount()"; + else + std::cout << "0"; + + std::cout << ";" << std::endl << std::endl; + + int num = 0; + for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { + std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl + << "\t\t\t" << "return offset + " << num << ";" << std::endl; + num++; + } + + std::cout << std::endl + << "\t\t" << "return "; + + if (!klass.Parent.empty()) + std::cout << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldId(name)"; + else + std::cout << "-1"; + + std::cout << ";" << std::endl + << "\t" << "}" << std::endl << std::endl; + + /* GetFieldInfo */ + std::cout << "\t" << "virtual ReflectionField GetFieldInfo(int id) const" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return StaticGetFieldInfo(id);" << std::endl + << "\t" << "}" << std::endl << std::endl; + + /* StaticGetFieldInfo */ + std::cout << "\t" << "static ReflectionField StaticGetFieldInfo(int id)" << std::endl + << "\t" << "{" << std::endl; + + if (!klass.Parent.empty()) + std::cout << "\t\t" << "int real_id = id - " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount();" << std::endl + << "\t\t" << "if (real_id < 0) { return " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldInfo(id); }" << std::endl; + + std::cout << "\t\t" << "switch ("; + + if (!klass.Parent.empty()) + std::cout << "real_id"; + else + std::cout << "id"; + + std::cout << ") {" << std::endl; + + num = 0; + for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { + std::cout << "\t\t\t" << "case " << num << ":" << std::endl + << "\t\t\t\t" << "return ReflectionField(" << num << ", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl; + num++; + } + + std::cout << "\t\t\t" << "default:" << std::endl + << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl + << "\t\t" << "}" << std::endl; + + std::cout << "\t" << "}" << std::endl << std::endl; + + /* GetFieldCount */ + std::cout << "\t" << "virtual int GetFieldCount(void) const" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return StaticGetFieldCount();" << std::endl + << "\t" << "}" << std::endl << std::endl; + + /* StaticGetFieldCount */ + std::cout << "\t" << "static int StaticGetFieldCount(void)" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return " << klass.Fields.size(); + + if (!klass.Parent.empty()) + std::cout << " + " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount()"; + + std::cout << ";" << std::endl + << "\t" << "}" << std::endl << std::endl; + + std::cout << "};" << std::endl << std::endl; + + /* ReflectionObjectImpl */ std::cout << "template<>" << std::endl << "class ReflectionObjectImpl<" << klass.Name << ">" << " : public " << (klass.Parent.empty() ? "ReflectionObject" : klass.Parent) << std::endl << "{" << std::endl << "public:" << std::endl - << "\t" << "DECLARE_PTR_TYPEDEFS(ReflectionObjectImpl<" << klass.Name << ">);" << std::endl; + << "\t" << "DECLARE_PTR_TYPEDEFS(ReflectionObjectImpl<" << klass.Name << ">);" << std::endl << std::endl; + + /* GetType */ + std::cout << "\t" << "virtual const ReflectionType *GetReflectionType(void) const" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return ReflectionTypeImpl<" << klass.Name << ">::GetInstance();" << std::endl + << "\t" << "}" << std::endl << std::endl; if (!klass.Fields.empty()) { /* constructor */ @@ -103,88 +209,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp) std::cout << "\t" << "}" << std::endl << std::endl; - /* GetFieldId */ - std::cout << "public:" << std::endl - << "\t" << "virtual int GetFieldId(const String& name) const" << std::endl - << "\t" << "{" << std::endl - << "\t\t" << "int offset = "; - - if (!klass.Parent.empty()) - std::cout << klass.Parent << "::GetFieldCount()"; - else - std::cout << "0"; - - std::cout << ";" << std::endl << std::endl; - - int num = 0; - for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { - std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl - << "\t\t\t" << "return offset + " << num << ";" << std::endl; - num++; - } - - std::cout << std::endl - << "\t\t" << "return "; - - if (!klass.Parent.empty()) - std::cout << klass.Parent << "::GetFieldId(name)"; - else - std::cout << "-1"; - - std::cout << ";" << std::endl - << "\t" << "}" << std::endl << std::endl; - - /* GetFieldInfo */ - std::cout << "public:" << std::endl - << "\t" << "virtual ReflectionField GetFieldInfo(int id) const" << std::endl - << "\t" << "{" << std::endl; - - if (!klass.Parent.empty()) - std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl - << "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetFieldInfo(id); }" << std::endl; - - std::cout << "\t\t" << "switch ("; - - if (!klass.Parent.empty()) - std::cout << "real_id"; - else - std::cout << "id"; - - std::cout << ") {" << std::endl; - - num = 0; - for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { - std::cout << "\t\t\t" << "case " << num << ":" << std::endl - << "\t\t\t\t" << "return ReflectionField(" << num << ", \"" << it->Name << "\", " << it->Attributes << ", " << "GetDefault" << it->GetFriendlyName() << "());" << std::endl; - num++; - } - - std::cout << "\t\t\t" << "default:" << std::endl - << "\t\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl - << "\t\t" << "}" << std::endl; - - std::cout << "\t" << "}" << std::endl << std::endl; - - /* GetFieldCount */ - std::cout << "public:" << std::endl - << "\t" << "virtual int GetFieldCount(void) const" << std::endl - << "\t" << "{" << std::endl - << "\t\t" << "return " << klass.Fields.size(); - - if (!klass.Parent.empty()) - std::cout << " + " << klass.Parent + "::GetFieldCount()"; - - std::cout << ";" << std::endl - << "\t" << "}" << std::endl << std::endl; - /* SetField */ std::cout << "protected:" << std::endl << "\t" << "virtual void SetField(int id, const Value& value)" << std::endl << "\t" << "{" << std::endl; if (!klass.Parent.empty()) - std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl - << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl; + std::cout << "\t\t" << "int real_id = id - ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl + << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl; std::cout << "\t\t" << "switch ("; @@ -225,7 +257,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp) << "\t" << "{" << std::endl; if (!klass.Parent.empty()) - std::cout << "\t\t" << "int real_id = id - " << klass.Parent << "::GetFieldCount();" << std::endl + std::cout << "\t\t" << "int real_id = id - ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl << "\t\t" << "if (real_id < 0) { return " << klass.Parent << "::GetField(id); }" << std::endl; std::cout << "\t\t" << "switch ("; @@ -337,6 +369,7 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream *stream) stream->exceptions(std::istream::badbit); std::cout << "#include \"base/reflectionobject.h\"" << std::endl + << "#include \"base/singleton.h\"" << std::endl << "#include \"base/debug.h\"" << std::endl << "#include \"base/value.h\"" << std::endl << "#include \"base/array.h\"" << std::endl