23 std::unordered_map<Method::HttpMethod, Value> value;
27 std::vector<std::shared_ptr<Node<Value>>> childNodes;
29 virtual ~Node() =
default;
31 virtual MatchMode match(
const std::string_view& segment) = 0;
32 constexpr virtual bool operator==(
const std::string_view& pathSegment) = 0;
44struct StandardNode :
public Node<Value> {
46 StandardNode(
const std::string& segment) : segment(segment) {
50 MatchMode match(
const std::string_view& segment)
override {
51 return segment == this->segment ? MatchMode::SingleSegment : MatchMode::NoMatch;
53 constexpr virtual bool operator==(
const std::string_view& pathSegment)
override {
54 return pathSegment == this->segment;
59struct TemplateNode :
public Node<Value> {
61 if constexpr (std::is_same_v<NodeType, std::string_view>) {
63 }
else if constexpr (std::is_same_v<NodeType, int64_t>) {
66 static_assert(
false,
"Invalid type");
69 virtual MatchMode match(
const std::string_view& segment)
override {
75 if constexpr (std::is_same_v<NodeType, std::string_view>) {
76 return MatchMode::SingleSegment;
77 }
else if constexpr (std::is_same_v<NodeType, int64_t>) {
78 for (
size_t i = 0; i < segment.size(); ++i) {
79 auto c = segment.at(i);
80 if ((c <
'0' || c >
'9') && c !=
'+' && c !=
'-') {
81 return MatchMode::NoMatch;
84 return MatchMode::SingleSegment;
86 static_assert(
false,
"Invalid type");
90 constexpr virtual bool operator==(
const std::string_view& pathSegment)
override {
91 if constexpr (std::is_same_v<NodeType, std::string_view>) {
92 return pathSegment.starts_with(
"{string}");
93 }
else if constexpr (std::is_same_v<NodeType, int64_t>) {
94 return pathSegment.starts_with(
"{int}");
96 static_assert(
false,
"Invalid type");
118 std::shared_ptr<RootNode<Value>> root;
131 std::variant<FindError, Value>
getRoute(
const std::vector<std::string_view>& route, Method::HttpMethod method)
const {
132 std::shared_ptr<Node<Value>> node = root;
134 for (
auto& segment : route) {
135 bool hasMatch =
false;
136 for (
auto& childNode : node->childNodes) {
137 auto matchType = childNode->match(segment);
138 if (matchType == MatchMode::SingleSegment) {
142 }
else if (matchType == MatchMode::CatchAll) {
143 throw std::runtime_error(
"Not implemented");
148 return FindError::NoMatch;
155 if (node->value.size() == 0) {
156 return FindError::NoMatch;
158 auto it = node->value.find(method);
159 if (it == node->value.end()) {
160 return FindError::IllegalMethod;
165 constexpr void pushRoute(
167 Method::HttpMethod method,
168 const std::vector<std::string_view>& route
170 std::shared_ptr<Node<Value>> node = root;
172 for (
auto& segment : route) {
173 bool hasRoute =
false;
177 for (
auto& childNode : node->childNodes) {
178 if (*childNode == segment) {
188 std::shared_ptr<Node<Value>> newNode;
191 if (segment.starts_with(
"{string}")) {
192 newNode = std::make_shared<TemplateNode<Value, routing::TypeInfo<
"{string}">::type>>();
193 }
else if (segment.starts_with(
"{int}")) {
194 newNode = std::make_shared<TemplateNode<Value, routing::TypeInfo<
"{int}">::type>>();
196 if (segment.find(
'{') != std::string_view::npos) {
198 throw std::runtime_error(
199 std::string(segment) +
" is an invalid template that wasn't discarded. This should never happen"
203 newNode = std::make_shared<StandardNode<Value>>(std::string(segment));
206 node->childNodes.push_back(newNode);
209 node->childNodes.begin(),
210 node->childNodes.end(),
211 [](
const auto& a,
const auto& b) {
212 return a->weight > b->weight;
221 if (node->value.contains(method)) {
223 throw std::runtime_error(
"Illegal multiple use of the same route with the same method");
225 node->value[method] = value;
std::variant< FindError, Value > getRoute(const std::vector< std::string_view > &route, Method::HttpMethod method) const
Definition RadixTree.hpp:131