Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(764)

Side by Side Diff: content/browser/indexed_db/leveldb/avltree.h

Issue 15659013: Revert "Migrate the IndexedDB backend from Blink to Chromium" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /*
6 * Copyright (C) 2008 Apple Inc. All rights reserved.
7 *
8 * Based on Abstract AVL Tree Template v1.5 by Walt Karas
9 * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
21 * its contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
25 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
37 #define CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
38
39 #include "base/logging.h"
40 #include "content/browser/indexed_db/leveldb/fixed_array.h"
41
42 namespace content {
43
44 // Here is the reference class for BSet.
45 //
46 // class BSet
47 // {
48 // public:
49 //
50 // class ANY_bitref
51 // {
52 // public:
53 // operator bool ();
54 // void operator = (bool b);
55 // };
56 //
57 // // Does not have to initialize bits.
58 // BSet();
59 //
60 // // Must return a valid value for index when 0 <= index < maxDepth
61 // ANY_bitref operator [] (unsigned index);
62 //
63 // // Set all bits to 1.
64 // void set();
65 //
66 // // Set all bits to 0.
67 // void reset();
68 // };
69
70 template <unsigned maxDepth> class AVLTreeDefaultBSet {
71 public:
72 bool& operator[](unsigned i) {
73 #if defined(ADDRESS_SANITIZER)
74 CHECK(i < maxDepth);
75 #endif
76 return m_data[i];
77 }
78 void set() {
79 for (unsigned i = 0; i < maxDepth; ++i)
80 m_data[i] = true;
81 }
82 void reset() {
83 for (unsigned i = 0; i < maxDepth; ++i)
84 m_data[i] = false;
85 }
86
87 private:
88 FixedArray<bool, maxDepth> m_data;
89 };
90
91 // How to determine maxDepth:
92 // d Minimum number of nodes
93 // 2 2
94 // 3 4
95 // 4 7
96 // 5 12
97 // 6 20
98 // 7 33
99 // 8 54
100 // 9 88
101 // 10 143
102 // 11 232
103 // 12 376
104 // 13 609
105 // 14 986
106 // 15 1,596
107 // 16 2,583
108 // 17 4,180
109 // 18 6,764
110 // 19 10,945
111 // 20 17,710
112 // 21 28,656
113 // 22 46,367
114 // 23 75,024
115 // 24 121,392
116 // 25 196,417
117 // 26 317,810
118 // 27 514,228
119 // 28 832,039
120 // 29 1,346,268
121 // 30 2,178,308
122 // 31 3,524,577
123 // 32 5,702,886
124 // 33 9,227,464
125 // 34 14,930,351
126 // 35 24,157,816
127 // 36 39,088,168
128 // 37 63,245,985
129 // 38 102,334,154
130 // 39 165,580,140
131 // 40 267,914,295
132 // 41 433,494,436
133 // 42 701,408,732
134 // 43 1,134,903,169
135 // 44 1,836,311,902
136 // 45 2,971,215,072
137 //
138 // E.g., if, in a particular instantiation, the maximum number of nodes in a
139 // tree instance is 1,000,000, the maximum depth should be 28.
140 // You pick 28 because MN(28) is 832,039, which is less than or equal to
141 // 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
142
143 template <class Abstractor,
144 unsigned maxDepth = 32,
145 class BSet = AVLTreeDefaultBSet<maxDepth> >
146 class AVLTree {
147 public:
148 typedef typename Abstractor::key key;
149 typedef typename Abstractor::handle handle;
150 typedef typename Abstractor::size size;
151
152 enum SearchType {
153 EQUAL = 1,
154 LESS = 2,
155 GREATER = 4,
156 LESS_EQUAL = EQUAL | LESS,
157 GREATER_EQUAL = EQUAL | GREATER
158 };
159
160 Abstractor& abstractor() { return abs; }
161
162 inline handle insert(handle h);
163
164 inline handle search(key k, SearchType st = EQUAL);
165 inline handle search_least();
166 inline handle search_greatest();
167
168 inline handle remove(key k);
169
170 inline handle subst(handle new_node);
171
172 void purge() { abs.root = null(); }
173
174 bool is_empty() { return abs.root == null(); }
175
176 AVLTree() { abs.root = null(); }
177
178 class Iterator {
179 public:
180 // Initialize depth to invalid value, to indicate iterator is
181 // invalid. (Depth is zero-base.)
182 Iterator() { depth = ~0U; }
183
184 void start_iter(AVLTree& tree, key k, SearchType st = EQUAL) {
185 // Mask of high bit in an int.
186 const int kMaskHighBit = (int) ~((~(unsigned) 0) >> 1);
187
188 // Save the tree that we're going to iterate through in a
189 // member variable.
190 tree_ = &tree;
191
192 int cmp, target_cmp;
193 handle h = tree_->abs.root;
194 unsigned d = 0;
195
196 depth = ~0U;
197
198 if (h == null()) {
199 // Tree is empty.
200 return;
201 }
202
203 if (st & LESS) {
204 // Key can be greater than key of starting node.
205 target_cmp = 1;
206 } else if (st & GREATER) {
207 // Key can be less than key of starting node.
208 target_cmp = -1;
209 } else {
210 // Key must be same as key of starting node.
211 target_cmp = 0;
212 }
213
214 for (;;) {
215 cmp = cmp_k_n(k, h);
216 if (cmp == 0) {
217 if (st & EQUAL) {
218 // Equal node was sought and found as starting node.
219 depth = d;
220 break;
221 }
222 cmp = -target_cmp;
223 } else if (target_cmp != 0) {
224 if (!((cmp ^ target_cmp) & kMaskHighBit)) {
225 // cmp and target_cmp are both negative or both positive.
226 depth = d;
227 }
228 }
229 h = cmp < 0 ? get_lt(h) : get_gt(h);
230 if (h == null())
231 break;
232 branch[d] = cmp > 0;
233 path_h[d++] = h;
234 }
235 }
236
237 void start_iter_least(AVLTree& tree) {
238 tree_ = &tree;
239
240 handle h = tree_->abs.root;
241
242 depth = ~0U;
243
244 branch.reset();
245
246 while (h != null()) {
247 if (depth != ~0U)
248 path_h[depth] = h;
249 depth++;
250 h = get_lt(h);
251 }
252 }
253
254 void start_iter_greatest(AVLTree& tree) {
255 tree_ = &tree;
256
257 handle h = tree_->abs.root;
258
259 depth = ~0U;
260
261 branch.set();
262
263 while (h != null()) {
264 if (depth != ~0U)
265 path_h[depth] = h;
266 depth++;
267 h = get_gt(h);
268 }
269 }
270
271 handle operator*() {
272 if (depth == ~0U)
273 return null();
274
275 return depth == 0 ? tree_->abs.root : path_h[depth - 1];
276 }
277
278 void operator++() {
279 if (depth != ~0U) {
280 handle h = get_gt(**this);
281 if (h == null()) {
282 do {
283 if (depth == 0) {
284 depth = ~0U;
285 break;
286 }
287 depth--;
288 } while (branch[depth]);
289 } else {
290 branch[depth] = true;
291 path_h[depth++] = h;
292 for (;;) {
293 h = get_lt(h);
294 if (h == null())
295 break;
296 branch[depth] = false;
297 path_h[depth++] = h;
298 }
299 }
300 }
301 }
302
303 void operator--() {
304 if (depth != ~0U) {
305 handle h = get_lt(**this);
306 if (h == null()) {
307 do {
308 if (depth == 0) {
309 depth = ~0U;
310 break;
311 }
312 depth--;
313 } while (!branch[depth]);
314 } else {
315 branch[depth] = false;
316 path_h[depth++] = h;
317 for (;;) {
318 h = get_gt(h);
319 if (h == null())
320 break;
321 branch[depth] = true;
322 path_h[depth++] = h;
323 }
324 }
325 }
326 }
327
328 void operator++(int) { ++(*this); }
329 void operator--(int) { --(*this); }
330
331 protected:
332
333 // Tree being iterated over.
334 AVLTree* tree_;
335
336 // Records a path into the tree. If branch[n] is true, indicates
337 // take greater branch from the nth node in the path, otherwise
338 // take the less branch. branch[0] gives branch from root, and
339 // so on.
340 BSet branch;
341
342 // Zero-based depth of path into tree.
343 unsigned depth;
344
345 // Handles of nodes in path from root to current node (returned by *).
346 handle path_h[maxDepth - 1];
347
348 int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
349 int cmp_n_n(handle h1, handle h2) {
350 return tree_->abs.compare_node_node(h1, h2);
351 }
352 handle get_lt(handle h) { return tree_->abs.get_less(h); }
353 handle get_gt(handle h) { return tree_->abs.get_greater(h); }
354 handle null() { return tree_->abs.null(); }
355 };
356
357 template <typename fwd_iter> bool build(fwd_iter p, size num_nodes) {
358 if (num_nodes == 0) {
359 abs.root = null();
360 return true;
361 }
362
363 // Gives path to subtree being built. If branch[N] is false, branch
364 // less from the node at depth N, if true branch greater.
365 BSet branch;
366
367 // If rem[N] is true, then for the current subtree at depth N, it's
368 // greater subtree has one more node than it's less subtree.
369 BSet rem;
370
371 // Depth of root node of current subtree.
372 unsigned depth = 0;
373
374 // Number of nodes in current subtree.
375 size num_sub = num_nodes;
376
377 // The algorithm relies on a stack of nodes whose less subtree has
378 // been built, but whose right subtree has not yet been built. The
379 // stack is implemented as linked list. The nodes are linked
380 // together by having the "greater" handle of a node set to the
381 // next node in the list. "less_parent" is the handle of the first
382 // node in the list.
383 handle less_parent = null();
384
385 // h is root of current subtree, child is one of its children.
386 handle h, child;
387
388 for (;;) {
389 while (num_sub > 2) {
390 // Subtract one for root of subtree.
391 num_sub--;
392 rem[depth] = !!(num_sub & 1);
393 branch[depth++] = false;
394 num_sub >>= 1;
395 }
396
397 if (num_sub == 2) {
398 // Build a subtree with two nodes, slanting to greater.
399 // I arbitrarily chose to always have the extra node in the
400 // greater subtree when there is an odd number of nodes to
401 // split between the two subtrees.
402
403 h = *p;
404 p++;
405 child = *p;
406 p++;
407 set_lt(child, null());
408 set_gt(child, null());
409 set_bf(child, 0);
410 set_gt(h, child);
411 set_lt(h, null());
412 set_bf(h, 1);
413 } else { // num_sub == 1
414 // Build a subtree with one node.
415
416 h = *p;
417 p++;
418 set_lt(h, null());
419 set_gt(h, null());
420 set_bf(h, 0);
421 }
422
423 while (depth) {
424 depth--;
425 if (!branch[depth]) {
426 // We've completed a less subtree.
427 break;
428 }
429
430 // We've completed a greater subtree, so attach it to
431 // its parent (that is less than it). We pop the parent
432 // off the stack of less parents.
433 child = h;
434 h = less_parent;
435 less_parent = get_gt(h);
436 set_gt(h, child);
437 // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
438 num_sub <<= 1;
439 num_sub += 1 - rem[depth];
440 if (num_sub & (num_sub - 1)) {
441 // num_sub is not a power of 2
442 set_bf(h, 0);
443 } else {
444 // num_sub is a power of 2
445 set_bf(h, 1);
446 }
447 }
448
449 if (num_sub == num_nodes) {
450 // We've completed the full tree.
451 break;
452 }
453
454 // The subtree we've completed is the less subtree of the
455 // next node in the sequence.
456
457 child = h;
458 h = *p;
459 p++;
460 set_lt(h, child);
461
462 // Put h into stack of less parents.
463 set_gt(h, less_parent);
464 less_parent = h;
465
466 // Proceed to creating greater than subtree of h.
467 branch[depth] = true;
468 num_sub += rem[depth++];
469
470 } // end for (;;)
471
472 abs.root = h;
473
474 return true;
475 }
476
477 protected:
478
479 friend class Iterator;
480
481 // Create a class whose sole purpose is to take advantage of
482 // the "empty member" optimization.
483 struct abs_plus_root : public Abstractor {
484 // The handle of the root element in the AVL tree.
485 handle root;
486 };
487
488 abs_plus_root abs;
489
490 handle get_lt(handle h) { return abs.get_less(h); }
491 void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
492
493 handle get_gt(handle h) { return abs.get_greater(h); }
494 void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
495
496 int get_bf(handle h) { return abs.get_balance_factor(h); }
497 void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
498
499 int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
500 int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
501
502 handle null() { return abs.null(); }
503
504 private:
505
506 // Balances subtree, returns handle of root node of subtree
507 // after balancing.
508 handle balance(handle bal_h) {
509 handle deep_h;
510
511 // Either the "greater than" or the "less than" subtree of
512 // this node has to be 2 levels deeper (or else it wouldn't
513 // need balancing).
514
515 if (get_bf(bal_h) > 0) {
516 // "Greater than" subtree is deeper.
517
518 deep_h = get_gt(bal_h);
519
520 if (get_bf(deep_h) < 0) {
521 handle old_h = bal_h;
522 bal_h = get_lt(deep_h);
523
524 set_gt(old_h, get_lt(bal_h));
525 set_lt(deep_h, get_gt(bal_h));
526 set_lt(bal_h, old_h);
527 set_gt(bal_h, deep_h);
528
529 int bf = get_bf(bal_h);
530 if (bf != 0) {
531 if (bf > 0) {
532 set_bf(old_h, -1);
533 set_bf(deep_h, 0);
534 } else {
535 set_bf(deep_h, 1);
536 set_bf(old_h, 0);
537 }
538 set_bf(bal_h, 0);
539 } else {
540 set_bf(old_h, 0);
541 set_bf(deep_h, 0);
542 }
543 } else {
544 set_gt(bal_h, get_lt(deep_h));
545 set_lt(deep_h, bal_h);
546 if (get_bf(deep_h) == 0) {
547 set_bf(deep_h, -1);
548 set_bf(bal_h, 1);
549 } else {
550 set_bf(deep_h, 0);
551 set_bf(bal_h, 0);
552 }
553 bal_h = deep_h;
554 }
555 } else {
556 // "Less than" subtree is deeper.
557
558 deep_h = get_lt(bal_h);
559
560 if (get_bf(deep_h) > 0) {
561 handle old_h = bal_h;
562 bal_h = get_gt(deep_h);
563 set_lt(old_h, get_gt(bal_h));
564 set_gt(deep_h, get_lt(bal_h));
565 set_gt(bal_h, old_h);
566 set_lt(bal_h, deep_h);
567
568 int bf = get_bf(bal_h);
569 if (bf != 0) {
570 if (bf < 0) {
571 set_bf(old_h, 1);
572 set_bf(deep_h, 0);
573 } else {
574 set_bf(deep_h, -1);
575 set_bf(old_h, 0);
576 }
577 set_bf(bal_h, 0);
578 } else {
579 set_bf(old_h, 0);
580 set_bf(deep_h, 0);
581 }
582 } else {
583 set_lt(bal_h, get_gt(deep_h));
584 set_gt(deep_h, bal_h);
585 if (get_bf(deep_h) == 0) {
586 set_bf(deep_h, 1);
587 set_bf(bal_h, -1);
588 } else {
589 set_bf(deep_h, 0);
590 set_bf(bal_h, 0);
591 }
592 bal_h = deep_h;
593 }
594 }
595
596 return bal_h;
597 }
598
599 };
600
601 template <class Abstractor, unsigned maxDepth, class BSet>
602 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
603 AVLTree<Abstractor, maxDepth, BSet>::insert(handle h) {
604 set_lt(h, null());
605 set_gt(h, null());
606 set_bf(h, 0);
607
608 if (abs.root == null()) {
609 abs.root = h;
610 } else {
611 // Last unbalanced node encountered in search for insertion point.
612 handle unbal = null();
613 // Parent of last unbalanced node.
614 handle parent_unbal = null();
615 // Balance factor of last unbalanced node.
616 int unbal_bf;
617
618 // Zero-based depth in tree.
619 unsigned depth = 0, unbal_depth = 0;
620
621 // Records a path into the tree. If branch[n] is true, indicates
622 // take greater branch from the nth node in the path, otherwise
623 // take the less branch. branch[0] gives branch from root, and
624 // so on.
625 BSet branch;
626
627 handle hh = abs.root;
628 handle parent = null();
629 int cmp;
630
631 do {
632 if (get_bf(hh) != 0) {
633 unbal = hh;
634 parent_unbal = parent;
635 unbal_depth = depth;
636 }
637 cmp = cmp_n_n(h, hh);
638 if (cmp == 0) {
639 // Duplicate key.
640 return hh;
641 }
642 parent = hh;
643 hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
644 branch[depth++] = cmp > 0;
645 } while (hh != null());
646
647 // Add node to insert as leaf of tree.
648 if (cmp < 0)
649 set_lt(parent, h);
650 else
651 set_gt(parent, h);
652
653 depth = unbal_depth;
654
655 if (unbal == null()) {
656 hh = abs.root;
657 } else {
658 cmp = branch[depth++] ? 1 : -1;
659 unbal_bf = get_bf(unbal);
660 if (cmp < 0)
661 unbal_bf--;
662 else // cmp > 0
663 unbal_bf++;
664 hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
665 if ((unbal_bf != -2) && (unbal_bf != 2)) {
666 // No rebalancing of tree is necessary.
667 set_bf(unbal, unbal_bf);
668 unbal = null();
669 }
670 }
671
672 if (hh != null()) {
673 while (h != hh) {
674 cmp = branch[depth++] ? 1 : -1;
675 if (cmp < 0) {
676 set_bf(hh, -1);
677 hh = get_lt(hh);
678 } else { // cmp > 0
679 set_bf(hh, 1);
680 hh = get_gt(hh);
681 }
682 }
683 }
684
685 if (unbal != null()) {
686 unbal = balance(unbal);
687 if (parent_unbal == null()) {
688 abs.root = unbal;
689 } else {
690 depth = unbal_depth - 1;
691 cmp = branch[depth] ? 1 : -1;
692 if (cmp < 0)
693 set_lt(parent_unbal, unbal);
694 else // cmp > 0
695 set_gt(parent_unbal, unbal);
696 }
697 }
698 }
699
700 return h;
701 }
702
703 template <class Abstractor, unsigned maxDepth, class BSet>
704 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
705 AVLTree<Abstractor, maxDepth, BSet>::search(
706 key k,
707 typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st) {
708 const int kMaskHighBit = (int) ~((~(unsigned) 0) >> 1);
709
710 int cmp, target_cmp;
711 handle match_h = null();
712 handle h = abs.root;
713
714 if (st & LESS)
715 target_cmp = 1;
716 else if (st & GREATER)
717 target_cmp = -1;
718 else
719 target_cmp = 0;
720
721 while (h != null()) {
722 cmp = cmp_k_n(k, h);
723 if (cmp == 0) {
724 if (st & EQUAL) {
725 match_h = h;
726 break;
727 }
728 cmp = -target_cmp;
729 } else if (target_cmp != 0) {
730 if (!((cmp ^ target_cmp) & kMaskHighBit)) {
731 // cmp and target_cmp are both positive or both negative.
732 match_h = h;
733 }
734 }
735 h = cmp < 0 ? get_lt(h) : get_gt(h);
736 }
737
738 return match_h;
739 }
740
741 template <class Abstractor, unsigned maxDepth, class BSet>
742 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
743 AVLTree<Abstractor, maxDepth, BSet>::search_least() {
744 handle h = abs.root, parent = null();
745
746 while (h != null()) {
747 parent = h;
748 h = get_lt(h);
749 }
750
751 return parent;
752 }
753
754 template <class Abstractor, unsigned maxDepth, class BSet>
755 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
756 AVLTree<Abstractor, maxDepth, BSet>::search_greatest() {
757 handle h = abs.root, parent = null();
758
759 while (h != null()) {
760 parent = h;
761 h = get_gt(h);
762 }
763
764 return parent;
765 }
766
767 template <class Abstractor, unsigned maxDepth, class BSet>
768 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
769 AVLTree<Abstractor, maxDepth, BSet>::remove(key k) {
770 // Zero-based depth in tree.
771 unsigned depth = 0, rm_depth;
772
773 // Records a path into the tree. If branch[n] is true, indicates
774 // take greater branch from the nth node in the path, otherwise
775 // take the less branch. branch[0] gives branch from root, and
776 // so on.
777 BSet branch;
778
779 handle h = abs.root;
780 handle parent = null(), child;
781 int cmp, cmp_shortened_sub_with_path = 0;
782
783 for (;;) {
784 if (h == null()) {
785 // No node in tree with given key.
786 return null();
787 }
788 cmp = cmp_k_n(k, h);
789 if (cmp == 0) {
790 // Found node to remove.
791 break;
792 }
793 parent = h;
794 h = cmp < 0 ? get_lt(h) : get_gt(h);
795 branch[depth++] = cmp > 0;
796 cmp_shortened_sub_with_path = cmp;
797 }
798 handle rm = h;
799 handle parent_rm = parent;
800 rm_depth = depth;
801
802 // If the node to remove is not a leaf node, we need to get a
803 // leaf node, or a node with a single leaf as its child, to put
804 // in the place of the node to remove. We will get the greatest
805 // node in the less subtree (of the node to remove), or the least
806 // node in the greater subtree. We take the leaf node from the
807 // deeper subtree, if there is one.
808
809 if (get_bf(h) < 0) {
810 child = get_lt(h);
811 branch[depth] = false;
812 cmp = -1;
813 } else {
814 child = get_gt(h);
815 branch[depth] = true;
816 cmp = 1;
817 }
818 depth++;
819
820 if (child != null()) {
821 cmp = -cmp;
822 do {
823 parent = h;
824 h = child;
825 if (cmp < 0) {
826 child = get_lt(h);
827 branch[depth] = false;
828 } else {
829 child = get_gt(h);
830 branch[depth] = true;
831 }
832 depth++;
833 } while (child != null());
834
835 if (parent == rm) {
836 // Only went through do loop once. Deleted node will be replaced
837 // in the tree structure by one of its immediate children.
838 cmp_shortened_sub_with_path = -cmp;
839 } else {
840 cmp_shortened_sub_with_path = cmp;
841 }
842
843 // Get the handle of the opposite child, which may not be null.
844 child = cmp > 0 ? get_lt(h) : get_gt(h);
845 }
846
847 if (parent == null()) {
848 // There were only 1 or 2 nodes in this tree.
849 abs.root = child;
850 } else if (cmp_shortened_sub_with_path < 0) {
851 set_lt(parent, child);
852 } else {
853 set_gt(parent, child);
854 }
855
856 // "path" is the parent of the subtree being eliminated or reduced
857 // from a depth of 2 to 1. If "path" is the node to be removed, we
858 // set path to the node we're about to poke into the position of the
859 // node to be removed.
860 handle path = parent == rm ? h : parent;
861
862 if (h != rm) {
863 // Poke in the replacement for the node to be removed.
864 set_lt(h, get_lt(rm));
865 set_gt(h, get_gt(rm));
866 set_bf(h, get_bf(rm));
867 if (parent_rm == null()) {
868 abs.root = h;
869 } else {
870 depth = rm_depth - 1;
871 if (branch[depth])
872 set_gt(parent_rm, h);
873 else
874 set_lt(parent_rm, h);
875 }
876 }
877
878 if (path != null()) {
879 // Create a temporary linked list from the parent of the path node
880 // to the root node.
881 h = abs.root;
882 parent = null();
883 depth = 0;
884 while (h != path) {
885 if (branch[depth++]) {
886 child = get_gt(h);
887 set_gt(h, parent);
888 } else {
889 child = get_lt(h);
890 set_lt(h, parent);
891 }
892 parent = h;
893 h = child;
894 }
895
896 // Climb from the path node to the root node using the linked
897 // list, restoring the tree structure and rebalancing as necessary.
898 bool reduced_depth = true;
899 int bf;
900 cmp = cmp_shortened_sub_with_path;
901 for (;;) {
902 if (reduced_depth) {
903 bf = get_bf(h);
904 if (cmp < 0)
905 bf++;
906 else // cmp > 0
907 bf--;
908 if ((bf == -2) || (bf == 2)) {
909 h = balance(h);
910 bf = get_bf(h);
911 } else {
912 set_bf(h, bf);
913 }
914 reduced_depth = (bf == 0);
915 }
916 if (parent == null())
917 break;
918 child = h;
919 h = parent;
920 cmp = branch[--depth] ? 1 : -1;
921 if (cmp < 0) {
922 parent = get_lt(h);
923 set_lt(h, child);
924 } else {
925 parent = get_gt(h);
926 set_gt(h, child);
927 }
928 }
929 abs.root = h;
930 }
931
932 return rm;
933 }
934
935 template <class Abstractor, unsigned maxDepth, class BSet>
936 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
937 AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) {
938 handle h = abs.root;
939 handle parent = null();
940 int cmp, last_cmp;
941
942 // Search for node already in tree with same key.
943 for (;;) {
944 if (h == null()) {
945 // No node in tree with same key as new node.
946 return null();
947 }
948 cmp = cmp_n_n(new_node, h);
949 if (cmp == 0) {
950 // Found the node to substitute new one for.
951 break;
952 }
953 last_cmp = cmp;
954 parent = h;
955 h = cmp < 0 ? get_lt(h) : get_gt(h);
956 }
957
958 // Copy tree housekeeping fields from node in tree to new node.
959 set_lt(new_node, get_lt(h));
960 set_gt(new_node, get_gt(h));
961 set_bf(new_node, get_bf(h));
962
963 if (parent == null()) {
964 // New node is also new root.
965 abs.root = new_node;
966 } else {
967 // Make parent point to new node.
968 if (last_cmp < 0)
969 set_lt(parent, new_node);
970 else
971 set_gt(parent, new_node);
972 }
973
974 return h;
975 }
976
977 } // namespace content
978
979 #endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_unittest.cc ('k') | content/browser/indexed_db/leveldb/fixed_array.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698