7373#include < tuple>
7474#include < unistd.h>
7575#include < unordered_map>
76+ #include < unordered_set>
7677#include < utility>
7778#include < variant>
7879#include < vector>
@@ -6510,9 +6511,21 @@ namespace li {
65106511
65116512namespace internal {
65126513
6513- template <typename V> struct drt_node {
6514+ // A simple memory pool for drt_node objects
6515+ template <typename T> struct drt_node_pool {
6516+ template <typename ... Args> T* allocate (Args&&... args) {
6517+ auto new_node = std::make_unique<T>(std::forward<Args>(args)...);
6518+ T* ptr = new_node.get ();
6519+ pool_.emplace_back (std::move (new_node));
6520+ return ptr;
6521+ }
65146522
6515- drt_node () : v_{0 , nullptr } {}
6523+ std::vector<std::unique_ptr<T>> pool_;
6524+ };
6525+
6526+ template <typename V> struct drt_node {
6527+ drt_node () : pool_(nullptr ), v_{0 , nullptr } {}
6528+ drt_node (drt_node_pool<drt_node>& pool) : pool_(pool), v_{0 , nullptr } {}
65166529
65176530 struct iterator {
65186531 const drt_node<V>* ptr;
@@ -6537,17 +6550,10 @@ template <typename V> struct drt_node {
65376550 c++;
65386551 std::string_view k = r.substr (s, c - s);
65396552
6540- auto it = children_.find (k);
6541- if (it != children_.end ())
6542- return children_[k]->find_or_create (r, c);
6543- else {
6544- auto new_node = std::make_shared<drt_node>();
6545- children_shared_pointers_.push_back (new_node);
6546- children_.insert ({k, new_node.get ()});
6547- return new_node->find_or_create (r, c);
6553+ if (children_.find (k) == children_.end ()) {
6554+ children_[k] = pool_.allocate (pool_);
65486555 }
6549-
6550- return v_;
6556+ return children_[k]->find_or_create (r, c);
65516557 }
65526558
65536559 template <typename F> void for_all_routes (F f, std::string prefix = " " ) const {
@@ -6556,8 +6562,8 @@ template <typename V> struct drt_node {
65566562 else {
65576563 if (prefix.size () && prefix.back () != ' /' )
65586564 prefix += ' /' ;
6559- for (auto pair : children_)
6560- pair .second ->for_all_routes (f, prefix + std::string (pair .first ));
6565+ for (const auto & kv : children_)
6566+ kv .second ->for_all_routes (f, prefix + std::string (kv .first ));
65616567 }
65626568 }
65636569
@@ -6594,7 +6600,7 @@ template <typename V> struct drt_node {
65946600
65956601 {
65966602 // if one child is a url param {{param_name}}, choose it
6597- for (auto & kv : children_) {
6603+ for (const auto & kv : children_) {
65986604 auto name = kv.first ;
65996605 if (name.size () > 4 and name[0 ] == ' {' and name[1 ] == ' {' and
66006606 name[name.size () - 2 ] == ' }' and name[name.size () - 1 ] == ' }' )
@@ -6606,22 +6612,22 @@ template <typename V> struct drt_node {
66066612
66076613 V v_;
66086614 std::unordered_map<std::string_view, drt_node*> children_;
6609- std::vector<std::shared_ptr< drt_node>> children_shared_pointers_ ;
6615+ drt_node_pool< drt_node>& pool_ ;
66106616};
6611- } // namespace internal
66126617
6613- template <typename V> struct dynamic_routing_table {
6618+ template <typename V> struct dynamic_routing_table_impl {
6619+ dynamic_routing_table_impl () : root(pool) {}
66146620
66156621 // Find a route and return reference to a procedure.
66166622 auto & operator [](const std::string_view& r) {
6617- strings.push_back (std::make_shared<std:: string> (r));
6618- std::string_view r2 (*strings. back () );
6623+ auto [itr, is_inserted] = strings.emplace (std::string (r));
6624+ std::string_view r2 (*itr );
66196625 return root.find_or_create (r2, 0 );
66206626 }
6621- auto & operator [](const std::string& r ) {
6622- strings.push_back (std::make_shared<std::string>(r) );
6623- std::string_view r2 (*strings. back () );
6624- return root.find_or_create (r2 , 0 );
6627+ auto & operator [](const std::string& s ) {
6628+ auto [itr, is_inserted] = strings.emplace (s );
6629+ std::string_view r (*itr );
6630+ return root.find_or_create (r , 0 );
66256631 }
66266632
66276633 // Find a route and return an iterator.
@@ -6630,8 +6636,36 @@ template <typename V> struct dynamic_routing_table {
66306636 template <typename F> void for_all_routes (F f) const { root.for_all_routes (f); }
66316637 auto end () const { return root.end (); }
66326638
6633- std::vector<std::shared_ptr<std::string>> strings;
6634- internal::drt_node<V> root;
6639+ std::unordered_set<std::string> strings;
6640+ drt_node_pool<drt_node<V>> pool;
6641+ drt_node<V> root;
6642+ };
6643+ } // namespace internal
6644+
6645+ template <typename V> struct dynamic_routing_table {
6646+ dynamic_routing_table () : impl_(std::make_shared<internal::dynamic_routing_table_impl<V>>()) {}
6647+ dynamic_routing_table (const dynamic_routing_table& other) : impl_(other.impl_) {}
6648+
6649+ // Assignment operator
6650+ dynamic_routing_table& operator =(const dynamic_routing_table& other) {
6651+ if (this != &other) {
6652+ impl_ = other.impl_ ;
6653+ }
6654+ return *this ;
6655+ }
6656+
6657+ // Find a route and return reference to a procedure.
6658+ auto & operator [](const std::string_view& r) { return impl_->operator [](r); }
6659+ auto & operator [](const std::string& s) { return impl_->operator [](s); }
6660+
6661+ // Find a route and return an iterator.
6662+ auto find (const std::string_view& r) const { return impl_->find (r); }
6663+
6664+ template <typename F> void for_all_routes (F f) const { impl_->for_all_routes (f); }
6665+ auto end () const { return impl_->end (); }
6666+
6667+ private:
6668+ std::shared_ptr<internal::dynamic_routing_table_impl<V>> impl_;
66356669};
66366670
66376671} // namespace li
0 commit comments