Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mdds-3.1.0/include/mdds/flat_segment_tree_def.inl
Line
Count
Source
1
/*************************************************************************
2
 *
3
 * Copyright (c) 2010-2023 Kohei Yoshida
4
 *
5
 * Permission is hereby granted, free of charge, to any person
6
 * obtaining a copy of this software and associated documentation
7
 * files (the "Software"), to deal in the Software without
8
 * restriction, including without limitation the rights to use,
9
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following
12
 * conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
 * OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 ************************************************************************/
27
28
namespace mdds {
29
30
template<typename Key, typename Value>
31
typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<
32
    Key, Value>::const_iterator::to_segment() const
33
{
34
    const node* pos = get_pos();
35
    const auto* parent = get_parent();
36
    if (!parent || is_end_pos() || !pos || !pos->next)
37
        return parent->end_segment();
38
39
    return const_segment_iterator(pos, pos->next.get());
40
}
41
42
template<typename Key, typename Value>
43
flat_segment_tree<Key, Value>::const_segment_range_type::const_segment_range_type(
44
    node_ptr left_leaf, node_ptr right_leaf)
45
    : m_left_leaf(left_leaf), m_right_leaf(right_leaf)
46
{}
47
48
template<typename Key, typename Value>
49
typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<
50
    Key, Value>::const_segment_range_type::begin() const
51
{
52
    return const_segment_iterator(m_left_leaf.get(), m_left_leaf->next.get());
53
}
54
55
template<typename Key, typename Value>
56
typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<
57
    Key, Value>::const_segment_range_type::end() const
58
{
59
    return const_segment_iterator(m_right_leaf.get(), nullptr);
60
}
61
62
template<typename Key, typename Value>
63
typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<Key, Value>::begin_segment() const
64
{
65
    return const_segment_iterator(m_left_leaf.get(), m_left_leaf->next.get());
66
}
67
68
template<typename Key, typename Value>
69
typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<Key, Value>::end_segment() const
70
{
71
    return const_segment_iterator(m_right_leaf.get(), nullptr);
72
}
73
74
template<typename Key, typename Value>
75
typename flat_segment_tree<Key, Value>::const_segment_range_type flat_segment_tree<Key, Value>::segment_range() const
76
{
77
    return const_segment_range_type(m_left_leaf, m_right_leaf);
78
}
79
80
template<typename Key, typename Value>
81
flat_segment_tree<Key, Value>::flat_segment_tree(key_type min_val, key_type max_val, value_type init_val)
82
1.08k
    : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)),
83
1.08k
      m_valid_tree(false)
84
1.08k
{
85
    // we need to create two end nodes during initialization.
86
1.08k
    m_left_leaf->key = std::move(min_val);
87
1.08k
    m_left_leaf->value_leaf.value = m_init_val; // copy
88
1.08k
    m_left_leaf->next = m_right_leaf;
89
90
1.08k
    m_right_leaf->key = std::move(max_val);
91
1.08k
    m_right_leaf->prev = m_left_leaf;
92
93
    // We don't ever use the value of the right leaf node, but we need the
94
    // value to be always the same, to make it easier to check for
95
    // equality.
96
1.08k
    m_right_leaf->value_leaf.value = value_type{};
97
1.08k
}
mdds::flat_segment_tree<unsigned int, float>::flat_segment_tree(unsigned int, unsigned int, float)
Line
Count
Source
82
390
    : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)),
83
390
      m_valid_tree(false)
84
390
{
85
    // we need to create two end nodes during initialization.
86
390
    m_left_leaf->key = std::move(min_val);
87
390
    m_left_leaf->value_leaf.value = m_init_val; // copy
88
390
    m_left_leaf->next = m_right_leaf;
89
90
390
    m_right_leaf->key = std::move(max_val);
91
390
    m_right_leaf->prev = m_left_leaf;
92
93
    // We don't ever use the value of the right leaf node, but we need the
94
    // value to be always the same, to make it easier to check for
95
    // equality.
96
390
    m_right_leaf->value_leaf.value = value_type{};
97
390
}
mdds::flat_segment_tree<unsigned int, bool>::flat_segment_tree(unsigned int, unsigned int, bool)
Line
Count
Source
82
390
    : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)),
83
390
      m_valid_tree(false)
84
390
{
85
    // we need to create two end nodes during initialization.
86
390
    m_left_leaf->key = std::move(min_val);
87
390
    m_left_leaf->value_leaf.value = m_init_val; // copy
88
390
    m_left_leaf->next = m_right_leaf;
89
90
390
    m_right_leaf->key = std::move(max_val);
91
390
    m_right_leaf->prev = m_left_leaf;
92
93
    // We don't ever use the value of the right leaf node, but we need the
94
    // value to be always the same, to make it easier to check for
95
    // equality.
96
390
    m_right_leaf->value_leaf.value = value_type{};
97
390
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::flat_segment_tree(unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>)
Line
Count
Source
82
300
    : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)),
83
300
      m_valid_tree(false)
84
300
{
85
    // we need to create two end nodes during initialization.
86
300
    m_left_leaf->key = std::move(min_val);
87
300
    m_left_leaf->value_leaf.value = m_init_val; // copy
88
300
    m_left_leaf->next = m_right_leaf;
89
90
300
    m_right_leaf->key = std::move(max_val);
91
300
    m_right_leaf->prev = m_left_leaf;
92
93
    // We don't ever use the value of the right leaf node, but we need the
94
    // value to be always the same, to make it easier to check for
95
    // equality.
96
300
    m_right_leaf->value_leaf.value = value_type{};
97
300
}
98
99
template<typename Key, typename Value>
100
flat_segment_tree<Key, Value>::flat_segment_tree(const flat_segment_tree& r)
101
283
    : m_root_node(nullptr), m_left_leaf(new node(*r.m_left_leaf)), m_right_leaf(), m_init_val(r.m_init_val),
102
283
      m_valid_tree(false) // tree is invalid because we only copy the leaf nodes.
103
283
{
104
    // Copy all the leaf nodes from the original instance.
105
283
    node* src_node = r.m_left_leaf.get();
106
283
    node_ptr dest_node = m_left_leaf;
107
837
    while (true)
108
837
    {
109
837
        dest_node->next.reset(new node(*src_node->next));
110
111
        // Move on to the next source node.
112
837
        src_node = src_node->next.get();
113
114
        // Move on to the next destination node, and have the next node point
115
        // back to the previous node.
116
837
        node_ptr old_node = dest_node;
117
837
        dest_node = dest_node->next;
118
837
        dest_node->prev = std::move(old_node);
119
120
837
        if (src_node == r.m_right_leaf.get())
121
283
        {
122
            // Reached the right most leaf node.  We can stop here.
123
283
            m_right_leaf = dest_node;
124
283
            break;
125
283
        }
126
837
    }
127
283
}
128
129
template<typename Key, typename Value>
130
flat_segment_tree<Key, Value>::flat_segment_tree(flat_segment_tree&& other)
131
600
    : m_nonleaf_node_pool(std::move(other.m_nonleaf_node_pool)), m_root_node(other.m_root_node),
132
600
      m_left_leaf(other.m_left_leaf), m_right_leaf(other.m_right_leaf), m_init_val(other.m_init_val),
133
600
      m_valid_tree(other.m_valid_tree)
134
600
{
135
    // NB: boost::intrusive_ptr doesn't have move constructor
136
600
    other.m_left_leaf.reset();
137
600
    other.m_right_leaf.reset();
138
600
    other.m_root_node = nullptr;
139
600
    other.m_valid_tree = false;
140
600
}
141
142
template<typename Key, typename Value>
143
flat_segment_tree<Key, Value>::~flat_segment_tree()
144
1.96k
{
145
1.96k
    destroy();
146
1.96k
}
mdds::flat_segment_tree<unsigned int, bool>::~flat_segment_tree()
Line
Count
Source
144
390
{
145
390
    destroy();
146
390
}
mdds::flat_segment_tree<unsigned int, float>::~flat_segment_tree()
Line
Count
Source
144
390
{
145
390
    destroy();
146
390
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::~flat_segment_tree()
Line
Count
Source
144
1.18k
{
145
1.18k
    destroy();
146
1.18k
}
147
148
template<typename Key, typename Value>
149
flat_segment_tree<Key, Value>& flat_segment_tree<Key, Value>::operator=(const flat_segment_tree& other)
150
0
{
151
0
    flat_segment_tree copy(other);
152
0
    swap(copy);
153
0
    return *this;
154
0
}
155
156
template<typename Key, typename Value>
157
flat_segment_tree<Key, Value>& flat_segment_tree<Key, Value>::operator=(flat_segment_tree&& other)
158
{
159
    flat_segment_tree moved(std::move(other));
160
    swap(moved);
161
    return *this;
162
}
163
164
template<typename Key, typename Value>
165
void flat_segment_tree<Key, Value>::swap(flat_segment_tree& other)
166
0
{
167
0
    m_nonleaf_node_pool.swap(other.m_nonleaf_node_pool);
168
0
    std::swap(m_root_node, other.m_root_node);
169
0
    std::swap(m_left_leaf, other.m_left_leaf);
170
0
    std::swap(m_right_leaf, other.m_right_leaf);
171
0
    std::swap(m_init_val, other.m_init_val);
172
0
    std::swap(m_valid_tree, other.m_valid_tree);
173
0
}
174
175
template<typename Key, typename Value>
176
void flat_segment_tree<Key, Value>::clear()
177
{
178
    // the border nodes should not be destroyed--add a ref to keep them alive
179
    node_ptr left(m_left_leaf);
180
    node_ptr right(m_right_leaf);
181
182
    // destroy the tree
183
    destroy();
184
185
    // and construct the default tree
186
    st::detail::link_nodes<node_ptr>(m_left_leaf, m_right_leaf);
187
    m_left_leaf->value_leaf.value = m_init_val;
188
    m_valid_tree = false;
189
}
190
191
template<typename Key, typename Value>
192
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<
193
    Key, Value>::insert_segment_impl(key_type start_key, key_type end_key, value_type val, bool forward)
194
2.69k
{
195
2.69k
    typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type;
196
197
2.69k
    if (!adjust_segment_range(start_key, end_key))
198
1
        return ret_type(const_iterator(this, true), false);
199
200
    // Find the node with value that either equals or is greater than the
201
    // start value.
202
203
2.68k
    node_ptr start_pos;
204
2.68k
    if (forward)
205
0
    {
206
0
        const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get());
207
0
        start_pos.reset(const_cast<node*>(p));
208
0
    }
209
2.68k
    else
210
2.68k
    {
211
2.68k
        const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get());
212
2.68k
        if (p)
213
2.10k
            start_pos = p->next;
214
587
        else
215
587
            start_pos = m_left_leaf;
216
2.68k
    }
217
2.68k
    if (!start_pos)
218
0
    {
219
        // Insertion position not found.  Bail out.
220
0
        assert(!"Insertion position not found.  Bail out");
221
0
        return ret_type(const_iterator(this, true), false);
222
0
    }
223
224
2.68k
    return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val));
225
2.68k
}
mdds::flat_segment_tree<unsigned int, float>::insert_segment_impl(unsigned int, unsigned int, float, bool)
Line
Count
Source
194
1.20k
{
195
1.20k
    typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type;
196
197
1.20k
    if (!adjust_segment_range(start_key, end_key))
198
0
        return ret_type(const_iterator(this, true), false);
199
200
    // Find the node with value that either equals or is greater than the
201
    // start value.
202
203
1.20k
    node_ptr start_pos;
204
1.20k
    if (forward)
205
0
    {
206
0
        const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get());
207
0
        start_pos.reset(const_cast<node*>(p));
208
0
    }
209
1.20k
    else
210
1.20k
    {
211
1.20k
        const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get());
212
1.20k
        if (p)
213
907
            start_pos = p->next;
214
296
        else
215
296
            start_pos = m_left_leaf;
216
1.20k
    }
217
1.20k
    if (!start_pos)
218
0
    {
219
        // Insertion position not found.  Bail out.
220
0
        assert(!"Insertion position not found.  Bail out");
221
0
        return ret_type(const_iterator(this, true), false);
222
0
    }
223
224
1.20k
    return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val));
225
1.20k
}
mdds::flat_segment_tree<unsigned int, bool>::insert_segment_impl(unsigned int, unsigned int, bool, bool)
Line
Count
Source
194
1.19k
{
195
1.19k
    typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type;
196
197
1.19k
    if (!adjust_segment_range(start_key, end_key))
198
0
        return ret_type(const_iterator(this, true), false);
199
200
    // Find the node with value that either equals or is greater than the
201
    // start value.
202
203
1.19k
    node_ptr start_pos;
204
1.19k
    if (forward)
205
0
    {
206
0
        const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get());
207
0
        start_pos.reset(const_cast<node*>(p));
208
0
    }
209
1.19k
    else
210
1.19k
    {
211
1.19k
        const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get());
212
1.19k
        if (p)
213
905
            start_pos = p->next;
214
291
        else
215
291
            start_pos = m_left_leaf;
216
1.19k
    }
217
1.19k
    if (!start_pos)
218
0
    {
219
        // Insertion position not found.  Bail out.
220
0
        assert(!"Insertion position not found.  Bail out");
221
0
        return ret_type(const_iterator(this, true), false);
222
0
    }
223
224
1.19k
    return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val));
225
1.19k
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::insert_segment_impl(unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>, bool)
Line
Count
Source
194
291
{
195
291
    typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type;
196
197
291
    if (!adjust_segment_range(start_key, end_key))
198
1
        return ret_type(const_iterator(this, true), false);
199
200
    // Find the node with value that either equals or is greater than the
201
    // start value.
202
203
290
    node_ptr start_pos;
204
290
    if (forward)
205
0
    {
206
0
        const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get());
207
0
        start_pos.reset(const_cast<node*>(p));
208
0
    }
209
290
    else
210
290
    {
211
290
        const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get());
212
290
        if (p)
213
290
            start_pos = p->next;
214
0
        else
215
0
            start_pos = m_left_leaf;
216
290
    }
217
290
    if (!start_pos)
218
0
    {
219
        // Insertion position not found.  Bail out.
220
0
        assert(!"Insertion position not found.  Bail out");
221
0
        return ret_type(const_iterator(this, true), false);
222
0
    }
223
224
290
    return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val));
225
290
}
226
227
template<typename Key, typename Value>
228
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::insert_to_pos(
229
    node_ptr start_pos, key_type start_key, key_type end_key, value_type val)
230
2.68k
{
231
2.68k
    node_ptr end_pos;
232
2.68k
    {
233
2.68k
        const node* p = get_insertion_pos_leaf(end_key, start_pos.get());
234
2.68k
        end_pos.reset(const_cast<node*>(p));
235
2.68k
    }
236
2.68k
    if (!end_pos)
237
0
        end_pos = m_right_leaf;
238
239
2.68k
    node_ptr new_start_node;
240
2.68k
    value_type old_value;
241
242
    // Set the start node.
243
244
2.68k
    bool changed = false;
245
246
2.68k
    if (start_pos->key == start_key)
247
1.48k
    {
248
        // Re-use the existing node, but save the old value for later.
249
250
1.48k
        if (start_pos->prev && start_pos->prev->value_leaf.value == val)
251
882
        {
252
            // Extend the existing segment.
253
882
            old_value = start_pos->value_leaf.value;
254
882
            new_start_node = start_pos->prev;
255
882
        }
256
607
        else
257
607
        {
258
            // Update the value of the existing node.
259
607
            old_value = start_pos->value_leaf.value;
260
607
            start_pos->value_leaf.value = val;
261
607
            new_start_node = std::move(start_pos);
262
263
607
            changed = (old_value != val);
264
607
        }
265
1.48k
    }
266
1.20k
    else if (start_pos->prev->value_leaf.value == val)
267
903
    {
268
        // Extend the existing segment.
269
903
        old_value = start_pos->prev->value_leaf.value;
270
903
        new_start_node = start_pos->prev;
271
903
    }
272
297
    else
273
297
    {
274
        // Insert a new node before the insertion position node.
275
297
        node_ptr new_node(new node);
276
297
        new_node->key = std::move(start_key);
277
297
        new_node->value_leaf.value = val;
278
297
        new_start_node = new_node;
279
280
297
        node_ptr left_node = start_pos->prev;
281
297
        old_value = left_node->value_leaf.value;
282
283
        // Link to the left node.
284
297
        st::detail::link_nodes<node_ptr>(left_node, new_node);
285
286
        // Link to the right node.
287
297
        st::detail::link_nodes<node_ptr>(new_node, start_pos);
288
297
        changed = true;
289
297
    }
290
291
2.68k
    node_ptr cur_node = new_start_node->next;
292
3.57k
    while (cur_node != end_pos)
293
882
    {
294
        // Disconnect the link between the current node and the previous node.
295
882
        cur_node->prev->next.reset();
296
882
        cur_node->prev.reset();
297
882
        old_value = cur_node->value_leaf.value;
298
299
882
        cur_node = cur_node->next;
300
882
        changed = true;
301
882
    }
302
303
    // Set the end node.
304
305
2.68k
    if (end_pos->key == end_key)
306
392
    {
307
        // The new segment ends exactly at the end node position.
308
309
392
        if (end_pos->next && end_pos->value_leaf.value == val)
310
0
        {
311
            // Remove this node, and connect the new start node with the
312
            // node that comes after this node.
313
0
            new_start_node->next = end_pos->next;
314
0
            if (end_pos->next)
315
0
                end_pos->next->prev = new_start_node;
316
0
            disconnect_all_nodes(end_pos.get());
317
0
            changed = true;
318
0
        }
319
392
        else if (new_start_node->next != end_pos)
320
170
        {
321
            // Just link the new segment to this node.
322
170
            new_start_node->next = end_pos;
323
170
            end_pos->prev = new_start_node;
324
170
            changed = true;
325
170
        }
326
392
    }
327
2.29k
    else if (old_value == val)
328
1.00k
    {
329
1.00k
        if (new_start_node->next != end_pos)
330
0
        {
331
0
            st::detail::link_nodes<node_ptr>(new_start_node, end_pos);
332
0
            changed = true;
333
0
        }
334
1.00k
    }
335
1.29k
    else
336
1.29k
    {
337
        // Insert a new node before the insertion position node.
338
1.29k
        node_ptr new_node(new node);
339
1.29k
        new_node->key = std::move(end_key);
340
1.29k
        new_node->value_leaf.value = std::move(old_value);
341
342
        // Link to the left node.
343
1.29k
        st::detail::link_nodes<node_ptr>(new_start_node, new_node);
344
345
        // Link to the right node.
346
1.29k
        st::detail::link_nodes<node_ptr>(new_node, end_pos);
347
1.29k
        changed = true;
348
1.29k
    }
349
350
2.68k
    if (changed)
351
1.49k
        m_valid_tree = false;
352
353
2.68k
    return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed);
354
2.68k
}
mdds::flat_segment_tree<unsigned int, float>::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> >, unsigned int, unsigned int, float)
Line
Count
Source
230
1.20k
{
231
1.20k
    node_ptr end_pos;
232
1.20k
    {
233
1.20k
        const node* p = get_insertion_pos_leaf(end_key, start_pos.get());
234
1.20k
        end_pos.reset(const_cast<node*>(p));
235
1.20k
    }
236
1.20k
    if (!end_pos)
237
0
        end_pos = m_right_leaf;
238
239
1.20k
    node_ptr new_start_node;
240
1.20k
    value_type old_value;
241
242
    // Set the start node.
243
244
1.20k
    bool changed = false;
245
246
1.20k
    if (start_pos->key == start_key)
247
1.19k
    {
248
        // Re-use the existing node, but save the old value for later.
249
250
1.19k
        if (start_pos->prev && start_pos->prev->value_leaf.value == val)
251
880
        {
252
            // Extend the existing segment.
253
880
            old_value = start_pos->value_leaf.value;
254
880
            new_start_node = start_pos->prev;
255
880
        }
256
313
        else
257
313
        {
258
            // Update the value of the existing node.
259
313
            old_value = start_pos->value_leaf.value;
260
313
            start_pos->value_leaf.value = val;
261
313
            new_start_node = std::move(start_pos);
262
263
313
            changed = (old_value != val);
264
313
        }
265
1.19k
    }
266
10
    else if (start_pos->prev->value_leaf.value == val)
267
1
    {
268
        // Extend the existing segment.
269
1
        old_value = start_pos->prev->value_leaf.value;
270
1
        new_start_node = start_pos->prev;
271
1
    }
272
9
    else
273
9
    {
274
        // Insert a new node before the insertion position node.
275
9
        node_ptr new_node(new node);
276
9
        new_node->key = std::move(start_key);
277
9
        new_node->value_leaf.value = val;
278
9
        new_start_node = new_node;
279
280
9
        node_ptr left_node = start_pos->prev;
281
9
        old_value = left_node->value_leaf.value;
282
283
        // Link to the left node.
284
9
        st::detail::link_nodes<node_ptr>(left_node, new_node);
285
286
        // Link to the right node.
287
9
        st::detail::link_nodes<node_ptr>(new_node, start_pos);
288
9
        changed = true;
289
9
    }
290
291
1.20k
    node_ptr cur_node = new_start_node->next;
292
2.08k
    while (cur_node != end_pos)
293
880
    {
294
        // Disconnect the link between the current node and the previous node.
295
880
        cur_node->prev->next.reset();
296
880
        cur_node->prev.reset();
297
880
        old_value = cur_node->value_leaf.value;
298
299
880
        cur_node = cur_node->next;
300
880
        changed = true;
301
880
    }
302
303
    // Set the end node.
304
305
1.20k
    if (end_pos->key == end_key)
306
197
    {
307
        // The new segment ends exactly at the end node position.
308
309
197
        if (end_pos->next && end_pos->value_leaf.value == val)
310
0
        {
311
            // Remove this node, and connect the new start node with the
312
            // node that comes after this node.
313
0
            new_start_node->next = end_pos->next;
314
0
            if (end_pos->next)
315
0
                end_pos->next->prev = new_start_node;
316
0
            disconnect_all_nodes(end_pos.get());
317
0
            changed = true;
318
0
        }
319
197
        else if (new_start_node->next != end_pos)
320
170
        {
321
            // Just link the new segment to this node.
322
170
            new_start_node->next = end_pos;
323
170
            end_pos->prev = new_start_node;
324
170
            changed = true;
325
170
        }
326
197
    }
327
1.00k
    else if (old_value == val)
328
3
    {
329
3
        if (new_start_node->next != end_pos)
330
0
        {
331
0
            st::detail::link_nodes<node_ptr>(new_start_node, end_pos);
332
0
            changed = true;
333
0
        }
334
3
    }
335
1.00k
    else
336
1.00k
    {
337
        // Insert a new node before the insertion position node.
338
1.00k
        node_ptr new_node(new node);
339
1.00k
        new_node->key = std::move(end_key);
340
1.00k
        new_node->value_leaf.value = std::move(old_value);
341
342
        // Link to the left node.
343
1.00k
        st::detail::link_nodes<node_ptr>(new_start_node, new_node);
344
345
        // Link to the right node.
346
1.00k
        st::detail::link_nodes<node_ptr>(new_node, end_pos);
347
1.00k
        changed = true;
348
1.00k
    }
349
350
1.20k
    if (changed)
351
1.19k
        m_valid_tree = false;
352
353
1.20k
    return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed);
354
1.20k
}
mdds::flat_segment_tree<unsigned int, bool>::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> >, unsigned int, unsigned int, bool)
Line
Count
Source
230
1.19k
{
231
1.19k
    node_ptr end_pos;
232
1.19k
    {
233
1.19k
        const node* p = get_insertion_pos_leaf(end_key, start_pos.get());
234
1.19k
        end_pos.reset(const_cast<node*>(p));
235
1.19k
    }
236
1.19k
    if (!end_pos)
237
0
        end_pos = m_right_leaf;
238
239
1.19k
    node_ptr new_start_node;
240
1.19k
    value_type old_value;
241
242
    // Set the start node.
243
244
1.19k
    bool changed = false;
245
246
1.19k
    if (start_pos->key == start_key)
247
294
    {
248
        // Re-use the existing node, but save the old value for later.
249
250
294
        if (start_pos->prev && start_pos->prev->value_leaf.value == val)
251
2
        {
252
            // Extend the existing segment.
253
2
            old_value = start_pos->value_leaf.value;
254
2
            new_start_node = start_pos->prev;
255
2
        }
256
292
        else
257
292
        {
258
            // Update the value of the existing node.
259
292
            old_value = start_pos->value_leaf.value;
260
292
            start_pos->value_leaf.value = val;
261
292
            new_start_node = std::move(start_pos);
262
263
292
            changed = (old_value != val);
264
292
        }
265
294
    }
266
902
    else if (start_pos->prev->value_leaf.value == val)
267
902
    {
268
        // Extend the existing segment.
269
902
        old_value = start_pos->prev->value_leaf.value;
270
902
        new_start_node = start_pos->prev;
271
902
    }
272
0
    else
273
0
    {
274
        // Insert a new node before the insertion position node.
275
0
        node_ptr new_node(new node);
276
0
        new_node->key = std::move(start_key);
277
0
        new_node->value_leaf.value = val;
278
0
        new_start_node = new_node;
279
280
0
        node_ptr left_node = start_pos->prev;
281
0
        old_value = left_node->value_leaf.value;
282
283
        // Link to the left node.
284
0
        st::detail::link_nodes<node_ptr>(left_node, new_node);
285
286
        // Link to the right node.
287
0
        st::detail::link_nodes<node_ptr>(new_node, start_pos);
288
0
        changed = true;
289
0
    }
290
291
1.19k
    node_ptr cur_node = new_start_node->next;
292
1.19k
    while (cur_node != end_pos)
293
2
    {
294
        // Disconnect the link between the current node and the previous node.
295
2
        cur_node->prev->next.reset();
296
2
        cur_node->prev.reset();
297
2
        old_value = cur_node->value_leaf.value;
298
299
2
        cur_node = cur_node->next;
300
2
        changed = true;
301
2
    }
302
303
    // Set the end node.
304
305
1.19k
    if (end_pos->key == end_key)
306
193
    {
307
        // The new segment ends exactly at the end node position.
308
309
193
        if (end_pos->next && end_pos->value_leaf.value == val)
310
0
        {
311
            // Remove this node, and connect the new start node with the
312
            // node that comes after this node.
313
0
            new_start_node->next = end_pos->next;
314
0
            if (end_pos->next)
315
0
                end_pos->next->prev = new_start_node;
316
0
            disconnect_all_nodes(end_pos.get());
317
0
            changed = true;
318
0
        }
319
193
        else if (new_start_node->next != end_pos)
320
0
        {
321
            // Just link the new segment to this node.
322
0
            new_start_node->next = end_pos;
323
0
            end_pos->prev = new_start_node;
324
0
            changed = true;
325
0
        }
326
193
    }
327
1.00k
    else if (old_value == val)
328
1.00k
    {
329
1.00k
        if (new_start_node->next != end_pos)
330
0
        {
331
0
            st::detail::link_nodes<node_ptr>(new_start_node, end_pos);
332
0
            changed = true;
333
0
        }
334
1.00k
    }
335
3
    else
336
3
    {
337
        // Insert a new node before the insertion position node.
338
3
        node_ptr new_node(new node);
339
3
        new_node->key = std::move(end_key);
340
3
        new_node->value_leaf.value = std::move(old_value);
341
342
        // Link to the left node.
343
3
        st::detail::link_nodes<node_ptr>(new_start_node, new_node);
344
345
        // Link to the right node.
346
3
        st::detail::link_nodes<node_ptr>(new_node, end_pos);
347
3
        changed = true;
348
3
    }
349
350
1.19k
    if (changed)
351
3
        m_valid_tree = false;
352
353
1.19k
    return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed);
354
1.19k
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> >, unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>)
Line
Count
Source
230
290
{
231
290
    node_ptr end_pos;
232
290
    {
233
290
        const node* p = get_insertion_pos_leaf(end_key, start_pos.get());
234
290
        end_pos.reset(const_cast<node*>(p));
235
290
    }
236
290
    if (!end_pos)
237
0
        end_pos = m_right_leaf;
238
239
290
    node_ptr new_start_node;
240
290
    value_type old_value;
241
242
    // Set the start node.
243
244
290
    bool changed = false;
245
246
290
    if (start_pos->key == start_key)
247
2
    {
248
        // Re-use the existing node, but save the old value for later.
249
250
2
        if (start_pos->prev && start_pos->prev->value_leaf.value == val)
251
0
        {
252
            // Extend the existing segment.
253
0
            old_value = start_pos->value_leaf.value;
254
0
            new_start_node = start_pos->prev;
255
0
        }
256
2
        else
257
2
        {
258
            // Update the value of the existing node.
259
2
            old_value = start_pos->value_leaf.value;
260
2
            start_pos->value_leaf.value = val;
261
2
            new_start_node = std::move(start_pos);
262
263
2
            changed = (old_value != val);
264
2
        }
265
2
    }
266
288
    else if (start_pos->prev->value_leaf.value == val)
267
0
    {
268
        // Extend the existing segment.
269
0
        old_value = start_pos->prev->value_leaf.value;
270
0
        new_start_node = start_pos->prev;
271
0
    }
272
288
    else
273
288
    {
274
        // Insert a new node before the insertion position node.
275
288
        node_ptr new_node(new node);
276
288
        new_node->key = std::move(start_key);
277
288
        new_node->value_leaf.value = val;
278
288
        new_start_node = new_node;
279
280
288
        node_ptr left_node = start_pos->prev;
281
288
        old_value = left_node->value_leaf.value;
282
283
        // Link to the left node.
284
288
        st::detail::link_nodes<node_ptr>(left_node, new_node);
285
286
        // Link to the right node.
287
288
        st::detail::link_nodes<node_ptr>(new_node, start_pos);
288
288
        changed = true;
289
288
    }
290
291
290
    node_ptr cur_node = new_start_node->next;
292
290
    while (cur_node != end_pos)
293
0
    {
294
        // Disconnect the link between the current node and the previous node.
295
0
        cur_node->prev->next.reset();
296
0
        cur_node->prev.reset();
297
0
        old_value = cur_node->value_leaf.value;
298
299
0
        cur_node = cur_node->next;
300
0
        changed = true;
301
0
    }
302
303
    // Set the end node.
304
305
290
    if (end_pos->key == end_key)
306
2
    {
307
        // The new segment ends exactly at the end node position.
308
309
2
        if (end_pos->next && end_pos->value_leaf.value == val)
310
0
        {
311
            // Remove this node, and connect the new start node with the
312
            // node that comes after this node.
313
0
            new_start_node->next = end_pos->next;
314
0
            if (end_pos->next)
315
0
                end_pos->next->prev = new_start_node;
316
0
            disconnect_all_nodes(end_pos.get());
317
0
            changed = true;
318
0
        }
319
2
        else if (new_start_node->next != end_pos)
320
0
        {
321
            // Just link the new segment to this node.
322
0
            new_start_node->next = end_pos;
323
0
            end_pos->prev = new_start_node;
324
0
            changed = true;
325
0
        }
326
2
    }
327
288
    else if (old_value == val)
328
0
    {
329
0
        if (new_start_node->next != end_pos)
330
0
        {
331
0
            st::detail::link_nodes<node_ptr>(new_start_node, end_pos);
332
0
            changed = true;
333
0
        }
334
0
    }
335
288
    else
336
288
    {
337
        // Insert a new node before the insertion position node.
338
288
        node_ptr new_node(new node);
339
288
        new_node->key = std::move(end_key);
340
288
        new_node->value_leaf.value = std::move(old_value);
341
342
        // Link to the left node.
343
288
        st::detail::link_nodes<node_ptr>(new_start_node, new_node);
344
345
        // Link to the right node.
346
288
        st::detail::link_nodes<node_ptr>(new_node, end_pos);
347
288
        changed = true;
348
288
    }
349
350
290
    if (changed)
351
290
        m_valid_tree = false;
352
353
290
    return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed);
354
290
}
355
356
template<typename Key, typename Value>
357
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::insert(
358
    const_iterator pos, key_type start_key, key_type end_key, value_type val)
359
{
360
    const node* p = pos.get_pos();
361
    if (!p || this != pos.get_parent())
362
    {
363
        // Switch to normal insert.
364
        return insert_front(start_key, end_key, val);
365
    }
366
367
    assert(p->is_leaf);
368
369
    if (start_key < p->key)
370
    {
371
        // Specified position is already past the start key position.  Not good.
372
        return insert_front(start_key, end_key, val);
373
    }
374
375
    if (!adjust_segment_range(start_key, end_key))
376
    {
377
        typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type;
378
        return ret_type(const_iterator(this, true), false);
379
    }
380
381
    p = get_insertion_pos_leaf(start_key, p);
382
    node_ptr start_pos(const_cast<node*>(p));
383
    return insert_to_pos(std::move(start_pos), start_key, end_key, std::move(val));
384
}
385
386
template<typename Key, typename Value>
387
void flat_segment_tree<Key, Value>::shift_left(key_type start_key, key_type end_key)
388
{
389
    if (start_key >= end_key)
390
        return;
391
392
    key_type left_leaf_key = m_left_leaf->key;
393
    key_type right_leaf_key = m_right_leaf->key;
394
    if (start_key < left_leaf_key || end_key < left_leaf_key)
395
        // invalid key value
396
        return;
397
398
    if (start_key > right_leaf_key || end_key > right_leaf_key)
399
        // invalid key value.
400
        return;
401
402
    node_ptr node_pos;
403
    if (left_leaf_key == start_key)
404
        node_pos = m_left_leaf;
405
    else
406
    {
407
        // Get the first node with a key value equal to or greater than the
408
        // start key value.  But we want to skip the leftmost node.
409
        const node* p = get_insertion_pos_leaf(start_key, m_left_leaf->next.get());
410
        node_pos.reset(const_cast<node*>(p));
411
    }
412
413
    if (!node_pos)
414
        return;
415
416
    key_type segment_size = end_key - start_key;
417
418
    if (node_pos == m_right_leaf)
419
    {
420
        // The segment being removed begins after the last node before the
421
        // right-most node.
422
423
        if (right_leaf_key <= end_key)
424
        {
425
            // The end position equals or is past the right-most node.
426
            append_new_segment(start_key);
427
        }
428
        else
429
        {
430
            // The end position stops before the right-most node.  Simply
431
            // append the blank segment to the end.
432
            append_new_segment(right_leaf_key - segment_size);
433
        }
434
        return;
435
    }
436
437
    if (end_key < node_pos->key)
438
    {
439
        // The removed segment does not overlap with any nodes.  Simply
440
        // shift the key values of those nodes that come after the removed
441
        // segment.
442
        shift_leaf_key_left(node_pos, m_right_leaf, segment_size);
443
        append_new_segment(right_leaf_key - segment_size);
444
        m_valid_tree = false;
445
        return;
446
    }
447
448
    // Move the first node to the starting position, and from there search
449
    // for the first node whose key value is greater than the end value.
450
    node_pos->key = start_key;
451
    node_ptr start_pos = node_pos;
452
    node_pos = node_pos->next;
453
    value_type last_seg_value = start_pos->value_leaf.value;
454
    while (node_pos.get() != m_right_leaf.get() && node_pos->key <= end_key)
455
    {
456
        last_seg_value = node_pos->value_leaf.value;
457
        node_ptr next = node_pos->next;
458
        disconnect_all_nodes(node_pos.get());
459
        node_pos = std::move(next);
460
    }
461
462
    start_pos->value_leaf.value = last_seg_value;
463
    start_pos->next = node_pos;
464
    node_pos->prev = start_pos;
465
    if (start_pos->prev && start_pos->prev->value_leaf.value == start_pos->value_leaf.value)
466
    {
467
        // Removing a segment resulted in two consecutive segments with
468
        // identical value. Combine them by removing the 2nd redundant
469
        // node.
470
        start_pos->prev->next = start_pos->next;
471
        start_pos->next->prev = start_pos->prev;
472
        disconnect_all_nodes(start_pos.get());
473
    }
474
475
    shift_leaf_key_left(node_pos, m_right_leaf, segment_size);
476
    m_valid_tree = false;
477
478
    // Insert at the end a new segment with the initial base value, for
479
    // the length of the removed segment.
480
    append_new_segment(right_leaf_key - segment_size);
481
}
482
483
template<typename Key, typename Value>
484
void flat_segment_tree<Key, Value>::shift_right(key_type pos, key_type size, bool skip_start_node)
485
{
486
    if (size <= 0)
487
        return;
488
489
    if (pos < m_left_leaf->key || m_right_leaf->key <= pos)
490
        // specified position is out-of-bound
491
        return;
492
493
    if (m_left_leaf->key == pos)
494
    {
495
        // Position is at the leftmost node.  Shift all the other nodes,
496
        // and insert a new node at (pos + size) position.
497
        node_ptr cur_node = m_left_leaf->next;
498
        shift_leaf_key_right(cur_node, m_right_leaf, size);
499
500
        if (m_left_leaf->value_leaf.value != m_init_val && !skip_start_node)
501
        {
502
            if (size < m_right_leaf->key - m_left_leaf->key)
503
            {
504
                // The leftmost leaf node has a non-initial value.  We need to
505
                // insert a new node to carry that value after the shift.
506
                node_ptr new_node(new node);
507
                new_node->key = pos + size;
508
                new_node->value_leaf.value = m_left_leaf->value_leaf.value;
509
                m_left_leaf->value_leaf.value = m_init_val;
510
                new_node->prev = m_left_leaf;
511
                new_node->next = m_left_leaf->next;
512
                m_left_leaf->next->prev = new_node;
513
                m_left_leaf->next = std::move(new_node);
514
            }
515
            else
516
            {
517
                // We shifted out the whole range, so there would be no new
518
                // node inserted. Just set default value.
519
                m_left_leaf->value_leaf.value = m_init_val;
520
            }
521
        }
522
523
        m_valid_tree = false;
524
        return;
525
    }
526
527
    // Get the first node with a key value equal to or greater than the
528
    // start key value.  But we want to skip the leftmost node.
529
    const node* p = get_insertion_pos_leaf(pos, m_left_leaf->next.get());
530
    node_ptr cur_node(const_cast<node*>(p));
531
532
    // If the point of insertion is at an existing node position, don't
533
    // shift that node but start with the one after it if that's
534
    // requested.
535
    if (skip_start_node && cur_node && cur_node->key == pos)
536
        cur_node = cur_node->next;
537
538
    if (!cur_node)
539
        return;
540
541
    shift_leaf_key_right(cur_node, m_right_leaf, size);
542
    m_valid_tree = false;
543
}
544
545
template<typename Key, typename Value>
546
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search_impl(
547
    const node* pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const
548
{
549
    typedef ::std::pair<const_iterator, bool> ret_type;
550
551
    if (pos->key == key)
552
    {
553
        value = pos->value_leaf.value;
554
        if (start_key)
555
            *start_key = pos->key;
556
        if (end_key && pos->next)
557
            *end_key = pos->next->key;
558
        return ret_type(const_iterator(this, pos), true);
559
    }
560
    else if (pos->prev && pos->prev->key < key)
561
    {
562
        value = pos->prev->value_leaf.value;
563
        if (start_key)
564
            *start_key = pos->prev->key;
565
        if (end_key)
566
            *end_key = pos->key;
567
        return ret_type(const_iterator(this, pos->prev.get()), true);
568
    }
569
570
    return ret_type(const_iterator(this, true), false);
571
}
572
573
template<typename Key, typename Value>
574
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search(
575
    key_type key, value_type& value, key_type* start_key, key_type* end_key) const
576
{
577
    typedef ::std::pair<const_iterator, bool> ret_type;
578
579
    if (key < m_left_leaf->key || m_right_leaf->key <= key)
580
        // key value is out-of-bound.
581
        return ret_type(const_iterator(this, true), false);
582
583
    const node* pos = get_insertion_pos_leaf(key, m_left_leaf.get());
584
    return search_impl(pos, key, value, start_key, end_key);
585
}
586
587
template<typename Key, typename Value>
588
::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search(
589
    const_iterator pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const
590
{
591
    typedef ::std::pair<const_iterator, bool> ret_type;
592
593
    if (key < m_left_leaf->key || m_right_leaf->key <= key)
594
        // key value is out-of-bound.
595
        return ret_type(const_iterator(this, true), false);
596
597
    const node* p = pos.get_pos();
598
    if (!p || this != pos.get_parent())
599
    {
600
        // Switch to normal search.
601
        return search(key, value, start_key, end_key);
602
    }
603
604
    assert(p->is_leaf);
605
606
    if (key < p->key)
607
    {
608
        // Specified position is already past the start key position.  Fall
609
        // back to normal search.
610
        return search(key, value, start_key, end_key);
611
    }
612
613
    p = get_insertion_pos_leaf(key, p);
614
    return search_impl(p, key, value, start_key, end_key);
615
}
616
617
template<typename Key, typename Value>
618
typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search(key_type key) const
619
{
620
    return search_by_key_impl(m_left_leaf.get(), key);
621
}
622
623
template<typename Key, typename Value>
624
typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search(
625
    const_iterator pos, key_type key) const
626
{
627
    return search_by_key_impl(pos.get_pos(), key);
628
}
629
630
template<typename Key, typename Value>
631
typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search_by_key_impl(
632
    const node* start_pos, key_type key) const
633
{
634
    if (key < m_left_leaf->key || m_right_leaf->key <= key)
635
        // key value is out-of-bound.
636
        return const_iterator(this, true);
637
638
    const node* pos = get_insertion_pos_leaf(key, start_pos);
639
    if (!pos)
640
        return const_iterator(this, true);
641
642
    if (pos->key == key)
643
        return const_iterator(this, pos);
644
    else if (pos->prev && pos->prev->key < key)
645
        return const_iterator(this, pos->prev.get());
646
647
    return const_iterator(this, true);
648
}
649
650
template<typename Key, typename Value>
651
std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search_tree(
652
    key_type key, value_type& value, key_type* start_key, key_type* end_key) const
653
1.79k
{
654
1.79k
    using ret_type = std::pair<const_iterator, bool>;
655
656
1.79k
    const node* dest_node = search_tree_for_leaf_node(key);
657
1.79k
    if (!dest_node)
658
0
        return ret_type(const_iterator(this, true), false);
659
660
1.79k
    value = dest_node->value_leaf.value;
661
1.79k
    if (start_key)
662
0
        *start_key = dest_node->key;
663
664
1.79k
    if (end_key)
665
0
    {
666
0
        assert(dest_node->next);
667
0
        if (dest_node->next)
668
0
            *end_key = dest_node->next->key;
669
0
        else
670
            // This should never happen, but just in case....
671
0
            *end_key = m_right_leaf->key;
672
0
    }
673
674
1.79k
    return ret_type(const_iterator(this, dest_node), true);
675
1.79k
}
676
677
template<typename Key, typename Value>
678
typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search_tree(key_type key) const
679
{
680
    const node* dest_node = search_tree_for_leaf_node(key);
681
    if (!dest_node)
682
        return const_iterator(this, true);
683
684
    return const_iterator(this, dest_node);
685
}
686
687
template<typename Key, typename Value>
688
const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::search_tree_for_leaf_node(
689
    key_type key) const
690
1.79k
{
691
1.79k
    if (!m_root_node || !m_valid_tree)
692
0
    {
693
        // either tree has not been built, or is in an invalid state.
694
0
        return nullptr;
695
0
    }
696
697
1.79k
    if (key < m_left_leaf->key || m_right_leaf->key <= key)
698
0
    {
699
        // key value is out-of-bound.
700
0
        return nullptr;
701
0
    }
702
703
    // Descend down the tree through the last non-leaf layer.
704
705
1.79k
    const nonleaf_node* cur_node = m_root_node;
706
3.56k
    while (true)
707
3.56k
    {
708
3.56k
        if (cur_node->left)
709
3.56k
        {
710
3.56k
            if (cur_node->left->is_leaf)
711
1.79k
                break;
712
713
1.77k
            const nonleaf_node* left_nonleaf = static_cast<const nonleaf_node*>(cur_node->left);
714
1.77k
            if (left_nonleaf->low <= key && key < left_nonleaf->high)
715
809
            {
716
                // Descend one level through the left child node.
717
809
                cur_node = left_nonleaf;
718
809
                continue;
719
809
            }
720
1.77k
        }
721
0
        else
722
0
        {
723
            // left child node can't be missing !
724
0
            return nullptr;
725
0
        }
726
727
962
        if (cur_node->right)
728
962
        {
729
962
            assert(!cur_node->right->is_leaf);
730
962
            const nonleaf_node* right_nonleaf = static_cast<const nonleaf_node*>(cur_node->right);
731
962
            if (right_nonleaf->low <= key && key < right_nonleaf->high)
732
962
            {
733
                // Descend one level through the right child node.
734
962
                cur_node = right_nonleaf;
735
962
                continue;
736
962
            }
737
962
        }
738
0
        return nullptr;
739
962
    }
740
741
    // Current node must be a non-leaf whose child nodes are leaf nodes.
742
1.79k
    assert(cur_node->left->is_leaf && cur_node->right->is_leaf);
743
744
1.79k
    const node* dest_node = nullptr;
745
1.79k
    const node* leaf_left = static_cast<const node*>(cur_node->left);
746
1.79k
    const node* leaf_right = static_cast<const node*>(cur_node->right);
747
1.79k
    key_type key1 = leaf_left->key;
748
1.79k
    key_type key2 = leaf_right->key;
749
750
1.79k
    if (key1 <= key && key < key2)
751
1.52k
    {
752
1.52k
        dest_node = leaf_left;
753
1.52k
    }
754
272
    else if (key2 <= key && key < cur_node->high)
755
272
    {
756
272
        dest_node = leaf_right;
757
272
    }
758
759
1.79k
    if (!dest_node)
760
0
        return nullptr;
761
762
1.79k
    return dest_node;
763
1.79k
}
764
765
template<typename Key, typename Value>
766
void flat_segment_tree<Key, Value>::build_tree()
767
270
{
768
270
    if (!m_left_leaf)
769
0
        return;
770
771
270
    m_nonleaf_node_pool.clear();
772
773
    // Count the number of leaf nodes.
774
270
    size_t leaf_count = leaf_size();
775
776
    // Determine the total number of non-leaf nodes needed to build the whole tree.
777
270
    size_t nonleaf_count = st::detail::count_needed_nonleaf_nodes(leaf_count);
778
779
270
    m_nonleaf_node_pool.resize(nonleaf_count);
780
270
    mdds::st::detail::tree_builder<flat_segment_tree> builder(m_nonleaf_node_pool);
781
270
    m_root_node = builder.build(m_left_leaf);
782
270
    m_valid_tree = true;
783
270
}
784
785
template<typename Key, typename Value>
786
typename flat_segment_tree<Key, Value>::size_type flat_segment_tree<Key, Value>::leaf_size() const
787
270
{
788
270
    return st::detail::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get());
789
270
}
790
791
template<typename Key, typename Value>
792
bool flat_segment_tree<Key, Value>::operator==(const flat_segment_tree& other) const
793
{
794
    const node* n1 = m_left_leaf.get();
795
    const node* n2 = other.m_left_leaf.get();
796
797
    if ((!n1 && n2) || (n1 && !n2))
798
        // Either one of them is nullptr;
799
        return false;
800
801
    while (n1)
802
    {
803
        if (!n2)
804
            return false;
805
806
        if (n1->key != n2->key)
807
            return false;
808
809
        if (n1->value_leaf != n2->value_leaf)
810
            return false;
811
812
        n1 = n1->next.get();
813
        n2 = n2->next.get();
814
    }
815
816
    if (n2)
817
        // n1 is nullptr, but n2 is not.
818
        return false;
819
820
    // All leaf nodes are equal.
821
    return true;
822
}
823
824
template<typename Key, typename Value>
825
const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::get_insertion_pos_leaf_reverse(
826
    const key_type& key, const node* start_pos) const
827
2.68k
{
828
2.68k
    const node* cur_node = start_pos;
829
6.87k
    while (cur_node)
830
6.28k
    {
831
6.28k
        if (cur_node->key < key)
832
2.10k
        {
833
            // Found the insertion position.
834
2.10k
            return cur_node;
835
2.10k
        }
836
4.18k
        cur_node = cur_node->prev.get();
837
4.18k
    }
838
587
    return nullptr;
839
2.68k
}
mdds::flat_segment_tree<unsigned int, float>::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> const*) const
Line
Count
Source
827
1.20k
{
828
1.20k
    const node* cur_node = start_pos;
829
3.60k
    while (cur_node)
830
3.30k
    {
831
3.30k
        if (cur_node->key < key)
832
907
        {
833
            // Found the insertion position.
834
907
            return cur_node;
835
907
        }
836
2.40k
        cur_node = cur_node->prev.get();
837
2.40k
    }
838
296
    return nullptr;
839
1.20k
}
mdds::flat_segment_tree<unsigned int, bool>::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> const*) const
Line
Count
Source
827
1.19k
{
828
1.19k
    const node* cur_node = start_pos;
829
2.68k
    while (cur_node)
830
2.39k
    {
831
2.39k
        if (cur_node->key < key)
832
905
        {
833
            // Found the insertion position.
834
905
            return cur_node;
835
905
        }
836
1.49k
        cur_node = cur_node->prev.get();
837
1.49k
    }
838
291
    return nullptr;
839
1.19k
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> const*) const
Line
Count
Source
827
290
{
828
290
    const node* cur_node = start_pos;
829
584
    while (cur_node)
830
584
    {
831
584
        if (cur_node->key < key)
832
290
        {
833
            // Found the insertion position.
834
290
            return cur_node;
835
290
        }
836
294
        cur_node = cur_node->prev.get();
837
294
    }
838
0
    return nullptr;
839
290
}
840
841
template<typename Key, typename Value>
842
const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::get_insertion_pos_leaf(
843
    const key_type& key, const node* start_pos) const
844
2.68k
{
845
2.68k
    assert(m_left_leaf->key <= key);
846
847
2.68k
    const node* cur_node = start_pos;
848
4.17k
    while (cur_node)
849
4.17k
    {
850
4.17k
        if (key <= cur_node->key)
851
2.68k
        {
852
            // Found the insertion position.
853
2.68k
            return cur_node;
854
2.68k
        }
855
1.48k
        cur_node = cur_node->next.get();
856
1.48k
    }
857
0
    return nullptr;
858
2.68k
}
mdds::flat_segment_tree<unsigned int, float>::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> const*) const
Line
Count
Source
844
1.20k
{
845
1.20k
    assert(m_left_leaf->key <= key);
846
847
1.20k
    const node* cur_node = start_pos;
848
2.39k
    while (cur_node)
849
2.39k
    {
850
2.39k
        if (key <= cur_node->key)
851
1.20k
        {
852
            // Found the insertion position.
853
1.20k
            return cur_node;
854
1.20k
        }
855
1.19k
        cur_node = cur_node->next.get();
856
1.19k
    }
857
0
    return nullptr;
858
1.20k
}
mdds::flat_segment_tree<unsigned int, bool>::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> const*) const
Line
Count
Source
844
1.19k
{
845
1.19k
    assert(m_left_leaf->key <= key);
846
847
1.19k
    const node* cur_node = start_pos;
848
1.49k
    while (cur_node)
849
1.49k
    {
850
1.49k
        if (key <= cur_node->key)
851
1.19k
        {
852
            // Found the insertion position.
853
1.19k
            return cur_node;
854
1.19k
        }
855
294
        cur_node = cur_node->next.get();
856
294
    }
857
0
    return nullptr;
858
1.19k
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> const*) const
Line
Count
Source
844
290
{
845
290
    assert(m_left_leaf->key <= key);
846
847
290
    const node* cur_node = start_pos;
848
292
    while (cur_node)
849
292
    {
850
292
        if (key <= cur_node->key)
851
290
        {
852
            // Found the insertion position.
853
290
            return cur_node;
854
290
        }
855
2
        cur_node = cur_node->next.get();
856
2
    }
857
0
    return nullptr;
858
290
}
859
860
template<typename Key, typename Value>
861
void flat_segment_tree<Key, Value>::destroy()
862
1.96k
{
863
1.96k
    disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get());
864
1.96k
    m_nonleaf_node_pool.clear();
865
1.96k
    m_root_node = nullptr;
866
1.96k
}
mdds::flat_segment_tree<unsigned int, bool>::destroy()
Line
Count
Source
862
390
{
863
390
    disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get());
864
390
    m_nonleaf_node_pool.clear();
865
390
    m_root_node = nullptr;
866
390
}
mdds::flat_segment_tree<unsigned int, float>::destroy()
Line
Count
Source
862
390
{
863
390
    disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get());
864
390
    m_nonleaf_node_pool.clear();
865
390
    m_root_node = nullptr;
866
390
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::destroy()
Line
Count
Source
862
1.18k
{
863
1.18k
    disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get());
864
1.18k
    m_nonleaf_node_pool.clear();
865
1.18k
    m_root_node = nullptr;
866
1.18k
}
867
868
template<typename Key, typename Value>
869
bool flat_segment_tree<Key, Value>::adjust_segment_range(key_type& start_key, key_type& end_key) const
870
2.69k
{
871
2.69k
    if (end_key <= start_key)
872
        // Invalid order of segment range.
873
0
        return false;
874
875
2.69k
    if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key)
876
        // The new segment does not overlap the current interval.
877
1
        return false;
878
879
2.68k
    if (start_key < m_left_leaf->key)
880
        // The start value should not be smaller than the current minimum.
881
0
        start_key = m_left_leaf->key;
882
883
2.68k
    if (m_right_leaf->key < end_key)
884
        // The end value should not be larger than the current maximum.
885
0
        end_key = m_right_leaf->key;
886
887
2.68k
    return true;
888
2.69k
}
mdds::flat_segment_tree<unsigned int, float>::adjust_segment_range(unsigned int&, unsigned int&) const
Line
Count
Source
870
1.20k
{
871
1.20k
    if (end_key <= start_key)
872
        // Invalid order of segment range.
873
0
        return false;
874
875
1.20k
    if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key)
876
        // The new segment does not overlap the current interval.
877
0
        return false;
878
879
1.20k
    if (start_key < m_left_leaf->key)
880
        // The start value should not be smaller than the current minimum.
881
0
        start_key = m_left_leaf->key;
882
883
1.20k
    if (m_right_leaf->key < end_key)
884
        // The end value should not be larger than the current maximum.
885
0
        end_key = m_right_leaf->key;
886
887
1.20k
    return true;
888
1.20k
}
mdds::flat_segment_tree<unsigned int, bool>::adjust_segment_range(unsigned int&, unsigned int&) const
Line
Count
Source
870
1.19k
{
871
1.19k
    if (end_key <= start_key)
872
        // Invalid order of segment range.
873
0
        return false;
874
875
1.19k
    if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key)
876
        // The new segment does not overlap the current interval.
877
0
        return false;
878
879
1.19k
    if (start_key < m_left_leaf->key)
880
        // The start value should not be smaller than the current minimum.
881
0
        start_key = m_left_leaf->key;
882
883
1.19k
    if (m_right_leaf->key < end_key)
884
        // The end value should not be larger than the current maximum.
885
0
        end_key = m_right_leaf->key;
886
887
1.19k
    return true;
888
1.19k
}
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::adjust_segment_range(unsigned int&, unsigned int&) const
Line
Count
Source
870
291
{
871
291
    if (end_key <= start_key)
872
        // Invalid order of segment range.
873
0
        return false;
874
875
291
    if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key)
876
        // The new segment does not overlap the current interval.
877
1
        return false;
878
879
290
    if (start_key < m_left_leaf->key)
880
        // The start value should not be smaller than the current minimum.
881
0
        start_key = m_left_leaf->key;
882
883
290
    if (m_right_leaf->key < end_key)
884
        // The end value should not be larger than the current maximum.
885
0
        end_key = m_right_leaf->key;
886
887
290
    return true;
888
291
}
889
890
} // namespace mdds