diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-25 12:56:57 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2020-10-25 12:56:57 +0000 |
commit | b677e823d0c2c82624c45aa7d7e82ea4d946cbde (patch) | |
tree | eeb9da3e89a71f85ec6a36b6602c36c006631dca | |
parent | Tidy CppNamed reference IO (diff) | |
download | slicer-b677e823d0c2c82624c45aa7d7e82ea4d946cbde.tar.bz2 slicer-b677e823d0c2c82624c45aa7d7e82ea4d946cbde.tar.xz slicer-b677e823d0c2c82624c45aa7d7e82ea4d946cbde.zip |
First cut constexpr hooks and metadata
-rw-r--r-- | slicer/db/sqlCommon.cpp | 20 | ||||
-rw-r--r-- | slicer/json/serializer.cpp | 6 | ||||
-rw-r--r-- | slicer/slicer/Jamfile.jam | 1 | ||||
-rw-r--r-- | slicer/slicer/enumMap.h | 1 | ||||
-rw-r--r-- | slicer/slicer/hookMap.h | 1 | ||||
-rw-r--r-- | slicer/slicer/metadata-test.cpp | 15 | ||||
-rw-r--r-- | slicer/slicer/metadata.cpp | 48 | ||||
-rw-r--r-- | slicer/slicer/metadata.h | 96 | ||||
-rw-r--r-- | slicer/slicer/modelParts.cpp | 1 | ||||
-rw-r--r-- | slicer/slicer/modelParts.h | 6 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.h | 3 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 19 | ||||
-rw-r--r-- | slicer/test/Jamfile.jam | 1 | ||||
-rw-r--r-- | slicer/test/preprocessor.cpp | 26 | ||||
-rw-r--r-- | slicer/tool/Jamfile.jam | 1 | ||||
-rw-r--r-- | slicer/tool/icemetadata.cpp | 45 | ||||
-rw-r--r-- | slicer/tool/icemetadata.h | 40 | ||||
-rw-r--r-- | slicer/tool/parser.cpp | 170 | ||||
-rw-r--r-- | slicer/tool/parser.h | 24 | ||||
-rw-r--r-- | slicer/xml/serializer.cpp | 32 |
20 files changed, 353 insertions, 203 deletions
diff --git a/slicer/db/sqlCommon.cpp b/slicer/db/sqlCommon.cpp index ecce6cc..7ef0046 100644 --- a/slicer/db/sqlCommon.cpp +++ b/slicer/db/sqlCommon.cpp @@ -4,41 +4,39 @@ #include <sqlExceptions.h> namespace Slicer { - const std::string md_pkey = "db:pkey"; - const std::string md_auto = "db:auto"; - const std::string md_ignore = "db:ignore"; - const std::string md_global_ignore = "ignore"; + constexpr std::string_view md_pkey {"db:pkey"}; + constexpr std::string_view md_auto {"db:auto"}; + constexpr std::string_view md_ignore {"db:ignore"}; + constexpr std::string_view md_global_ignore {"ignore"}; bool isPKey(const HookCommon * h) { - return metaDataFlagSet(h->GetMetadata(), md_pkey) && isBind(h); + return h->GetMetadata().flagSet(md_pkey) && isBind(h); } bool isAuto(const HookCommon * h) { - return metaDataFlagSet(h->GetMetadata(), md_auto) && isBind(h); + return h->GetMetadata().flagSet(md_auto) && isBind(h); } bool isNotAuto(const HookCommon * h) { - return metaDataFlagNotSet(h->GetMetadata(), md_auto) && isBind(h); + return h->GetMetadata().flagNotSet(md_auto) && isBind(h); } bool isBind(const HookCommon * h) { - return metaDataFlagNotSet(h->GetMetadata(), md_global_ignore) - && metaDataFlagNotSet(h->GetMetadata(), md_ignore); + return h->GetMetadata().flagNotSet(md_global_ignore) && h->GetMetadata().flagNotSet(md_ignore); } bool isValue(const HookCommon * h) { - return metaDataFlagNotSet(h->GetMetadata(), md_auto) && metaDataFlagNotSet(h->GetMetadata(), md_pkey) - && isBind(h); + return h->GetMetadata().flagNotSet(md_auto) && h->GetMetadata().flagNotSet(md_pkey) && isBind(h); } void diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp index 0fa736c..aaf1999 100644 --- a/slicer/json/serializer.cpp +++ b/slicer/json/serializer.cpp @@ -164,7 +164,7 @@ namespace Slicer { } } modelPart->Create(); - if (metaDataFlagSet(modelPart->GetMetadata(), md_object)) { + if (modelPart->GetMetadata().flagSet(md_object)) { for (const auto & element : o) { auto emp = modelPart->GetAnonChild(); emp->Create(); @@ -278,7 +278,7 @@ namespace Slicer { break; case ModelPartType::Dictionary: if (mp->HasValue()) { - if (metaDataFlagSet(mp->GetMetadata(), md_object)) { + if (mp->GetMetadata().flagSet(md_object)) { mp->OnEachChild( [capture0 = &std::get<json::Object>(*n).insert({name, json::Object()}).first->second]( auto &&, auto && PH2, auto &&) { @@ -327,7 +327,7 @@ namespace Slicer { }); break; case ModelPartType::Dictionary: - if (metaDataFlagSet(mp->GetMetadata(), md_object)) { + if (mp->GetMetadata().flagSet(md_object)) { *n = json::Object(); mp->OnEachChild([n](auto &&, auto && PH2, auto &&) { return JsonSerializer::ModelTreeIterateDictObj(n, PH2); diff --git a/slicer/slicer/Jamfile.jam b/slicer/slicer/Jamfile.jam index 38a0c66..ab6420e 100644 --- a/slicer/slicer/Jamfile.jam +++ b/slicer/slicer/Jamfile.jam @@ -4,6 +4,7 @@ lib stdc++fs ; obj enum-test : enum-test.cpp ; obj hook-test : hook-test.cpp : <use>..//adhocutil <implicit-dependency>common ; +obj metadata-test : metadata-test.cpp : <use>..//adhocutil <implicit-dependency>common ; obj common : common.ice : <toolset>tidy:<checker>none ; diff --git a/slicer/slicer/enumMap.h b/slicer/slicer/enumMap.h index a7b42c2..a6f941d 100644 --- a/slicer/slicer/enumMap.h +++ b/slicer/slicer/enumMap.h @@ -38,6 +38,7 @@ namespace Slicer { return nullptr; } + protected: const Node * begin {}; const Node * end {}; }; diff --git a/slicer/slicer/hookMap.h b/slicer/slicer/hookMap.h index 5b99f96..153f9c0 100644 --- a/slicer/slicer/hookMap.h +++ b/slicer/slicer/hookMap.h @@ -126,6 +126,7 @@ namespace Slicer { return _end; } + protected: const HookPtr * _begin {}; const HookPtr * _end {}; }; diff --git a/slicer/slicer/metadata-test.cpp b/slicer/slicer/metadata-test.cpp new file mode 100644 index 0000000..2d3215a --- /dev/null +++ b/slicer/slicer/metadata-test.cpp @@ -0,0 +1,15 @@ +#include "metadata.h" + +constexpr Slicer::MetaDataImpl<4> md {{{ + "slicer:yes", + "slicer:no", + "slicer:sub:scope", + "notslicer:dontcare", +}}}; + +static_assert(md.flagSet("slicer:yes")); +static_assert(md.flagSet("slicer:no")); +static_assert(md.flagNotSet("slicer:chickens")); +static_assert(md.value("slicer:").has_value()); +static_assert(md.value("slicer:").value() == "yes"); +static_assert(!md.value("nope:").has_value()); diff --git a/slicer/slicer/metadata.cpp b/slicer/slicer/metadata.cpp deleted file mode 100644 index 6429cc8..0000000 --- a/slicer/slicer/metadata.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "metadata.h" -#include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/predicate.hpp> -#include <boost/algorithm/string/split.hpp> - -bool -Slicer::metaDataFlagSet(const std::list<std::string> & md, const std::string & flag) -{ - return std::find(md.cbegin(), md.cend(), flag) != md.cend(); -} - -bool -Slicer::metaDataFlagNotSet(const std::list<std::string> & md, const std::string & flag) -{ - return std::find(md.cbegin(), md.cend(), flag) == md.cend(); -} - -std::list<std::string> -Slicer::metaDataValues(const std::string & prefix, const std::list<std::string> & metadata) -{ - std::list<std::string> mds; - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, prefix)) { - mds.push_back(md.substr(prefix.length())); - } - } - return mds; -} - -std::vector<std::string> -Slicer::metaDataSplit(const std::string & metadata) -{ - std::vector<std::string> parts; - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - boost::algorithm::split(parts, metadata, boost::algorithm::is_any_of(":"), boost::algorithm::token_compress_off); - return parts; -} - -std::optional<std::string> -Slicer::metaDataValue(const std::string & prefix, const std::list<std::string> & metadata) -{ - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, prefix)) { - return md.substr(prefix.length()); - } - } - return std::optional<std::string>(); -} diff --git a/slicer/slicer/metadata.h b/slicer/slicer/metadata.h index e604658..ced234f 100644 --- a/slicer/slicer/metadata.h +++ b/slicer/slicer/metadata.h @@ -1,21 +1,97 @@ #ifndef SLICER_METADATA_H #define SLICER_METADATA_H -#include <list> +#include <algorithm> +#include <array> #include <optional> #include <string> #include <vector> +#include <visibility.h> namespace Slicer { -#pragma GCC visibility push(default) - // Flags - bool metaDataFlagSet(const std::list<std::string> &, const std::string & flag); - bool metaDataFlagNotSet(const std::list<std::string> &, const std::string & flag); - // Values - std::optional<std::string> metaDataValue(const std::string & prefix, const std::list<std::string> & metadata); - std::list<std::string> metaDataValues(const std::string & prefix, const std::list<std::string> & metadata); - std::vector<std::string> metaDataSplit(const std::string & metadata); -#pragma GCC visibility pop + template<typename Iter = std::array<std::string_view, 1>::const_iterator> class DLL_PUBLIC MetaData { + public: + using Value = std::string_view; + + constexpr MetaData() = default; + + // Flags + constexpr inline bool + flagSet(std::string_view flag) const + { + return find(flag) != _end; + } + + constexpr inline bool + flagNotSet(std::string_view flag) const + { + return find(flag) == _end; + } + + // Values + constexpr std::optional<std::string_view> + value(std::string_view prefix) const + { + for (auto mditr = _begin; mditr != _end; mditr++) { + const std::string_view md {*mditr}; + if (md.substr(0, prefix.length()) == prefix) { + return md.substr(prefix.length()); + } + } + return {}; + } + + std::vector<std::string_view> + values(std::string_view prefix) const + { + std::vector<std::string_view> mds; + for (auto mditr = _begin; mditr != _end; mditr++) { + const std::string_view md {*mditr}; + if (md.substr(0, prefix.length()) == prefix) { + mds.push_back(md.substr(prefix.length())); + } + } + return mds; + } + + constexpr auto + begin() const + { + return _begin; + } + constexpr auto + end() const + { + return _end; + } + + protected: + Iter _begin {}; + Iter _end {}; + + constexpr Iter + find(Value v) const + { + for (auto mdptr = _begin; mdptr != _end; mdptr++) { + if (*mdptr == v) { + return mdptr; + } + } + return _end; + } + }; + + template<std::size_t N> class DLL_PUBLIC MetaDataImpl : public MetaData<> { + public: + using Arr = std::array<Value, N>; + constexpr inline MetaDataImpl(Arr a) : arr(std::move(a)) + { + _begin = arr.begin(); + _end = arr.end(); + } + + Arr arr; + }; } #endif diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp index ccfd647..bbb142a 100644 --- a/slicer/slicer/modelParts.cpp +++ b/slicer/slicer/modelParts.cpp @@ -1,7 +1,6 @@ #include "modelParts.h" namespace Slicer { - const Metadata emptyMetadata; void ModelPart::Create() { diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h index bcc6a05..1596ad8 100644 --- a/slicer/slicer/modelParts.h +++ b/slicer/slicer/modelParts.h @@ -1,9 +1,9 @@ #ifndef SLICER_MODELPARTS_H #define SLICER_MODELPARTS_H +#include "metadata.h" #include <Ice/Config.h> #include <functional> -#include <list> #include <optional> #include <stdexcept> #include <vector> @@ -73,8 +73,8 @@ namespace Slicer { using ChildHandler = std::function<void(const std::string &, ModelPartPtr, const HookCommon *)>; using ClassRef = std::function<ModelPartPtr(void *)>; using HookFilter = std::function<bool(const HookCommon *)>; - using Metadata = std::list<std::string>; - DLL_PUBLIC extern const Metadata emptyMetadata; + using Metadata = MetaData<>; + constexpr Metadata emptyMetadata; enum class ModelPartType { Null, diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index a95b5c5..eff56b7 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -146,7 +146,7 @@ namespace Slicer { template<typename MT, typename MP> class DLL_PRIVATE Hook; - template<typename MT, typename MP> class DLL_PRIVATE HookMetadata; + template<typename MT, typename MP, std::size_t> class DLL_PRIVATE HookMetadata; void OnEachChild(const ChildHandler & ch) override; @@ -161,7 +161,6 @@ namespace Slicer { template<typename R> DLL_PRIVATE ChildRef GetChildRefFromRange(const R & range, const HookFilter & flt); static const Hooks<T> & hooks(); - static const Metadata metadata; }; template<typename T> diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 409a4ed..f8e2a65 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -444,13 +444,6 @@ namespace Slicer { } } - template<typename T> - const Metadata & - ModelPartForComplex<T>::GetMetadata() const - { - return metadata; - } - template<typename T> class DLL_PRIVATE ModelPartForComplex<T>::HookBase : public HookCommon { public: using HookCommon::HookCommon; @@ -484,12 +477,16 @@ namespace Slicer { }; template<typename T> - template<typename MT, typename MP> + template<typename MT, typename MP, std::size_t N> class DLL_PRIVATE ModelPartForComplex<T>::HookMetadata : public ModelPartForComplex<T>::template Hook<MT, MP> { public: - HookMetadata(MT T::*member, std::string_view n, std::string_view nl, const std::string * ns, Metadata md) : - Hook<MT, MP>(member, n, nl, ns), hookMetadata(std::move(md)) + template<typename... MD> + constexpr HookMetadata( + MT T::*member, std::string_view n, std::string_view nl, const std::string * ns, MD &&... md) : + Hook<MT, MP>(member, n, nl, ns), + hookMetadata {{std::forward<MD>(md)...}} { + static_assert(sizeof...(MD) == N, "Wrong amount of metadata"); } [[nodiscard]] const Metadata & @@ -499,7 +496,7 @@ namespace Slicer { } private: - const Metadata hookMetadata; + const MetaDataImpl<N> hookMetadata; }; // ModelPartForClass diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index 6801a77..74b03ee 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -59,7 +59,6 @@ run preprocessor.cpp <library>..//adhocutil <include>.. <library>../tool//slicer-compiler - <dependency>types : preprocess ; diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp index 2513f99..21ed5f1 100644 --- a/slicer/test/preprocessor.cpp +++ b/slicer/test/preprocessor.cpp @@ -49,14 +49,34 @@ processAll(Slicer::Slicer & s) BOOST_REQUIRE_EQUAL(total(), s.Components()); } -BOOST_AUTO_TEST_CASE(slicer_test_counts_path) +BOOST_AUTO_TEST_CASE(slicer_metadata_split_empty, *boost::unit_test::timeout(5)) +{ + BOOST_CHECK(Slicer::IceMetaData::split("").empty()); +} + +BOOST_AUTO_TEST_CASE(slicer_metadata_split_single, *boost::unit_test::timeout(5)) +{ + auto md {Slicer::IceMetaData::split("string")}; + BOOST_REQUIRE_EQUAL(md.size(), 1); + BOOST_CHECK_EQUAL(md.front(), "string"); +} + +BOOST_AUTO_TEST_CASE(slicer_metadata_split_many, *boost::unit_test::timeout(5)) +{ + auto md {Slicer::IceMetaData::split("string:and:some:other:values")}; + BOOST_REQUIRE_EQUAL(md.size(), 5); + BOOST_CHECK_EQUAL(md.front(), "string"); + BOOST_CHECK_EQUAL(md.back(), "values"); +} + +BOOST_AUTO_TEST_CASE(slicer_test_counts_path, *boost::unit_test::timeout(5)) { Slicer::Slicer s; s.cppPath = "/dev/null"; processAll(s); } -BOOST_AUTO_TEST_CASE(slicer_test_counts_filestar) +BOOST_AUTO_TEST_CASE(slicer_test_counts_filestar, *boost::unit_test::timeout(5)) { FILE * file = fopen("/dev/null", "a"); BOOST_REQUIRE(file); @@ -66,7 +86,7 @@ BOOST_AUTO_TEST_CASE(slicer_test_counts_filestar) fclose(file); } -BOOST_AUTO_TEST_CASE(slicer_test_counts_nullfilestar) +BOOST_AUTO_TEST_CASE(slicer_test_counts_nullfilestar, *boost::unit_test::timeout(5)) { Slicer::Slicer s; processAll(s); diff --git a/slicer/tool/Jamfile.jam b/slicer/tool/Jamfile.jam index 98067b9..4ee2d76 100644 --- a/slicer/tool/Jamfile.jam +++ b/slicer/tool/Jamfile.jam @@ -5,6 +5,7 @@ lib stdc++fs ; lib slice-parser ; lib slicer-compiler : + icemetadata.cpp parser.cpp : <library>slice-parser diff --git a/slicer/tool/icemetadata.cpp b/slicer/tool/icemetadata.cpp new file mode 100644 index 0000000..422b17e --- /dev/null +++ b/slicer/tool/icemetadata.cpp @@ -0,0 +1,45 @@ +#include "icemetadata.h" +#include <boost/algorithm/string/predicate.hpp> + +namespace Slicer { + IceMetaData::IceMetaData() { } + IceMetaData::IceMetaData(Slice::StringList && a) : arr {std::forward<Slice::StringList>(a)} + { + _begin = arr.begin(); + _end = arr.end(); + } + + std::vector<std::string_view> + IceMetaData::split(std::string_view metaData) + { + std::vector<std::string_view> output; + + for (size_t first = 0; first < metaData.size();) { + const auto second = metaData.find(':', first); + + if (first != second) { + output.emplace_back(metaData.substr(first, second - first)); + } + + if (second == std::string_view::npos) { + break; + } + + first = second + 1; + } + + return output; + } + + size_t + IceMetaData::countSlicerMetaData() const + { + return std::count_if(_begin, _end, isSlicerMetaData); + } + + bool + IceMetaData::hasSlicerMetaData() const + { + return std::any_of(_begin, _end, isSlicerMetaData); + } +} diff --git a/slicer/tool/icemetadata.h b/slicer/tool/icemetadata.h new file mode 100644 index 0000000..90bfe5e --- /dev/null +++ b/slicer/tool/icemetadata.h @@ -0,0 +1,40 @@ +#ifndef SLICER_TOOL_METADATA_H +#define SLICER_TOOL_METADATA_H + +#include <Slice/Parser.h> +#include <c++11Helpers.h> +#include <list> +#include <metadata.h> + +namespace Slicer { + class DLL_PUBLIC IceMetaData : public MetaData<Slice::StringList::const_iterator> { + public: + static constexpr std::string_view slicer_prefix {"slicer:"}; + + explicit IceMetaData(); + explicit IceMetaData(Slice::StringList && arr); + + SPECIAL_MEMBERS_DELETE(IceMetaData); + + [[nodiscard]] static std::vector<std::string_view> split(std::string_view metaData); + + bool hasSlicerMetaData() const; + size_t countSlicerMetaData() const; + + constexpr bool static isSlicerMetaData(std::string_view md) + { + return md.substr(0, slicer_prefix.length()) == slicer_prefix; + } + + auto + getSlicerMetaData() const + { + return values(slicer_prefix); + } + + private: + Slice::StringList arr; + }; +} + +#endif diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 87c48f3..ef9139d 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -8,7 +8,6 @@ #include <boost/algorithm/string/trim.hpp> #include <common.h> #include <fprintbf.h> -#include <metadata.h> #include <safeMapFind.h> namespace fs = std::filesystem; @@ -99,7 +98,7 @@ namespace Slicer { const Count & count; }; - SplitString::SplitString(const std::string & in, const char * by) + SplitString::SplitString(std::string_view in, std::string_view by) { boost::algorithm::split(*this, in, boost::algorithm::is_any_of(by), boost::algorithm::token_compress_off); } @@ -212,7 +211,8 @@ namespace Slicer { fprintbf(cpp, "#include <%s>\n", fs::path(topLevelFile.filename()).replace_extension(".h").string()); for (const auto & m : u->modules()) { - for (const auto & i : metaDataValues("slicer:include:", m->getMetaData())) { + IceMetaData md {m->getMetaData()}; + for (const auto & i : md.values("slicer:include:")) { fprintbf(cpp, "#include <%s>\n", i); } } @@ -254,7 +254,7 @@ namespace Slicer { } void - Slicer::defineRoot(const std::string & type, const std::string & name, const Slice::TypePtr & stype) const + Slicer::defineRoot(const std::string & type, std::string_view name, const Slice::TypePtr & stype) const { if (stype->isLocal()) { fprintbf(cpp, "template<>\n"); @@ -298,14 +298,15 @@ namespace Slicer { visitComplexDataMembers(decl.get(), c->allDataMembers()); fprintbf(cpp, "template<> DLL_PUBLIC\n"); - auto typeId = metaDataValue("slicer:typeid:", c->getMetaData()); + const IceMetaData md {c->getMetaData()}; + auto typeId = md.value("slicer:typeid:"); fprintbf(cpp, "const std::string ModelPartForClass< %s >::typeIdProperty(\"%s\");\n\n", decl->typeId(), typeId ? *typeId : "slicer-typeid"); - auto name = metaDataValue("slicer:root:", c->getMetaData()); + auto name = md.value("slicer:root:"); defineRoot(typeToString(decl), name ? *name : c->name(), decl); - auto typeName = metaDataValue("slicer:typename:", c->getMetaData()); + auto typeName = md.value("slicer:typename:"); fprintbf(cpp, "template<> DLL_PUBLIC\n"); fprintbf(cpp, "const std::string * ModelPartForClass< %s >::className = nullptr;\n", decl->typeId()); fprintbf(cpp, "template<> DLL_PUBLIC\n"); @@ -322,17 +323,19 @@ namespace Slicer { } fprintbf(cpp, "\n}\n"); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", c->scoped()); - copyMetadata(c->getMetaData()); - fprintbf(cpp, ";\n\n"); + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata & ModelPartForComplex< %s >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + c->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); - if (auto implementation = metaDataValue("slicer:implementation:", c->getMetaData())) { + if (auto implementation = md.value("slicer:implementation:")) { fprintbf(cpp, "\ttemplate<> void ModelPartForClass<%s>::Create() {\n", c->scoped()); fprintf(cpp, "\t\tBOOST_ASSERT(this->Model);\n"); fprintbf(cpp, "\t\t*this->Model = std::make_shared<%s>();\n}\n\n", CppName {*implementation}); } - if (auto cmp = metaDataValue("slicer:custommodelpart:", c->getMetaData())) { + if (auto cmp = md.value("slicer:custommodelpart:")) { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, %s< %s >, %s);\n\n", Slice::typeToString(decl), getBasicModelPart(decl), c->scoped(), CppName {*cmp}); } @@ -363,14 +366,17 @@ namespace Slicer { fprintbf(cpp, "// Struct %s\n", c->name()); visitComplexDataMembers(c.get(), c->dataMembers()); - auto name = metaDataValue("slicer:root:", c->getMetaData()); + const IceMetaData md {c->getMetaData()}; + auto name = md.value("slicer:root:"); defineRoot(c->scoped(), name ? *name : c->name(), c); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", c->scoped()); - copyMetadata(c->getMetaData()); - fprintbf(cpp, ";\n\n"); + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata & ModelPartForComplex< %s >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + c->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); - defineMODELPART(c->scoped(), c, c->getMetaData()); + defineMODELPART(c->scoped(), c, md); return true; } @@ -389,7 +395,10 @@ namespace Slicer { size_t en = 0; for (const auto & dm : dataMembers) { - auto name = metaDataValue("slicer:name:", dm->getMetaData()).value_or(dm->name()); + const IceMetaData md {getAllMetadata(dm)}; + auto name = std::string {md.value("slicer:name:").value_or(dm->name())}; + auto lname = std::string {name}; + boost::algorithm::to_lower(lname); fprintbf(cpp, "\tconst std::string hstr%d_%d { \"%s\" };\n", components, en, name); auto c = Slice::ContainedPtr::dynamicCast(dm->container()); @@ -398,15 +407,17 @@ namespace Slicer { t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); } auto type = dm->type(); - fprintbf(cpp, "\t%s C%d::%s<", hasMetadata(dm->getMetaData()) ? "static" : "constexpr", components, - hasMetadata(dm->getMetaData()) ? "HookMetadata" : "Hook"); + fprintbf(cpp, "\tconstexpr C%d::%s<", components, md.countSlicerMetaData() ? "HookMetadata" : "Hook"); fprintbf(cpp, " %s, ", Slice::typeToString(type, dm->optional())); - createNewModelPartPtrFor(type, dm, getAllMetadata(dm)); - fprintbf(cpp, " > hook%d_%d {&%s, \"%s\", \"%s\", &hstr%d_%d", components, en, dm->scoped(), name, - boost::algorithm::to_lower_copy(name), components, en); - if (hasMetadata(dm->getMetaData())) { - fprintbf(cpp, ", Metadata "); - copyMetadata(dm->getMetaData()); + createNewModelPartPtrFor(type, dm, md); + if (auto n = md.countSlicerMetaData()) { + fprintbf(cpp, ", %d", n); + } + fprintbf(cpp, " > hook%d_%d {&%s, \"%s\", \"%s\", &hstr%d_%d", components, en, dm->scoped(), name, lname, + components, en); + if (md.hasSlicerMetaData()) { + fprintbf(cpp, ","); + copyMetadata(md); } fprintbf(cpp, "};\n"); en++; @@ -437,9 +448,12 @@ namespace Slicer { } fprintbf(cpp, "// Enumeration %s\n", e->name()); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForEnum< %s >::metadata ", e->scoped()); - copyMetadata(e->getMetaData()); - fprintbf(cpp, ";\n\n"); + const IceMetaData md {e->getMetaData()}; + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata & ModelPartForEnum< %s >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + e->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); size_t en = 0; for (const auto & ee : e->enumerators()) { @@ -457,11 +471,11 @@ namespace Slicer { "enumerations%d; }\n", e->scoped(), e->scoped(), components); - auto name = metaDataValue("slicer:root:", e->getMetaData()); + auto name = md.value("slicer:root:"); const Slice::TypePtr t = e; defineRoot(e->scoped(), name ? *name : e->name(), t); - defineMODELPART(e->scoped(), e, e->getMetaData()); + defineMODELPART(e->scoped(), e, md); } void @@ -484,7 +498,8 @@ namespace Slicer { "ChildRef ModelPartForSequence< %s >::GetChildRef(const std::string & name, const HookFilter & flt, " "bool matchCase)\n{\n", s->scoped()); - auto iname = metaDataValue("slicer:item:", s->getMetaData()); + const IceMetaData md {s->getMetaData()}; + auto iname = md.value("slicer:item:"); if (iname) { fprintbf(cpp, "\tif (!name.empty() && !optionalCaseEq(name, \"%s\", matchCase)) { throw " @@ -498,18 +513,20 @@ namespace Slicer { fprintbf(cpp, "\treturn GetAnonChildRef(flt);\n}\n\n"); fprintbf(cpp, "template<> DLL_PUBLIC\n"); - auto ename = metaDataValue("slicer:element:", s->getMetaData()); + auto ename = md.value("slicer:element:"); fprintbf(cpp, "const std::string ModelPartForSequence< %s >::elementName(\"%s\");\n\n", s->scoped(), ename ? *ename : "element"); - auto name = metaDataValue("slicer:root:", s->getMetaData()); + auto name = md.value("slicer:root:"); defineRoot(s->scoped(), name ? *name : s->name(), s); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForSequence< %s >::metadata ", s->scoped()); - copyMetadata(s->getMetaData()); - fprintbf(cpp, ";\n\n"); + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata & ModelPartForSequence< %s >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + s->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); - defineMODELPART(s->scoped(), s, s->getMetaData()); + defineMODELPART(s->scoped(), s, md); } void @@ -528,21 +545,24 @@ namespace Slicer { fprintbf(cpp, "// Dictionary %s\n", d->name()); externType(d->keyType()); externType(d->valueType()); - auto iname = metaDataValue("slicer:item:", d->getMetaData()); + const IceMetaData md {d->getMetaData()}; + auto iname = md.value("slicer:item:"); fprintbf(cpp, "template<> DLL_PUBLIC\n"); fprintbf(cpp, "const std::string ModelPartForDictionary< %s >::pairName(\"%s\");\n\n", d->scoped(), iname ? *iname : "element"); fprintbf(cpp, "using C%d = ModelPartForComplex< %s::value_type >;\n", components, d->scoped()); - auto addHook = [&](const std::string & name, const char * element, const Slice::TypePtr & t) { + auto addHook = [&](std::string_view name, const char * element, const Slice::TypePtr & t) { + auto lname = std::string {name}; + boost::algorithm::to_lower(lname); fprintbf(cpp, "\tconst std::string hstr%d_%d { \"%s\" };\n", components, element, name); fprintbf(cpp, "\tconstexpr C%d::Hook< const %s, ", components, Slice::typeToString(t)); createNewModelPartPtrFor(t); fprintbf(cpp, " > hook%d_%s {&%s::value_type::%s, \"%s\", \"%s\", &hstr%d_%s};\n", components, element, - d->scoped(), element, name, boost::algorithm::to_lower_copy(name), components, element); + d->scoped(), element, name, lname, components, element); }; - addHook(metaDataValue("slicer:key:", d->getMetaData()).value_or("key"), "first", d->keyType()); - addHook(metaDataValue("slicer:value:", d->getMetaData()).value_or("value"), "second", d->valueType()); + addHook(md.value("slicer:key:").value_or("key"), "first", d->keyType()); + addHook(md.value("slicer:value:").value_or("value"), "second", d->valueType()); fprintbf(cpp, "constexpr const HooksImpl< %s::value_type, 2 > hooks%d {{{\n", d->scoped(), components); fprintbf(cpp, " &hook%d_first,\n", components); @@ -551,19 +571,23 @@ namespace Slicer { fprintbf(cpp, "\ttemplate<> const Hooks< %s::value_type > & C%d::hooks() { return hooks%d; }\n", d->scoped(), components, components); - auto name = metaDataValue("slicer:root:", d->getMetaData()); + auto name = md.value("slicer:root:"); defineRoot(d->scoped(), name ? *name : d->name(), d); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForDictionary< %s >::metadata ", d->scoped()); - copyMetadata(d->getMetaData()); - fprintbf(cpp, ";\n\n"); + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata & ModelPartForDictionary< %s >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + d->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex<%s::value_type>::metadata ", - d->scoped()); - copyMetadata(d->getMetaData()); - fprintbf(cpp, ";\n\n"); + fprintbf(cpp, + "template<> DLL_PUBLIC\nconst Metadata & ModelPartForComplex< %s::value_type >::GetMetadata() const {\n\ + static constexpr MetaDataImpl<%d> md {{{", + d->scoped(), md.values("slicer:").size()); + copyMetadata(md); + fprintbf(cpp, "}}}; return md;}\n\n"); - defineMODELPART(d->scoped(), d, d->getMetaData()); + defineMODELPART(d->scoped(), d, md); } void @@ -590,14 +614,14 @@ namespace Slicer { void Slicer::createNewModelPartPtrFor( - const Slice::TypePtr & type, const Slice::DataMemberPtr & dm, const Slice::StringList & md) const + const Slice::TypePtr & type, const Slice::DataMemberPtr & dm, const IceMetaData & md) const { auto conversions = getConversions(md); if (dm && !conversions.empty()) { createModelPartForConverted( type, boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), dm); } - else if (auto cmp = metaDataValue("slicer:custommodelpart:", md)) { + else if (auto cmp = md.value("slicer:custommodelpart:")) { fprintbf(cpp, "%s", CppName {*cmp}); } else { @@ -629,30 +653,15 @@ namespace Slicer { throw CompilerError("Unknown basic type"); } - bool - Slicer::hasMetadata(const std::list<std::string> & metadata) const - { - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, "slicer:")) { - return true; - } - } - return false; - } - void - Slicer::copyMetadata(const std::list<std::string> & metadata) const + Slicer::copyMetadata(const IceMetaData & metadata) const { - fprintbf(cpp, "{\n"); - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, "slicer:")) { - fprintbf(cpp, "\t\"%s\",\n", md.c_str() + 7); - } + for (const auto & md : metadata.getSlicerMetaData()) { + fprintbf(cpp, "\t\"%s\",\n", md); } - fprintbf(cpp, "}"); } - Slice::StringList + IceMetaData Slicer::getAllMetadata(const Slice::DataMemberPtr & dm) { auto metadata = dm->getMetaData(); @@ -662,20 +671,19 @@ namespace Slicer { typec = cd->definition(); } if (typec) { - auto typeMetadata = typec->getMetaData(); - std::copy(typeMetadata.begin(), typeMetadata.end(), std::back_inserter(metadata)); + metadata.merge(typec->getMetaData()); } } - return metadata; + return IceMetaData {std::move(metadata)}; } Slicer::Conversions - Slicer::getConversions(const std::list<std::string> & dm) + Slicer::getConversions(const IceMetaData & md) { Conversions rtn; - auto conversions = metaDataValues("slicer:conversion:", dm); + auto conversions = md.values("slicer:conversion:"); for (const auto & conversion : conversions) { - auto split = metaDataSplit(conversion); + auto split = IceMetaData::split(conversion); if (split.size() < 3) { throw CompilerError("conversion needs at least 3 parts type:toModelFunc:toExchangeFunc[:options]"); } @@ -685,9 +693,9 @@ namespace Slicer { } void - Slicer::defineMODELPART(const std::string & type, const Slice::TypePtr & stype, const Slice::StringList & metadata) + Slicer::defineMODELPART(const std::string & type, const Slice::TypePtr & stype, const IceMetaData & metadata) { - if (auto cmp = metaDataValue("slicer:custommodelpart:", metadata)) { + if (auto cmp = metadata.value("slicer:custommodelpart:")) { fprintbf(cpp, "CUSTOMMODELPARTFOR(%s, %s< %s >, %s);\n\n", type, getBasicModelPart(stype), type, CppName {*cmp}); } diff --git a/slicer/tool/parser.h b/slicer/tool/parser.h index 517c0e3..40c8b28 100644 --- a/slicer/tool/parser.h +++ b/slicer/tool/parser.h @@ -1,6 +1,7 @@ #ifndef SLICER_PARSER_H #define SLICER_PARSER_H +#include "icemetadata.h" #include <Slice/Parser.h> #include <filesystem> #include <visibility.h> @@ -8,18 +9,18 @@ namespace Slicer { class SplitString : public std::vector<std::string> { public: - SplitString(const std::string & in, const char *); + SplitString(std::string_view in, std::string_view split); using std::vector<std::string>::vector; }; struct CppName : public SplitString { - inline CppName(const std::string & in) : SplitString(in, ".") { } + inline CppName(std::string_view in) : SplitString {in, "."} { } }; class DLL_PUBLIC Slicer : public Slice::ParserVisitor { public: struct Args : public SplitString { - inline Args(const std::string & in) : SplitString(in, ",") { } + inline Args(std::string_view in) : SplitString {in, ","} { } using SplitString::SplitString; }; @@ -66,23 +67,20 @@ namespace Slicer { private: void createModelPartForConverted( const Slice::TypePtr & type, const std::string & container, const Slice::DataMemberPtr & dm) const; - void createNewModelPartPtrFor(const Slice::TypePtr & type, - const Slice::DataMemberPtr & dm = Slice::DataMemberPtr(), - const Slice::StringList & md = Slice::StringList()) const; + void createNewModelPartPtrFor(const Slice::TypePtr & type, const Slice::DataMemberPtr & dm = {}, + const IceMetaData & md = IceMetaData {}) const; [[nodiscard]] std::string getBasicModelPart(const Slice::TypePtr & type) const; - void defineMODELPART( - const std::string & type, const Slice::TypePtr & stype, const Slice::StringList & metadata); + void defineMODELPART(const std::string & type, const Slice::TypePtr & stype, const IceMetaData & metadata); void visitComplexDataMembers(const Slice::ConstructedPtr & t, const Slice::DataMemberList &) const; void defineConversions(const Slice::DataMemberPtr & dm) const; - void defineRoot(const std::string & type, const std::string & name, const Slice::TypePtr & stype) const; + void defineRoot(const std::string & type, std::string_view name, const Slice::TypePtr & stype) const; void externType(const Slice::TypePtr &) const; - [[nodiscard]] bool hasMetadata(const std::list<std::string> & metadata) const; - void copyMetadata(const std::list<std::string> & metadata) const; - static Slice::StringList getAllMetadata(const Slice::DataMemberPtr & dm); - static Conversions getConversions(const Slice::StringList & metadata); + void copyMetadata(const IceMetaData & metadata) const; + static IceMetaData getAllMetadata(const Slice::DataMemberPtr & dm); + static Conversions getConversions(const IceMetaData & metadata); std::set<std::string> definedTypes; #pragma GCC visibility pop diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp index fbda026..afdb636 100644 --- a/slicer/xml/serializer.cpp +++ b/slicer/xml/serializer.cpp @@ -17,11 +17,11 @@ NAMEDFACTORY("application/xml", Slicer::XmlStreamDeserializer, Slicer::StreamDes namespace Slicer { using namespace std::placeholders; - const std::string md_attribute = "xml:attribute"; - const std::string md_text = "xml:text"; - const std::string md_bare = "xml:bare"; - const std::string md_attributes = "xml:attributes"; - const std::string md_elements = "xml:elements"; + constexpr std::string_view md_attribute {"xml:attribute"}; + constexpr std::string_view md_text {"xml:text"}; + constexpr std::string_view md_bare {"xml:bare"}; + constexpr std::string_view md_attributes {"xml:attributes"}; + constexpr std::string_view md_elements {"xml:elements"}; const std::string keyName = "key"; const std::string valueName = "value"; using ElementCreatorF = xmlpp::Element * (xmlpp::Element::*)(const Glib::ustring &, const Glib::ustring &); @@ -240,13 +240,13 @@ namespace Slicer { } } smp->Create(); - if (metaDataFlagSet(smpr.ChildMetaData(), md_attributes)) { + if (smpr.ChildMetaData().flagSet(md_attributes)) { auto attrs(element->get_attributes()); if (!attrs.empty()) { DocumentTreeIterateDictAttrs(attrs, smp); } } - else if (metaDataFlagSet(smpr.ChildMetaData(), md_elements)) { + else if (smpr.ChildMetaData().flagSet(md_elements)) { DocumentTreeIterateDictElements(element, smp); } else { @@ -271,11 +271,11 @@ namespace Slicer { while (node) { if (auto element = dynamic_cast<const xmlpp::Element *>(node)) { auto smpr = mp->GetChildRef(element->get_name(), [](const auto & h) { - return metaDataFlagNotSet(h->GetMetadata(), md_attribute); + return h->GetMetadata().flagNotSet(md_attribute); }); if (smpr) { auto smp = smpr.Child(); - if (metaDataFlagSet(smpr.ChildMetaData(), md_bare)) { + if (smpr.ChildMetaData().flagSet(md_bare)) { smp = smp->GetAnonChild(); } if (smp) { @@ -285,7 +285,7 @@ namespace Slicer { } else if (auto attribute = dynamic_cast<const xmlpp::Attribute *>(node)) { auto smp = mp->GetChild(attribute->get_name(), [](const auto & h) { - return metaDataFlagSet(h->GetMetadata(), md_attribute); + return h->GetMetadata().flagSet(md_attribute); }); if (smp) { smp->Create(); @@ -297,7 +297,7 @@ namespace Slicer { ModelPartPtr smp; if (!content->is_white_space()) { smp = mp->GetAnonChild([](const auto & h) { - return metaDataFlagSet(h->GetMetadata(), md_text); + return h->GetMetadata().flagSet(md_text); }); } if (smp) { @@ -324,20 +324,20 @@ namespace Slicer { if (name.empty()) { return; } - if (hp && metaDataFlagSet(hp->GetMetadata(), md_attribute)) { + if (hp && hp->GetMetadata().flagSet(md_attribute)) { mp->GetValue(XmlAttributeValueTarget(n, name)); } - else if (hp && metaDataFlagSet(hp->GetMetadata(), md_text)) { + else if (hp && hp->GetMetadata().flagSet(md_text)) { mp->GetValue(XmlContentValueTarget(n)); } - else if (hp && metaDataFlagSet(hp->GetMetadata(), md_attributes)) { + else if (hp && hp->GetMetadata().flagSet(md_attributes)) { ModelTreeIterateDictAttrs(n->add_child_element(name), mp); } - else if (hp && metaDataFlagSet(hp->GetMetadata(), md_elements)) { + else if (hp && hp->GetMetadata().flagSet(md_elements)) { ModelTreeIterateDictElements(n->add_child_element(name), mp); } else { - if (hp && metaDataFlagSet(hp->GetMetadata(), md_bare)) { + if (hp && hp->GetMetadata().flagSet(md_bare)) { ModelTreeProcessElement(n, mp, [name](auto && PH1, auto &&) { return PH1->add_child_element(name); }); |