From 02314ac7dd009cad632e6328dbc7c6ed503ceb97 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 23 Oct 2020 12:06:39 +0200 Subject: [PATCH] util/TemplateString: rewrite as constexpr functions Hooray C++17! --- src/lib/dbus/AppendIter.hxx | 8 +- src/lib/dbus/Types.hxx | 38 +++--- src/neighbor/plugins/UdisksNeighborPlugin.cxx | 4 +- src/util/TemplateString.hxx | 126 +++++++++--------- 4 files changed, 89 insertions(+), 87 deletions(-) diff --git a/src/lib/dbus/AppendIter.hxx b/src/lib/dbus/AppendIter.hxx index 183f24537..446bb0ff3 100644 --- a/src/lib/dbus/AppendIter.hxx +++ b/src/lib/dbus/AppendIter.hxx @@ -103,7 +103,7 @@ public: template AppendMessageIter &AppendEmptyArray() { return AppendMessageIter(*this, DBUS_TYPE_ARRAY, - T::TypeAsString::value) + T::as_string.value) .CloseContainer(*this); } @@ -120,7 +120,7 @@ public: AppendMessageIter &AppendVariant(const T &value) { typedef VariantTypeTraits Traits; return AppendMessageIter(*this, Traits::TYPE, - Traits::TypeAsString::value) + Traits::as_string.value) .Append(value) .CloseContainer(*this); } @@ -146,7 +146,7 @@ public: typedef typename W::ContainedTraits ContainedTraits; return AppendMessageIter(*this, Traits::TYPE, - ContainedTraits::TypeAsString::value) + ContainedTraits::as_string.value) .Append(value.value) .CloseContainer(*this); } @@ -158,7 +158,7 @@ public: typedef typename W::ContainedTraits ContainedTraits; return AppendMessageIter(*this, Traits::TYPE, - ContainedTraits::TypeAsString::value) + ContainedTraits::as_string.value) .AppendFixedArray(value.value) .CloseContainer(*this); } diff --git a/src/lib/dbus/Types.hxx b/src/lib/dbus/Types.hxx index 331861c08..3319d04e3 100644 --- a/src/lib/dbus/Types.hxx +++ b/src/lib/dbus/Types.hxx @@ -42,7 +42,7 @@ namespace ODBus { template struct BasicTypeTraits { static constexpr int TYPE = type; - using TypeAsString = TemplateString::CharAsString; + static constexpr auto as_string = TemplateString::CharAsString(TYPE); }; template @@ -73,20 +73,20 @@ struct ArrayTypeTraits { using ContainedTraits = T; static constexpr int TYPE = DBUS_TYPE_ARRAY; - using TypeAsString = - TemplateString::InsertBefore; + static constexpr auto as_string = + TemplateString::Concat(TemplateString::CharAsString(TYPE), + ContainedTraits::as_string); }; template struct DictEntryTypeTraits { static constexpr int TYPE = DBUS_TYPE_DICT_ENTRY; - using TypeAsString = - TemplateString::Concat, - typename KeyT::TypeAsString, - typename ValueT::TypeAsString, - TemplateString::CharAsString>; + static constexpr auto as_string = + TemplateString::Concat(TemplateString::CharAsString(DBUS_DICT_ENTRY_BEGIN_CHAR), + KeyT::as_string, + ValueT::as_string, + TemplateString::CharAsString(DBUS_DICT_ENTRY_END_CHAR)); }; using VariantTypeTraits = BasicTypeTraits; @@ -95,21 +95,25 @@ using VariantTypeTraits = BasicTypeTraits; * Concatenate all TypeAsString members to one string. */ template -struct ConcatTypeAsString - : TemplateString::Concat> {}; +struct ConcatTypeAsString { + static constexpr auto as_string = + TemplateString::Concat(T::as_string, + ConcatTypeAsString::as_string); +}; template -struct ConcatTypeAsString : T::TypeAsString {}; +struct ConcatTypeAsString { + static constexpr auto as_string = T::as_string; +}; template struct StructTypeTraits { static constexpr int TYPE = DBUS_TYPE_STRUCT; - using TypeAsString = - TemplateString::Concat, - ConcatTypeAsString, - TemplateString::CharAsString>; + static constexpr auto as_string = + TemplateString::Concat(TemplateString::CharAsString(DBUS_STRUCT_BEGIN_CHAR), + ConcatTypeAsString::as_string, + TemplateString::CharAsString(DBUS_STRUCT_END_CHAR)); }; } /* namespace ODBus */ diff --git a/src/neighbor/plugins/UdisksNeighborPlugin.cxx b/src/neighbor/plugins/UdisksNeighborPlugin.cxx index f907b0131..b43331051 100644 --- a/src/neighbor/plugins/UdisksNeighborPlugin.cxx +++ b/src/neighbor/plugins/UdisksNeighborPlugin.cxx @@ -245,7 +245,7 @@ UdisksNeighborExplorer::HandleMessage(DBusConnection *, DBusMessage *message) no if (dbus_message_is_signal(message, DBUS_OM_INTERFACE, "InterfacesAdded") && - dbus_message_has_signature(message, InterfacesAddedType::value)) { + dbus_message_has_signature(message, InterfacesAddedType::as_string.value)) { RecurseInterfaceDictEntry(ReadMessageIter(*message), [this](const char *path, auto &&i){ UDisks2::Object o(path); UDisks2::ParseObject(o, std::forward(i)); @@ -256,7 +256,7 @@ UdisksNeighborExplorer::HandleMessage(DBusConnection *, DBusMessage *message) no return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(message, DBUS_OM_INTERFACE, "InterfacesRemoved") && - dbus_message_has_signature(message, InterfacesRemovedType::value)) { + dbus_message_has_signature(message, InterfacesRemovedType::as_string.value)) { Remove(ReadMessageIter(*message).GetString()); return DBUS_HANDLER_RESULT_HANDLED; } else diff --git a/src/util/TemplateString.hxx b/src/util/TemplateString.hxx index 15f99f280..79969a88a 100644 --- a/src/util/TemplateString.hxx +++ b/src/util/TemplateString.hxx @@ -30,95 +30,93 @@ #ifndef TEMPLATE_STRING_HXX #define TEMPLATE_STRING_HXX +#include // for std::size() #include namespace TemplateString { -/** - * Construct a null-terminated string from a list of chars. - */ -template -struct Construct { - static constexpr char value[] = {_value..., 0}; - static constexpr std::size_t size = sizeof...(_value); +template +struct Buffer { + static constexpr std::size_t size = _size; + char value[size + 1]; }; /** * An empty string. */ -struct Empty : Construct<> {}; +constexpr auto +Empty() noexcept +{ + return Buffer<0>{}; +} /** * A string consisting of a single character. */ -template -struct CharAsString : Construct {}; +constexpr auto +CharAsString(char ch) noexcept +{ + Buffer<1> result{}; + result.value[0] = ch; + return result; +} -/** - * Invoke #F, pass all characters in #src from #i to #length - * as variadic arguments. - */ -template class F, - const char *src, std::size_t length, std::size_t i, - char... _value> -struct VariadicChars : VariadicChars { - static_assert(length > 0, "Wrong length"); -}; +namespace detail { -template class F, - const char *src, std::size_t length, - char... _value> -struct VariadicChars : F<_value...> {}; +constexpr auto +size(const char &) noexcept +{ + return 1; +} -/** - * Like #VariadicChars, but pass an additional argument to #F. - */ -template class F, typename Arg, - const char *src, std::size_t length, std::size_t i, - char... _value> -struct VariadicChars1 : VariadicChars1 { - static_assert(length > 0, "Wrong length"); -}; +constexpr const char * +data(const char &ch) noexcept +{ + return &ch; +} -template class F, typename Arg, - const char *src, std::size_t length, - char... _value> -struct VariadicChars1 : F {}; +template +constexpr auto +size(const Buffer &b) noexcept +{ + return b.size; +} -template -struct _BuildString : VariadicChars {}; +template +constexpr const char * +data(const Buffer &b) noexcept +{ + return b.value; +} -template -struct InsertBefore : _BuildString {}; +constexpr char * +copy_n(const char *src, std::size_t n, char *dest) noexcept +{ + for (std::size_t i = 0; i < n; ++i) + dest[i] = src[i]; + return dest + n; +} -/** - * Concatenate several strings. - */ -template -struct Concat; - -template -struct _Concat : Concat, Args...> {}; +} template -struct Concat : _Concat {}; +constexpr auto +Concat(Args... args) noexcept +{ + using std::size; + using std::data; + using detail::size; + using detail::data; + using detail::copy_n; -template -struct _Concat2 : _BuildString {}; + constexpr std::size_t total_size = (std::size_t(0) + ... + size(args)); + Buffer result{}; -template -struct Concat - :VariadicChars1<_Concat2, Second, - First::value, First::size, 0> {}; + char *p = result.value; + ((p = copy_n(data(args), size(args), p)), ...); -template -struct Concat : First {}; - -template<> -struct Concat<> : Empty {}; + return result; +} } // namespace TemplateString