$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 <filesystem>
27 #include <map>
28 #include <mutex>
29 #include <shared_mutex>
30 #include <stdexcept>
31 #include <string>
32 #include <utility>
33 #include <vector>
34 
35 namespace oak {
36 
37 using Parameters = std::map<std::string, std::string>;
38 
60 template <typename T>
61 class Muxer {
62  public:
75  static std::string normalize(const std::string& route) {
76  std::string s = route.substr(0, route.find("?"));
77  std::filesystem::path p(s);
78  if (!p.is_absolute()) {
79  return "";
80  }
81  s = p.lexically_normal().string();
82  s = s.substr(0, s.find_last_not_of("/. \n\t\r") + 1);
83  if (s.empty()) {
84  return "/";
85  }
86  return s;
87  }
88 
95  static bool is_identifier(const std::string& s) {
96  auto is_illegal = [](char c) -> bool {
97  return !(isalnum(c) || c == '_' || c == '-' || c == '.');
98  };
99  return std::find_if(s.begin(), s.end(), is_illegal) == s.end();
100  }
101 
108  std::string resolve(const std::string& route) const {
109  auto key = normalize(route);
110  std::shared_lock read_lock(access_);
111  if (!backtrack_) {
112  if (routes_.count(key)) {
113  return key;
114  }
115  return "";
116  } else {
117  std::filesystem::path p(key);
118  while (!routes_.count(p.string())) {
119  if (p.string() == "/") {
120  return "";
121  }
122  p = p.parent_path();
123  }
124  return p.string();
125  }
126  }
127 
131  void set_backtrack(bool enabled) {
132  std::unique_lock write_lock(access_);
133  backtrack_ = enabled;
134  }
135 
139  void set_default(T def) { routes_[""] = def; }
140 
141  std::vector<std::string> routes() const {
142  std::vector<std::string> vs;
143  std::shared_lock read_lock(access_);
144  for (const auto& kv : routes_) {
145  if (kv.first.empty()) {
146  continue;
147  }
148  vs.push_back(kv.first);
149  }
150  return vs;
151  }
152 
153  bool has(const std::string& route) const {
154  auto key = normalize(route);
155  std::shared_lock read_lock(access_);
156  return routes_.count(key) != 0;
157  }
158 
159  void add(const std::string& route, T val) {
160  auto key = normalize(route);
161  std::unique_lock write_lock(access_);
162  if (routes_.count(key)) {
163  throw std::runtime_error("route already exists");
164  }
165  routes_[key] = val;
166  }
167 
168  void set(const std::string& route, T val) {
169  auto key = normalize(route);
170  std::unique_lock write_lock(access_);
171  routes_[key] = val;
172  }
173 
180  std::pair<T, Parameters> get(const std::string& route) const {
181  auto key = resolve(route);
182  Parameters p{};
183  std::shared_lock read_lock(access_);
184  return std::make_pair(routes_.at(key), p);
185  }
186 
187  void set_unsafe(const std::string& key, T val) {
188  std::unique_lock write_lock(access_);
189  routes_[key] = val;
190  }
191 
192  std::pair<T, Parameters> get_unsafe(const std::string& key) const {
193  Parameters p{};
194  std::shared_lock read_lock(access_);
195  return std::make_pair(routes_.at(key), p);
196  }
197 
198  private:
199  // Configuration:
200  bool backtrack_ = false;
201 
202  // State:
203  std::map<std::string, T> routes_;
204  mutable std::shared_mutex access_;
205 };
206 
207 } // namespace oak
Definition: route_muxer.hpp:61
static bool is_identifier(const std::string &s)
Definition: route_muxer.hpp:95
std::string resolve(const std::string &route) const
Definition: route_muxer.hpp:108
static std::string normalize(const std::string &route)
Definition: route_muxer.hpp:75
void set_default(T def)
Definition: route_muxer.hpp:139
std::pair< T, Parameters > get(const std::string &route) const
Definition: route_muxer.hpp:180
void set_backtrack(bool enabled)
Definition: route_muxer.hpp:131