// Copyright (c) Benjamin Kietzman (github.com/bkietz) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef DBUS_ELEMENT_HPP #define DBUS_ELEMENT_HPP #include #include #include #include #include namespace dbus { /// Message elements /** * D-Bus Messages are composed of simple elements of one of these types */ // bool // is this simply valid? It might pack wrong... // http://maemo.org/api_refs/5.0/5.0-final/dbus/api/group__DBusTypes.html typedef boost::uint8_t byte; typedef boost::int16_t int16; typedef boost::uint16_t uint16; typedef boost::int32_t int32; typedef boost::uint32_t uint32; typedef boost::int64_t int64; typedef boost::uint64_t uint64; // double // unix_fd typedef std::string string; typedef boost::variant dbus_variant; struct object_path { string value; bool operator<(const object_path& b) const { return value < b.value; } }; struct signature { string value; }; /** * D-Bus Message elements are identified by unique integer type codes. */ template struct element { static constexpr int code = DBUS_TYPE_INVALID; }; template <> struct element { static constexpr int code = DBUS_TYPE_BOOLEAN; }; template <> struct element { static constexpr int code = DBUS_TYPE_BYTE; }; template <> struct element { static constexpr int code = DBUS_TYPE_INT16; }; template <> struct element { static constexpr int code = DBUS_TYPE_UINT16; }; template <> struct element { static constexpr int code = DBUS_TYPE_INT32; }; template <> struct element { static constexpr int code = DBUS_TYPE_UINT32; }; template <> struct element { static constexpr int code = DBUS_TYPE_INT64; }; template <> struct element { static constexpr int code = DBUS_TYPE_UINT64; }; template <> struct element { static constexpr int code = DBUS_TYPE_DOUBLE; }; template <> struct element { static constexpr int code = DBUS_TYPE_STRING; }; template <> struct element { static constexpr int code = DBUS_TYPE_VARIANT; }; template <> struct element { static constexpr int code = DBUS_TYPE_OBJECT_PATH; }; template <> struct element { static constexpr int code = DBUS_TYPE_SIGNATURE; }; template struct element> { static constexpr int code = DBUS_TYPE_ARRAY; }; template struct is_fixed_type : std::false_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template <> struct is_fixed_type : std::true_type {}; template struct is_string_type : std::false_type {}; template <> struct is_string_type : std::true_type {}; template <> struct is_string_type : std::true_type {}; template <> struct is_string_type : std::true_type {}; template struct seq {}; template struct gen_seq : gen_seq {}; template struct gen_seq<0, Is...> : seq {}; template constexpr std::array concat_helper( const std::array& a1, const std::array& a2, seq, seq) { return {{a1[I1]..., a2[I2]...}}; } template // Initializer for the recursion constexpr const std::array concat( const std::array& a1, const std::array& a2) { // note, this function expects both character arrays to be null // terminated. The -1 below drops the null terminator on the first string return concat_helper(a1, a2, gen_seq{}, gen_seq{}); } // Base case for types that should never be asserted template struct element_signature {}; // Element signature for building raw c_strings of known element_codes // Case for fixed "final" types (double, float ect) that have their own code by // default., This includes strings and variants. // Put another way, this is the catch for everything that is not a container template struct element_signature< Element, typename std::enable_if::value || is_string_type::value || std::is_same::value>::type> { static auto constexpr code = std::array{{element::code, 0}}; }; template struct element_signature< Element, typename std::enable_if::value>::type> { static auto const constexpr code = element_signature::type>::code; }; template struct has_const_iterator { private: typedef char yes; typedef struct { char array[2]; } no; template static yes test(typename C::const_iterator*); template static no test(...); public: static constexpr bool value = sizeof(test(0)) == sizeof(yes); }; // Specialization for "container" types. Containers are defined as anything // that can be iterated through. This allows running any iterable type, so long // as its value_type is a known dbus type (which could also be a container) // Note: technically std::string is an iterable container, so it needs to be // explicitly excluded from this specialization template struct element_signature< Container, typename std::enable_if::value && !is_string_type::value>::type> { static auto const constexpr code = concat(std::array{{DBUS_TYPE_ARRAY, 0}}, element_signature::code); }; // Specialization for std::pair type. Std::pair is treated as a "dict entry" // element. In dbus, dictionarys are represented as arrays of dict entries, so // this specialization builds type codes based on anything that produces a // std::pair and constructs the signature for the dict entry, for example {si} // would be a string of ints template struct element_signature> { static auto const constexpr code = concat(std::array{{'{', 0}}, concat(element_signature::code, concat(element_signature::code, std::array{{'}', 0}}))); }; } // namespace dbus #endif // DBUS_ELEMENT_HPP