From: Gunnar Beutner Date: Mon, 4 Nov 2013 18:12:34 +0000 (+0100) Subject: Implement the ReflectionType class. X-Git-Tag: v0.0.4~56^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2140cef04150875f0cca39a7936da19ace87503c;p=icinga2 Implement the ReflectionType class. Refs #4996 --- 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 ReflectionObject : public Object +class I2_BASE_API ReflectionType { 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; +}; + +class I2_BASE_API ReflectionObject : public Object +{ +public: + DECLARE_PTR_TYPEDEFS(ReflectionObject); + + 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,101 +81,133 @@ 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 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; + << "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++; + } - if (!klass.Fields.empty()) { - /* constructor */ - std::cout << "public:" << std::endl - << "\t" << "ReflectionObjectImpl<" << klass.Name << ">(void)" << std::endl - << "\t" << "{" << std::endl; + std::cout << std::endl + << "\t\t" << "return "; - for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { - std::cout << "\t\t" << "Set" << it->GetFriendlyName() << "(" << "GetDefault" << it->GetFriendlyName() << "());" << std::endl; - } + if (!klass.Parent.empty()) + std::cout << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldId(name)"; + else + std::cout << "-1"; - std::cout << "\t" << "}" << std::endl << std::endl; + std::cout << ";" << std::endl + << "\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 = "; + /* 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; - if (!klass.Parent.empty()) - std::cout << klass.Parent << "::GetFieldCount()"; - else - std::cout << "0"; + /* StaticGetFieldInfo */ + std::cout << "\t" << "static ReflectionField StaticGetFieldInfo(int id)" << std::endl + << "\t" << "{" << std::endl; - std::cout << ";" << std::endl << 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; - 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 << "\t\t" << "switch ("; - std::cout << std::endl - << "\t\t" << "return "; + if (!klass.Parent.empty()) + std::cout << "real_id"; + else + std::cout << "id"; - if (!klass.Parent.empty()) - std::cout << klass.Parent << "::GetFieldId(name)"; - else - std::cout << "-1"; + std::cout << ") {" << std::endl; - std::cout << ";" << std::endl - << "\t" << "}" << std::endl << 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++; + } - /* GetFieldInfo */ - std::cout << "public:" << std::endl - << "\t" << "virtual ReflectionField GetFieldInfo(int id) const" << std::endl - << "\t" << "{" << std::endl; + 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; - 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" << "}" << std::endl << std::endl; - std::cout << "\t\t" << "switch ("; + /* 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; - if (!klass.Parent.empty()) - std::cout << "real_id"; - else - std::cout << "id"; + /* StaticGetFieldCount */ + std::cout << "\t" << "static int StaticGetFieldCount(void)" << std::endl + << "\t" << "{" << std::endl + << "\t\t" << "return " << klass.Fields.size(); - std::cout << ") {" << std::endl; + if (!klass.Parent.empty()) + std::cout << " + " << "ReflectionTypeImpl<" << klass.Parent << ">::StaticGetFieldCount()"; - 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 << ";" << std::endl + << "\t" << "}" << std::endl << std::endl; - 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 << "};" << std::endl << std::endl; - std::cout << "\t" << "}" << 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 << std::endl; - /* GetFieldCount */ + /* 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 */ std::cout << "public:" << std::endl - << "\t" << "virtual int GetFieldCount(void) const" << std::endl - << "\t" << "{" << std::endl - << "\t\t" << "return " << klass.Fields.size(); + << "\t" << "ReflectionObjectImpl<" << klass.Name << ">(void)" << std::endl + << "\t" << "{" << std::endl; - if (!klass.Parent.empty()) - std::cout << " + " << klass.Parent + "::GetFieldCount()"; + for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) { + std::cout << "\t\t" << "Set" << it->GetFriendlyName() << "(" << "GetDefault" << it->GetFriendlyName() << "());" << std::endl; + } - std::cout << ";" << std::endl - << "\t" << "}" << std::endl << std::endl; + std::cout << "\t" << "}" << std::endl << std::endl; /* SetField */ std::cout << "protected:" << std::endl @@ -183,8 +215,8 @@ 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 - << "\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