diff options
| -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 | ||||
| -rw-r--r-- | slicer/test/Jamfile.jam | 1 | ||||
| -rw-r--r-- | slicer/test/initial/builtins.xml | 8 | ||||
| -rw-r--r-- | slicer/test/initial/optionals-areset.xml | 42 | ||||
| -rw-r--r-- | slicer/test/initial/optionals-notset.xml | 5 | ||||
| -rw-r--r-- | slicer/test/run-slicer.cpp | 6 | ||||
| -rw-r--r-- | slicer/test/types.ice | 19 | ||||
| -rw-r--r-- | slicer/xml/serializer.cpp | 9 | 
11 files changed, 202 insertions, 95 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;  	};  } diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index 88c981f..ebc6c25 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -26,6 +26,7 @@ lib common :  	: :  	<library>boost_filesystem  	<library>boost_system +	<include>../../libmisc  	;  unit-test do-slicer : diff --git a/slicer/test/initial/builtins.xml b/slicer/test/initial/builtins.xml index 650d187..d77126e 100644 --- a/slicer/test/initial/builtins.xml +++ b/slicer/test/initial/builtins.xml @@ -1,11 +1,11 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?>  <BuiltIns>    <mbool>true</mbool>    <mbyte>4</mbyte> -  <mdouble>3.14159265359</mdouble> -  <mfloat>3.14</mfloat> +  <mshort>40</mshort>    <mint>80</mint>    <mlong>800</mlong> -  <mshort>40</mshort> +  <mfloat>3.125</mfloat> +  <mdouble>3.0625</mdouble>    <mstring>Sample text</mstring>  </BuiltIns> diff --git a/slicer/test/initial/optionals-areset.xml b/slicer/test/initial/optionals-areset.xml index e4cdf42..aa2a97a 100644 --- a/slicer/test/initial/optionals-areset.xml +++ b/slicer/test/initial/optionals-areset.xml @@ -1,14 +1,14 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?>  <Optionals>    <optSimple>4</optSimple> -  <optClass> -    <a>1</a> -    <b>2</b> -  </optClass>    <optStruct>      <a>1</a>      <b>2</b>    </optStruct> +  <optClass> +    <a>1</a> +    <b>2</b> +  </optClass>    <optSeq>      <element>        <a>3</a> @@ -19,20 +19,20 @@        <b>6</b>      </element>    </optSeq> -	<optDict> -		<element> -			<key>10</key> -			<value> -				<a>11</a> -				<b>12</b> -			</value> -		</element> -		<element> -			<key>13</key> -			<value> -				<a>14</a> -				<b>15</b> -			</value> -		</element> -	</optDict> +  <optDict> +    <element> +      <key>10</key> +      <value> +        <a>11</a> +        <b>12</b> +      </value> +    </element> +    <element> +      <key>13</key> +      <value> +        <a>14</a> +        <b>15</b> +      </value> +    </element> +  </optDict>  </Optionals> diff --git a/slicer/test/initial/optionals-notset.xml b/slicer/test/initial/optionals-notset.xml index 8fbb701..8c679d1 100644 --- a/slicer/test/initial/optionals-notset.xml +++ b/slicer/test/initial/optionals-notset.xml @@ -1,3 +1,2 @@ -<?xml version="1.0"?> -<Optionals> -</Optionals> +<?xml version="1.0" encoding="UTF-8"?> +<Optionals/> diff --git a/slicer/test/run-slicer.cpp b/slicer/test/run-slicer.cpp index 897d9ee..35db875 100644 --- a/slicer/test/run-slicer.cpp +++ b/slicer/test/run-slicer.cpp @@ -7,6 +7,8 @@  #include <boost/function.hpp>  #include <boost/assert.hpp>  #include <types.h> +#include <misc.h> +#include "helpers.h"  namespace fs = boost::filesystem; @@ -26,6 +28,8 @@ verify(const fs::path & root, const fs::path & tmp, const fs::path & infile, con  	fprintf(stderr, "%s : Check2\n", input.string().c_str());  	if (check) check(*p);  	fprintf(stderr, "%s : OK\n", input.string().c_str()); + +	system(stringbf("diff -w %s %s", input, output));  }  void @@ -85,6 +89,8 @@ main(int, char ** argv)  	verify<TestModule::BuiltIns, Slicer::Xml>(root, tmp, "builtins.xml");  	verify<TestModule::Optionals, Slicer::Xml>(root, tmp, "optionals-notset.xml", checkOptionals_notset);  	verify<TestModule::Optionals, Slicer::Xml>(root, tmp, "optionals-areset.xml", checkOptionals_areset); +	verify<TestModule::InheritanceCont, Slicer::Xml>(root, tmp, "inherit-a.xml"); +	verify<TestModule::InheritanceCont, Slicer::Xml>(root, tmp, "inherit-b.xml");  	return 0;  } diff --git a/slicer/test/types.ice b/slicer/test/types.ice index 46f834f..bdcd4be 100644 --- a/slicer/test/types.ice +++ b/slicer/test/types.ice @@ -38,4 +38,23 @@ module TestModule {  		StructType str;  		int simp;  	}; +	class Base { +		int a; +	}; +	class D1 extends Base { +		int b; +	}; +	class D2 extends Base { +		int c; +	}; +	class D3 extends D2 { +		int d; +	}; +	sequence<Base> BaseSeq; +	dictionary<int, Base> BaseMap; +	class InheritanceCont { +		Base b; +		BaseSeq bs; +		BaseMap bm; +	};  }; diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index 1ff6058..b08e274 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -167,6 +167,10 @@ namespace Slicer {  			if (auto element = dynamic_cast<const xmlpp::Element *>(node)) {  				auto smp = mp->GetChild(element->get_name());  				if (smp) { +					auto typeAttr = element->get_attribute("slicer-typeid"); +					if (typeAttr) { +						smp = smp->GetSubclassModelPart(typeAttr->get_value()); +					}  					smp->Create();  					auto attrs(element->get_attributes());  					if (!attrs.empty()) { @@ -208,6 +212,11 @@ namespace Slicer {  		}  		else if (mp) {  			auto element = n->add_child(name); +			auto typeId = mp->GetTypeId(); +			if (typeId) { +				element->set_attribute("slicer-typeid", *typeId); +				mp = mp->GetSubclassModelPart(*typeId); +			}  			mp->GetValue(new XmlContentValueTarget(element));  			mp->OnEachChild(boost::bind(&Xml::ModelTreeIterate, element, _1, _2));  		} | 
