summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-01-19 22:19:23 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2016-01-19 22:19:23 +0000
commit336b1f9ca5cbb96027c768c3109c6aacafa6e1af (patch)
treeb28c67f27f3163914dfc23d509220b24e3cb0bdd
parentSplit type specific model parts into their own file. (diff)
downloadslicer-336b1f9ca5cbb96027c768c3109c6aacafa6e1af.tar.bz2
slicer-336b1f9ca5cbb96027c768c3109c6aacafa6e1af.tar.xz
slicer-336b1f9ca5cbb96027c768c3109c6aacafa6e1af.zip
Add support for json/xml stream serializers and support for serializer factories based on mime types and file extensions
-rw-r--r--slicer/json/Jamfile.jam20
-rw-r--r--slicer/json/serializer.cpp35
-rw-r--r--slicer/json/serializer.h20
-rw-r--r--slicer/json/testSpecifics.cpp18
-rw-r--r--slicer/slicer/serializer.cpp10
-rw-r--r--slicer/slicer/serializer.h11
-rw-r--r--slicer/slicer/slicer.h28
-rw-r--r--slicer/test/serializers.cpp38
-rw-r--r--slicer/xml/serializer.cpp32
-rw-r--r--slicer/xml/serializer.h20
-rw-r--r--slicer/xml/testSpecifics.cpp10
11 files changed, 234 insertions, 8 deletions
diff --git a/slicer/json/Jamfile.jam b/slicer/json/Jamfile.jam
index 29c40c0..f99e4ab 100644
--- a/slicer/json/Jamfile.jam
+++ b/slicer/json/Jamfile.jam
@@ -1,14 +1,17 @@
+import testing ;
+
lib jsonpp : : : :
<library>../..//glibmm
;
lib boost_system ;
lib boost_filesystem ;
+lib boost_utf : : <name>boost_unit_test_framework ;
lib IceUtil ;
lib adhocutil : : : : <include>/usr/include/adhocutil ;
lib slicer-json :
- [ glob *.cpp ]
+ [ glob *.cpp : test*.cpp ]
:
<include>..
<library>boost_system
@@ -22,3 +25,18 @@ lib slicer-json :
: :
<library>jsonpp
;
+
+run testSpecifics.cpp
+ : : :
+ <define>BOOST_TEST_DYN_LINK
+ <library>slicer-json
+ <library>boost_utf
+ <library>../test//slicer-test
+ <library>../test//common
+ <library>../slicer//slicer
+ <include>..
+ <dependency>../test//compilation
+ :
+ testSpecifics
+ ;
+
diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp
index 7476a0d..5e6bf01 100644
--- a/slicer/json/serializer.cpp
+++ b/slicer/json/serializer.cpp
@@ -6,6 +6,15 @@
#include <fstream>
#include <glibmm/ustring.h>
+NAMEDFACTORY(".js", Slicer::JsonFileSerializer, Slicer::FileSerializerFactory);
+NAMEDFACTORY(".js", Slicer::JsonFileDeserializer, Slicer::FileDeserializerFactory);
+NAMEDFACTORY(".json", Slicer::JsonFileSerializer, Slicer::FileSerializerFactory);
+NAMEDFACTORY(".json", Slicer::JsonFileDeserializer, Slicer::FileDeserializerFactory);
+NAMEDFACTORY("application/javascript", Slicer::JsonStreamSerializer, Slicer::StreamSerializerFactory);
+NAMEDFACTORY("application/javascript", Slicer::JsonStreamDeserializer, Slicer::StreamDeserializerFactory);
+NAMEDFACTORY("application/json", Slicer::JsonStreamSerializer, Slicer::StreamSerializerFactory);
+NAMEDFACTORY("application/json", Slicer::JsonStreamDeserializer, Slicer::StreamDeserializerFactory);
+
namespace Slicer {
class JsonValueSource : public ValueSource {
public:
@@ -237,6 +246,32 @@ namespace Slicer {
}
}
+ JsonStreamSerializer::JsonStreamSerializer(std::ostream & s) :
+ strm(s)
+ {
+ }
+
+ JsonStreamDeserializer::JsonStreamDeserializer(std::istream & s) :
+ strm(s)
+ {
+ }
+
+ void
+ JsonStreamDeserializer::Deserialize(ModelPartPtr modelRoot)
+ {
+ json::Value obj = json::parseValue(strm);
+ auto mp = modelRoot->GetAnonChild();
+ boost::apply_visitor(DocumentTreeIterate(mp), obj);
+ }
+
+ void
+ JsonStreamSerializer::Serialize(ModelPartPtr modelRoot)
+ {
+ json::Value doc;
+ modelRoot->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateRoot, &doc, _2));
+ json::serializeValue(doc, strm, "utf-8");
+ }
+
JsonFileSerializer::JsonFileSerializer(const boost::filesystem::path & p) :
path(p)
{
diff --git a/slicer/json/serializer.h b/slicer/json/serializer.h
index 55c48d3..64f591b 100644
--- a/slicer/json/serializer.h
+++ b/slicer/json/serializer.h
@@ -13,6 +13,16 @@ namespace Slicer {
static void ModelTreeIterateRoot(json::Value *, ModelPartPtr mp);
};
+ class JsonStreamSerializer : public JsonSerializer {
+ public:
+ DLL_PUBLIC JsonStreamSerializer(std::ostream &);
+
+ virtual void Serialize(ModelPartPtr) override;
+
+ private:
+ std::ostream & strm;
+ };
+
class JsonFileSerializer : public JsonSerializer {
public:
DLL_PUBLIC JsonFileSerializer(const boost::filesystem::path &);
@@ -33,6 +43,16 @@ namespace Slicer {
json::Value & value;
};
+ class JsonStreamDeserializer : public Deserializer {
+ public:
+ DLL_PUBLIC JsonStreamDeserializer(std::istream &);
+
+ virtual void Deserialize(ModelPartPtr) override;
+
+ private:
+ std::istream & strm;
+ };
+
class JsonFileDeserializer : public Deserializer {
public:
DLL_PUBLIC JsonFileDeserializer(const boost::filesystem::path &);
diff --git a/slicer/json/testSpecifics.cpp b/slicer/json/testSpecifics.cpp
new file mode 100644
index 0000000..c0a54d4
--- /dev/null
+++ b/slicer/json/testSpecifics.cpp
@@ -0,0 +1,18 @@
+#define BOOST_TEST_MODULE json_specifics
+#include <boost/test/unit_test.hpp>
+#include <slicer/slicer.h>
+#include "serializer.h"
+#include <types.h>
+
+BOOST_AUTO_TEST_CASE( factories )
+{
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::FileSerializerFactory::createNew(".json", "/some.json")));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::FileDeserializerFactory::createNew(".json", "/some.json")));
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::FileSerializerFactory::createNew(".js", "/some.js")));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::FileDeserializerFactory::createNew(".js", "/some.js")));
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::StreamSerializerFactory::createNew("application/javascript", std::cout)));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::StreamDeserializerFactory::createNew("application/javascript", std::cin)));
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::StreamSerializerFactory::createNew("application/javascript", std::cout)));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::StreamDeserializerFactory::createNew("application/javascript", std::cin)));
+}
+
diff --git a/slicer/slicer/serializer.cpp b/slicer/slicer/serializer.cpp
new file mode 100644
index 0000000..4856350
--- /dev/null
+++ b/slicer/slicer/serializer.cpp
@@ -0,0 +1,10 @@
+#define BOOST_FILESYSTEM_DYN_LINK
+#define BOOST_FILESYSTEM_SOURCE
+#include "serializer.h"
+#include <factory.impl.h>
+
+INSTANTIATEFACTORY(Slicer::Serializer, std::ostream &);
+INSTANTIATEFACTORY(Slicer::Deserializer, std::istream &);
+INSTANTIATEFACTORY(Slicer::Serializer, const boost::filesystem::path &);
+INSTANTIATEFACTORY(Slicer::Deserializer, const boost::filesystem::path &);
+
diff --git a/slicer/slicer/serializer.h b/slicer/slicer/serializer.h
index b7b4541..44cce01 100644
--- a/slicer/slicer/serializer.h
+++ b/slicer/slicer/serializer.h
@@ -5,19 +5,26 @@
#include <IceUtil/Handle.h>
#include <boost/filesystem/path.hpp>
#include <slicer/modelParts.h>
+#include <visibility.h>
+#include <factory.h>
namespace Slicer {
- class Serializer : public IceUtil::Shared {
+ class DLL_PUBLIC Serializer : public IceUtil::Shared {
public:
virtual void Serialize(ModelPartPtr) = 0;
};
typedef IceUtil::Handle<Serializer> SerializerPtr;
- class Deserializer : public IceUtil::Shared {
+ class DLL_PUBLIC Deserializer : public IceUtil::Shared {
public:
virtual void Deserialize(ModelPartPtr) = 0;
};
typedef IceUtil::Handle<Deserializer> DeserializerPtr;
+
+ typedef AdHoc::Factory<Serializer, std::ostream &> StreamSerializerFactory;
+ typedef AdHoc::Factory<Deserializer, std::istream &> StreamDeserializerFactory;
+ typedef AdHoc::Factory<Serializer, const boost::filesystem::path &> FileSerializerFactory;
+ typedef AdHoc::Factory<Deserializer, const boost::filesystem::path &> FileDeserializerFactory;
}
#endif
diff --git a/slicer/slicer/slicer.h b/slicer/slicer/slicer.h
index f58e8e1..dc5084d 100644
--- a/slicer/slicer/slicer.h
+++ b/slicer/slicer/slicer.h
@@ -7,29 +7,49 @@
namespace Slicer {
template <typename Deserializer, typename Object, typename ... SerializerParams>
+ IceInternal::Handle<Object>
+ Deserialize(SerializerParams && ... sp) __attribute__ ((deprecated));
+ template <typename Deserializer, typename Object, typename ... SerializerParams>
+ void
+ Serialize(IceInternal::Handle<Object> object, SerializerParams && ... sp) __attribute__ ((deprecated));
+
+ template <typename Object>
Object
- DeserializeAny(SerializerParams && ... sp)
+ DeserializeAnyWith(DeserializerPtr deserializer)
{
IceUtil::Handle<ModelPartForRoot<Object>> root = new ModelPartForRoot<Object>();
- DeserializerPtr deserializer = new Deserializer(sp ...);
deserializer->Deserialize(root);
return root->GetModel();
}
template <typename Deserializer, typename Object, typename ... SerializerParams>
+ Object
+ DeserializeAny(SerializerParams && ... sp)
+ {
+ return DeserializeAnyWith<Object>(new Deserializer(sp ...));
+ }
+
+ template <typename Deserializer, typename Object, typename ... SerializerParams>
IceInternal::Handle<Object>
Deserialize(SerializerParams && ... sp)
{
return DeserializeAny<Deserializer, IceInternal::Handle<Object>, SerializerParams...>(sp ...);
}
+ template <typename Object>
+ void
+ SerializeAnyWith(Object object, SerializerPtr serializer)
+ {
+ IceUtil::Handle<ModelPartForRoot<Object>> root = new ModelPartForRoot<Object>(object);
+ serializer->Serialize(root);
+ }
+
template <typename Serializer, typename Object, typename ... SerializerParams>
void
SerializeAny(Object object, SerializerParams && ... sp)
{
IceUtil::Handle<ModelPartForRoot<Object>> root = new ModelPartForRoot<Object>(object);
- SerializerPtr serializer = new Serializer(sp ...);
- serializer->Serialize(root);
+ SerializeAnyWith(object, new Serializer(sp ...));
}
template <typename Serializer, typename Object, typename ... SerializerParams>
diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp
index 0d309dc..4870bec 100644
--- a/slicer/test/serializers.cpp
+++ b/slicer/test/serializers.cpp
@@ -422,6 +422,38 @@ BOOST_AUTO_TEST_CASE( json_rootEnums_json )
verifyByFile<TestModule::SomeNumbers, Slicer::JsonFileDeserializer>("enum2.json", checkSomeNumbers);
}
+BOOST_AUTO_TEST_CASE( json_streams )
+{
+ const auto tmpf = tmp / "byStream";
+ const auto inFile = root / "initial" / "inherit-c.json";
+ const auto outFile = tmpf / "streamout.json";
+ boost::filesystem::create_directories(tmpf);
+ {
+ std::ifstream in(inFile.string());
+ auto d = Slicer::DeserializeAny<Slicer::JsonStreamDeserializer, TestModule::InheritanceContPtr>(in);
+ checkInherits_types(d);
+ std::ofstream out(outFile.string());
+ Slicer::SerializeAny<Slicer::JsonStreamSerializer>(d, out);
+ }
+ diff(inFile, outFile);
+}
+
+BOOST_AUTO_TEST_CASE( xml_streams )
+{
+ const auto tmpf = tmp / "byStream";
+ const auto inFile = root / "initial" / "inherit-b.xml";
+ const auto outFile = tmpf / "streamout.xml";
+ boost::filesystem::create_directories(tmpf);
+ {
+ std::ifstream in(inFile.string());
+ auto d = Slicer::DeserializeAny<Slicer::XmlStreamDeserializer, TestModule::InheritanceContPtr>(in);
+ checkInherits_types(d);
+ std::ofstream out(outFile.string());
+ Slicer::SerializeAny<Slicer::XmlStreamSerializer>(d, out);
+ }
+ diff(inFile, outFile);
+}
+
BOOST_AUTO_TEST_CASE( invalid_enum )
{
IceUtil::Handle<Slicer::ModelPartForRoot<TestModule::SomeNumbers>> rootmp = new Slicer::ModelPartForRoot<TestModule::SomeNumbers>();
@@ -461,13 +493,19 @@ BOOST_AUTO_TEST_CASE( any )
const boost::filesystem::path output = tmpf / "builtins.xml";
BOOST_TEST_CHECKPOINT("Deserialize with wrapper");
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
TestModule::BuiltInsPtr object = Slicer::Deserialize<Slicer::XmlFileDeserializer, TestModule::BuiltIns>(input);
+#pragma GCC diagnostic pop
BOOST_TEST_CHECKPOINT("Test object");
checkBuiltIns_valuesCorrect(object);
BOOST_TEST_CHECKPOINT("Serialize with wrapper");
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Slicer::Serialize<Slicer::XmlFileSerializer>(object, output);
+#pragma GCC diagnostic pop
BOOST_TEST_CHECKPOINT("Checksum: " << input << " === " << output);
diff(input, output);
diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp
index 6f5df3a..c6c6c5f 100644
--- a/slicer/xml/serializer.cpp
+++ b/slicer/xml/serializer.cpp
@@ -8,6 +8,11 @@
#include <stdexcept>
#include <glibmm/ustring.h>
+NAMEDFACTORY(".xml", Slicer::XmlFileSerializer, Slicer::FileSerializerFactory);
+NAMEDFACTORY(".xml", Slicer::XmlFileDeserializer, Slicer::FileDeserializerFactory);
+NAMEDFACTORY("application/xml", Slicer::XmlStreamSerializer, Slicer::StreamSerializerFactory);
+NAMEDFACTORY("application/xml", Slicer::XmlStreamDeserializer, Slicer::StreamDeserializerFactory);
+
namespace Slicer {
const std::string md_attribute = "xml:attribute";
const std::string md_text = "xml:text";
@@ -274,6 +279,33 @@ namespace Slicer {
ModelTreeProcessElement(doc->create_root_node(name), mp, defaultElementCreator);
}
+ XmlStreamSerializer::XmlStreamSerializer(std::ostream & s) :
+ strm(s)
+ {
+ }
+
+ XmlStreamDeserializer::XmlStreamDeserializer(std::istream & s) :
+ strm(s)
+ {
+ }
+
+ void
+ XmlStreamDeserializer::Deserialize(ModelPartPtr modelRoot)
+ {
+ xmlpp::DomParser dom;
+ dom.parse_stream(strm);
+ auto doc = dom.get_document();
+ DocumentTreeIterate(doc, modelRoot);
+ }
+
+ void
+ XmlStreamSerializer::Serialize(ModelPartPtr modelRoot)
+ {
+ xmlpp::Document doc;
+ modelRoot->OnEachChild(boost::bind(&XmlSerializer::ModelTreeIterateRoot, &doc, _1, _2));
+ doc.write_to_stream(strm);
+ }
+
XmlFileSerializer::XmlFileSerializer(const boost::filesystem::path & p) :
path(p)
{
diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h
index a57e846..c580cde 100644
--- a/slicer/xml/serializer.h
+++ b/slicer/xml/serializer.h
@@ -21,6 +21,16 @@ namespace Slicer {
static void ModelTreeProcessElement(xmlpp::Element * n, ModelPartPtr mp, const ElementCreator &);
};
+ class XmlStreamSerializer : public XmlSerializer {
+ public:
+ DLL_PUBLIC XmlStreamSerializer(std::ostream &);
+
+ virtual void Serialize(ModelPartPtr) override;
+
+ private:
+ std::ostream & strm;
+ };
+
class XmlFileSerializer : public XmlSerializer {
public:
DLL_PUBLIC XmlFileSerializer(const boost::filesystem::path &);
@@ -47,6 +57,16 @@ namespace Slicer {
static void DocumentTreeIterate(const xmlpp::Document * doc, ModelPartPtr mp);
};
+ class XmlStreamDeserializer : public XmlDeserializer {
+ public:
+ DLL_PUBLIC XmlStreamDeserializer(std::istream &);
+
+ virtual void Deserialize(ModelPartPtr) override;
+
+ private:
+ std::istream & strm;
+ };
+
class XmlFileDeserializer : public XmlDeserializer {
public:
DLL_PUBLIC XmlFileDeserializer(const boost::filesystem::path &);
diff --git a/slicer/xml/testSpecifics.cpp b/slicer/xml/testSpecifics.cpp
index 20f65fe..001cfb0 100644
--- a/slicer/xml/testSpecifics.cpp
+++ b/slicer/xml/testSpecifics.cpp
@@ -1,4 +1,4 @@
-#define BOOST_TEST_MODULE db_insert
+#define BOOST_TEST_MODULE xml_specifics
#include <boost/test/unit_test.hpp>
#include <slicer/slicer.h>
#include "serializer.h"
@@ -46,3 +46,11 @@ BOOST_AUTO_TEST_CASE( int_values )
BOOST_REQUIRE_THROW(BoostThrowWrapperHelper<Ice::Int>(doc.get_document()), std::bad_cast);
}
+BOOST_AUTO_TEST_CASE( factories )
+{
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::FileSerializerFactory::createNew(".xml", "/some.xml")));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::FileDeserializerFactory::createNew(".xml", "/some.xml")));
+ BOOST_REQUIRE(Slicer::SerializerPtr(Slicer::StreamSerializerFactory::createNew("application/xml", std::cout)));
+ BOOST_REQUIRE(Slicer::DeserializerPtr(Slicer::StreamDeserializerFactory::createNew("application/xml", std::cin)));
+}
+