$darkmode
route_muxer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
23 #pragma once
24 
25 #include <algorithm>
26 #include <map>
27 #include <stdexcept>
28 #include <string>
29 #include <utility>
30 #include <vector>
31 
32 #include <boost/algorithm/string/predicate.hpp>
33 #include <boost/filesystem/path.hpp>
34 #include <boost/thread/locks.hpp>
35 #include <boost/thread/shared_mutex.hpp>
36 
37 namespace oak {
38 
39 using Parameters = std::map<std::string, std::string>;
40 
62 template <typename T>
63 class Muxer {
64  public:
77  static std::string normalize(const std::string& route) {
78  std::string s = route.substr(0, route.find("?"));
79  boost::filesystem::path p(s);
80  if (!p.is_absolute()) {
81  return "";
82  }
83  s = p.normalize().string();
84  s = s.substr(0, s.find_last_not_of("/. \n\t\r") + 1);
85  if (s.empty()) {
86  return "/";
87  }
88  return s;
89  }
90 
97  static bool is_identifier(const std::string& s) {
98  auto is_illegal = [](char c) -> bool {
99  return !(isalnum(c) || c == '_' || c == '-' || c == '.');
100  };
101  return std::find_if(s.begin(), s.end(), is_illegal) == s.end();
102  }
103 
110  std::string resolve(const std::string& route) const {
111  auto key = normalize(route);
112  boost::shared_lock<boost::shared_mutex> read_lock(access_);
113  if (!backtrack_) {
114  if (routes_.count(key)) {
115  return key;
116  }
117  return "";
118  } else {
119  boost::filesystem::path p(key);
120  while (!routes_.count(p.string())) {
121  p = p.parent_path();
122  }
123  return p.string();
124  }
125  }
126 
130  void set_backtrack(bool enabled) {
131  boost::unique_lock<boost::shared_mutex> write_lock(access_);
132  backtrack_ = enabled;
133  }
134 
138  void set_default(T def) { routes_[""] = def; }
139 
140  std::vector<std::string> routes() const {
141  std::vector<std::string> vs;
142  boost::shared_lock<boost::shared_mutex> read_lock(access_);
143  for (const auto& kv : routes_) {
144  if (kv.first.empty()) {
145  continue;
146  }
147  vs.push_back(kv.first);
148  }
149  return vs;
150  }
151 
152  bool has(const std::string& route) const {
153  auto key = normalize(route);
154  boost::shared_lock<boost::shared_mutex> read_lock(access_);
155  return routes_.count(key) != 0;
156  }
157 
158  void add(const std::string& route, T val) {
159  auto key = normalize(route);
160  boost::unique_lock<boost::shared_mutex> write_lock(access_);
161  if (routes_.count(key)) {
162  throw std::runtime_error("route already exists");
163  }
164  routes_[key] = val;
165  }
166 
167  void set(const std::string& route, T val) {
168  auto key = normalize(route);
169  boost::unique_lock<boost::shared_mutex> write_lock(access_);
170  routes_[key] = val;
171  }
172 
179  std::pair<T, Parameters> get(const std::string& route) const {
180  auto key = resolve(route);
181  Parameters p{};
182  boost::shared_lock<boost::shared_mutex> read_lock(access_);
183  return std::make_pair(routes_.at(key), p);
184  }
185 
186  void set_unsafe(const std::string& key, T val) {
187  boost::unique_lock<boost::shared_mutex> write_lock(access_);
188  routes_[key] = val;
189  }
190 
191  std::pair<T, Parameters> get_unsafe(const std::string& key) const {
192  Parameters p{};
193  boost::shared_lock<boost::shared_mutex> read_lock(access_);
194  return std::make_pair(routes_.at(key), p);
195  }
196 
197  private:
198  // Configuration:
199  bool backtrack_ = false;
200 
201  // State:
202  std::map<std::string, T> routes_;
203  mutable boost::shared_mutex access_;
204 };
205 
206 } // namespace oak
static bool is_identifier(const std::string &s)
Definition: route_muxer.hpp:97
Definition: registrar.hpp:38
static std::string normalize(const std::string &route)
Definition: route_muxer.hpp:77
Definition: route_muxer.hpp:63
void set_backtrack(bool enabled)
Definition: route_muxer.hpp:130
std::string resolve(const std::string &route) const
Definition: route_muxer.hpp:110
void set_default(T def)
Definition: route_muxer.hpp:138