From e5e5b4589c2b30e819d55834dbc19348d800cc53 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 26 Jan 2015 01:47:54 +0000 Subject: Add support for enumerations --- slicer/slicer/modelParts.cpp | 6 +++++ slicer/slicer/modelParts.h | 44 ++++++++++++++++++++++++++++++++ slicer/slicer/parser.cpp | 53 +++++++++++++++++++++++++++++++++++++++ slicer/slicer/parser.h | 6 +++-- slicer/test/compilation.cpp | 5 ++++ slicer/test/initial/enum.xml | 2 ++ slicer/test/initial/someenums.xml | 5 ++++ slicer/test/preprocessor.cpp | 2 +- slicer/test/serializers.cpp | 23 +++++++++++++++++ slicer/test/types.ice | 7 ++++++ 10 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 slicer/test/initial/enum.xml create mode 100644 slicer/test/initial/someenums.xml diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index ede9d64..b234777 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -1,4 +1,5 @@ #include "modelParts.h" +#include namespace Slicer { const Metadata emptyMetadata; @@ -12,6 +13,11 @@ namespace Slicer { std::invalid_argument(n) { } + InvalidEnumerationValue::InvalidEnumerationValue(const std::string & n, const std::string & e) : + std::invalid_argument("No such value '" + n + "' in " + e) { } + + InvalidEnumerationValue::InvalidEnumerationValue(::Ice::Int n, const std::string & e) : + std::invalid_argument("Invalid value " + boost::lexical_cast(n) + " in " + e) { } ClassNameMap * & classNameMap() diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index 5b1e634..97f7037 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -31,6 +31,12 @@ namespace Slicer { UnknownType(const std::string & n); }; + class InvalidEnumerationValue : public std::invalid_argument { + public: + InvalidEnumerationValue(const std::string & n, const std::string & e); + InvalidEnumerationValue(::Ice::Int n, const std::string & e); + }; + template class TValueTarget { public: @@ -536,6 +542,44 @@ namespace Slicer { static std::string rootName; }; + template + class ModelPartForEnum : public ModelPart { + public: + typedef T element_type; + typedef boost::bimap Enumerations; + + ModelPartForEnum(T & s) : + modelPart(s) + { + } + + ModelPartForEnum(T * s) : + modelPart(*s) + { + } + + virtual void OnEachChild(const ChildHandler &) override { } + + ChildRefPtr GetAnonChildRef(const HookFilter &) override { return NULL; } + + ChildRefPtr GetChildRef(const std::string &, const HookFilter &) override { return NULL; } + + virtual bool HasValue() const override { return true; } + + virtual ModelPartType GetType() const { return mpt_Simple; } + + virtual const Metadata & GetMetadata() const override { return metadata; } + + virtual void SetValue(ValueSourcePtr s) override; + + virtual void GetValue(ValueTargetPtr s) override; + + private: + T & modelPart; + static Metadata metadata; + static Enumerations enumerations; + }; + template class ModelPartForSequence : public ModelPart { public: diff --git a/slicer/slicer/parser.cpp b/slicer/slicer/parser.cpp index a4ee2dd..928984e 100644 --- a/slicer/slicer/parser.cpp +++ b/slicer/slicer/parser.cpp @@ -292,6 +292,56 @@ namespace Slicer { } } + void + Slicer::visitEnum(const Slice::EnumPtr & e) + { + if (e->hasMetaData("slicer:ignore")) { return; } + + components += 1; + + if (!cpp) return; + + fprintf(cpp, "// Enumeration %s\n", e->name().c_str()); + fprintf(cpp, "template<>\nMetadata ModelPartForEnum< %s >::metadata ", + e->scoped().c_str()); + copyMetadata(e->getMetaData()); + + fprintf(cpp, "template<>\nModelPartForEnum< %s >::Enumerations\nModelPartForEnum< %s >::enumerations([]() -> ModelPartForEnum< %s >::Enumerations\n", + e->scoped().c_str(), + e->scoped().c_str(), + e->scoped().c_str()); + fprintf(cpp, "{\n\tModelPartForEnum< %s >::Enumerations e;\n", + e->scoped().c_str()); + for (const auto & ee : e->getEnumerators()) { + fprintf(cpp, "\te.insert( { %s, \"%s\" } );\n", ee->scoped().c_str(), ee->name().c_str()); + + } + fprintf(cpp, "\treturn e;\n}());\n\n"); + + fprintf(cpp, "template<>\nvoid ModelPartForEnum< %s >::SetValue(ValueSourcePtr s) {\n\ + std::string val;\n\ + s->set(val);\n\ + auto i = enumerations.right.find(val);\n\ + if (i == enumerations.right.end()) throw InvalidEnumerationValue(val, \"%s\");\n\ + modelPart = i->second;\n\ +}\n\n", + e->scoped().c_str(), + e->scoped().c_str()); + fprintf(cpp, "template<>\nvoid ModelPartForEnum< %s >::GetValue(ValueTargetPtr s) {\n\ + auto i = enumerations.left.find(modelPart);\n\ + if (i == enumerations.left.end()) throw InvalidEnumerationValue((::Ice::Int)modelPart, \"%s\");\n\ + s->get(i->second);\n\ +}\n\n", + e->scoped().c_str(), + e->scoped().c_str()); + + auto name = metaDataValue("slicer:root:", e->getMetaData()); + defineRootName(e->scoped(), name ? *name : e->name()); + + fprintf(cpp, "templateMODELPARTFOR(%s, ModelPartForEnum);\n\n", + e->scoped().c_str()); + } + void Slicer::visitSequence(const Slice::SequencePtr & s) { @@ -436,6 +486,9 @@ namespace Slicer { else if (auto dictionary = Slice::DictionaryPtr::dynamicCast(type)) { fprintf(cpp, "ModelPartForDictionary"); } + else if (auto enumeration = Slice::EnumPtr::dynamicCast(type)) { + fprintf(cpp, "ModelPartForEnum"); + } } void diff --git a/slicer/slicer/parser.h b/slicer/slicer/parser.h index 6253cf5..8e7c469 100644 --- a/slicer/slicer/parser.h +++ b/slicer/slicer/parser.h @@ -33,9 +33,11 @@ namespace Slicer { virtual bool visitStructStart(const Slice::StructPtr&) override; - void visitSequence(const Slice::SequencePtr & s) override; + virtual void visitEnum(const Slice::EnumPtr &) override; - void visitDictionary(const Slice::DictionaryPtr & d) override; + virtual void visitSequence(const Slice::SequencePtr & s) override; + + virtual void visitDictionary(const Slice::DictionaryPtr & d) override; virtual void visitModuleEnd(const Slice::ModulePtr & m) override; diff --git a/slicer/test/compilation.cpp b/slicer/test/compilation.cpp index d48afd0..cc5d2e5 100644 --- a/slicer/test/compilation.cpp +++ b/slicer/test/compilation.cpp @@ -100,3 +100,8 @@ BOOST_AUTO_TEST_CASE( compile_auto_modelpart_type_struct ) StackTypeTest(TestModule::StructType, ModelPartForStruct, mpt_Complex); } +BOOST_AUTO_TEST_CASE( compile_auto_modelpart_type_enum ) +{ + StackTypeTest(TestModule::SomeNumbers, ModelPartForEnum, mpt_Simple); +} + diff --git a/slicer/test/initial/enum.xml b/slicer/test/initial/enum.xml new file mode 100644 index 0000000..06e0abb --- /dev/null +++ b/slicer/test/initial/enum.xml @@ -0,0 +1,2 @@ + +FiftyFive diff --git a/slicer/test/initial/someenums.xml b/slicer/test/initial/someenums.xml new file mode 100644 index 0000000..5691fc2 --- /dev/null +++ b/slicer/test/initial/someenums.xml @@ -0,0 +1,5 @@ + + + Ten + FiftyFive + diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp index c318e84..fa65a44 100644 --- a/slicer/test/preprocessor.cpp +++ b/slicer/test/preprocessor.cpp @@ -13,7 +13,7 @@ namespace fs = boost::filesystem; -const unsigned int COMPONENTS_IN_TEST_ICE = 28; +const unsigned int COMPONENTS_IN_TEST_ICE = 30; BOOST_FIXTURE_TEST_SUITE ( preprocessor, FileStructure ); diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index a13bb49..df6c052 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -222,6 +222,19 @@ checkBare(const TestModule::BareContainers & bc) BOOST_REQUIRE_EQUAL(bc.bareMap.size(), 2); } +void +checkSomeEnums(const TestModule::SomeEnumsPtr & se) +{ + BOOST_REQUIRE_EQUAL(se->one, TestModule::Ten); + BOOST_REQUIRE_EQUAL(se->two, TestModule::FiftyFive); +} + +void +checkSomeNumbers(const TestModule::SomeNumbers & sn) +{ + BOOST_REQUIRE_EQUAL(sn, TestModule::FiftyFive); +} + xmlpp::Document * readXml(const fs::path & path) { @@ -375,6 +388,16 @@ BOOST_AUTO_TEST_CASE( xml_barecontainers_xml ) verifyByFile("bare.xml", checkBare); } +BOOST_AUTO_TEST_CASE( xml_classOfEnums_xml ) +{ + verifyByFile("someenums.xml", checkSomeEnums); +} + +BOOST_AUTO_TEST_CASE( xml_rootEnums_xml ) +{ + verifyByFile("enum.xml", checkSomeNumbers); +} + BOOST_AUTO_TEST_SUITE_END(); diff --git a/slicer/test/types.ice b/slicer/test/types.ice index 4192448..198116b 100644 --- a/slicer/test/types.ice +++ b/slicer/test/types.ice @@ -1,6 +1,9 @@ [["cpp:include:boost/date_time/posix_time/posix_time_types.hpp"]] module TestModule { + enum SomeNumbers { + One = 1, Ten = 10, FiftyFive = 55 + }; struct DateTime { short year; short month; @@ -106,6 +109,10 @@ module TestModule { [ "slicer:xml:bare" ] ClassMap bareMap; }; + class SomeEnums { + SomeNumbers one; + SomeNumbers two; + }; }; module TestModule2 { -- cgit v1.2.3