summaryrefslogtreecommitdiff
path: root/slicer/slicer
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2014-06-26 13:20:58 +0000
committerrandomdan <randomdan@localhost>2014-06-26 13:20:58 +0000
commit9b0fb1a52dd7b8db1dab98cebf7b928e4d921111 (patch)
tree346f7c2dfe4530f86b44d304a5b620ce3a4dce06 /slicer/slicer
parentMove the name into the hook (diff)
downloadslicer-9b0fb1a52dd7b8db1dab98cebf7b928e4d921111.tar.bz2
slicer-9b0fb1a52dd7b8db1dab98cebf7b928e4d921111.tar.xz
slicer-9b0fb1a52dd7b8db1dab98cebf7b928e4d921111.zip
Adds support for classes with inheritance
Adds more unit tests and verifies written XML is the same as the initial
Diffstat (limited to 'slicer/slicer')
-rw-r--r--slicer/slicer/modelParts.cpp31
-rw-r--r--slicer/slicer/modelParts.h34
-rw-r--r--slicer/slicer/parser.cpp137
-rw-r--r--slicer/slicer/parser.h5
4 files changed, 140 insertions, 67 deletions
diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp
index 9d33d51..4c05513 100644
--- a/slicer/slicer/modelParts.cpp
+++ b/slicer/slicer/modelParts.cpp
@@ -1,14 +1,45 @@
#include "modelParts.h"
namespace Slicer {
+ IncorrectElementName::IncorrectElementName(const std::string & n) :
+ std::invalid_argument(n)
+ {
+ }
+
+ UnknownType::UnknownType(const std::string & n) :
+ std::invalid_argument(n)
+ {
+ }
+
+ ClassRefMap * &
+ classRefMap()
+ {
+ static ClassRefMap * refs = new ClassRefMap();
+ return refs;
+ }
+
void
ModelPart::Create()
{
}
+
void
ModelPart::Complete()
{
}
+
+ ModelPartPtr
+ ModelPart::GetSubclassModelPart(const std::string &)
+ {
+ return this;
+ }
+
+ TypeId
+ ModelPart::GetTypeId() const
+ {
+ return TypeId();
+ }
+
void
ModelPart::SetValue(ValueSourcePtr)
{
diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h
index 9c2bf45..28ab86d 100644
--- a/slicer/slicer/modelParts.h
+++ b/slicer/slicer/modelParts.h
@@ -15,8 +15,12 @@
namespace Slicer {
class IncorrectElementName : public std::invalid_argument {
public:
- IncorrectElementName() :
- std::invalid_argument("") { }
+ IncorrectElementName(const std::string & n);
+ };
+
+ class UnknownType : public std::invalid_argument {
+ public:
+ UnknownType(const std::string & n);
};
class ValueTarget : public IceUtil::Shared {
@@ -49,15 +53,22 @@ namespace Slicer {
typedef IceUtil::Handle<ModelPart> ModelPartPtr;
typedef std::map<std::string, ModelPartPtr> ModelParts;
+ typedef IceUtil::Optional<std::string> TypeId;
typedef boost::function<void(const std::string &, ModelPartPtr)> ChildHandler;
+ typedef boost::function<ModelPartPtr(void *)> ClassRef;
+ typedef std::map<std::string, ClassRef> ClassRefMap;
+ ClassRefMap * & classRefMap();
+
class ModelPart : public IceUtil::Shared {
public:
virtual ~ModelPart() = default;
virtual void OnEachChild(const ChildHandler &) = 0;
- virtual ModelPartPtr GetChild(const std::string &) = 0;
+ virtual ModelPartPtr GetChild(const std::string & memberName) = 0;
+ virtual ModelPartPtr GetSubclassModelPart(const std::string &);
+ virtual TypeId GetTypeId() const;
virtual void Create();
virtual void Complete();
virtual void SetValue(ValueSourcePtr);
@@ -165,7 +176,7 @@ namespace Slicer {
};
typedef IceUtil::Handle<HookBase> HookPtr;
- template <typename MT, MT T::*M, typename MP>
+ template <typename MT, typename CT, MT CT::*M, typename MP>
class Hook : public HookBase {
public:
Hook(const std::string & n) :
@@ -239,8 +250,19 @@ namespace Slicer {
return ModelObject.get();
}
+ virtual ModelPartPtr GetSubclassModelPart(const std::string & name) override
+ {
+ auto ref = classRefMap()->find(name);
+ if (ref == classRefMap()->end()) {
+ throw UnknownType(name);
+ }
+ return ref->second(&this->ModelObject);
+ }
+
virtual bool HasValue() const override { return ModelObject; }
+ virtual TypeId GetTypeId() const override;
+
private:
T & ModelObject;
};
@@ -288,7 +310,7 @@ namespace Slicer {
virtual ModelPartPtr GetChild(const std::string & name) override
{
if (!name.empty() && name != rootName) {
- throw IncorrectElementName();
+ throw IncorrectElementName(rootName);
}
ModelPartForClass<T>::Create();
return new ModelPartForClass<T>(ModelObject);
@@ -406,7 +428,7 @@ namespace Slicer {
ModelPartPtr GetChild(const std::string & name) override
{
if (!name.empty() && name != pairName) {
- throw IncorrectElementName();
+ throw IncorrectElementName(pairName);
}
return new ModelPartForDictionaryElementInserter<T>(dictionary);
}
diff --git a/slicer/slicer/parser.cpp b/slicer/slicer/parser.cpp
index c874f57..8e2bfa9 100644
--- a/slicer/slicer/parser.cpp
+++ b/slicer/slicer/parser.cpp
@@ -11,7 +11,8 @@ namespace fs = boost::filesystem;
namespace Slicer {
Slicer::Slicer(FILE * c) :
- cpp(c)
+ cpp(c),
+ classNo(0)
{
}
@@ -47,47 +48,43 @@ namespace Slicer {
{
if (c->hasMetaData("slicer:ignore")) { return false; }
+ auto decl = c->declaration();
fprintf(cpp, "// Class %s\n", c->name().c_str());
fprintf(cpp, "template<>\n");
fprintf(cpp, "ModelPartForComplex< %s::%s >::Hooks ",
modulePath().c_str(), c->name().c_str());
fprintf(cpp, "ModelPartForComplex< %s::%s >::hooks {\n",
modulePath().c_str(), c->name().c_str());
- BOOST_FOREACH (const auto & dm, c->allDataMembers()) {
- auto name = metaDataValue("slicer:name:", dm->getMetaData());
- fprintf(cpp, "\t\t{ ");
- auto type = dm->type();
- fprintf(cpp, "new ModelPartForClass< %s::%sPtr >::Hook< ",
- modulePath().c_str(), c->name().c_str());
- if (dm->optional()) {
- fprintf(cpp, "::IceUtil::Optional< %s >",
- Slice::typeToString(type).c_str());
- }
- else {
- fprintf(cpp, "%s",
- Slice::typeToString(type).c_str());
- }
- fprintf(cpp, ", &%s::%s::%s, ",
- modulePath().c_str(), c->name().c_str(), dm->name().c_str());
- if (dm->optional()) {
- fprintf(cpp, "ModelPartForOptional< ");
- }
- createNewModelPartPtrFor(type);
- fprintf(cpp, "< %s",
- Slice::typeToString(type).c_str());
- if (dm->optional()) {
- fprintf(cpp, " > ");
- }
- fprintf(cpp, " > >(\"%s\") },\n",
- name ? name->c_str() : dm->name().c_str());
- }
- fprintf(cpp, "\t};\n");
+ visitComplexDataMembers(decl, c->allDataMembers());
+ fprintf(cpp, "\t};\n\n");
fprintf(cpp, "template<>\n");
auto name = metaDataValue("slicer:root:", c->getMetaData());
- fprintf(cpp, "std::string ModelPartForClassRoot< %s::%sPtr >::rootName(\"%s\");\n\n",
- modulePath().c_str(), c->name().c_str(),
+ fprintf(cpp, "std::string ModelPartForClassRoot< %s >::rootName(\"%s\");\n\n",
+ typeToString(decl).c_str(),
name ? name->c_str() : c->name().c_str());
+
+ fprintf(cpp, "static void registerClass_%u() __attribute__ ((constructor(210)));\n", classNo);
+ fprintf(cpp, "static void registerClass_%u()\n{\n", classNo);
+ fprintf(cpp, "\tSlicer::classRefMap()->insert({ \"%s::%s\", [](void * p){ return new ModelPartForClass< %s >(*static_cast< %s *>(p)); } });\n",
+ modulePath().c_str(), c->name().c_str(),
+ typeToString(decl).c_str(),
+ typeToString(decl).c_str());
+ fprintf(cpp, "}\n\n");
+ fprintf(cpp, "static void unregisterClass_%u() __attribute__ ((destructor(210)));\n", classNo);
+ fprintf(cpp, "static void unregisterClass_%u()\n{\n", classNo);
+ fprintf(cpp, "\tSlicer::classRefMap()->erase(\"%s::%s\");\n",
+ modulePath().c_str(), c->name().c_str());
+ fprintf(cpp, "}\n\n");
+
+ fprintf(cpp, "template<>\nTypeId\nModelPartForClass< %s >::GetTypeId() const\n{\n",
+ typeToString(decl).c_str());
+ fprintf(cpp, "\tauto id = ModelObject->ice_id();\n");
+ fprintf(cpp, "\treturn (id == \"%s::%s\") ? TypeId() : id;\n}\n\n",
+ modulePath().c_str(), c->name().c_str());
+
+ classNo += 1;
+
return true;
}
@@ -102,22 +99,43 @@ namespace Slicer {
modulePath().c_str(), c->name().c_str());
fprintf(cpp, "ModelPartForComplex< %s::%s >::hooks {\n",
modulePath().c_str(), c->name().c_str());
- BOOST_FOREACH (const auto & dm, c->dataMembers()) {
+ visitComplexDataMembers(c, c->dataMembers());
+ fprintf(cpp, "\t};\n\n");
+
+ return true;
+ }
+
+ void
+ Slicer::visitComplexDataMembers(Slice::TypePtr it, const Slice::DataMemberList & dataMembers) const
+ {
+ BOOST_FOREACH (const auto & dm, dataMembers) {
+ auto c = Slice::ContainedPtr::dynamicCast(dm->container());
+ auto t = Slice::TypePtr::dynamicCast(dm->container());
+ if (!t) {
+ t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration();
+ }
auto name = metaDataValue("slicer:name:", dm->getMetaData());
- fprintf(cpp, "\t\t{ ");
+ fprintf(cpp, "\t\tnew ");
auto type = dm->type();
- fprintf(cpp, "new ModelPartForStruct< %s::%s >::Hook< %s, &%s::%s::%s, ",
- modulePath().c_str(), c->name().c_str(),
- Slice::typeToString(type).c_str(),
- modulePath().c_str(), c->name().c_str(), dm->name().c_str());
+ createNewModelPartPtrFor(t);
+ fprintf(cpp, "< %s >::Hook< %s",
+ typeToString(it).c_str(),
+ Slice::typeToString(type, dm->optional()).c_str());
+ fprintf(cpp, ", %s::%s, &%s::%s::%s, ",
+ modulePath().c_str(), c->name().c_str(),
+ modulePath().c_str(), c->name().c_str(), dm->name().c_str());
+ if (dm->optional()) {
+ fprintf(cpp, "ModelPartForOptional< ");
+ }
createNewModelPartPtrFor(type);
- fprintf(cpp, "< %s > >(\"%s\") },\n",
- Slice::typeToString(type).c_str(),
+ fprintf(cpp, "< %s",
+ Slice::typeToString(type).c_str());
+ if (dm->optional()) {
+ fprintf(cpp, " > ");
+ }
+ fprintf(cpp, " > >(\"%s\"),\n",
name ? name->c_str() : dm->name().c_str());
}
- fprintf(cpp, "\t};\n\n");
-
- return true;
}
void
@@ -137,13 +155,11 @@ namespace Slicer {
else {
fprintf(cpp, "\t(void)name;\n");
}
- fprintf(cpp, "\tsequence.push_back(%s());\n",
- Slice::typeToString(s->type()).c_str());
+ fprintf(cpp, "\tsequence.push_back(typename element_type::value_type());\n");
fprintf(cpp, "\treturn new ");
auto etype = s->type();
createNewModelPartPtrFor(etype);
- fprintf(cpp, "< %s >(sequence.back());\n}\n\n",
- Slice::typeToString(etype).c_str());
+ fprintf(cpp, "<typename element_type::value_type>(sequence.back());\n}\n\n");
fprintf(cpp, "template<>\n");
fprintf(cpp, "ModelPartPtr\n");
fprintf(cpp, "ModelPartForSequence< %s::%s >::elementModelPart(typename %s::%s::value_type & e) const {\n",
@@ -151,8 +167,7 @@ namespace Slicer {
modulePath().c_str(), s->name().c_str());
fprintf(cpp, "\treturn new ");
createNewModelPartPtrFor(etype);
- fprintf(cpp, "< %s >(e);\n}\n\n",
- Slice::typeToString(etype).c_str());
+ fprintf(cpp, "<typename element_type::value_type>(e);\n}\n\n");
fprintf(cpp, "template<>\n");
auto ename = metaDataValue("slicer:element:", s->getMetaData());
fprintf(cpp, "std::string ModelPartForSequence< %s::%s >::elementName(\"%s\");\n\n",
@@ -179,23 +194,25 @@ namespace Slicer {
modulePath().c_str(), d->name().c_str());
auto kname = metaDataValue("slicer:key:", d->getMetaData());
auto vname = metaDataValue("slicer:value:", d->getMetaData());
- fprintf(cpp, "\t\t{ ");
+ fprintf(cpp, "\t\t");
auto ktype = d->keyType();
- fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, &ModelPartForDictionaryElement< %s::%s >::key, ",
+ fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, ModelPartForDictionaryElement< %s::%s >, &ModelPartForDictionaryElement< %s::%s >::key, ",
modulePath().c_str(), d->name().c_str(),
Slice::typeToString(ktype).c_str(),
+ modulePath().c_str(), d->name().c_str(),
modulePath().c_str(), d->name().c_str());
createNewModelPartPtrFor(ktype);
- fprintf(cpp, "< %s > >(\"%s\") },\n\t\t{ ",
+ fprintf(cpp, "< %s > >(\"%s\"),\n\t\t",
Slice::typeToString(ktype).c_str(),
kname ? kname->c_str() : "key");
auto vtype = d->valueType();
- fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, &ModelPartForDictionaryElement< %s::%s >::value, ",
+ fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, ModelPartForDictionaryElement< %s::%s >, &ModelPartForDictionaryElement< %s::%s >::value, ",
modulePath().c_str(), d->name().c_str(),
Slice::typeToString(vtype).c_str(),
+ modulePath().c_str(), d->name().c_str(),
modulePath().c_str(), d->name().c_str());
createNewModelPartPtrFor(vtype);
- fprintf(cpp, "< %s > >(\"%s\") },\n",
+ fprintf(cpp, "< %s > >(\"%s\"),\n",
Slice::typeToString(vtype).c_str(),
vname ? vname->c_str() : "value");
fprintf(cpp, "\t};\n");
@@ -213,24 +230,24 @@ namespace Slicer {
Slicer::createNewModelPartPtrFor(const Slice::TypePtr & type) const
{
if (auto builtin = Slice::BuiltinPtr::dynamicCast(type)) {
- fprintf(cpp, "ModelPartForSimple ");
+ fprintf(cpp, "ModelPartForSimple");
}
else if (auto complexClass = Slice::ClassDeclPtr::dynamicCast(type)) {
- fprintf(cpp, "ModelPartForClass ");
+ fprintf(cpp, "ModelPartForClass");
}
else if (auto complexStruct = Slice::StructPtr::dynamicCast(type)) {
- fprintf(cpp, "ModelPartForStruct ");
+ fprintf(cpp, "ModelPartForStruct");
}
else if (auto sequence = Slice::SequencePtr::dynamicCast(type)) {
- fprintf(cpp, "ModelPartForSequence ");
+ fprintf(cpp, "ModelPartForSequence");
}
else if (auto dictionary = Slice::DictionaryPtr::dynamicCast(type)) {
- fprintf(cpp, "ModelPartForDictionary ");
+ fprintf(cpp, "ModelPartForDictionary");
}
}
std::string
- Slicer::modulePath()
+ Slicer::modulePath() const
{
std::string path;
BOOST_FOREACH (const auto & m, modules) {
diff --git a/slicer/slicer/parser.h b/slicer/slicer/parser.h
index 90aa05a..816738d 100644
--- a/slicer/slicer/parser.h
+++ b/slicer/slicer/parser.h
@@ -34,12 +34,15 @@ namespace Slicer {
private:
void createNewModelPartPtrFor(const Slice::TypePtr & type) const;
- std::string modulePath();
+ void visitComplexDataMembers(Slice::TypePtr t, const Slice::DataMemberList &) const;
+
+ std::string modulePath() const;
static boost::optional<std::string> metaDataValue(const std::string & prefix, const std::list<std::string> & metadata);
FILE * cpp;
std::vector<Slice::ModulePtr> modules;
+ unsigned int classNo;
};
}