diff options
-rw-r--r-- | slicer/slicer/metadata-test.cpp | 28 | ||||
-rw-r--r-- | slicer/slicer/metadata.h | 87 | ||||
-rw-r--r-- | slicer/tool/icemetadata.cpp | 7 | ||||
-rw-r--r-- | slicer/tool/icemetadata.h | 10 |
4 files changed, 98 insertions, 34 deletions
diff --git a/slicer/slicer/metadata-test.cpp b/slicer/slicer/metadata-test.cpp index a2cd6ec..1fe9cec 100644 --- a/slicer/slicer/metadata-test.cpp +++ b/slicer/slicer/metadata-test.cpp @@ -1,6 +1,23 @@ #include "metadata.h" namespace test { + constexpr auto rc = [](std::string_view sv) { + return Slicer::MetaData<>::remove_colons(sv); + }; + static_assert(rc("scope") == "scope"); + static_assert(rc("scope:") == "scope"); + static_assert(rc("scope::") == "scope"); + static_assert(rc("scope:sub:") == "scope:sub"); + static_assert(rc("scope:sub::") == "scope:sub"); + static_assert(Slicer::MetaData<>::in_scope("scope", "scope")); + static_assert(!Slicer::MetaData<>::in_scope("scope2", "scope")); + static_assert(!Slicer::MetaData<>::in_scope("scope", "scope2")); + static_assert(Slicer::MetaData<>::in_scope("scope:sub", "scope")); + static_assert(Slicer::MetaData<>::in_scope("scope:sub:subsub", "scope")); + static_assert(Slicer::MetaData<>::in_scope("scope:sub:subsub", "scope:sub")); + static_assert(!Slicer::MetaData<>::in_scope("scope:sub2:subsub", "scope:sub")); + static_assert(!Slicer::MetaData<>::in_scope("scope:sub:subsub", "scope:sub2")); + constexpr Slicer::MetaDataImpl<4> md {{{ "slicer:yes", "slicer:no", @@ -8,10 +25,21 @@ namespace test { "notslicer:dontcare", }}}; + static_assert(md.arr[0].first == "slicer:yes"); + static_assert(md.arr[0].second == "slicer"); + static_assert(md.arr[2].first == "slicer:sub:scope"); + static_assert(md.arr[2].second == "slicer:sub"); + 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("slicer").has_value()); + static_assert(md.value("slicer").value() == "yes"); + static_assert(md.value("slicer:sub:").has_value()); + static_assert(md.value("slicer:sub:").value() == "scope"); + static_assert(md.value("slicer:sub").has_value()); + static_assert(md.value("slicer:sub").value() == "scope"); static_assert(!md.value("nope:").has_value()); } diff --git a/slicer/slicer/metadata.h b/slicer/slicer/metadata.h index 5ca3781..455507a 100644 --- a/slicer/slicer/metadata.h +++ b/slicer/slicer/metadata.h @@ -1,19 +1,21 @@ #ifndef SLICER_METADATA_H #define SLICER_METADATA_H -#include <algorithm> #include <array> #include <optional> -#include <string> +#include <string_view> +#include <type_traits> #include <vector> #include <visibility.h> namespace Slicer { - template<typename Iter = std::array<std::string_view, 1>::const_iterator> class DLL_PUBLIC MetaData { + template<bool FixedSize = true, typename Value = std::string_view> class DLL_PUBLIC MetaData { public: - using Value = std::string_view; - - constexpr MetaData() = default; + using Pair = std::pair<Value, std::string_view>; + using PairView = std::pair<std::string_view, std::string_view>; + template<size_t size = 0> + using ContainerBase = std::conditional_t<FixedSize, std::array<Pair, size>, std::vector<Pair>>; + using Iter = typename ContainerBase<>::const_iterator; // Flags [[nodiscard]] constexpr inline bool @@ -32,60 +34,89 @@ namespace Slicer { [[nodiscard]] 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()); + remove_colons(prefix); + for (const auto & md : *this) { + // cppcheck-suppress useStlAlgorithm; (not constexpr) + if (md.second == prefix) { + return std::string_view(md.first).substr(prefix.length() + 1); } } return {}; } [[nodiscard]] std::vector<std::string_view> - values(std::string_view prefix) const + values(std::string_view scope) const { + remove_colons(scope); 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())); + for (const auto & md : *this) { + // cppcheck-suppress useStlAlgorithm; (not constexpr) + if (in_scope(md.first, scope)) { + mds.push_back(std::string_view(md.first).substr(scope.length() + 1)); } } return mds; } - [[nodiscard]] constexpr auto + [[nodiscard]] inline constexpr auto begin() const { return _begin; } - [[nodiscard]] constexpr auto + [[nodiscard]] inline constexpr auto end() const { return _end; } - protected: - Iter _begin {}; - Iter _end {}; - - [[nodiscard]] constexpr Iter - find(Value v) const + [[nodiscard]] constexpr auto + find(std::string_view v) const { - for (auto mdptr = _begin; mdptr != _end; mdptr++) { - if (*mdptr == v) { - return mdptr; + for (const auto & md : *this) { + // cppcheck-suppress useStlAlgorithm; (not constexpr) + if (md.first == v) { + return &md; } } return _end; } + + static constexpr inline auto + remove_colons(std::string_view & s) + { + if (auto c = s.find_last_not_of(':'); c != std::string_view::npos) { + s.remove_suffix(s.length() - 1 - c); + } + return s; + } + + static constexpr inline auto + in_scope(std::string_view md, std::string_view scope) + { + return ((md.length() == scope.length() || (md.length() >= scope.length() && md[scope.length()] == ':')) + && md.compare(0, scope.length(), scope) == 0); + } + + protected: + Iter _begin {}; + Iter _end {}; }; template<std::size_t N> class DLL_PUBLIC MetaDataImpl : public MetaData<> { public: - using Arr = std::array<Value, N>; - constexpr inline explicit MetaDataImpl(Arr a) : arr(std::move(a)) + using Arr = ContainerBase<N>; + constexpr inline explicit MetaDataImpl(const std::array<std::string_view, N> & a) : + arr {[&a]() { + Arr arr; + auto out = arr.begin(); + for (const auto & md : a) { + out->first = md; + out->second = out->first.substr(0, out->first.rfind(':')); + out++; + } + return arr; + }()} { _begin = arr.begin(); _end = arr.end(); diff --git a/slicer/tool/icemetadata.cpp b/slicer/tool/icemetadata.cpp index 60bd5a3..64806d6 100644 --- a/slicer/tool/icemetadata.cpp +++ b/slicer/tool/icemetadata.cpp @@ -2,8 +2,13 @@ #include <boost/algorithm/string/predicate.hpp> namespace Slicer { - IceMetaData::IceMetaData(Slice::StringList && a) : arr {std::forward<Slice::StringList>(a)} + IceMetaData::IceMetaData(Slice::StringList && a) { + arr.reserve(a.size()); + std::transform(a.begin(), a.end(), std::back_inserter(arr), [](auto a) { + auto prefix = std::string_view(a).substr(0, a.rfind(':')); + return std::make_pair(std::move(a), prefix); + }); _begin = arr.begin(); _end = arr.end(); } diff --git a/slicer/tool/icemetadata.h b/slicer/tool/icemetadata.h index 07d4db2..bd00686 100644 --- a/slicer/tool/icemetadata.h +++ b/slicer/tool/icemetadata.h @@ -7,9 +7,9 @@ #include <metadata.h> namespace Slicer { - class DLL_PUBLIC IceMetaData : public MetaData<Slice::StringList::const_iterator> { + class DLL_PUBLIC IceMetaData : public MetaData<false, std::string> { public: - static constexpr std::string_view slicer_prefix {"slicer:"}; + static constexpr std::string_view slicer_prefix {"slicer"}; explicit IceMetaData() = default; explicit IceMetaData(Slice::StringList && arr); @@ -22,9 +22,9 @@ namespace Slicer { [[nodiscard]] bool hasSlicerMetaData() const; [[nodiscard]] size_t countSlicerMetaData() const; - [[nodiscard]] constexpr bool static isSlicerMetaData(std::string_view md) + [[nodiscard]] constexpr bool static isSlicerMetaData(PairView md) { - return md.substr(0, slicer_prefix.length()) == slicer_prefix; + return in_scope(md.first, slicer_prefix); } [[nodiscard]] auto @@ -34,7 +34,7 @@ namespace Slicer { } private: - Slice::StringList arr; + ContainerBase<> arr; }; } |