Implement the ReflectionType class.

Refs #4996
This commit is contained in:
Gunnar Beutner 2013-11-04 19:12:34 +01:00 committed by Gunnar Beutner
parent 67b82a81c9
commit 2140cef041
4 changed files with 136 additions and 90 deletions

View 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;

View 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 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<typename T>
class ReflectionTypeImpl
{
};
template<typename T>
class ReflectionObjectImpl
{

View File

@ -48,9 +48,8 @@ public:
return instance;
}
private:
friend T *T::GetInstance(void);
private:
static T *m_Instance;
};

View File

@ -81,15 +81,121 @@ 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 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++;
}
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