Coverage Report

Created: 2026-10-20 19:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/path_trie.hpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <map>
21
#include <memory>
22
#include <string>
23
#include <vector>
24
25
namespace doris {
26
27
// This tree is usd for manage restful api path.
28
template <class T>
29
class PathTrie {
30
public:
31
494
    PathTrie() : _root("/", "*"), _root_value(nullptr), _separator('/') {}
_ZN5doris8PathTrieIiEC2Ev
Line
Count
Source
31
8
    PathTrie() : _root("/", "*"), _root_value(nullptr), _separator('/') {}
_ZN5doris8PathTrieIPNS_11HttpHandlerEEC2Ev
Line
Count
Source
31
486
    PathTrie() : _root("/", "*"), _root_value(nullptr), _separator('/') {}
32
33
494
    ~PathTrie() {
34
494
        if (_root_value != nullptr) {
35
2
            _allocator.destroy(_root_value);
36
2
            _allocator.deallocate(_root_value, 1);
37
2
        }
38
494
    }
_ZN5doris8PathTrieIiED2Ev
Line
Count
Source
33
8
    ~PathTrie() {
34
8
        if (_root_value != nullptr) {
35
1
            _allocator.destroy(_root_value);
36
1
            _allocator.deallocate(_root_value, 1);
37
1
        }
38
8
    }
_ZN5doris8PathTrieIPNS_11HttpHandlerEED2Ev
Line
Count
Source
33
486
    ~PathTrie() {
34
486
        if (_root_value != nullptr) {
35
1
            _allocator.destroy(_root_value);
36
1
            _allocator.deallocate(_root_value, 1);
37
1
        }
38
486
    }
39
40
    class Allocator {
41
    public:
42
        using value_type = T;
43
44
221
        T* allocate(size_t n) { return static_cast<T*>(::operator new(sizeof(T) * n)); }
_ZN5doris8PathTrieIiE9Allocator8allocateEm
Line
Count
Source
44
12
        T* allocate(size_t n) { return static_cast<T*>(::operator new(sizeof(T) * n)); }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE9Allocator8allocateEm
Line
Count
Source
44
209
        T* allocate(size_t n) { return static_cast<T*>(::operator new(sizeof(T) * n)); }
45
46
        template <typename... Args>
47
598
        void construct(T* p, Args&&... args) {
48
598
            new (p) T(std::forward<Args>(args)...);
49
598
        }
_ZN5doris8PathTrieIiE9Allocator9constructIJRKiEEEvPiDpOT_
Line
Count
Source
47
12
        void construct(T* p, Args&&... args) {
48
12
            new (p) T(std::forward<Args>(args)...);
49
12
        }
_ZN5doris8PathTrieIiE9Allocator9constructIJRiEEEvPiDpOT_
Line
Count
Source
47
13
        void construct(T* p, Args&&... args) {
48
13
            new (p) T(std::forward<Args>(args)...);
49
13
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE9Allocator9constructIJRKS2_EEEvPS2_DpOT_
Line
Count
Source
47
209
        void construct(T* p, Args&&... args) {
48
209
            new (p) T(std::forward<Args>(args)...);
49
209
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE9Allocator9constructIJRS2_EEEvPS2_DpOT_
Line
Count
Source
47
364
        void construct(T* p, Args&&... args) {
48
364
            new (p) T(std::forward<Args>(args)...);
49
364
        }
50
51
221
        void destroy(T* p) { p->~T(); }
_ZN5doris8PathTrieIiE9Allocator7destroyEPi
Line
Count
Source
51
12
        void destroy(T* p) { p->~T(); }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE9Allocator7destroyEPS2_
Line
Count
Source
51
209
        void destroy(T* p) { p->~T(); }
52
53
221
        void deallocate(T* p, size_t n) { ::operator delete(p); }
_ZN5doris8PathTrieIiE9Allocator10deallocateEPim
Line
Count
Source
53
12
        void deallocate(T* p, size_t n) { ::operator delete(p); }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE9Allocator10deallocateEPS2_m
Line
Count
Source
53
209
        void deallocate(T* p, size_t n) { ::operator delete(p); }
54
    };
55
56
    class TrieNode {
57
    public:
58
        TrieNode(const std::string& key, const std::string& wildcard)
59
543
                : _value(nullptr), _wildcard(wildcard) {
60
543
            if (is_named_wildcard(key)) {
61
9
                _named_wildcard = extract_template(key);
62
9
            }
63
543
        }
_ZN5doris8PathTrieIiE8TrieNodeC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_
Line
Count
Source
59
19
                : _value(nullptr), _wildcard(wildcard) {
60
19
            if (is_named_wildcard(key)) {
61
4
                _named_wildcard = extract_template(key);
62
4
            }
63
19
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNodeC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_
Line
Count
Source
59
524
                : _value(nullptr), _wildcard(wildcard) {
60
524
            if (is_named_wildcard(key)) {
61
5
                _named_wildcard = extract_template(key);
62
5
            }
63
524
        }
64
65
        TrieNode(const std::string& key, const T& value, const std::string& wildcard)
66
218
                : _value(nullptr), _wildcard(wildcard) {
67
218
            _value = _allocator.allocate(1);
68
218
            _allocator.construct(_value, value);
69
218
            if (is_named_wildcard(key)) {
70
12
                _named_wildcard = extract_template(key);
71
12
            }
72
218
        }
_ZN5doris8PathTrieIiE8TrieNodeC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKiSA_
Line
Count
Source
66
10
                : _value(nullptr), _wildcard(wildcard) {
67
10
            _value = _allocator.allocate(1);
68
10
            _allocator.construct(_value, value);
69
10
            if (is_named_wildcard(key)) {
70
2
                _named_wildcard = extract_template(key);
71
2
            }
72
10
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNodeC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS2_SC_
Line
Count
Source
66
208
                : _value(nullptr), _wildcard(wildcard) {
67
208
            _value = _allocator.allocate(1);
68
208
            _allocator.construct(_value, value);
69
208
            if (is_named_wildcard(key)) {
70
10
                _named_wildcard = extract_template(key);
71
10
            }
72
208
        }
73
74
761
        ~TrieNode() {
75
761
            for (auto& iter : _children) {
76
267
                delete iter.second;
77
267
                iter.second = nullptr;
78
267
            }
79
761
            if (_value != nullptr) {
80
219
                _allocator.destroy(_value);
81
219
                _allocator.deallocate(_value, 1);
82
219
            }
83
761
        }
_ZN5doris8PathTrieIiE8TrieNodeD2Ev
Line
Count
Source
74
29
        ~TrieNode() {
75
29
            for (auto& iter : _children) {
76
21
                delete iter.second;
77
21
                iter.second = nullptr;
78
21
            }
79
29
            if (_value != nullptr) {
80
11
                _allocator.destroy(_value);
81
11
                _allocator.deallocate(_value, 1);
82
11
            }
83
29
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNodeD2Ev
Line
Count
Source
74
732
        ~TrieNode() {
75
732
            for (auto& iter : _children) {
76
246
                delete iter.second;
77
246
                iter.second = nullptr;
78
246
            }
79
732
            if (_value != nullptr) {
80
208
                _allocator.destroy(_value);
81
208
                _allocator.deallocate(_value, 1);
82
208
            }
83
732
        }
84
85
        // Return true if insert success.
86
326
        bool insert(const std::vector<std::string> path, int index, const T& value) {
87
326
            if (index >= path.size()) {
88
0
                return false;
89
0
            }
90
326
            const std::string& token = path[index];
91
326
            std::string key = token;
92
93
326
            if (is_named_wildcard(token)) {
94
30
                key = _wildcard;
95
30
            }
96
97
326
            TrieNode* node = get_child(key);
98
99
326
            if (node == nullptr) {
100
                // no exist child for this key
101
267
                if (index == path.size() - 1) {
102
218
                    node = new TrieNode(token, value, _wildcard);
103
218
                    _children.insert(std::make_pair(key, node));
104
218
                    return true;
105
218
                } else {
106
49
                    node = new TrieNode(token, _wildcard);
107
49
                    _children.insert(std::make_pair(key, node));
108
49
                }
109
267
            } else {
110
                // If this is a template, set this to the node
111
59
                if (is_named_wildcard(token)) {
112
9
                    std::string temp = extract_template(token);
113
9
                    if (node->_named_wildcard.empty() || node->_named_wildcard.compare(temp) == 0) {
114
8
                        node->_named_wildcard = temp;
115
8
                    } else {
116
                        // Duplicated
117
1
                        return false;
118
1
                    }
119
9
                }
120
58
                if (index == path.size() - 1) {
121
2
                    if (node->_value == nullptr) {
122
1
                        node->_value = _allocator.allocate(1);
123
1
                        _allocator.construct(node->_value, value);
124
1
                        return true;
125
1
                    }
126
                    // Already register by other path
127
1
                    return false;
128
2
                }
129
58
            }
130
105
            return node->insert(path, index + 1, value);
131
326
        }
_ZN5doris8PathTrieIiE8TrieNode6insertESt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EEiRKi
Line
Count
Source
86
34
        bool insert(const std::vector<std::string> path, int index, const T& value) {
87
34
            if (index >= path.size()) {
88
0
                return false;
89
0
            }
90
34
            const std::string& token = path[index];
91
34
            std::string key = token;
92
93
34
            if (is_named_wildcard(token)) {
94
8
                key = _wildcard;
95
8
            }
96
97
34
            TrieNode* node = get_child(key);
98
99
34
            if (node == nullptr) {
100
                // no exist child for this key
101
21
                if (index == path.size() - 1) {
102
10
                    node = new TrieNode(token, value, _wildcard);
103
10
                    _children.insert(std::make_pair(key, node));
104
10
                    return true;
105
11
                } else {
106
11
                    node = new TrieNode(token, _wildcard);
107
11
                    _children.insert(std::make_pair(key, node));
108
11
                }
109
21
            } else {
110
                // If this is a template, set this to the node
111
13
                if (is_named_wildcard(token)) {
112
2
                    std::string temp = extract_template(token);
113
2
                    if (node->_named_wildcard.empty() || node->_named_wildcard.compare(temp) == 0) {
114
1
                        node->_named_wildcard = temp;
115
1
                    } else {
116
                        // Duplicated
117
1
                        return false;
118
1
                    }
119
2
                }
120
12
                if (index == path.size() - 1) {
121
2
                    if (node->_value == nullptr) {
122
1
                        node->_value = _allocator.allocate(1);
123
1
                        _allocator.construct(node->_value, value);
124
1
                        return true;
125
1
                    }
126
                    // Already register by other path
127
1
                    return false;
128
2
                }
129
12
            }
130
21
            return node->insert(path, index + 1, value);
131
34
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode6insertESt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EEiRKS2_
Line
Count
Source
86
292
        bool insert(const std::vector<std::string> path, int index, const T& value) {
87
292
            if (index >= path.size()) {
88
0
                return false;
89
0
            }
90
292
            const std::string& token = path[index];
91
292
            std::string key = token;
92
93
292
            if (is_named_wildcard(token)) {
94
22
                key = _wildcard;
95
22
            }
96
97
292
            TrieNode* node = get_child(key);
98
99
292
            if (node == nullptr) {
100
                // no exist child for this key
101
246
                if (index == path.size() - 1) {
102
208
                    node = new TrieNode(token, value, _wildcard);
103
208
                    _children.insert(std::make_pair(key, node));
104
208
                    return true;
105
208
                } else {
106
38
                    node = new TrieNode(token, _wildcard);
107
38
                    _children.insert(std::make_pair(key, node));
108
38
                }
109
246
            } else {
110
                // If this is a template, set this to the node
111
46
                if (is_named_wildcard(token)) {
112
7
                    std::string temp = extract_template(token);
113
7
                    if (node->_named_wildcard.empty() || node->_named_wildcard.compare(temp) == 0) {
114
7
                        node->_named_wildcard = temp;
115
7
                    } else {
116
                        // Duplicated
117
0
                        return false;
118
0
                    }
119
7
                }
120
46
                if (index == path.size() - 1) {
121
0
                    if (node->_value == nullptr) {
122
0
                        node->_value = _allocator.allocate(1);
123
0
                        _allocator.construct(node->_value, value);
124
0
                        return true;
125
0
                    }
126
                    // Already register by other path
127
0
                    return false;
128
0
                }
129
46
            }
130
84
            return node->insert(path, index + 1, value);
131
292
        }
132
133
        bool retrieve(const std::vector<std::string> path, int index, T* value,
134
481
                      std::map<std::string, std::string>* params) {
135
            // check max index
136
481
            if (index >= path.size()) {
137
0
                return false;
138
0
            }
139
481
            bool use_wildcard = false;
140
481
            const std::string& token = path[index];
141
481
            TrieNode* node = get_child(token);
142
481
            if (node == nullptr) {
143
25
                node = get_child(_wildcard);
144
25
                if (node == nullptr) {
145
3
                    return false;
146
3
                }
147
22
                use_wildcard = true;
148
456
            } else {
149
                // If we the last one, but we have no value, check wildcard
150
456
                if (index == path.size() - 1 && node->_value == nullptr &&
151
456
                    get_child(_wildcard) != nullptr) {
152
0
                    node = get_child(_wildcard);
153
0
                    use_wildcard = true;
154
456
                } else {
155
456
                    use_wildcard = (token.compare(_wildcard) == 0);
156
456
                }
157
456
            }
158
159
478
            put(params, node, token);
160
161
478
            if (index == path.size() - 1) {
162
375
                if (node->_value == nullptr) {
163
0
                    return false;
164
0
                }
165
375
                _allocator.construct(value, *node->_value);
166
375
                return true;
167
375
            }
168
169
            // find exact
170
103
            if (node->retrieve(path, index + 1, value, params)) {
171
101
                return true;
172
101
            }
173
174
            // backtrace to test if wildcard can match
175
2
            if (!use_wildcard) {
176
2
                node = get_child(_wildcard);
177
2
                if (node != nullptr) {
178
0
                    put(params, node, token);
179
0
                    return node->retrieve(path, index + 1, value, params);
180
0
                }
181
2
            }
182
2
            return false;
183
2
        }
_ZN5doris8PathTrieIiE8TrieNode8retrieveESt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EEiPiPSt3mapIS9_S9_St4lessIS9_ESaISt4pairIKS9_S9_EEE
Line
Count
Source
134
33
                      std::map<std::string, std::string>* params) {
135
            // check max index
136
33
            if (index >= path.size()) {
137
0
                return false;
138
0
            }
139
33
            bool use_wildcard = false;
140
33
            const std::string& token = path[index];
141
33
            TrieNode* node = get_child(token);
142
33
            if (node == nullptr) {
143
11
                node = get_child(_wildcard);
144
11
                if (node == nullptr) {
145
2
                    return false;
146
2
                }
147
9
                use_wildcard = true;
148
22
            } else {
149
                // If we the last one, but we have no value, check wildcard
150
22
                if (index == path.size() - 1 && node->_value == nullptr &&
151
22
                    get_child(_wildcard) != nullptr) {
152
0
                    node = get_child(_wildcard);
153
0
                    use_wildcard = true;
154
22
                } else {
155
22
                    use_wildcard = (token.compare(_wildcard) == 0);
156
22
                }
157
22
            }
158
159
31
            put(params, node, token);
160
161
31
            if (index == path.size() - 1) {
162
11
                if (node->_value == nullptr) {
163
0
                    return false;
164
0
                }
165
11
                _allocator.construct(value, *node->_value);
166
11
                return true;
167
11
            }
168
169
            // find exact
170
20
            if (node->retrieve(path, index + 1, value, params)) {
171
18
                return true;
172
18
            }
173
174
            // backtrace to test if wildcard can match
175
2
            if (!use_wildcard) {
176
2
                node = get_child(_wildcard);
177
2
                if (node != nullptr) {
178
0
                    put(params, node, token);
179
0
                    return node->retrieve(path, index + 1, value, params);
180
0
                }
181
2
            }
182
2
            return false;
183
2
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode8retrieveESt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaISB_EEiPS2_PSt3mapISB_SB_St4lessISB_ESaISt4pairIKSB_SB_EEE
Line
Count
Source
134
448
                      std::map<std::string, std::string>* params) {
135
            // check max index
136
448
            if (index >= path.size()) {
137
0
                return false;
138
0
            }
139
448
            bool use_wildcard = false;
140
448
            const std::string& token = path[index];
141
448
            TrieNode* node = get_child(token);
142
448
            if (node == nullptr) {
143
14
                node = get_child(_wildcard);
144
14
                if (node == nullptr) {
145
1
                    return false;
146
1
                }
147
13
                use_wildcard = true;
148
434
            } else {
149
                // If we the last one, but we have no value, check wildcard
150
434
                if (index == path.size() - 1 && node->_value == nullptr &&
151
434
                    get_child(_wildcard) != nullptr) {
152
0
                    node = get_child(_wildcard);
153
0
                    use_wildcard = true;
154
434
                } else {
155
434
                    use_wildcard = (token.compare(_wildcard) == 0);
156
434
                }
157
434
            }
158
159
447
            put(params, node, token);
160
161
447
            if (index == path.size() - 1) {
162
364
                if (node->_value == nullptr) {
163
0
                    return false;
164
0
                }
165
364
                _allocator.construct(value, *node->_value);
166
364
                return true;
167
364
            }
168
169
            // find exact
170
83
            if (node->retrieve(path, index + 1, value, params)) {
171
83
                return true;
172
83
            }
173
174
            // backtrace to test if wildcard can match
175
0
            if (!use_wildcard) {
176
0
                node = get_child(_wildcard);
177
0
                if (node != nullptr) {
178
0
                    put(params, node, token);
179
0
                    return node->retrieve(path, index + 1, value, params);
180
0
                }
181
0
            }
182
0
            return false;
183
0
        }
184
185
    private:
186
1.14k
        bool is_named_wildcard(const std::string& key) {
187
1.14k
            if (key.find('{') != std::string::npos && key.find('}') != std::string::npos) {
188
60
                return true;
189
60
            }
190
1.08k
            return false;
191
1.14k
        }
_ZN5doris8PathTrieIiE8TrieNode17is_named_wildcardERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
186
76
        bool is_named_wildcard(const std::string& key) {
187
76
            if (key.find('{') != std::string::npos && key.find('}') != std::string::npos) {
188
16
                return true;
189
16
            }
190
60
            return false;
191
76
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode17is_named_wildcardERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
186
1.07k
        bool is_named_wildcard(const std::string& key) {
187
1.07k
            if (key.find('{') != std::string::npos && key.find('}') != std::string::npos) {
188
44
                return true;
189
44
            }
190
1.02k
            return false;
191
1.07k
        }
192
193
30
        std::string extract_template(const std::string& key) {
194
30
            std::size_t left = key.find_first_of('{') + 1;
195
30
            std::size_t right = key.find_last_of('}');
196
30
            return key.substr(left, right - left);
197
30
        }
_ZN5doris8PathTrieIiE8TrieNode16extract_templateERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
193
8
        std::string extract_template(const std::string& key) {
194
8
            std::size_t left = key.find_first_of('{') + 1;
195
8
            std::size_t right = key.find_last_of('}');
196
8
            return key.substr(left, right - left);
197
8
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode16extract_templateERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
193
22
        std::string extract_template(const std::string& key) {
194
22
            std::size_t left = key.find_first_of('{') + 1;
195
22
            std::size_t right = key.find_last_of('}');
196
22
            return key.substr(left, right - left);
197
22
        }
198
199
834
        TrieNode* get_child(const std::string& key) {
200
834
            auto pair = _children.find(key);
201
834
            if (pair == _children.end()) {
202
297
                return nullptr;
203
297
            }
204
537
            return pair->second;
205
834
        }
_ZN5doris8PathTrieIiE8TrieNode9get_childERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
199
80
        TrieNode* get_child(const std::string& key) {
200
80
            auto pair = _children.find(key);
201
80
            if (pair == _children.end()) {
202
36
                return nullptr;
203
36
            }
204
44
            return pair->second;
205
80
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode9get_childERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
199
754
        TrieNode* get_child(const std::string& key) {
200
754
            auto pair = _children.find(key);
201
754
            if (pair == _children.end()) {
202
261
                return nullptr;
203
261
            }
204
493
            return pair->second;
205
754
        }
206
207
        void put(std::map<std::string, std::string>* params, TrieNode* node,
208
478
                 const std::string& token) {
209
478
            if (params != nullptr && !node->_named_wildcard.empty()) {
210
                // The query string is parsed into the same map before routing runs, so
211
                // insert() would silently keep a "?db=" over the {db} the path matched.
212
19
                (*params)[node->_named_wildcard] = token;
213
19
            }
214
478
        }
_ZN5doris8PathTrieIiE8TrieNode3putEPSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_St4lessIS9_ESaISt4pairIKS9_S9_EEEPS2_RSD_
Line
Count
Source
208
31
                 const std::string& token) {
209
31
            if (params != nullptr && !node->_named_wildcard.empty()) {
210
                // The query string is parsed into the same map before routing runs, so
211
                // insert() would silently keep a "?db=" over the {db} the path matched.
212
6
                (*params)[node->_named_wildcard] = token;
213
6
            }
214
31
        }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8TrieNode3putEPSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESB_St4lessISB_ESaISt4pairIKSB_SB_EEEPS4_RSF_
Line
Count
Source
208
447
                 const std::string& token) {
209
447
            if (params != nullptr && !node->_named_wildcard.empty()) {
210
                // The query string is parsed into the same map before routing runs, so
211
                // insert() would silently keep a "?db=" over the {db} the path matched.
212
13
                (*params)[node->_named_wildcard] = token;
213
13
            }
214
447
        }
215
216
        T* _value;
217
        std::string _wildcard;
218
        std::string _named_wildcard;
219
        std::map<std::string, TrieNode*> _children;
220
        Allocator _allocator;
221
    };
222
223
224
    bool insert(const std::string& path, const T& value) {
224
224
        std::vector<std::string> path_array;
225
224
        split(path, &path_array);
226
224
        if (path_array.empty()) {
227
3
            if (_root_value == nullptr) {
228
2
                _root_value = _allocator.allocate(1);
229
2
                _allocator.construct(_root_value, value);
230
2
                return true;
231
2
            } else {
232
1
                return false;
233
1
            }
234
3
        }
235
221
        int index = 0;
236
221
        if (path_array[0].empty()) {
237
0
            index = 1;
238
0
        }
239
221
        return _root.insert(path_array, index, value);
240
224
    }
_ZN5doris8PathTrieIiE6insertERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKi
Line
Count
Source
223
15
    bool insert(const std::string& path, const T& value) {
224
15
        std::vector<std::string> path_array;
225
15
        split(path, &path_array);
226
15
        if (path_array.empty()) {
227
2
            if (_root_value == nullptr) {
228
1
                _root_value = _allocator.allocate(1);
229
1
                _allocator.construct(_root_value, value);
230
1
                return true;
231
1
            } else {
232
1
                return false;
233
1
            }
234
2
        }
235
13
        int index = 0;
236
13
        if (path_array[0].empty()) {
237
0
            index = 1;
238
0
        }
239
13
        return _root.insert(path_array, index, value);
240
15
    }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE6insertERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKS2_
Line
Count
Source
223
209
    bool insert(const std::string& path, const T& value) {
224
209
        std::vector<std::string> path_array;
225
209
        split(path, &path_array);
226
209
        if (path_array.empty()) {
227
1
            if (_root_value == nullptr) {
228
1
                _root_value = _allocator.allocate(1);
229
1
                _allocator.construct(_root_value, value);
230
1
                return true;
231
1
            } else {
232
0
                return false;
233
0
            }
234
1
        }
235
208
        int index = 0;
236
208
        if (path_array[0].empty()) {
237
0
            index = 1;
238
0
        }
239
208
        return _root.insert(path_array, index, value);
240
209
    }
241
242
9
    bool retrieve(const std::string& path, T* value) { return retrieve(path, value, nullptr); }
243
244
380
    bool retrieve(const std::string& path, T* value, std::map<std::string, std::string>* params) {
245
380
        if (path.empty()) {
246
1
            if (_root_value == nullptr) {
247
0
                return false;
248
1
            } else {
249
1
                _allocator.construct(value, *_root_value);
250
1
                return true;
251
1
            }
252
1
        }
253
379
        std::vector<std::string> path_array;
254
379
        split(path, &path_array);
255
379
        if (path_array.empty()) {
256
1
            if (_root_value == nullptr) {
257
0
                return false;
258
1
            } else {
259
1
                _allocator.construct(value, *_root_value);
260
1
                return true;
261
1
            }
262
1
        }
263
378
        int index = 0;
264
378
        if (path_array[0].empty()) {
265
0
            index = 1;
266
0
        }
267
378
        return _root.retrieve(path_array, index, value, params);
268
379
    }
_ZN5doris8PathTrieIiE8retrieveERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPiPSt3mapIS7_S7_St4lessIS7_ESaISt4pairIS8_S7_EEE
Line
Count
Source
244
15
    bool retrieve(const std::string& path, T* value, std::map<std::string, std::string>* params) {
245
15
        if (path.empty()) {
246
1
            if (_root_value == nullptr) {
247
0
                return false;
248
1
            } else {
249
1
                _allocator.construct(value, *_root_value);
250
1
                return true;
251
1
            }
252
1
        }
253
14
        std::vector<std::string> path_array;
254
14
        split(path, &path_array);
255
14
        if (path_array.empty()) {
256
1
            if (_root_value == nullptr) {
257
0
                return false;
258
1
            } else {
259
1
                _allocator.construct(value, *_root_value);
260
1
                return true;
261
1
            }
262
1
        }
263
13
        int index = 0;
264
13
        if (path_array[0].empty()) {
265
0
            index = 1;
266
0
        }
267
13
        return _root.retrieve(path_array, index, value, params);
268
14
    }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE8retrieveERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPS2_PSt3mapIS9_S9_St4lessIS9_ESaISt4pairISA_S9_EEE
Line
Count
Source
244
365
    bool retrieve(const std::string& path, T* value, std::map<std::string, std::string>* params) {
245
365
        if (path.empty()) {
246
0
            if (_root_value == nullptr) {
247
0
                return false;
248
0
            } else {
249
0
                _allocator.construct(value, *_root_value);
250
0
                return true;
251
0
            }
252
0
        }
253
365
        std::vector<std::string> path_array;
254
365
        split(path, &path_array);
255
365
        if (path_array.empty()) {
256
0
            if (_root_value == nullptr) {
257
0
                return false;
258
0
            } else {
259
0
                _allocator.construct(value, *_root_value);
260
0
                return true;
261
0
            }
262
0
        }
263
365
        int index = 0;
264
365
        if (path_array[0].empty()) {
265
0
            index = 1;
266
0
        }
267
365
        return _root.retrieve(path_array, index, value, params);
268
365
    }
269
270
private:
271
607
    void split(const std::string& path, std::vector<std::string>* array) {
272
607
        const char* path_str = path.c_str();
273
607
        std::size_t start = 0;
274
607
        std::size_t pos = 0;
275
5.15k
        for (; pos < path.length(); ++pos) {
276
4.55k
            if (path_str[pos] == _separator) {
277
822
                if (pos - start > 0) {
278
215
                    array->push_back(path.substr(start, pos - start));
279
215
                }
280
822
                start = pos + 1;
281
822
            }
282
4.55k
        }
283
607
        if (pos - start > 0) {
284
601
            array->push_back(path.substr(start, pos - start));
285
601
        }
286
607
    }
_ZN5doris8PathTrieIiE5splitERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPSt6vectorIS7_SaIS7_EE
Line
Count
Source
271
33
    void split(const std::string& path, std::vector<std::string>* array) {
272
33
        const char* path_str = path.c_str();
273
33
        std::size_t start = 0;
274
33
        std::size_t pos = 0;
275
403
        for (; pos < path.length(); ++pos) {
276
370
            if (path_str[pos] == _separator) {
277
82
                if (pos - start > 0) {
278
48
                    array->push_back(path.substr(start, pos - start));
279
48
                }
280
82
                start = pos + 1;
281
82
            }
282
370
        }
283
33
        if (pos - start > 0) {
284
28
            array->push_back(path.substr(start, pos - start));
285
28
        }
286
33
    }
_ZN5doris8PathTrieIPNS_11HttpHandlerEE5splitERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPSt6vectorIS9_SaIS9_EE
Line
Count
Source
271
574
    void split(const std::string& path, std::vector<std::string>* array) {
272
574
        const char* path_str = path.c_str();
273
574
        std::size_t start = 0;
274
574
        std::size_t pos = 0;
275
4.75k
        for (; pos < path.length(); ++pos) {
276
4.18k
            if (path_str[pos] == _separator) {
277
740
                if (pos - start > 0) {
278
167
                    array->push_back(path.substr(start, pos - start));
279
167
                }
280
740
                start = pos + 1;
281
740
            }
282
4.18k
        }
283
574
        if (pos - start > 0) {
284
573
            array->push_back(path.substr(start, pos - start));
285
573
        }
286
574
    }
287
288
    TrieNode _root;
289
    T* _root_value;
290
    char _separator;
291
    Allocator _allocator;
292
};
293
294
} // namespace doris