24#ifndef __mqtt_topic_matcher_h
25#define __mqtt_topic_matcher_h
27#include <forward_list>
28#include <initializer_list>
126 using ptr_t = std::unique_ptr<node>;
127 using map_t = std::map<string, ptr_t>;
135 static ptr_t create() {
return std::make_unique<node>(); }
137 bool empty()
const {
return !content && children.empty(); }
141 for (
auto& child : children) {
142 child.second->prune();
145 for (
auto child = children.cbegin(); child != children.cend();) {
146 if (child->second->empty()) {
147 child = children.erase(child);
155 using node_ptr =
typename node::ptr_t;
156 using node_map =
typename node::map_t;
168 std::vector<node*> nodes_;
172 if (nodes_.empty()) {
178 auto snode = std::move(nodes_.back());
182 for (
auto const& child : snode->children) {
183 nodes_.push_back(child.second.get());
188 pval_ = snode->content.get();
196 iterator(node* root) : pval_{nullptr} {
197 nodes_.push_back(root);
246 bool operator!=(
const iterator& other)
const noexcept {
return pval_ != other.pval_; }
250 class const_iterator :
public iterator
252 using base = iterator;
255 const_iterator(iterator it) : base(it) {}
282 std::forward_list<string> fields_;
286 search_node(node* nd,
const std::forward_list<string>& sy,
bool first =
false)
287 : node_{nd}, fields_{sy}, first_{first} {}
288 search_node(node* nd, std::forward_list<string>&& sy,
bool first =
false)
289 : node_{nd}, fields_{std::move(sy)}, first_{first} {}
295 std::vector<search_node> nodes_;
312 auto snode = std::move(nodes_.back());
317 if (snode.fields_.empty()) {
318 pval_ = snode.node_->content.get();
325 auto field = std::move(snode.fields_.front());
326 snode.fields_.pop_front();
328 typename node_map::iterator child;
329 const auto map_end = snode.node_->children.end();
332 if ((child = snode.node_->children.find(field)) != map_end) {
333 nodes_.push_back({child->second.get(), snode.fields_});
340 if (!snode.first_ || field.empty() || field[0] !=
'$') {
342 if ((child = snode.node_->children.find(
"+")) != map_end) {
343 nodes_.push_back({child->second.get(), snode.fields_});
347 if ((child = snode.node_->children.find(
"#")) != map_end) {
349 pval_ = child->second->content.get();
359 match_iterator() : pval_{nullptr} {}
361 match_iterator(node* root,
const string&
topic) : pval_{nullptr} {
363 std::forward_list<string> fields{v.begin(), v.end()};
364 nodes_.push_back(search_node{root, std::move(fields),
true});
413 bool operator!=(
const match_iterator& other)
const noexcept {
414 return pval_ != other.pval_;
421 class const_match_iterator :
public match_iterator
423 using base = match_iterator;
426 const_match_iterator(match_iterator it) : base(it) {}
459 topic_matcher(std::initializer_list<value_type> lst) : root_(node::create()) {
460 for (
const auto& v : lst) {
469 bool empty()
const {
return root_.empty(); }
475 auto nd = root_.get();
478 for (
const auto& field : fields) {
479 auto it = nd->children.find(field);
480 if (it == nd->children.end()) {
481 nd->children[field] = node::create();
482 it = nd->children.find(field);
484 nd = it->second.get();
486 nd->content = std::make_unique<value_type>(std::move(val));
495 this->
insert(std::move(v));
506 auto nd = root_.get();
509 for (
auto& field : fields) {
510 auto it = nd->children.find(field);
511 if (it == nd->children.end())
514 nd = it->second.get();
517 nd->content.swap(valpair);
519 return (valpair) ? std::make_unique<mapped_type>(valpair->second) :
mapped_ptr{};
558 auto nd = root_.get();
561 for (
auto& field : fields) {
562 auto it = nd->children.find(field);
563 if (it == nd->children.end())
565 nd = it->second.get();
Definition topic_matcher.h:251
const value_type * operator->() const noexcept
Definition topic_matcher.h:267
const_reference operator*() const noexcept
Definition topic_matcher.h:262
friend class topic_matcher
Definition topic_matcher.h:254
Definition topic_matcher.h:422
const value_type * operator->() const noexcept
Definition topic_matcher.h:438
const_reference operator*() const noexcept
Definition topic_matcher.h:433
friend class topic_matcher
Definition topic_matcher.h:425
Definition topic_matcher.h:164
const value_type * operator->() const noexcept
Definition topic_matcher.h:221
iterator operator++(int) noexcept
Definition topic_matcher.h:226
reference operator*() noexcept
Definition topic_matcher.h:206
const_reference operator*() const noexcept
Definition topic_matcher.h:211
iterator & operator++() noexcept
Definition topic_matcher.h:235
bool operator!=(const iterator &other) const noexcept
Definition topic_matcher.h:246
friend class topic_matcher
Definition topic_matcher.h:193
value_type * operator->() noexcept
Definition topic_matcher.h:216
Definition topic_matcher.h:275
reference operator*() noexcept
Definition topic_matcher.h:373
match_iterator & operator++() noexcept
Definition topic_matcher.h:402
const_reference operator*() const noexcept
Definition topic_matcher.h:378
bool operator!=(const match_iterator &other) const noexcept
Definition topic_matcher.h:413
value_type * operator->() noexcept
Definition topic_matcher.h:383
match_iterator operator++(int) noexcept
Definition topic_matcher.h:393
const value_type * operator->() const noexcept
Definition topic_matcher.h:388
friend class topic_matcher
Definition topic_matcher.h:357
value_type reference
Definition topic_matcher.h:114
std::unique_ptr< value_type > value_ptr
Definition topic_matcher.h:117
const_match_iterator matches(const string &topic) const
Definition topic_matcher.h:589
bool empty() const
Definition topic_matcher.h:469
void insert(const value_type &val)
Definition topic_matcher.h:493
const_iterator cend() const noexcept
Definition topic_matcher.h:551
string key_type
Definition topic_matcher.h:111
void insert(value_type &&val)
Definition topic_matcher.h:474
mapped_ptr remove(const key_type &filter)
Definition topic_matcher.h:505
std::pair< key_type, mapped_type > value_type
Definition topic_matcher.h:113
iterator end()
Definition topic_matcher.h:534
const_iterator end() const noexcept
Definition topic_matcher.h:539
const_match_iterator matches_end() const noexcept
Definition topic_matcher.h:600
T mapped_type
Definition topic_matcher.h:112
iterator begin()
Definition topic_matcher.h:529
match_iterator matches(const string &topic)
Definition topic_matcher.h:583
const_iterator find(const key_type &filter) const
Definition topic_matcher.h:575
const_iterator cbegin() const
Definition topic_matcher.h:546
iterator find(const key_type &filter)
Definition topic_matcher.h:557
topic_matcher(std::initializer_list< value_type > lst)
Definition topic_matcher.h:459
void prune()
Definition topic_matcher.h:524
bool has_match(const string &topic)
Definition topic_matcher.h:616
const_match_iterator matches_cend() const noexcept
Definition topic_matcher.h:609
const value_type & const_reference
Definition topic_matcher.h:115
std::unique_ptr< mapped_type > mapped_ptr
Definition topic_matcher.h:118
topic_matcher()
Definition topic_matcher.h:444
static std::vector< std::string > split(const std::string &topic)
Definition async_client.h:60
std::string string
Definition types.h:43