Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
topic_match.hpp
Go to the documentation of this file.
1/*
2 _____ _ __ __ _ _
3|_ _|__ _ __ (_) ___ | \/ | __ _ | |_ ___| |__
4 | |/ _ \| '_ \ | |/ __| | |\/| |/ _` || __/ __| '_ \
5 | | (_) | |_) | | | (__ | | | | (_| || || (__| | | |
6 |_|\___/| .__/ |_|\___| |_| |_|\__,_| \__\___|_| |_|
7 |_|
8
9Pure MQTT-style topic wildcard matching. No dependency on Agent or ZMQ, so it
10is directly unit-testable and reusable outside the subscribe path.
11
12Grammar (mirrors MQTT):
13 - '+' matches exactly one topic level.
14 - '#' matches this level and everything below it, INCLUDING the level it
15 replaces -- e.g. pattern "sensors/#" also matches the bare topic
16 "sensors", not just "sensors/x" and deeper. Legal only as the final
17 token of a pattern; a pattern where '#' appears anywhere but last is
18 invalid, and topic_match() always returns false for it (never matches,
19 rather than throwing -- callers get "no delivery" instead of a crash on
20 a malformed sub_topic string).
21 - Any other token matches its topic-level counterpart literally.
22 - A pattern containing neither '+' nor '#' is an exact-match literal: it
23 must equal the topic character-for-character. (Byte-prefix matching is a
24 property of the raw ZeroMQ SUBSCRIBE frame, not of this function --
25 literal sub_topic entries keep using that path untouched; see
26 Agent::connect_sub().)
27
28Topic levels are separated by '/'. Only a token that is *exactly* "+" or "#"
29is treated as a wildcard; a token that merely contains one of those
30characters (e.g. "a+b") is matched literally, mirroring strict MQTT grammar.
31
32topic_match() alone is NOT the whole delivery rule a MADS agent applies: a
33literal (wildcard-free) sub_topic entry never reaches topic_match() at
34runtime, it is handed to ZeroMQ as-is and matched by byte prefix. Use
35subscription_match() below whenever the question is "would this agent
36actually receive this message?" -- it is the single definition both
37Agent::_topic_matches_subscription() and `mads doctor --graph` are built on,
38so the wire and the topology graph can never drift apart.
39
40Author(s): Paolo Bosetti
41*/
42
43#pragma once
44
45#include <string>
46#include <string_view>
47
48namespace Mads {
49
58bool topic_match(std::string_view pattern, std::string_view topic);
59
74bool has_wildcard(std::string_view sub_entry);
75
80enum class SubMatch {
81 None,
82 Exact,
83 Prefix,
84 Wildcard,
85};
86
109SubMatch subscription_match(std::string_view sub_entry, std::string_view topic);
110
118inline bool subscription_matches(std::string_view sub_entry,
119 std::string_view topic) {
120 return subscription_match(sub_entry, topic) != SubMatch::None;
121}
122
151std::string literal_prefix(std::string_view pattern);
152
153} // namespace Mads
Definition agent.hpp:67
bool topic_match(std::string_view pattern, std::string_view topic)
Tests whether a concrete topic matches an MQTT-style pattern.
@ Exact
Literal entry equal to the topic.
@ None
Not delivered.
@ Prefix
Literal entry that is a strict byte prefix of the topic.
@ Wildcard
Entry containing '+'/'#', matched per topic_match().
std::string literal_prefix(std::string_view pattern)
Computes the longest literal (wildcard-free) prefix of a pattern.
bool subscription_matches(std::string_view sub_entry, std::string_view topic)
Convenience predicate over subscription_match().
SubMatch subscription_match(std::string_view sub_entry, std::string_view topic)
Single source of truth for "would an agent subscribing to `sub_entry` receive a message published on ...
bool has_wildcard(std::string_view sub_entry)
Tells whether a sub_topic entry is a wildcard pattern.