diff options
| author | randomdan <randomdan@localhost> | 2014-06-26 13:20:58 +0000 |
|---|---|---|
| committer | randomdan <randomdan@localhost> | 2014-06-26 13:20:58 +0000 |
| commit | 9b0fb1a52dd7b8db1dab98cebf7b928e4d921111 (patch) | |
| tree | 346f7c2dfe4530f86b44d304a5b620ce3a4dce06 /slicer/slicer | |
| parent | Move the name into the hook (diff) | |
| download | slicer-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.cpp | 31 | ||||
| -rw-r--r-- | slicer/slicer/modelParts.h | 34 | ||||
| -rw-r--r-- | slicer/slicer/parser.cpp | 137 | ||||
| -rw-r--r-- | slicer/slicer/parser.h | 5 |
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; }; } |
