diff options
| -rw-r--r-- | slicer/Jamfile.jam | 9 | ||||
| -rw-r--r-- | slicer/slicer/Jamfile.jam | 17 | ||||
| -rw-r--r-- | slicer/slicer/modelParts.cpp | 21 | ||||
| -rw-r--r-- | slicer/slicer/modelParts.h | 292 | ||||
| -rw-r--r-- | slicer/slicer/parser.cpp | 268 | ||||
| -rw-r--r-- | slicer/slicer/parser.h | 47 | ||||
| -rw-r--r-- | slicer/slicer/serializer.h | 19 | ||||
| -rw-r--r-- | slicer/slicer/slicer.h | 31 | ||||
| -rw-r--r-- | slicer/test/Jamfile.jam | 3 | ||||
| -rw-r--r-- | slicer/test/do-slicer.cpp | 13 | ||||
| -rw-r--r-- | slicer/test/types.ice | 38 | ||||
| -rw-r--r-- | slicer/tool/Jamfile.jam | 5 | ||||
| -rw-r--r-- | slicer/tool/slicer.cpp | 17 | ||||
| -rw-r--r-- | slicer/xml/Jamfile.jam | 16 | ||||
| -rw-r--r-- | slicer/xml/serializer.cpp | 239 | ||||
| -rw-r--r-- | slicer/xml/serializer.h | 29 | 
16 files changed, 1064 insertions, 0 deletions
diff --git a/slicer/Jamfile.jam b/slicer/Jamfile.jam new file mode 100644 index 0000000..b6de7a4 --- /dev/null +++ b/slicer/Jamfile.jam @@ -0,0 +1,9 @@ +import package ; + +build-project tool ; +build-project slicer ; +build-project xml ; +build-project test ; + +package.install install : <install-source-root>. : tool//slicer : slicer//slicer : [ glob slicer/*.h ] ; +package.install install-xml : <install-source-root>. : : xml//slicer-xml : [ glob xml/*.h ] ; diff --git a/slicer/slicer/Jamfile.jam b/slicer/slicer/Jamfile.jam new file mode 100644 index 0000000..96bd9a9 --- /dev/null +++ b/slicer/slicer/Jamfile.jam @@ -0,0 +1,17 @@ +lib Slice ; +lib IceUtil ; +lib boost_system ; +lib boost_filesystem ; + +lib slicer : +	[ glob *.cpp ] +	: +	<library>Slice +	<library>IceUtil +	<library>boost_system +	<library>boost_filesystem +	: : +	<include>.. +	<library>boost_system +	<library>boost_filesystem +	; diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp new file mode 100644 index 0000000..9d33d51 --- /dev/null +++ b/slicer/slicer/modelParts.cpp @@ -0,0 +1,21 @@ +#include "modelParts.h" + +namespace Slicer { +	void +	ModelPart::Create() +	{ +	} +	void +	ModelPart::Complete() +	{ +	} +	void +	ModelPart::SetValue(ValueSourcePtr) +	{ +	} +	void +	ModelPart::GetValue(ValueTargetPtr) +	{ +	} +} + diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h new file mode 100644 index 0000000..6dc450e --- /dev/null +++ b/slicer/slicer/modelParts.h @@ -0,0 +1,292 @@ +#ifndef SLICER_MODELPARTS_H +#define SLICER_MODELPARTS_H + +#include <Ice/Config.h> +#include <IceUtil/Shared.h> +#include <IceUtil/Handle.h> +#include <Ice/Handle.h> +#include <Slice/Parser.h> +#include <stdexcept> +#include <boost/function.hpp> +#include <boost/foreach.hpp> + +namespace Slicer { +	class IncorrectElementName : public std::invalid_argument { +		public: +			IncorrectElementName() : +				std::invalid_argument("") { } +	}; + +	class ValueTarget : public IceUtil::Shared { +		public: +			virtual void get(const bool &) const = 0; +			virtual void get(const Ice::Byte &) const = 0; +			virtual void set(const Ice::Short &) const = 0; +			virtual void get(const Ice::Int &) const = 0; +			virtual void get(const Ice::Long &) const = 0; +			virtual void get(const Ice::Float &) const = 0; +			virtual void get(const Ice::Double &) const = 0; +			virtual void get(const std::string &) const = 0; +	}; +	typedef IceUtil::Handle<ValueTarget> ValueTargetPtr; + +	class ValueSource : public IceUtil::Shared { +		public: +			virtual void set(bool &) const = 0; +			virtual void set(Ice::Byte &) const = 0; +			virtual void set(Ice::Short &) const = 0; +			virtual void set(Ice::Int &) const = 0; +			virtual void set(Ice::Long &) const = 0; +			virtual void set(Ice::Float &) const = 0; +			virtual void set(Ice::Double &) const = 0; +			virtual void set(std::string &) const = 0; +	}; +	typedef IceUtil::Handle<ValueSource> ValueSourcePtr; + +	class ModelPart; + +	typedef IceUtil::Handle<ModelPart> ModelPartPtr; +	typedef std::map<std::string, ModelPartPtr> ModelParts; + +	typedef boost::function<void(const std::string &, ModelPartPtr)> ChildHandler; + +	class ModelPart : public IceUtil::Shared { +		public: +			virtual ~ModelPart() = default; + +			virtual void OnEachChild(const ChildHandler &) = 0; +			virtual ModelPartPtr GetChild(const std::string &) = 0; +			virtual void Create(); +			virtual void Complete(); +			virtual void SetValue(ValueSourcePtr); +			virtual void GetValue(ValueTargetPtr); +	}; + +	template<typename T> +	class ModelPartForSimple : public ModelPart { +		public: +			ModelPartForSimple(T & h) : +				Member(h) +			{ +			} +			ModelPartForSimple(T * h) : +				Member(*h) +			{ +			} +			virtual void OnEachChild(const ChildHandler &) { } +			virtual ModelPartPtr GetChild(const std::string &) override { return NULL; } +			virtual void SetValue(ValueSourcePtr s) override { s->set(Member); } +			virtual void GetValue(ValueTargetPtr s) override { s->get(Member); } + +		private: +			T & Member; +	}; + +	template<typename T> +	class ModelPartForComplex : public ModelPart { +		public: +			class HookBase : public IceUtil::Shared { +				public: +					virtual ModelPartPtr Get(T & t) const = 0; +			}; +			typedef IceUtil::Handle<HookBase> HookPtr; + +			template <typename MT, MT T::*M, typename MP> +			class Hook : public HookBase { +				public: +					ModelPartPtr Get(T & t) const override +					{ +						return new MP(t.*M); +					} +			}; + +			virtual void OnEachChild(const ChildHandler & ch) +			{ +				for (auto h = hooks.begin(); h != hooks.end(); h++) { +					ch(h->first, h->second->Get(GetModel())); +				} +			} + +			ModelPartPtr GetChild(const std::string & name) override +			{ +				auto childitr = hooks.find(name); +				if (childitr != hooks.end()) { +					return childitr->second->Get(GetModel()); +				} +				return NULL; +			} + +			virtual T & GetModel() = 0; + +			typedef std::map<std::string, HookPtr> Hooks; + +		private: +			static Hooks hooks; +	}; +	 +	template<typename T> +	class ModelPartForClass : public ModelPartForComplex<T> { +		public: +			ModelPartForClass(IceInternal::Handle<T> & h) : +				ModelObject(h) +			{ +			} + +			virtual void Create() override +			{ +				ModelObject = new T(); +			} + +			T & GetModel() override +			{ +				return *ModelObject; +			} + +		private: +			IceInternal::Handle<T> & ModelObject; +	}; + +	template<typename T> +	class ModelPartForStruct : public ModelPartForComplex<T> { +		public: +			ModelPartForStruct(T & o) : +				ModelObject(o) +			{ +			} + +			T & GetModel() override +			{ +				return ModelObject; +			} + +		private: +			T & ModelObject; +	}; + +	template<typename T> +	class ModelPartForClassRoot : public ModelPartForClass<T> { +		public: +			ModelPartForClassRoot() : +				ModelPartForClass<T>(ModelObject) +			{ +			} + +			ModelPartForClassRoot(IceInternal::Handle<T> o) : +				ModelPartForClass<T>(ModelObject) +			{ +				ModelObject = o; +			} + +			virtual ModelPartPtr GetChild(const std::string & name) override +			{ +				if (!name.empty() && name != rootName) { +					throw IncorrectElementName(); +				} +				ModelPartForClass<T>::Create(); +				return new ModelPartForClass<T>(ModelObject); +			} + +			virtual void OnEachChild(const ChildHandler & ch) override +			{ +				ch(rootName, new ModelPartForClass<T>(ModelObject)); +			} + +			T & GetModel() override +			{ +				return *ModelObject; +			} + +		private: +			IceInternal::Handle<T> ModelObject; +			static std::string rootName; +	}; + +	template<typename T> +	class ModelPartForSequence : public ModelPart { +		public: +			ModelPartForSequence(T & s) : +				sequence(s) +			{ +			} +			virtual void OnEachChild(const ChildHandler & ch) override +			{ +				BOOST_FOREACH(auto & element, sequence) { +					ch(elementName, elementModelPart(element)); +				} +			} + +			ModelPartPtr GetChild(const std::string &) override; + +		private: +			ModelPartPtr elementModelPart(typename T::value_type &) const; + +			T & sequence; +			static std::string elementName; +	}; + +	template<typename T> +	class ModelPartForDictionaryElement : public ModelPartForComplex<ModelPartForDictionaryElement<T> > { +		public: +			ModelPartForDictionaryElement(typename T::key_type * k, typename T::mapped_type * v) : +				key(k), +				value(v) +			{ +			} + +			ModelPartForDictionaryElement<T> & GetModel() override +			{ +				return *this; +			} + +			typename T::key_type * key; +			typename T::mapped_type * value; +	}; + +	template<typename T> +	class ModelPartForDictionaryElementInserter : public ModelPartForDictionaryElement<T> { +		public: +			ModelPartForDictionaryElementInserter(T & d) : +				ModelPartForDictionaryElement<T>(&key, &value), +				dictionary(d) +			{ +			} + +			virtual void Complete() override { dictionary.insert(typename T::value_type(key, value)); } + +			mutable typename T::key_type key; +			mutable typename T::mapped_type value; + +		private: +			T & dictionary; +	}; + +	template<typename T> +	class ModelPartForDictionary : public ModelPart { +		public: +			ModelPartForDictionary(T & d) : +				dictionary(d) +			{ +			} +			virtual void OnEachChild(const ChildHandler & ch) override +			{ +				BOOST_FOREACH(auto & pair, dictionary) { +					ch(pairName, new ModelPartForDictionaryElement<T>(const_cast<typename T::key_type *>(&pair.first), &pair.second)); +				} +			} +			ModelPartPtr GetChild(const std::string & name) override +			{ +				if (!name.empty() && name != pairName) { +					throw IncorrectElementName(); +				} +				return new ModelPartForDictionaryElementInserter<T>(dictionary); +			} + + +		private: +			T & dictionary; +			static std::string pairName; +	}; +} + +#endif + diff --git a/slicer/slicer/parser.cpp b/slicer/slicer/parser.cpp new file mode 100644 index 0000000..a67f483 --- /dev/null +++ b/slicer/slicer/parser.cpp @@ -0,0 +1,268 @@ +#include "parser.h" +#include <Slice/Parser.h> +#include <Slice/Preprocessor.h> +#include <boost/foreach.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <Slice/CPlusPlusUtil.h> +#include <boost/shared_ptr.hpp> + +namespace Slicer { +	Slicer::Slicer(FILE * c) : +		cpp(c) +	{ +	} + +	void +	Slicer::leadIn() +	{ +		fprintf(cpp, "// Begin Slicer code\n\n"); +		fprintf(cpp, "#include <slicer/modelParts.h>\n\n"); +		fprintf(cpp, "namespace Slicer {\n"); +	} + +	void +	Slicer::leadOut() +	{ +		fprintf(cpp, "}\n\n"); +		fprintf(cpp, "// End Slicer code\n\n"); +	} + +	bool +	Slicer::visitModuleStart(const Slice::ModulePtr & m) +	{ +		fprintf(cpp, "// Begin module %s\n\n", m->name().c_str()); +		modules.push_back(m); +		return true; +	} + +	bool +	Slicer::visitClassDefStart(const Slice::ClassDefPtr & c) +	{ +		if (c->hasMetaData("slicer:ignore")) { return false; } + +		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{ \"%s\", ", +					name ? name->c_str() : dm->name().c_str()); +			auto type = dm->type(); +			fprintf(cpp, "new ModelPartForClass< %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(type); +			fprintf(cpp, " >() },\n"); +		} +		fprintf(cpp, "\t};\n"); +		 +		fprintf(cpp, "template<>\n"); +		auto name = metaDataValue("slicer:root:", c->getMetaData()); +		fprintf(cpp, "std::string ModelPartForClassRoot< %s::%s >::rootName(\"%s\");\n\n", +				modulePath().c_str(), c->name().c_str(), +				name ? name->c_str() : c->name().c_str()); +		return true; +	} + +	bool +	Slicer::visitStructStart(const Slice::StructPtr & c) +	{ +		if (c->hasMetaData("slicer:ignore")) { return false; } + +		fprintf(cpp, "// Struct %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->dataMembers()) { +			auto name = metaDataValue("slicer:name:", dm->getMetaData()); +			fprintf(cpp, "\t\t{ \"%s\", ", +					name ? name->c_str() : dm->name().c_str()); +			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(type); +			fprintf(cpp, " >() },\n"); +		} +		fprintf(cpp, "\t};\n\n"); +		 +		return true; +	} + +	void +	Slicer::visitSequence(const Slice::SequencePtr & s) +	{ +		if (s->hasMetaData("slicer:ignore")) { return; } + +		fprintf(cpp, "// Sequence %s\n", s->name().c_str()); +		fprintf(cpp, "template<>\n"); +		fprintf(cpp, "ModelPartPtr ModelPartForSequence< %s::%s >::GetChild(const std::string & name)\n{\n", +				modulePath().c_str(), s->name().c_str()); +		auto iname = metaDataValue("slicer:item:", s->getMetaData()); +		if (iname) { +			fprintf(cpp, "\tif (!name.empty() && name != \"%s\") { throw IncorrectElementName(); }\n", +					iname->c_str()); +		} +		else { +			fprintf(cpp, "\t(void)name;\n"); +		} +		fprintf(cpp, "\tsequence.push_back(%s());\n", +					Slice::typeToString(s->type()).c_str()); +		fprintf(cpp, "\treturn new "); +		createNewModelPartPtrFor(s->type()); +		fprintf(cpp, "(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", +				modulePath().c_str(), s->name().c_str(), +				modulePath().c_str(), s->name().c_str()); +		auto etype = s->type(); +		fprintf(cpp, "\treturn new "); +		createNewModelPartPtrFor(etype); +		fprintf(cpp, "(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", +				modulePath().c_str(), s->name().c_str(), +				ename ? ename->c_str() : "element"); +	} + +	void +	Slicer::visitDictionary(const Slice::DictionaryPtr & d) +	{ +		if (d->hasMetaData("slicer:ignore")) { return; } + +		fprintf(cpp, "// Dictionary %s\n", d->name().c_str()); +		auto iname = metaDataValue("slicer:item:", d->getMetaData()); +		fprintf(cpp, "template<>\n"); +		fprintf(cpp, "std::string ModelPartForDictionary< %s::%s >::pairName(\"%s\");\n\n", +				modulePath().c_str(), d->name().c_str(), +				iname ? iname->c_str() : "element"); + +		fprintf(cpp, "template<>\n"); +		fprintf(cpp, "ModelPartForComplex< ModelPartForDictionaryElement< %s::%s > >::Hooks ", +				modulePath().c_str(), d->name().c_str()); +		fprintf(cpp, "ModelPartForComplex< ModelPartForDictionaryElement< %s::%s > >::hooks {\n", +				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{ \"%s\", ", +				kname ? kname->c_str() : "key"); +		auto ktype = d->keyType(); +		fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, &ModelPartForDictionaryElement< %s::%s >::key, ", +				modulePath().c_str(), d->name().c_str(), +				Slice::typeToString(ktype).c_str(), +				modulePath().c_str(), d->name().c_str()); +		createNewModelPartPtrFor(ktype); +		fprintf(cpp, " >() },\n\t\t{ \"%s\", ", +				vname ? vname->c_str() : "value"); +		auto vtype = d->valueType(); +		fprintf(cpp, "new ModelPartForDictionaryElement< %s::%s >::Hook< %s*, &ModelPartForDictionaryElement< %s::%s >::value, ", +				modulePath().c_str(), d->name().c_str(), +				Slice::typeToString(vtype).c_str(), +				modulePath().c_str(), d->name().c_str()); +		createNewModelPartPtrFor(vtype); +		fprintf(cpp, " >() },\n"); +		fprintf(cpp, "\t};\n"); +		fprintf(cpp, "\n"); +	} + +	void +	Slicer::visitModuleEnd(const Slice::ModulePtr & m) +	{ +		fprintf(cpp, "// End module %s\n\n", m->name().c_str()); +		modules.pop_back(); +	} + +	void +	Slicer::createNewModelPartPtrFor(const Slice::TypePtr & type) const +	{ +		if (auto builtin = Slice::BuiltinPtr::dynamicCast(type)) { +			fprintf(cpp, "ModelPartForSimple< %s >", +					Slice::typeToString(type).c_str()); +		} +		else if (auto complexClass = Slice::ClassDeclPtr::dynamicCast(type)) { +			fprintf(cpp, "ModelPartForClass< %s::element_type >", +					Slice::typeToString(type).c_str()); +		} +		else if (auto complexStruct = Slice::StructPtr::dynamicCast(type)) { +			fprintf(cpp, "ModelPartForStruct< %s >", +					Slice::typeToString(type).c_str()); +		} +		else if (auto sequence = Slice::SequencePtr::dynamicCast(type)) { +			fprintf(cpp, "ModelPartForSequence< %s >", +					Slice::typeToString(type).c_str()); +		} +		else if (auto dictionary = Slice::DictionaryPtr::dynamicCast(type)) { +			fprintf(cpp, "ModelPartForDictionary< %s >", +					Slice::typeToString(type).c_str()); +		} +	} + +	std::string +	Slicer::modulePath() +	{ +		std::string path; +		BOOST_FOREACH (const auto & m, modules) { +			path += "::"; +			path += m->name(); +		} +		return path; +	} + +	boost::optional<std::string> +	Slicer::metaDataValue(const std::string & prefix, const std::list<std::string> & metadata) +	{ +		BOOST_FOREACH (const auto & md, metadata) { +			if (boost::algorithm::starts_with(md, prefix)) { +				return md.substr(prefix.length()); +			} +		} +		return boost::optional<std::string>(); +	} + +	void +	Slicer::Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp) +	{ +		std::vector<std::string> cppArgs; +		Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("slicer", ice.string(), cppArgs); +		FILE * cppHandle = icecpp->preprocess(false); + +		if (cppHandle == NULL) { +			throw std::runtime_error("preprocess failed"); +		} + +		Slice::UnitPtr u = Slice::Unit::createUnit(false, false, false, false); + +		int parseStatus = u->parse(ice.string(), cppHandle, false); + +		if (!icecpp->close()) { +			throw std::runtime_error("preprocess close failed"); +		} + +		if (parseStatus == EXIT_FAILURE) { +			throw std::runtime_error("unit parse failed"); +		} + +		FilePtr cppfile(fopen(cpp.string().c_str(), "a"), fclose); +		if (!cppfile) { +			throw std::runtime_error("failed to open code file"); +		} + +		Slicer s(cppfile.get()); +		s.leadIn(); +		u->visit(&s, false); +		s.leadOut(); + +		u->destroy(); +	} +}; + diff --git a/slicer/slicer/parser.h b/slicer/slicer/parser.h new file mode 100644 index 0000000..c660cc6 --- /dev/null +++ b/slicer/slicer/parser.h @@ -0,0 +1,47 @@ +#ifndef SLICER_PARSER_H +#define SLICER_PARSER_H + +#include <Slice/Parser.h> +#include <boost/optional.hpp> +#include <boost/filesystem/path.hpp> + +namespace Slicer { +	typedef boost::shared_ptr<FILE> FilePtr; + +	class Slicer : public Slice::ParserVisitor { +		public: +			Slicer(FILE * c); + +			static void Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp); + +			void leadIn(); + +			void leadOut(); + +			virtual bool visitModuleStart(const Slice::ModulePtr & m) override; + +			virtual bool visitClassDefStart(const Slice::ClassDefPtr & c) override; + +			virtual bool visitStructStart(const Slice::StructPtr&) override; + +			void visitSequence(const Slice::SequencePtr & s) override; + +			void visitDictionary(const Slice::DictionaryPtr & d) override; + +			virtual void visitModuleEnd(const Slice::ModulePtr & m) override; + + +		private: +			void createNewModelPartPtrFor(const Slice::TypePtr & type) const; + +			std::string modulePath(); + +			static boost::optional<std::string> metaDataValue(const std::string & prefix, const std::list<std::string> & metadata); + +			FILE * cpp; +			std::vector<Slice::ModulePtr> modules; +	}; +} + +#endif + diff --git a/slicer/slicer/serializer.h b/slicer/slicer/serializer.h new file mode 100644 index 0000000..dffa0f6 --- /dev/null +++ b/slicer/slicer/serializer.h @@ -0,0 +1,19 @@ +#ifndef SLICER_SERIALIZER_H +#define SLICER_SERIALIZER_H + +#include <IceUtil/Shared.h> +#include <IceUtil/Handle.h> +#include <boost/filesystem/path.hpp> +#include <slicer/modelParts.h> + +namespace Slicer { +	class Serializer : public IceUtil::Shared { +		public: +			virtual void Deserialize(const boost::filesystem::path &, ModelPartPtr) = 0; +			virtual void Serialize(const boost::filesystem::path &, ModelPartPtr) = 0; +	}; +	typedef IceUtil::Handle<Serializer> SerializerPtr; +} + +#endif + diff --git a/slicer/slicer/slicer.h b/slicer/slicer/slicer.h new file mode 100644 index 0000000..8421774 --- /dev/null +++ b/slicer/slicer/slicer.h @@ -0,0 +1,31 @@ +#ifndef SLICER_H +#define SLICER_H + +#include <Ice/Handle.h> +#include <boost/filesystem/path.hpp> +#include <slicer/modelParts.h> +#include <slicer/serializer.h> + +namespace Slicer { +	template <typename Serializer, typename Object> +	IceInternal::Handle<Object> +	Deserialize(const boost::filesystem::path & path) +	{ +		IceUtil::Handle<ModelPartForClassRoot<Object>> root = new ModelPartForClassRoot<Object>(); +		SerializerPtr serializer = new Serializer(); +		serializer->Deserialize(path, root); +		return &root->GetModel(); +	} + +	template <typename Serializer, typename Object> +	void +	Serialize(IceInternal::Handle<Object> object, const boost::filesystem::path & path) +	{ +		IceUtil::Handle<ModelPartForClassRoot<Object>> root = new ModelPartForClassRoot<Object>(object); +		SerializerPtr serializer = new Serializer(); +		serializer->Serialize(path, root); +	} +} + +#endif + diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam new file mode 100644 index 0000000..b4e05b3 --- /dev/null +++ b/slicer/test/Jamfile.jam @@ -0,0 +1,3 @@ +import testing ; + +run do-slicer.cpp ../slicer//slicer : : types.ice ; diff --git a/slicer/test/do-slicer.cpp b/slicer/test/do-slicer.cpp new file mode 100644 index 0000000..8b03a7d --- /dev/null +++ b/slicer/test/do-slicer.cpp @@ -0,0 +1,13 @@ +#include <slicer/parser.h> +#include <boost/filesystem/convenience.hpp> +#include <boost/filesystem/operations.hpp> + +int +main(int, char ** argv) +{ +	const boost::filesystem::path slice = argv[1]; +	Slicer::Slicer::Apply(slice, "/dev/null"); + +	return 0; +} + diff --git a/slicer/test/types.ice b/slicer/test/types.ice new file mode 100644 index 0000000..fdacb2d --- /dev/null +++ b/slicer/test/types.ice @@ -0,0 +1,38 @@ +module TestModule { +	class BuiltIns { +		bool mbool; +		byte mbyte; +		short mshort; +		int mint; +		long mlong; +		float mfloat; +		double mdouble; +		string mstring; +	}; +	class ClassType { +		int a; +		int b; +	}; +	struct StructType { +		int a; +		int b; +	}; +	class Optionals { +		optional(1) int simple; +		optional(2) StructType str; +	}; +	sequence<ClassType> Classes; +	sequence<StructType> Structs; +	dictionary<int, ClassType> ClassMap; +	dictionary<int, StructType> StructMap; +	class ClassClass { +		ClassType cls; +		StructType str; +		int simp; +	}; +	struct StructStruct { +		ClassType cls; +		StructType str; +		int simp; +	}; +}; diff --git a/slicer/tool/Jamfile.jam b/slicer/tool/Jamfile.jam new file mode 100644 index 0000000..de50043 --- /dev/null +++ b/slicer/tool/Jamfile.jam @@ -0,0 +1,5 @@ +exe slicer : +	[ glob *.cpp ] +	: +	<library>../slicer//slicer +	; diff --git a/slicer/tool/slicer.cpp b/slicer/tool/slicer.cpp new file mode 100644 index 0000000..ce58c57 --- /dev/null +++ b/slicer/tool/slicer.cpp @@ -0,0 +1,17 @@ +#include <slicer/parser.h> + +int +main(int argc, char ** argv) +{ +	if (argc < 3) { +		fprintf(stderr, "slicer <input.ice> <output.cpp>\n"); +		return 1; +	} + +	const boost::filesystem::path slice = argv[1]; +	const boost::filesystem::path cpp = argv[2]; + +	Slicer::Slicer::Apply(slice, cpp); + +	return 0; +} diff --git a/slicer/xml/Jamfile.jam b/slicer/xml/Jamfile.jam new file mode 100644 index 0000000..97f013c --- /dev/null +++ b/slicer/xml/Jamfile.jam @@ -0,0 +1,16 @@ +alias libxmlpp : : : : +	<cflags>"`pkg-config --cflags libxml++-2.6`" +	<linkflags>"`pkg-config --libs libxml++-2.6`" ; +lib boost_system ; +lib boost_filesystem ; +lib IceUtil ; + +lib slicer-xml : +	[ glob *.cpp ] +	: +	<include>.. +	<library>boost_system +	<library>boost_filesystem +	<library>IceUtil +	<library>libxmlpp +	; diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp new file mode 100644 index 0000000..0a065d8 --- /dev/null +++ b/slicer/xml/serializer.cpp @@ -0,0 +1,239 @@ +#include "serializer.h" +#include <libxml++/document.h> +#include <libxml++/parsers/domparser.h> +#include <boost/lexical_cast.hpp> +#include <boost/bind.hpp> +#include <stdexcept> +#include <glibmm/ustring.h> + +namespace Slicer { +	class BadBooleanValue : public std::invalid_argument { +		public: +			BadBooleanValue(const Glib::ustring &) : +				std::invalid_argument("Bad boolean value") +			{ +			} +	}; + +	static const Glib::ustring TrueText("true"); +	static const Glib::ustring FalseText("false"); + +	class XmlValueSource : public ValueSource { +		public: +			XmlValueSource(const Glib::ustring & s) : +				value(s) +			{ +			} + +			void set(bool & v) const override +			{ +				if (value == TrueText) { v = true; return; } +				if (value == FalseText) { v = false; return; } +				throw BadBooleanValue(value); +			} + +			void set(Ice::Byte & v) const override +			{ +				v = boost::lexical_cast<Ice::Byte>(value); +			} + +			void set(Ice::Short & v) const override +			{ +				v = boost::lexical_cast<Ice::Short>(value); +			} + +			void set(Ice::Int & v) const override +			{ +				v = boost::lexical_cast<Ice::Int>(value); +			} + +			void set(Ice::Long & v) const override +			{ +				v = boost::lexical_cast<Ice::Long>(value); +			} + +			void set(Ice::Float & v) const override +			{ +				v = boost::lexical_cast<Ice::Float>(value); +			} + +			void set(Ice::Double & v) const override +			{ +				v = boost::lexical_cast<Ice::Double>(value); +			} + +			void set(std::string & v) const override +			{ +				v = value.raw(); +			} + +		protected: +			const Glib::ustring value; +	}; + +	class XmlContentValueSource : public XmlValueSource { +		public: +			XmlContentValueSource(const xmlpp::ContentNode * c) : +				XmlValueSource(c->get_content()) +			{ +			} +	}; + +	class XmlAttributeValueSource : public XmlValueSource { +		public: +			XmlAttributeValueSource(const xmlpp::Attribute * a) : +				XmlValueSource(a->get_value()) +			{ +			} +	}; + +	class XmlValueTarget : public ValueTarget { +		public: +			XmlValueTarget(boost::function<void(const Glib::ustring &)> a) : +				apply(a) +			{ +			} + +			virtual void get(const bool & value) const +			{ +				if (value) { +					apply(TrueText); +				} +				else { +					apply(FalseText); +				} +			} + +			virtual void get(const Ice::Byte & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void set(const Ice::Short & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void get(const Ice::Int & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void get(const Ice::Long & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void get(const Ice::Float & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void get(const Ice::Double & value) const +			{ +				apply(boost::lexical_cast<Glib::ustring>(value)); +			} + +			virtual void get(const std::string & value) const +			{ +				apply(value); +			} + +		private: +			const boost::function<void(const Glib::ustring &)> apply; +	}; + + +	class XmlAttributeValueTarget : public XmlValueTarget { +		public: +			XmlAttributeValueTarget(xmlpp::Element * p, const std::string & n) : +				XmlValueTarget(boost::bind(&xmlpp::Element::set_attribute, p, Glib::ustring(n), _1, Glib::ustring())) +			{ +			} +	}; +	 +	class XmlContentValueTarget : public XmlValueTarget { +		public: +			XmlContentValueTarget(xmlpp::Element * p) : +				XmlValueTarget(boost::bind(&xmlpp::Element::set_child_text, p, _1)) +			{ +			} +	}; +	 +	void +	Xml::DocumentTreeIterate(const xmlpp::Node * node, ModelPartPtr mp) +	{ +		while (node) { +			if (auto element = dynamic_cast<const xmlpp::Element *>(node)) { +				auto smp = mp->GetChild(element->get_name()); +				if (smp) { +					smp->Create(); +					auto attrs(element->get_attributes()); +					if (!attrs.empty()) { +						DocumentTreeIterate(attrs.front(), smp); +					} +					DocumentTreeIterate(element->get_first_child(), smp); +					smp->Complete(); +				} +			} +			else if (auto attribute = dynamic_cast<const xmlpp::Attribute *>(node)) { +				auto smp = mp->GetChild("@" + attribute->get_name()); +				if (smp) { +					smp->Create(); +					smp->SetValue(new XmlAttributeValueSource(attribute)); +					smp->Complete(); +				} +			} +			else if (auto content = dynamic_cast<const xmlpp::ContentNode *>(node)) { +				mp->SetValue(new XmlContentValueSource(content)); +			} +			node = node->get_next_sibling(); +		} +	} + +	void +	Xml::DocumentTreeIterate(const xmlpp::Document * doc, ModelPartPtr mp) +	{ +		DocumentTreeIterate(doc->get_root_node(), mp); +	} + +	void +	Xml::ModelTreeIterate(xmlpp::Element * n, const std::string & name, ModelPartPtr mp) +	{ +		if (name.empty()) { +			return; +		} +		if (name[0] == '@') { +			mp->GetValue(new XmlAttributeValueTarget(n, name.substr(1))); +		} +		else { +			auto element = n->add_child(name); +			mp->GetValue(new XmlContentValueTarget(element)); +			mp->OnEachChild(boost::bind(&Xml::ModelTreeIterate, element, _1, _2)); +		} +	} + +	void +	Xml::ModelTreeIterateRoot(xmlpp::Document * doc, const std::string & name, ModelPartPtr mp) +	{ +		auto root = doc->create_root_node(name); +		mp->OnEachChild(boost::bind(&Xml::ModelTreeIterate, root, _1, _2)); +	} + +	void +	Xml::Deserialize(const boost::filesystem::path & path, ModelPartPtr modelRoot) +	{ +		xmlpp::DomParser dom(path.string()); +		auto doc = dom.get_document(); +		DocumentTreeIterate(doc, modelRoot); +	} + +	void +	Xml::Serialize(const boost::filesystem::path & path, ModelPartPtr modelRoot) +	{ +		xmlpp::Document doc; +		modelRoot->OnEachChild(boost::bind(&Xml::ModelTreeIterateRoot, &doc, _1, _2)); +		doc.write_to_file_formatted(path.string()); +	} +} + diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h new file mode 100644 index 0000000..8e8a023 --- /dev/null +++ b/slicer/xml/serializer.h @@ -0,0 +1,29 @@ +#ifndef SLICER_XML_H +#define SLICER_XML_H + +#include <slicer/serializer.h> + +namespace xmlpp { +	class Document; +	class Node; +	class Element; +	class Attribute; +	class ContentNode; +} + +namespace Slicer { +	class Xml : public Serializer { +		public: +			virtual void Deserialize(const boost::filesystem::path &, ModelPartPtr) override; +			virtual void Serialize(const boost::filesystem::path &, ModelPartPtr) override; + +		protected: +			static void DocumentTreeIterate(const xmlpp::Node * node, ModelPartPtr mp); +			static void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartPtr mp); +			static void ModelTreeIterate(xmlpp::Element *, const std::string &, ModelPartPtr mp); +			static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, ModelPartPtr mp); +	}; +} + +#endif +  | 
