24#ifndef __mqtt_topic_matcher_h
25#define __mqtt_topic_matcher_h
27#include <forward_list>
28#include <initializer_list>
133 using ptr_t = std::unique_ptr<node>;
134 using map_t = std::map<string, ptr_t>;
142 static ptr_t create() {
return std::make_unique<node>(); }
144 bool empty()
const {
return !content && children.empty(); }
148 for (
auto& child : children) {
149 child.second->prune();
152 for (
auto child = children.cbegin(); child != children.cend();) {
153 if (child->second->empty()) {
154 child = children.erase(child);
162 using node_ptr =
typename node::ptr_t;
163 using node_map =
typename node::map_t;
175 std::vector<node*> nodes_;
179 if (nodes_.empty()) {
185 auto snode = std::move(nodes_.back());
189 for (
auto const& child : snode->children) {
190 nodes_.push_back(child.second.get());
195 pval_ = snode->content.get();
203 iterator(node* root) : pval_{nullptr} {
204 nodes_.push_back(root);
253 bool operator!=(
const iterator& other)
const noexcept {
return pval_ != other.pval_; }
257 class const_iterator :
public iterator
259 using base = iterator;
262 const_iterator(iterator it) : base(it) {}
289 std::forward_list<string> fields_;
293 search_node(node* nd,
const std::forward_list<string>& sy,
bool first =
false)
294 : node_{nd}, fields_{sy}, first_{first} {}
295 search_node(node* nd, std::forward_list<string>&& sy,
bool first =
false)
296 : node_{nd}, fields_{std::move(sy)}, first_{first} {}
302 std::vector<search_node> nodes_;
319 auto snode = std::move(nodes_.back());
322 const auto map_end = snode.node_->children.end();
323 typename node_map::iterator child;
327 if (snode.fields_.empty()) {
328 pval_ = snode.node_->content.get();
331 if ((child = snode.node_->children.find(
"#")) != map_end) {
332 pval_ = child->second->content.get();
341 auto field = std::move(snode.fields_.front());
342 snode.fields_.pop_front();
345 if ((child = snode.node_->children.find(field)) != map_end) {
346 nodes_.push_back({child->second.get(), snode.fields_});
353 if (!snode.first_ || field.empty() || field[0] !=
'$') {
355 if ((child = snode.node_->children.find(
"+")) != map_end) {
356 nodes_.push_back({child->second.get(), snode.fields_});
360 if ((child = snode.node_->children.find(
"#")) != map_end) {
362 pval_ = child->second->content.get();
372 match_iterator() : pval_{nullptr} {}
374 match_iterator(node* root,
const string&
topic) : pval_{nullptr} {
376 std::forward_list<string> fields{v.begin(), v.end()};
377 nodes_.push_back(search_node{root, std::move(fields),
true});
426 bool operator!=(
const match_iterator& other)
const noexcept {
427 return pval_ != other.pval_;
434 class const_match_iterator :
public match_iterator
436 using base = match_iterator;
439 const_match_iterator(match_iterator it) : base(it) {}
472 topic_matcher(std::initializer_list<value_type> lst) : root_(node::create()) {
473 for (
const auto& v : lst) {
482 bool empty()
const {
return root_.empty(); }
488 auto nd = root_.get();
491 for (
const auto& field : fields) {
492 auto it = nd->children.find(field);
493 if (it == nd->children.end()) {
494 nd->children[field] = node::create();
495 it = nd->children.find(field);
497 nd = it->second.get();
499 nd->content = std::make_unique<value_type>(std::move(val));
508 this->
insert(std::move(v));
519 auto nd = root_.get();
522 for (
auto& field : fields) {
523 auto it = nd->children.find(field);
524 if (it == nd->children.end())
527 nd = it->second.get();
530 nd->content.swap(valpair);
532 return (valpair) ? std::make_unique<mapped_type>(valpair->second) :
mapped_ptr{};
571 auto nd = root_.get();
574 for (
auto& field : fields) {
575 auto it = nd->children.find(field);
576 if (it == nd->children.end())
578 nd = it->second.get();
Definition topic_matcher.h:258
const value_type * operator->() const noexcept
Definition topic_matcher.h:274
const_reference operator*() const noexcept
Definition topic_matcher.h:269
friend class topic_matcher
Definition topic_matcher.h:261
Definition topic_matcher.h:435
const value_type * operator->() const noexcept
Definition topic_matcher.h:451
const_reference operator*() const noexcept
Definition topic_matcher.h:446
friend class topic_matcher
Definition topic_matcher.h:438
Definition topic_matcher.h:171
const value_type * operator->() const noexcept
Definition topic_matcher.h:228
iterator operator++(int) noexcept
Definition topic_matcher.h:233
reference operator*() noexcept
Definition topic_matcher.h:213
const_reference operator*() const noexcept
Definition topic_matcher.h:218
iterator & operator++() noexcept
Definition topic_matcher.h:242
bool operator!=(const iterator &other) const noexcept
Definition topic_matcher.h:253
friend class topic_matcher
Definition topic_matcher.h:200
value_type * operator->() noexcept
Definition topic_matcher.h:223
Definition topic_matcher.h:282
reference operator*() noexcept
Definition topic_matcher.h:386
match_iterator & operator++() noexcept
Definition topic_matcher.h:415
const_reference operator*() const noexcept
Definition topic_matcher.h:391
bool operator!=(const match_iterator &other) const noexcept
Definition topic_matcher.h:426
value_type * operator->() noexcept
Definition topic_matcher.h:396
match_iterator operator++(int) noexcept
Definition topic_matcher.h:406
const value_type * operator->() const noexcept
Definition topic_matcher.h:401
friend class topic_matcher
Definition topic_matcher.h:370
value_type reference
Definition topic_matcher.h:121
std::unique_ptr< value_type > value_ptr
Definition topic_matcher.h:124
const_match_iterator matches(const string &topic) const
Definition topic_matcher.h:602
bool empty() const
Definition topic_matcher.h:482
void insert(const value_type &val)
Definition topic_matcher.h:506
const_iterator cend() const noexcept
Definition topic_matcher.h:564
string key_type
Definition topic_matcher.h:118
void insert(value_type &&val)
Definition topic_matcher.h:487
mapped_ptr remove(const key_type &filter)
Definition topic_matcher.h:518
std::pair< key_type, mapped_type > value_type
Definition topic_matcher.h:120
iterator end()
Definition topic_matcher.h:547
const_iterator end() const noexcept
Definition topic_matcher.h:552
const_match_iterator matches_end() const noexcept
Definition topic_matcher.h:613
T mapped_type
Definition topic_matcher.h:119
iterator begin()
Definition topic_matcher.h:542
match_iterator matches(const string &topic)
Definition topic_matcher.h:596
const_iterator find(const key_type &filter) const
Definition topic_matcher.h:588
const_iterator cbegin() const
Definition topic_matcher.h:559
iterator find(const key_type &filter)
Definition topic_matcher.h:570
topic_matcher(std::initializer_list< value_type > lst)
Definition topic_matcher.h:472
void prune()
Definition topic_matcher.h:537
bool has_match(const string &topic)
Definition topic_matcher.h:629
const_match_iterator matches_cend() const noexcept
Definition topic_matcher.h:622
const value_type & const_reference
Definition topic_matcher.h:122
std::unique_ptr< mapped_type > mapped_ptr
Definition topic_matcher.h:125
topic_matcher()
Definition topic_matcher.h:457
static std::vector< std::string > split(const std::string &topic)
Definition async_client.h:60
std::string string
Definition types.h:43