diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-07-23 18:56:25 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-07-23 18:56:25 +0100 | 
| commit | 6a7a44458431acee1fb2857c1130b47b4e704a28 (patch) | |
| tree | 0a6458f8f72c831e67a1248af771e23fd5bede39 | |
| parent | Don't copy (take by const reference) when serializing (although we do cast of... (diff) | |
| download | slicer-6a7a44458431acee1fb2857c1130b47b4e704a28.tar.bz2 slicer-6a7a44458431acee1fb2857c1130b47b4e704a28.tar.xz slicer-6a7a44458431acee1fb2857c1130b47b4e704a28.zip  | |
Adds the [input] streaming interfacesslicer-1.5.0
| -rw-r--r-- | slicer/slicer/common.ice | 4 | ||||
| -rw-r--r-- | slicer/slicer/modelPartsTypes.cpp | 12 | ||||
| -rw-r--r-- | slicer/slicer/modelPartsTypes.h | 50 | ||||
| -rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 43 | ||||
| -rw-r--r-- | slicer/slicer/slicer.cpp | 7 | ||||
| -rw-r--r-- | slicer/test/Jamfile.jam | 19 | ||||
| -rw-r--r-- | slicer/test/expected/streamOut.json | 1 | ||||
| -rw-r--r-- | slicer/test/expected/streamOut.xml | 13 | ||||
| -rw-r--r-- | slicer/test/streams-mp.cpp | 5 | ||||
| -rw-r--r-- | slicer/test/streams.cpp | 46 | ||||
| -rw-r--r-- | slicer/test/streams.h | 12 | 
11 files changed, 212 insertions, 0 deletions
diff --git a/slicer/slicer/common.ice b/slicer/slicer/common.ice index 6960f42..9198aaa 100644 --- a/slicer/slicer/common.ice +++ b/slicer/slicer/common.ice @@ -38,6 +38,10 @@ module Slicer {  		string symbol;  		string type;  	}; +	["cpp:ice_print"] +	exception InvalidStreamOperation extends SerializerError { +		string method; +	};  };  #endif diff --git a/slicer/slicer/modelPartsTypes.cpp b/slicer/slicer/modelPartsTypes.cpp index 801759d..c1661de 100644 --- a/slicer/slicer/modelPartsTypes.cpp +++ b/slicer/slicer/modelPartsTypes.cpp @@ -182,5 +182,17 @@ namespace Slicer {  	bool ModelPartForDictionaryBase::HasValue() const { return true; }  	ModelPartType ModelPartForDictionaryBase::GetType() const { return type; }  	const ModelPartType ModelPartForDictionaryBase::type = mpt_Dictionary; + +	// Streams +	ChildRefPtr ModelPartForStreamBase::GetAnonChildRef(const Slicer::HookFilter &) { throw InvalidStreamOperation(__FUNCTION__); } +	ChildRefPtr ModelPartForStreamBase::GetChildRef(const std::string &, const Slicer::HookFilter &) { throw InvalidStreamOperation(__FUNCTION__); } +	ModelPartType ModelPartForStreamBase::GetType() const { return mpt_Sequence; } +	bool ModelPartForStreamBase::HasValue() const { return true; } +	// Stream Roots +	ModelPartForStreamRootBase::ModelPartForStreamRootBase(ModelPartPtr mp) : ModelPartForRootBase(mp) { } +	void ModelPartForStreamRootBase::Write(Ice::OutputStreamPtr&) const { throw InvalidStreamOperation(__FUNCTION__); } +	void ModelPartForStreamRootBase::Read(Ice::InputStreamPtr&) { throw InvalidStreamOperation(__FUNCTION__); } +	bool ModelPartForStreamRootBase::HasValue() const { return mp->HasValue(); } +	void ModelPartForStreamRootBase::OnEachChild(const ChildHandler & ch) { ch(GetRootName(), mp, NULL); }  } diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 2038350..69c29b3 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -310,6 +310,56 @@ namespace Slicer {  			static const std::string pairName;  	}; +	template<typename T> +	class DLL_PUBLIC Stream { +		public: +			typedef boost::function<void(const T &)> Consumer; +			typedef T element_type; + +			virtual void Produce(const Consumer & c) = 0; +	}; + +	class DLL_PUBLIC ModelPartForStreamBase : public ModelPart { +		public: +			virtual ModelPartType GetType() const override; +			virtual bool HasValue() const override; +			virtual ChildRefPtr GetAnonChildRef(const HookFilter &) override; +			virtual ChildRefPtr GetChildRef(const std::string &, const HookFilter &) override; + +			virtual ModelPartPtr GetContainedModelPart() override = 0; +			virtual void OnEachChild(const ChildHandler & ch) override = 0; +	}; + +	template<typename T> +	class DLL_PUBLIC ModelPartForStream : public ModelPartForStreamBase, ModelPartModel<Stream<T>> { +		public: +			ModelPartForStream(Stream<T> * s); + +			virtual ModelPartPtr GetContainedModelPart() override; +			virtual void OnEachChild(const ChildHandler & ch) override; +	}; + +	class DLL_PUBLIC ModelPartForStreamRootBase : public ModelPartForRootBase { +		public: +			ModelPartForStreamRootBase(ModelPartPtr mp); + +			virtual void Write(Ice::OutputStreamPtr&) const override; +			virtual void Read(Ice::InputStreamPtr&) override; +			virtual bool HasValue() const override; +			virtual void OnEachChild(const ChildHandler & ch) override; +			virtual const std::string & GetRootName() const override = 0; +	}; + +	template<typename T> +	class DLL_PUBLIC ModelPartForStreamRoot : public ModelPartForStreamRootBase { +		public: +			ModelPartForStreamRoot(Stream<T> * s); + +			virtual const std::string & GetRootName() const override; + +		private: +			Stream<T> * stream; +	};  }  #endif diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 988d91e..3f701c2 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -24,6 +24,12 @@  #define MODELPARTFOR(Type, ModelPartType) \  	CUSTOMMODELPARTFOR(Type, ModelPartType<Type>, ModelPartType<Type>) +#define MODELPARTFORSTREAM(StreamImpl) \ +	namespace Slicer { \ +		template<> ModelPartForRootPtr ModelPart::CreateRootFor(const StreamImpl & stream) { \ +			return new ModelPartForStreamRoot<typename StreamImpl::element_type>(const_cast<StreamImpl *>(&stream)); \ +		} \ +	}  namespace Slicer {  	// ModelPartForRoot @@ -576,6 +582,43 @@ namespace Slicer {  	{  		return new ModelPartForStruct<typename T::value_type>(nullptr);  	} + +	// ModelPartForStream +	template<typename T> +	ModelPartForStream<T>::ModelPartForStream(Stream<T> * s) : +		ModelPartModel<Stream<T>>(s) +	{ +	} + +	template<typename T> +	ModelPartPtr +	ModelPartForStream<T>::GetContainedModelPart() +	{ +		return ModelPart::CreateFor<T>(); +	} + +	template<typename T> +	void +	ModelPartForStream<T>::OnEachChild(const ChildHandler & ch) +	{ +		BOOST_ASSERT(this->Model); +		this->Model->Produce([&ch](const T & element) { +			ch(ModelPartForSequence<std::vector<T>>::elementName, ModelPart::CreateFor(element), NULL); +		}); +	} + +	template<typename T> +	ModelPartForStreamRoot<T>::ModelPartForStreamRoot(Stream<T> * s) : +		ModelPartForStreamRootBase(new ModelPartForStream<T>(s)) +	{ +	} + +	template<typename T> +	const std::string & +	ModelPartForStreamRoot<T>::GetRootName() const +	{ +		return ModelPartForRoot<std::vector<T>>::rootName; +	}  }  #endif diff --git a/slicer/slicer/slicer.cpp b/slicer/slicer/slicer.cpp index dbda326..ba4db3f 100644 --- a/slicer/slicer/slicer.cpp +++ b/slicer/slicer/slicer.cpp @@ -109,5 +109,12 @@ namespace Slicer {  	{  		CompilerErrorMsg::write(s, what);  	} + +	AdHocFormatter(InvalidStreamOperationMsg, "%? is not valid on streams"); +	void +	InvalidStreamOperation::ice_print(std::ostream & s) const +	{ +		InvalidStreamOperationMsg::write(s, method); +	}  } diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index 53a9489..9a801c4 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -92,3 +92,22 @@ run serializers.cpp  	serializers  	; +lib streams-mp : +	streams-mp.cpp +	: +	<library>common +	<library>types +	; + +run streams.cpp +	helpers.cpp +	: : : +	<library>streams-mp +	<library>types +	<library>common +	<library>../slicer//slicer +	<implicit-dependency>../slicer//slicer +	<library>../xml//slicer-xml +	<library>../json//slicer-json +	; + diff --git a/slicer/test/expected/streamOut.json b/slicer/test/expected/streamOut.json new file mode 100644 index 0000000..385fa12 --- /dev/null +++ b/slicer/test/expected/streamOut.json @@ -0,0 +1 @@ +["0","1","2","3","4","5","6","7","8","9"] diff --git a/slicer/test/expected/streamOut.xml b/slicer/test/expected/streamOut.xml new file mode 100644 index 0000000..a595ade --- /dev/null +++ b/slicer/test/expected/streamOut.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<SimpleSeq> +  <element>0</element> +  <element>1</element> +  <element>2</element> +  <element>3</element> +  <element>4</element> +  <element>5</element> +  <element>6</element> +  <element>7</element> +  <element>8</element> +  <element>9</element> +</SimpleSeq> diff --git a/slicer/test/streams-mp.cpp b/slicer/test/streams-mp.cpp new file mode 100644 index 0000000..119ee1f --- /dev/null +++ b/slicer/test/streams-mp.cpp @@ -0,0 +1,5 @@ +#include <slicer/modelPartsTypes.impl.h> +#include "streams.h" + +MODELPARTFORSTREAM(TestStream); + diff --git a/slicer/test/streams.cpp b/slicer/test/streams.cpp new file mode 100644 index 0000000..2f8a513 --- /dev/null +++ b/slicer/test/streams.cpp @@ -0,0 +1,46 @@ +#define BOOST_TEST_MODULE streams +#include <boost/test/unit_test.hpp> + +#include <boost/lexical_cast.hpp> +#include <xml/serializer.h> +#include <json/serializer.h> +#include <slicer.h> +#include <collections.h> +#include <definedDirs.h> +#include "helpers.h" +#include "streams.h" + +void TestStream::Produce(const Consumer & c) +{ +	for (int x = 0; x < 10; x += 1) { +		auto str = boost::lexical_cast<std::string>(x); +		c(str); +	} +} + +BOOST_FIXTURE_TEST_SUITE( stream, TestStream ); + +BOOST_AUTO_TEST_CASE( streamToXml ) +{ +	const auto outputXml = binDir / "streamOut.xml"; +	Slicer::SerializeAny<Slicer::XmlFileSerializer, const TestStream>(*this, outputXml); +	diff(rootDir / "expected" / "streamOut.xml", outputXml); +	auto seq = Slicer::DeserializeAny<Slicer::XmlFileDeserializer, TestModule::SimpleSeq>(outputXml); +	BOOST_REQUIRE_EQUAL(10, seq.size()); +	BOOST_REQUIRE_EQUAL("0", seq.front()); +	BOOST_REQUIRE_EQUAL("9", seq.back()); +} + +BOOST_AUTO_TEST_CASE( streamToJson ) +{ +	const auto outputJson = binDir / "streamOut.json"; +	Slicer::SerializeAny<Slicer::JsonFileSerializer, const TestStream>(*this, outputJson); +	diff(rootDir / "expected" / "streamOut.json", outputJson); +	auto seq = Slicer::DeserializeAny<Slicer::JsonFileDeserializer, TestModule::SimpleSeq>(outputJson); +	BOOST_REQUIRE_EQUAL(10, seq.size()); +	BOOST_REQUIRE_EQUAL("0", seq.front()); +	BOOST_REQUIRE_EQUAL("9", seq.back()); +} + +BOOST_AUTO_TEST_SUITE_END(); + diff --git a/slicer/test/streams.h b/slicer/test/streams.h new file mode 100644 index 0000000..28c0c9d --- /dev/null +++ b/slicer/test/streams.h @@ -0,0 +1,12 @@ +#ifndef SLICER_TEST_STREAMS_H +#define SLICER_TEST_STREAMS_H + +#include <slicer/modelPartsTypes.h> + +class TestStream : public Slicer::Stream<std::string> { +	public: +		void Produce(const Consumer & c) override; +}; + +#endif +  | 
