mqtt_cpp
shared_subscriptions.hpp
Go to the documentation of this file.
1 // Copyright Takatoshi Kondo 2020
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 
8 #if !defined(MQTT_SHARED_SUBSCRIPTIONS_HPP)
9 #define MQTT_SHARED_SUBSCRIPTIONS_HPP
10 
11 #include <mqtt/config.hpp>
12 
13 #include <utility>
14 #include <type_traits>
15 
16 #include <boost/assert.hpp>
17 
18 #include <mqtt/namespace.hpp>
19 #include <mqtt/buffer.hpp>
20 #include <mqtt/move.hpp>
21 #include <mqtt/optional.hpp>
22 
23 namespace MQTT_NS {
24 
28  {
29  BOOST_ASSERT(!topic_filter.empty());
30  }
31 
34 };
35 
36 inline bool operator<(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {
37  if (lhs.share_name < rhs.share_name) return true;
38  if (rhs.share_name < lhs.share_name) return false;
39  return lhs.topic_filter < rhs.topic_filter;
40 }
41 
42 inline bool operator==(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {
43  return lhs.share_name == rhs.share_name && lhs.topic_filter == rhs.topic_filter;
44 }
45 
46 inline bool operator!=(share_name_topic_filter const& lhs, share_name_topic_filter const& rhs) {
47  return !(lhs == rhs);
48 }
49 
50 
51 inline optional<share_name_topic_filter> parse_shared_subscription(buffer whole_topic_filter) {
52  auto const shared_prefix = string_view("$share/");
53  if (whole_topic_filter.substr(0, shared_prefix.size()) != shared_prefix) {
54  return share_name_topic_filter{ buffer{}, force_move(whole_topic_filter) };
55  }
56 
57  // Remove $share/
58  whole_topic_filter.remove_prefix(shared_prefix.size());
59 
60  // This is the '/' seperating the subscription group from the actual topic_filter.
61  auto const idx = whole_topic_filter.find_first_of('/');
62  if (idx == string_view::npos) return nullopt;
63 
64  // We return the share_name and the topic_filter as buffers that point to the same
65  // storage. So we grab the substr for "share", and then remove it from whole_topic_filter.
66  auto share_name = whole_topic_filter.substr(0, idx);
67  whole_topic_filter.remove_prefix(std::min(idx + 1, whole_topic_filter.size()));
68 
69  if (share_name.empty() || whole_topic_filter.empty()) return nullopt;
70  return share_name_topic_filter{ force_move(share_name), force_move(whole_topic_filter) };
71 }
72 
73 namespace detail {
74 
75 template <typename T, typename U>
76 inline buffer create_topic_filter_buffer(T const& share_name, U const& topic_filter) {
77  string_view prefix = "$share/";
78  // 1 is the length of '/' between share_name and topic_filter
79  auto spa = make_shared_ptr_array(prefix.size() + share_name.size() + 1 + topic_filter.size());
80  auto it = spa.get();
81  auto start = it;
82  std::copy(prefix.begin(), prefix.end(), it);
83  it += prefix.size();
84  std::copy(share_name.begin(), share_name.end(), it);
85  it += share_name.size();
86  *it++ = '/';
87  std::copy(topic_filter.begin(), topic_filter.end(), it);
88  it += topic_filter.size();
89  return buffer(string_view(start, static_cast<std::size_t>(it - start)), force_move(spa));
90 }
91 
92 } // namespace detail
93 
94 inline buffer create_topic_filter_buffer(string_view share_name, string_view topic_filter) {
95  if (share_name.empty()) return allocate_buffer(topic_filter);
96  return detail::create_topic_filter_buffer(share_name, topic_filter);
97 }
98 inline buffer create_topic_filter_buffer(string_view share_name, buffer topic_filter) {
99  if (share_name.empty()) return topic_filter;
100  return detail::create_topic_filter_buffer(share_name, topic_filter);
101 }
102 
103 } // namespace MQTT_NS
104 
105 #endif // MQTT_SHARED_SUBSCRIPTIONS_HPP
buffer that has string_view interface This class provides string_view interface. This class hold stri...
Definition: buffer.hpp:30
buffer substr(std::size_t offset, std::size_t length=string_view::npos) const &
get substring The returned buffer ragnge is the same as std::string_view::substr()....
Definition: buffer.hpp:68
buffer create_topic_filter_buffer(T const &share_name, U const &topic_filter)
Definition: shared_subscriptions.hpp:76
Definition: any.hpp:27
bool operator==(null_strand const &lhs, null_strand const &rhs)
Definition: null_strand.hpp:52
boost::string_ref string_view
Definition: string_view.hpp:64
optional< share_name_topic_filter > parse_shared_subscription(buffer whole_topic_filter)
Definition: shared_subscriptions.hpp:51
constexpr std::remove_reference_t< T > && force_move(T &&t)
Definition: move.hpp:20
buffer allocate_buffer(Iterator b, Iterator e)
create buffer from the pair of iterators It copies string that from b to e into shared_ptr_array....
Definition: buffer.hpp:130
bool operator!=(null_strand const &lhs, null_strand const &rhs)
Definition: null_strand.hpp:56
bool operator<(share_name_topic_filter const &lhs, share_name_topic_filter const &rhs)
Definition: shared_subscriptions.hpp:36
buffer create_topic_filter_buffer(string_view share_name, string_view topic_filter)
Definition: shared_subscriptions.hpp:94
const_buffer buffer(MQTT_NS::buffer const &data)
create boost::asio::const_buffer from the MQTT_NS::buffer boost::asio::const_buffer is a kind of view...
Definition: buffer.hpp:253
shared_ptr_array make_shared_ptr_array(std::size_t size)
shared_ptr_array creating function. You can choose the target type.
Definition: shared_subscriptions.hpp:25
buffer share_name
Definition: shared_subscriptions.hpp:32
share_name_topic_filter(buffer share_name, buffer topic_filter)
Definition: shared_subscriptions.hpp:26
buffer topic_filter
Definition: shared_subscriptions.hpp:33