| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 | // Copyright Takatoshi Kondo 2020//// 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)#if !defined(MQTT_SHARED_SUBSCRIPTIONS_HPP)#define MQTT_SHARED_SUBSCRIPTIONS_HPP#include <mqtt/config.hpp>#include <utility>#include <type_traits>#include <boost/assert.hpp>#include <mqtt/namespace.hpp>#include <mqtt/buffer.hpp>#include <mqtt/move.hpp>#include <mqtt/optional.hpp>namespace MQTT_NS {struct share_name_topic_filter {    share_name_topic_filter(buffer share_name, buffer topic_filter)        : share_name { force_move(share_name) }, topic_filter{ force_move(topic_filter) }    {        BOOST_ASSERT(!topic_filter.empty());    }    buffer share_name;    buffer topic_filter;};inline bool operator<(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {    if (lhs.share_name < rhs.share_name) return true;    if (rhs.share_name < lhs.share_name) return false;    return lhs.topic_filter < rhs.topic_filter;}inline bool operator==(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {    return lhs.share_name == rhs.share_name && lhs.topic_filter == rhs.topic_filter;}inline bool operator!=(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {    return !(lhs == rhs);}inline optional<share_name_topic_filter> parse_shared_subscription(buffer whole_topic_filter) {    auto const shared_prefix = string_view("$share/");    if (whole_topic_filter.substr(0, shared_prefix.size()) != shared_prefix) {        return share_name_topic_filter{ buffer{}, force_move(whole_topic_filter) };    }    // Remove $share/    whole_topic_filter.remove_prefix(shared_prefix.size());    // This is the '/' seperating the subscription group from the actual topic_filter.    auto const idx = whole_topic_filter.find_first_of('/');    if (idx == string_view::npos) return nullopt;    // We return the share_name and the topic_filter as buffers that point to the same    // storage. So we grab the substr for "share", and then remove it from whole_topic_filter.    auto share_name = whole_topic_filter.substr(0, idx);    whole_topic_filter.remove_prefix(std::min(idx + 1, whole_topic_filter.size()));    if (share_name.empty() || whole_topic_filter.empty()) return nullopt;    return share_name_topic_filter{ force_move(share_name), force_move(whole_topic_filter) };}namespace detail {template <typename T, typename U>inline buffer create_topic_filter_buffer(T const& share_name, U const& topic_filter) {    string_view prefix = "$share/";    // 1 is the length of '/' between share_name and topic_filter    auto spa = make_shared_ptr_array(prefix.size() + share_name.size() + 1 + topic_filter.size());    auto it = spa.get();    auto start = it;    std::copy(prefix.begin(), prefix.end(), it);    it += prefix.size();    std::copy(share_name.begin(), share_name.end(), it);    it += share_name.size();    *it++ = '/';    std::copy(topic_filter.begin(), topic_filter.end(), it);    it += topic_filter.size();    return buffer(string_view(start, static_cast<std::size_t>(it - start)), force_move(spa));}} // namespace detailinline buffer create_topic_filter_buffer(string_view  share_name, string_view topic_filter) {    if (share_name.empty()) return allocate_buffer(topic_filter);    return detail::create_topic_filter_buffer(share_name, topic_filter);}inline buffer create_topic_filter_buffer(string_view share_name, buffer topic_filter) {    if (share_name.empty()) return topic_filter;    return detail::create_topic_filter_buffer(share_name, topic_filter);}} // namespace MQTT_NS#endif // MQTT_SHARED_SUBSCRIPTIONS_HPP
 |