]> granicus.if.org Git - icinga2/commitdiff
Implement the ReflectionType class.
authorGunnar Beutner <gunnar@beutner.name>
Mon, 4 Nov 2013 18:12:34 +0000 (19:12 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 5 Nov 2013 07:56:18 +0000 (08:56 +0100)
Refs #4996

lib/base/reflectionobject.cpp
lib/base/reflectionobject.h
lib/base/singleton.h
tools/mkclass/classcompiler.cpp

index ab990fcda106accb1676b73b71dac2613d50bab2..b39eabe39c6f304b00add19b9ae29df574b88175 100644 (file)
@@ -24,10 +24,12 @@ using namespace icinga;
 
 Dictionary::Ptr ReflectionObject::Serialize(int attributeTypes) const
 {
+       const ReflectionType *type = GetReflectionType();
+
        Dictionary::Ptr update = boost::make_shared<Dictionary>();
 
-       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;
index 842aa3a78f0df16d40b124dd37f12ba6b4dbbf7a..7429a6ff9214f71e8a23f1c328fe308348b9410c 100644 (file)
@@ -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<typename T>
+class ReflectionTypeImpl
+{
+};
+
 template<typename T>
 class ReflectionObjectImpl
 {
index 85fef10822ba866b432e5b8b10612b027a4e2fe8..1e882e58aac790c9ca7997e0f249370fa06c7044 100644 (file)
@@ -48,9 +48,8 @@ public:
 
                return instance;
        }
-private:
-       friend T *T::GetInstance(void);
 
+private:
        static T *m_Instance;
 };
 
index 106d47d9f9081b9ae406a2d69432e9a69773373a..24ddd4f72e2f8770541b18615cba1e38ce590fb3 100644 (file)
@@ -81,101 +81,133 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 {
        std::vector<Field>::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<ReflectionTypeImpl<" << klass.Name << "> >" << 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