diff options
| author | randomdan <randomdan@localhost> | 2014-05-29 13:01:20 +0000 |
|---|---|---|
| committer | randomdan <randomdan@localhost> | 2014-05-29 13:01:20 +0000 |
| commit | a15335691527bec1cdf55121ad4e28480cac1343 (patch) | |
| tree | c462d89f72e144f4c9c6a223da640006285f1aaf /slicer/slicer | |
| parent | Fix slice scanner and split .ice files back into logical blocks (diff) | |
| download | slicer-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
Diffstat (limited to 'slicer/slicer')
| -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 |
7 files changed, 695 insertions, 0 deletions
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 + |
