summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2014-05-29 13:01:20 +0000
committerrandomdan <randomdan@localhost>2014-05-29 13:01:20 +0000
commita15335691527bec1cdf55121ad4e28480cac1343 (patch)
treec462d89f72e144f4c9c6a223da640006285f1aaf
parentFix slice scanner and split .ice files back into logical blocks (diff)
downloadslicer-a15335691527bec1cdf55121ad4e28480cac1343.tar.bz2
slicer-a15335691527bec1cdf55121ad4e28480cac1343.tar.xz
slicer-a15335691527bec1cdf55121ad4e28480cac1343.zip
First hash of slicer, works well for the golden path, beyond that is uncharted territory
-rw-r--r--slicer/Jamfile.jam9
-rw-r--r--slicer/slicer/Jamfile.jam17
-rw-r--r--slicer/slicer/modelParts.cpp21
-rw-r--r--slicer/slicer/modelParts.h292
-rw-r--r--slicer/slicer/parser.cpp268
-rw-r--r--slicer/slicer/parser.h47
-rw-r--r--slicer/slicer/serializer.h19
-rw-r--r--slicer/slicer/slicer.h31
-rw-r--r--slicer/test/Jamfile.jam3
-rw-r--r--slicer/test/do-slicer.cpp13
-rw-r--r--slicer/test/types.ice38
-rw-r--r--slicer/tool/Jamfile.jam5
-rw-r--r--slicer/tool/slicer.cpp17
-rw-r--r--slicer/xml/Jamfile.jam16
-rw-r--r--slicer/xml/serializer.cpp239
-rw-r--r--slicer/xml/serializer.h29
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
+