24#ifndef GOBY_ZENOH_TRANSPORT_DETAIL_KEY_EXPRESSION_H
25#define GOBY_ZENOH_TRANSPORT_DETAIL_KEY_EXPRESSION_H
46 return c ==
'*' || c ==
'?' || c ==
'#' || c ==
'$' || c ==
'/' || c ==
'@' || c ==
'%';
60 static constexpr const char hex[] =
"0123456789ABCDEF";
62 escaped.reserve(chunk.size());
68 escaped += hex[(
static_cast<unsigned char>(c) >> 4) & 0xF];
69 escaped += hex[
static_cast<unsigned char>(c) & 0xF];
85 auto hex_value = [](
char c) ->
int
87 if (c >=
'0' && c <=
'9')
89 if (c >=
'A' && c <=
'F')
91 if (c >=
'a' && c <=
'f')
96 std::string unescaped;
97 unescaped.reserve(chunk.size());
98 for (std::size_t i = 0; i < chunk.size(); ++i)
100 int hi = -1, lo = -1;
101 if (chunk[i] ==
'%' && i + 2 < chunk.size() && (hi = hex_value(chunk[i + 1])) >= 0 &&
102 (lo = hex_value(chunk[i + 2])) >= 0)
104 unescaped +=
static_cast<char>((hi << 4) | lo);
109 unescaped += chunk[i];
125 if (end == std::string::npos)
126 end = identifier.size();
128 std::size_t start = 0;
129 if (start < end && identifier[start] == delimiter)
131 const bool framed = end > start && identifier[end - 1] == delimiter;
135 std::vector<std::string> components;
136 if (start == end && !framed)
141 auto next = identifier.find(delimiter, start);
142 if (next == std::string::npos || next > end)
144 components.push_back(identifier.substr(start, next - start));
156 std::string identifier;
157 for (
const auto& component : components)
159 identifier += delimiter;
160 identifier += component;
162 identifier += delimiter;
173 bool wildcard_suffix)
175 std::string key = root;
191 if (key.size() <= root.size() || key.compare(0, root.size(), root) != 0 ||
192 key[root.size()] !=
'/')
195 std::vector<std::string> components;
196 std::size_t start = root.size() + 1;
197 while (start <= key.size())
199 auto next = key.find(
'/', start);
200 components.push_back(
201 unescape_chunk(key.substr(start, next == std::string::npos ? next : next - start)));
202 if (next == std::string::npos)
static const char delimiter
static const char end_delimiter
detail namespace with internal helper functions
constexpr const char * empty_chunk
The chunk standing for an empty identifier component, which Zenoh would reject.
std::string identifier_to_key(const std::string &root, const std::string &identifier, bool wildcard_suffix)
Map a Goby identifier onto a key expression below root.
std::vector< std::string > split_identifier(const std::string &identifier)
Split a Goby interprocess identifier into its '/'-delimited components.
std::string escape_chunk(const std::string &chunk)
Percent-encode the characters a key expression chunk cannot carry.
std::string join_identifier(const std::vector< std::string > &components)
Rebuild a Goby identifier from key expression chunks, with the trailing delimiter Goby expects.
std::string key_to_identifier(const std::string &root, const std::string &key)
Invert identifier_to_key() for a received sample, whose key is always fully qualified.
bool is_reserved(char c)
Characters that cannot appear in a key expression chunk.
std::string unescape_chunk(const std::string &chunk)
Invert escape_chunk(). A trailing or malformed escape is passed through unchanged.
The global namespace for the Goby project.