OSSIA
Open Scenario System for Interactive Application
path.hpp
1 #pragma once
2 #include <ossia/detail/optional.hpp>
3 #include <ossia/detail/regex_fwd.hpp>
4 #include <ossia/network/base/address_scope.hpp>
5 #include <ossia/network/base/name_validation.hpp>
6 
7 #include <smallfun.hpp>
8 
9 #include <iosfwd>
10 #include <string>
11 
12 namespace ossia
13 {
14 namespace net
15 {
16 
17 class node_base;
18 }
33 namespace regex_path
34 {
38 struct OSSIA_EXPORT path_element
39 {
40  std::string address;
41  path_element(std::string s)
42  : address{std::move(s)}
43  {
44  }
45 
46  template <int N>
47  path_element(const char (&s)[N])
48  : address(s, N - 1)
49  {
50  }
51 
52  operator std::string() const { return address; }
53 };
54 
55 OSSIA_EXPORT
56 std::ostream& operator<<(std::ostream& s, const path_element& p);
57 
59 struct OSSIA_EXPORT device : public path_element
60 {
61  explicit device(std::string s)
62  : path_element{"^" + std::move(s) + ":"}
63  {
64  }
65 };
66 
68 struct OSSIA_EXPORT any_instance : public path_element
69 {
70  static std::string instance_regex()
71  {
72  static const auto str
73  = "(\\.[" + std::string(ossia::net::name_characters_no_instance()) + "]+)?";
74  return str;
75  }
76  explicit any_instance(std::string s)
77  : path_element{std::move(s) + instance_regex()}
78  {
79  }
80 };
81 
84 struct OSSIA_EXPORT any_between : public path_element
85 {
86  any_between(std::string s)
87  : path_element{std::move(s)}
88  {
89  }
90 
91  any_between(std::initializer_list<std::string> args)
92  : path_element{""}
93  {
94  const auto N = args.size();
95  if(N > 0)
96  {
97  address += '(';
98 
99  auto it = args.begin();
100  address += *it;
101 
102  for(std::size_t i = 1; i < N; i++)
103  {
104  ++it;
105  address += '|';
106  address += *it;
107  }
108 
109  address += ')';
110  }
111  }
112 };
113 
115 struct OSSIA_EXPORT any_node
116 {
117 };
118 
120 struct OSSIA_EXPORT any_path
121 {
122 };
123 
125 struct OSSIA_EXPORT stop
126 {
127 };
128 
129 inline path_element operator/(const path_element& lhs, const path_element& rhs)
130 {
131  return path_element{lhs.address + "\\/" + rhs.address};
132 }
133 
134 inline path_element operator/(const path_element& lhs, const any_instance& rhs)
135 {
136  return path_element{lhs.address + "\\/" + rhs.address};
137 }
138 
139 inline path_element operator/(const path_element& lhs, const any_node&)
140 {
141  return path_element{
142  lhs.address + "\\/[" + std::string(ossia::net::name_characters()) + "]*"};
143 }
144 
145 inline path_element operator/(const path_element& lhs, const any_path&)
146 {
147  return path_element{
148  lhs.address + "(\\/[" + std::string(ossia::net::name_characters()) + "]*)+"};
149 }
150 
151 inline path_element operator/(const any_path&, const path_element& rhs)
152 {
153  const std::string sub = std::string(ossia::net::name_characters());
154  std::string sub2 = "^([";
155  sub2 += sub;
156  sub2 += "]*:)(\\/?[";
157  sub2 += sub;
158  sub2 += "]*)+\\/";
159  sub2 += rhs.address;
160  return path_element{std::move(sub2)};
161 }
162 
163 inline path_element operator/(const path_element& lhs, const stop& rhs)
164 {
165  return path_element{lhs.address + "$"};
166 }
167 }
168 
206 namespace traversal
207 {
208 struct OSSIA_EXPORT path
209 {
210  // Used for hashing
211  std::string pattern;
212  ossia::net::address_scope scope;
213 
217  using child_function = smallfun::function<
218  void(std::vector<ossia::net::node_base*>&), sizeof_regex + sizeof(void*)>;
219  std::vector<child_function> child_functions;
220 
221  friend bool operator==(const path& lhs, const path& rhs)
222  {
223  return lhs.pattern == rhs.pattern;
224  }
225  friend bool operator!=(const path& lhs, const path& rhs)
226  {
227  return lhs.pattern != rhs.pattern;
228  }
229 };
230 
232 OSSIA_EXPORT bool is_pattern(std::string_view address);
233 
237 OSSIA_EXPORT std::optional<path> make_path(std::string_view address);
238 
247 OSSIA_EXPORT void apply(const path& p, std::vector<ossia::net::node_base*>& nodes);
248 
250 OSSIA_EXPORT bool match(const path& p, const ossia::net::node_base& node);
251 
253 OSSIA_EXPORT bool
254 match(const path& p, const ossia::net::node_base& node, ossia::net::node_base& root);
255 
257 OSSIA_EXPORT std::string substitute_characters(const std::string& path);
258 
260 OSSIA_EXPORT bool match(std::string_view address, const regex_path::path_element& e);
261 
262 }
263 }
264 
265 namespace std
266 {
267 template <>
268 struct hash<ossia::traversal::path>
269 {
270  std::size_t operator()(const ossia::traversal::path& p) const
271  {
272  return std::hash<std::string>{}(p.pattern);
273  }
274 };
275 }
The node_base class.
Definition: node.hpp:48
Definition: git_info.h:7
Utilities to construct regexes to validate paths.
Utilities to construct classes that will perform an action for nodes matching a path.
Definition: path.hpp:85
Can match nodes that are instances : foo:/bar, foo:/bar.1, etc.
Definition: path.hpp:69
Can match any node : foo:/bar, foo:/baz.1234, etc.
Definition: path.hpp:116
Can match any subpath : foo:/bar/baz, foo:/bar/bo.12/baz, etc.
Definition: path.hpp:121
Represents a device in a path, e.g. "foo:".
Definition: path.hpp:60
Base class for our paths.
Definition: path.hpp:39
Matches the end of a parameter.
Definition: path.hpp:126