tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RedBlackTree.h (24239B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // Portions of this file were originally under the following license:
      8 //
      9 // Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
     10 // All rights reserved.
     11 //
     12 // Redistribution and use in source and binary forms, with or without
     13 // modification, are permitted provided that the following conditions
     14 // are met:
     15 // 1. Redistributions of source code must retain the above copyright
     16 //    notice(s), this list of conditions and the following disclaimer
     17 //    unmodified other than the allowable addition of one or more
     18 //    copyright notices.
     19 // 2. Redistributions in binary form must reproduce the above copyright
     20 //    notice(s), this list of conditions and the following disclaimer in
     21 //    the documentation and/or other materials provided with the
     22 //    distribution.
     23 //
     24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
     25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     27 // PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
     28 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     29 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     30 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     31 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     32 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     33 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     34 // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35 //
     36 // ****************************************************************************
     37 //
     38 // C++ template implementation of left-leaning red-black trees.
     39 //
     40 // All operations are done non-recursively.  Parent pointers are not used, and
     41 // color bits are stored in the least significant bit of right-child pointers,
     42 // thus making node linkage as compact as is possible for red-black trees.
     43 //
     44 // The RedBlackTree template expects two type arguments: the type of the nodes,
     45 // containing a RedBlackTreeNode, and a trait providing two methods:
     46 //  - a GetTreeNode method that returns a reference to the RedBlackTreeNode
     47 //    corresponding to a given node with the following signature:
     48 //      static RedBlackTreeNode<T>& GetTreeNode(T*)
     49 //  - a Compare function with the following signature:
     50 //      static Order Compare(T* aNode, T* aOther)
     51 //                              ^^^^^
     52 //                           or aKey
     53 //
     54 // Interpretation of comparision function return values:
     55 //
     56 //   Order::eLess: aNode <  aOther
     57 //   Order::eEqual: aNode == aOther
     58 //   Order::eGreater: aNode >  aOther
     59 //
     60 // In all cases, the aNode or aKey argument is the first argument to the
     61 // comparison function, which makes it possible to write comparison functions
     62 // that treat the first argument specially.
     63 //
     64 // ***************************************************************************
     65 
     66 #ifndef RB_H_
     67 #define RB_H_
     68 
     69 #include "mozilla/Alignment.h"
     70 #include "mozilla/Assertions.h"
     71 #include "Utils.h"
     72 
     73 enum NodeColor {
     74  Black = 0,
     75  Red = 1,
     76 };
     77 
     78 // Node structure.
     79 template <typename T>
     80 class RedBlackTreeNode {
     81  T* mLeft;
     82  // The lowest bit is the color
     83  T* mRightAndColor;
     84 
     85 public:
     86  T* Left() { return mLeft; }
     87 
     88  void SetLeft(T* aValue) { mLeft = aValue; }
     89 
     90  T* Right() {
     91    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(mRightAndColor) &
     92                                uintptr_t(~1));
     93  }
     94 
     95  void SetRight(T* aValue) {
     96    mRightAndColor = reinterpret_cast<T*>(
     97        (reinterpret_cast<uintptr_t>(aValue) & uintptr_t(~1)) | Color());
     98  }
     99 
    100  NodeColor Color() {
    101 #pragma GCC diagnostic push
    102 #pragma GCC diagnostic ignored "-Wuninitialized"
    103    return static_cast<NodeColor>(reinterpret_cast<uintptr_t>(mRightAndColor) &
    104                                  1);
    105 #pragma GCC diagnostic pop
    106  }
    107 
    108  bool IsBlack() { return Color() == NodeColor::Black; }
    109 
    110  bool IsRed() { return Color() == NodeColor::Red; }
    111 
    112  void SetColor(NodeColor aColor) {
    113    mRightAndColor = reinterpret_cast<T*>(
    114        (reinterpret_cast<uintptr_t>(mRightAndColor) & uintptr_t(~1)) | aColor);
    115  }
    116 };
    117 
    118 // Tree structure.
    119 template <typename T, typename Trait>
    120 class RedBlackTree {
    121 public:
    122  constexpr RedBlackTree() : mRoot(nullptr) {}
    123 
    124  T* First(T* aStart = nullptr) { return First(TreeNode(aStart)).Get(); }
    125 
    126  T* Last(T* aStart = nullptr) { return Last(TreeNode(aStart)).Get(); }
    127 
    128  T* Next(T* aNode) { return Next(TreeNode(aNode)).Get(); }
    129 
    130  T* Prev(T* aNode) { return Prev(TreeNode(aNode)).Get(); }
    131 
    132  T* Search(T* aKey) { return Search(TreeNode(aKey)).Get(); }
    133 
    134  // Find a match if it exists. Otherwise, find the next greater node, if one
    135  // exists.
    136  T* SearchOrNext(T* aKey) { return SearchOrNext(TreeNode(aKey)).Get(); }
    137 
    138  void Insert(T* aNode) { Insert(TreeNode(aNode)); }
    139 
    140  void Remove(T* aNode) { Remove(TreeNode(aNode)); }
    141 
    142  // Helper class to avoid having all the tree traversal code further below
    143  // have to use Trait::GetTreeNode and do manual null pointer checks, adding
    144  // visual noise. Practically speaking TreeNode(nullptr) acts as a virtual
    145  // sentinel, that loops back to itself for Left() and Right() and is always
    146  // black.
    147  class TreeNode {
    148   public:
    149    constexpr TreeNode() : mNode(nullptr) {}
    150 
    151    MOZ_IMPLICIT TreeNode(T* aNode) : mNode(aNode) {}
    152 
    153    TreeNode& operator=(TreeNode aOther) {
    154      mNode = aOther.mNode;
    155      return *this;
    156    }
    157 
    158    TreeNode Left() {
    159      return TreeNode(mNode ? Trait::GetTreeNode(mNode).Left() : nullptr);
    160    }
    161 
    162    void SetLeft(TreeNode aNode) {
    163      MOZ_RELEASE_ASSERT(mNode);
    164      Trait::GetTreeNode(mNode).SetLeft(aNode.mNode);
    165    }
    166 
    167    TreeNode Right() {
    168      return TreeNode(mNode ? Trait::GetTreeNode(mNode).Right() : nullptr);
    169    }
    170 
    171    void SetRight(TreeNode aNode) {
    172      MOZ_RELEASE_ASSERT(mNode);
    173      Trait::GetTreeNode(mNode).SetRight(aNode.mNode);
    174    }
    175 
    176    NodeColor Color() {
    177      return mNode ? Trait::GetTreeNode(mNode).Color() : NodeColor::Black;
    178    }
    179 
    180    bool IsRed() { return Color() == NodeColor::Red; }
    181 
    182    bool IsBlack() { return Color() == NodeColor::Black; }
    183 
    184    void SetColor(NodeColor aColor) {
    185      MOZ_RELEASE_ASSERT(mNode);
    186      Trait::GetTreeNode(mNode).SetColor(aColor);
    187    }
    188 
    189    T* Get() { return mNode; }
    190 
    191    MOZ_IMPLICIT operator bool() { return !!mNode; }
    192 
    193    bool operator==(TreeNode& aOther) { return mNode == aOther.mNode; }
    194 
    195   private:
    196    T* mNode;
    197  };
    198 
    199 private:
    200  // Ideally we'd use a TreeNode for mRoot, but we need RedBlackTree to stay
    201  // a POD type to avoid a static initializer for gArenas.
    202  T* mRoot;
    203 
    204  TreeNode First(TreeNode aStart) {
    205    TreeNode ret;
    206    for (ret = aStart ? aStart : mRoot; ret.Left(); ret = ret.Left()) {
    207    }
    208    return ret;
    209  }
    210 
    211  TreeNode Last(TreeNode aStart) {
    212    TreeNode ret;
    213    for (ret = aStart ? aStart : mRoot; ret.Right(); ret = ret.Right()) {
    214    }
    215    return ret;
    216  }
    217 
    218  TreeNode Next(TreeNode aNode) {
    219    TreeNode ret;
    220    if (aNode.Right()) {
    221      ret = First(aNode.Right());
    222    } else {
    223      TreeNode rbp_n_t = mRoot;
    224      MOZ_ASSERT(rbp_n_t);
    225      ret = nullptr;
    226      while (true) {
    227        Order rbp_n_cmp = Trait::Compare(aNode.Get(), rbp_n_t.Get());
    228        if (rbp_n_cmp == Order::eLess) {
    229          ret = rbp_n_t;
    230          rbp_n_t = rbp_n_t.Left();
    231        } else if (rbp_n_cmp == Order::eGreater) {
    232          rbp_n_t = rbp_n_t.Right();
    233        } else {
    234          break;
    235        }
    236        MOZ_ASSERT(rbp_n_t);
    237      }
    238    }
    239    return ret;
    240  }
    241 
    242  TreeNode Prev(TreeNode aNode) {
    243    TreeNode ret;
    244    if (aNode.Left()) {
    245      ret = Last(aNode.Left());
    246    } else {
    247      TreeNode rbp_p_t = mRoot;
    248      MOZ_ASSERT(rbp_p_t);
    249      ret = nullptr;
    250      while (true) {
    251        Order rbp_p_cmp = Trait::Compare(aNode.Get(), rbp_p_t.Get());
    252        if (rbp_p_cmp == Order::eLess) {
    253          rbp_p_t = rbp_p_t.Left();
    254        } else if (rbp_p_cmp == Order::eGreater) {
    255          ret = rbp_p_t;
    256          rbp_p_t = rbp_p_t.Right();
    257        } else {
    258          break;
    259        }
    260        MOZ_ASSERT(rbp_p_t);
    261      }
    262    }
    263    return ret;
    264  }
    265 
    266  TreeNode Search(TreeNode aKey) {
    267    TreeNode ret = mRoot;
    268    Order rbp_se_cmp;
    269    while (ret && (rbp_se_cmp = Trait::Compare(aKey.Get(), ret.Get())) !=
    270                      Order::eEqual) {
    271      if (rbp_se_cmp == Order::eLess) {
    272        ret = ret.Left();
    273      } else {
    274        ret = ret.Right();
    275      }
    276    }
    277    return ret;
    278  }
    279 
    280  TreeNode SearchOrNext(TreeNode aKey) {
    281    TreeNode ret = nullptr;
    282    TreeNode rbp_ns_t = mRoot;
    283    while (rbp_ns_t) {
    284      Order rbp_ns_cmp = Trait::Compare(aKey.Get(), rbp_ns_t.Get());
    285      if (rbp_ns_cmp == Order::eLess) {
    286        ret = rbp_ns_t;
    287        rbp_ns_t = rbp_ns_t.Left();
    288      } else if (rbp_ns_cmp == Order::eGreater) {
    289        rbp_ns_t = rbp_ns_t.Right();
    290      } else {
    291        ret = rbp_ns_t;
    292        break;
    293      }
    294    }
    295    return ret;
    296  }
    297 
    298  void Insert(TreeNode aNode) {
    299    // rbp_i_s is only used as a placeholder for its RedBlackTreeNode. Use
    300    // AlignedStorage2 to avoid running the TreeNode base class constructor.
    301    mozilla::AlignedStorage2<T> rbp_i_s;
    302    TreeNode rbp_i_g, rbp_i_p, rbp_i_c, rbp_i_t, rbp_i_u;
    303    Order rbp_i_cmp = Order::eEqual;
    304    rbp_i_g = nullptr;
    305    rbp_i_p = rbp_i_s.addr();
    306    rbp_i_p.SetLeft(mRoot);
    307    rbp_i_p.SetRight(nullptr);
    308    rbp_i_p.SetColor(NodeColor::Black);
    309    rbp_i_c = mRoot;
    310    // Iteratively search down the tree for the insertion point,
    311    // splitting 4-nodes as they are encountered. At the end of each
    312    // iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
    313    // the tree, assuming a sufficiently deep tree.
    314    while (rbp_i_c) {
    315      rbp_i_t = rbp_i_c.Left();
    316      rbp_i_u = rbp_i_t.Left();
    317      if (rbp_i_t.IsRed() && rbp_i_u.IsRed()) {
    318        // rbp_i_c is the top of a logical 4-node, so split it.
    319        // This iteration does not move down the tree, due to the
    320        // disruptiveness of node splitting.
    321        //
    322        // Rotate right.
    323        rbp_i_t = RotateRight(rbp_i_c);
    324        // Pass red links up one level.
    325        rbp_i_u = rbp_i_t.Left();
    326        rbp_i_u.SetColor(NodeColor::Black);
    327        if (rbp_i_p.Left() == rbp_i_c) {
    328          rbp_i_p.SetLeft(rbp_i_t);
    329          rbp_i_c = rbp_i_t;
    330        } else {
    331          // rbp_i_c was the right child of rbp_i_p, so rotate
    332          // left in order to maintain the left-leaning invariant.
    333          MOZ_ASSERT(rbp_i_p.Right() == rbp_i_c);
    334          rbp_i_p.SetRight(rbp_i_t);
    335          rbp_i_u = LeanLeft(rbp_i_p);
    336          if (rbp_i_g.Left() == rbp_i_p) {
    337            rbp_i_g.SetLeft(rbp_i_u);
    338          } else {
    339            MOZ_ASSERT(rbp_i_g.Right() == rbp_i_p);
    340            rbp_i_g.SetRight(rbp_i_u);
    341          }
    342          rbp_i_p = rbp_i_u;
    343          rbp_i_cmp = Trait::Compare(aNode.Get(), rbp_i_p.Get());
    344          if (rbp_i_cmp == Order::eLess) {
    345            rbp_i_c = rbp_i_p.Left();
    346          } else {
    347            MOZ_ASSERT(rbp_i_cmp == Order::eGreater);
    348            rbp_i_c = rbp_i_p.Right();
    349          }
    350          continue;
    351        }
    352      }
    353      rbp_i_g = rbp_i_p;
    354      rbp_i_p = rbp_i_c;
    355      rbp_i_cmp = Trait::Compare(aNode.Get(), rbp_i_c.Get());
    356      if (rbp_i_cmp == Order::eLess) {
    357        rbp_i_c = rbp_i_c.Left();
    358      } else {
    359        MOZ_ASSERT(rbp_i_cmp == Order::eGreater);
    360        rbp_i_c = rbp_i_c.Right();
    361      }
    362    }
    363    // rbp_i_p now refers to the node under which to insert.
    364    aNode.SetLeft(nullptr);
    365    aNode.SetRight(nullptr);
    366    aNode.SetColor(NodeColor::Red);
    367    if (rbp_i_cmp == Order::eGreater) {
    368      rbp_i_p.SetRight(aNode);
    369      rbp_i_t = LeanLeft(rbp_i_p);
    370      if (rbp_i_g.Left() == rbp_i_p) {
    371        rbp_i_g.SetLeft(rbp_i_t);
    372      } else if (rbp_i_g.Right() == rbp_i_p) {
    373        rbp_i_g.SetRight(rbp_i_t);
    374      }
    375    } else {
    376      rbp_i_p.SetLeft(aNode);
    377    }
    378    // Update the root and make sure that it is black.
    379    TreeNode root = TreeNode(rbp_i_s.addr()).Left();
    380    root.SetColor(NodeColor::Black);
    381    mRoot = root.Get();
    382  }
    383 
    384  void Remove(TreeNode aNode) {
    385    // rbp_r_s is only used as a placeholder for its RedBlackTreeNode. Use
    386    // AlignedStorage2 to avoid running the TreeNode base class constructor.
    387    mozilla::AlignedStorage2<T> rbp_r_s;
    388    TreeNode rbp_r_p, rbp_r_c, rbp_r_xp, rbp_r_t, rbp_r_u;
    389    Order rbp_r_cmp;
    390    rbp_r_p = TreeNode(rbp_r_s.addr());
    391    rbp_r_p.SetLeft(mRoot);
    392    rbp_r_p.SetRight(nullptr);
    393    rbp_r_p.SetColor(NodeColor::Black);
    394    rbp_r_c = mRoot;
    395    rbp_r_xp = nullptr;
    396    // Iterate down the tree, but always transform 2-nodes to 3- or
    397    // 4-nodes in order to maintain the invariant that the current
    398    // node is not a 2-node. This allows simple deletion once a leaf
    399    // is reached. Handle the root specially though, since there may
    400    // be no way to convert it from a 2-node to a 3-node.
    401    rbp_r_cmp = Trait::Compare(aNode.Get(), rbp_r_c.Get());
    402    if (rbp_r_cmp == Order::eLess) {
    403      rbp_r_t = rbp_r_c.Left();
    404      rbp_r_u = rbp_r_t.Left();
    405      if (rbp_r_t.IsBlack() && rbp_r_u.IsBlack()) {
    406        // Apply standard transform to prepare for left move.
    407        rbp_r_t = MoveRedLeft(rbp_r_c);
    408        rbp_r_t.SetColor(NodeColor::Black);
    409        rbp_r_p.SetLeft(rbp_r_t);
    410        rbp_r_c = rbp_r_t;
    411      } else {
    412        // Move left.
    413        rbp_r_p = rbp_r_c;
    414        rbp_r_c = rbp_r_c.Left();
    415      }
    416    } else {
    417      if (rbp_r_cmp == Order::eEqual) {
    418        MOZ_ASSERT(aNode == rbp_r_c);
    419        if (!rbp_r_c.Right()) {
    420          // Delete root node (which is also a leaf node).
    421          if (rbp_r_c.Left()) {
    422            rbp_r_t = LeanRight(rbp_r_c);
    423            rbp_r_t.SetRight(nullptr);
    424          } else {
    425            rbp_r_t = nullptr;
    426          }
    427          rbp_r_p.SetLeft(rbp_r_t);
    428        } else {
    429          // This is the node we want to delete, but we will
    430          // instead swap it with its successor and delete the
    431          // successor. Record enough information to do the
    432          // swap later. rbp_r_xp is the aNode's parent.
    433          rbp_r_xp = rbp_r_p;
    434          rbp_r_cmp = Order::eGreater;  // Note that deletion is incomplete.
    435        }
    436      }
    437      if (rbp_r_cmp == Order::eGreater) {
    438        if (rbp_r_c.Right().Left().IsBlack()) {
    439          rbp_r_t = rbp_r_c.Left();
    440          if (rbp_r_t.IsRed()) {
    441            // Standard transform.
    442            rbp_r_t = MoveRedRight(rbp_r_c);
    443          } else {
    444            // Root-specific transform.
    445            rbp_r_c.SetColor(NodeColor::Red);
    446            rbp_r_u = rbp_r_t.Left();
    447            if (rbp_r_u.IsRed()) {
    448              rbp_r_u.SetColor(NodeColor::Black);
    449              rbp_r_t = RotateRight(rbp_r_c);
    450              rbp_r_u = RotateLeft(rbp_r_c);
    451              rbp_r_t.SetRight(rbp_r_u);
    452            } else {
    453              rbp_r_t.SetColor(NodeColor::Red);
    454              rbp_r_t = RotateLeft(rbp_r_c);
    455            }
    456          }
    457          rbp_r_p.SetLeft(rbp_r_t);
    458          rbp_r_c = rbp_r_t;
    459        } else {
    460          // Move right.
    461          rbp_r_p = rbp_r_c;
    462          rbp_r_c = rbp_r_c.Right();
    463        }
    464      }
    465    }
    466    if (rbp_r_cmp != Order::eEqual) {
    467      while (true) {
    468        MOZ_ASSERT(rbp_r_p);
    469        rbp_r_cmp = Trait::Compare(aNode.Get(), rbp_r_c.Get());
    470        if (rbp_r_cmp == Order::eLess) {
    471          rbp_r_t = rbp_r_c.Left();
    472          if (!rbp_r_t) {
    473            // rbp_r_c now refers to the successor node to
    474            // relocate, and rbp_r_xp/aNode refer to the
    475            // context for the relocation.
    476            if (rbp_r_xp.Left() == aNode) {
    477              rbp_r_xp.SetLeft(rbp_r_c);
    478            } else {
    479              MOZ_ASSERT(rbp_r_xp.Right() == (aNode));
    480              rbp_r_xp.SetRight(rbp_r_c);
    481            }
    482            rbp_r_c.SetLeft(aNode.Left());
    483            rbp_r_c.SetRight(aNode.Right());
    484            rbp_r_c.SetColor(aNode.Color());
    485            if (rbp_r_p.Left() == rbp_r_c) {
    486              rbp_r_p.SetLeft(nullptr);
    487            } else {
    488              MOZ_ASSERT(rbp_r_p.Right() == rbp_r_c);
    489              rbp_r_p.SetRight(nullptr);
    490            }
    491            break;
    492          }
    493          rbp_r_u = rbp_r_t.Left();
    494          if (rbp_r_t.IsBlack() && rbp_r_u.IsBlack()) {
    495            rbp_r_t = MoveRedLeft(rbp_r_c);
    496            if (rbp_r_p.Left() == rbp_r_c) {
    497              rbp_r_p.SetLeft(rbp_r_t);
    498            } else {
    499              rbp_r_p.SetRight(rbp_r_t);
    500            }
    501            rbp_r_c = rbp_r_t;
    502          } else {
    503            rbp_r_p = rbp_r_c;
    504            rbp_r_c = rbp_r_c.Left();
    505          }
    506        } else {
    507          // Check whether to delete this node (it has to be
    508          // the correct node and a leaf node).
    509          if (rbp_r_cmp == Order::eEqual) {
    510            MOZ_ASSERT(aNode == rbp_r_c);
    511            if (!rbp_r_c.Right()) {
    512              // Delete leaf node.
    513              if (rbp_r_c.Left()) {
    514                rbp_r_t = LeanRight(rbp_r_c);
    515                rbp_r_t.SetRight(nullptr);
    516              } else {
    517                rbp_r_t = nullptr;
    518              }
    519              if (rbp_r_p.Left() == rbp_r_c) {
    520                rbp_r_p.SetLeft(rbp_r_t);
    521              } else {
    522                rbp_r_p.SetRight(rbp_r_t);
    523              }
    524              break;
    525            }
    526            // This is the node we want to delete, but we
    527            // will instead swap it with its successor
    528            // and delete the successor. Record enough
    529            // information to do the swap later.
    530            // rbp_r_xp is aNode's parent.
    531            rbp_r_xp = rbp_r_p;
    532          }
    533          rbp_r_t = rbp_r_c.Right();
    534          rbp_r_u = rbp_r_t.Left();
    535          if (rbp_r_u.IsBlack()) {
    536            rbp_r_t = MoveRedRight(rbp_r_c);
    537            if (rbp_r_p.Left() == rbp_r_c) {
    538              rbp_r_p.SetLeft(rbp_r_t);
    539            } else {
    540              rbp_r_p.SetRight(rbp_r_t);
    541            }
    542            rbp_r_c = rbp_r_t;
    543          } else {
    544            rbp_r_p = rbp_r_c;
    545            rbp_r_c = rbp_r_c.Right();
    546          }
    547        }
    548      }
    549    }
    550    // Update root.
    551    mRoot = TreeNode(rbp_r_s.addr()).Left().Get();
    552    aNode.SetLeft(nullptr);
    553    aNode.SetRight(nullptr);
    554    aNode.SetColor(NodeColor::Black);
    555  }
    556 
    557  TreeNode RotateLeft(TreeNode aNode) {
    558    TreeNode node = aNode.Right();
    559    aNode.SetRight(node.Left());
    560    node.SetLeft(aNode);
    561    return node;
    562  }
    563 
    564  TreeNode RotateRight(TreeNode aNode) {
    565    TreeNode node = aNode.Left();
    566    aNode.SetLeft(node.Right());
    567    node.SetRight(aNode);
    568    return node;
    569  }
    570 
    571  TreeNode LeanLeft(TreeNode aNode) {
    572    TreeNode node = RotateLeft(aNode);
    573    NodeColor color = aNode.Color();
    574    node.SetColor(color);
    575    aNode.SetColor(NodeColor::Red);
    576    return node;
    577  }
    578 
    579  TreeNode LeanRight(TreeNode aNode) {
    580    TreeNode node = RotateRight(aNode);
    581    NodeColor color = aNode.Color();
    582    node.SetColor(color);
    583    aNode.SetColor(NodeColor::Red);
    584    return node;
    585  }
    586 
    587  TreeNode MoveRedLeft(TreeNode aNode) {
    588    TreeNode node;
    589    TreeNode rbp_mrl_t, rbp_mrl_u;
    590    rbp_mrl_t = aNode.Left();
    591    rbp_mrl_t.SetColor(NodeColor::Red);
    592    rbp_mrl_t = aNode.Right();
    593    rbp_mrl_u = rbp_mrl_t.Left();
    594    if (rbp_mrl_u.IsRed()) {
    595      rbp_mrl_u = RotateRight(rbp_mrl_t);
    596      aNode.SetRight(rbp_mrl_u);
    597      node = RotateLeft(aNode);
    598      rbp_mrl_t = aNode.Right();
    599      if (rbp_mrl_t.IsRed()) {
    600        rbp_mrl_t.SetColor(NodeColor::Black);
    601        aNode.SetColor(NodeColor::Red);
    602        rbp_mrl_t = RotateLeft(aNode);
    603        node.SetLeft(rbp_mrl_t);
    604      } else {
    605        aNode.SetColor(NodeColor::Black);
    606      }
    607    } else {
    608      aNode.SetColor(NodeColor::Red);
    609      node = RotateLeft(aNode);
    610    }
    611    return node;
    612  }
    613 
    614  TreeNode MoveRedRight(TreeNode aNode) {
    615    TreeNode node;
    616    TreeNode rbp_mrr_t;
    617    rbp_mrr_t = aNode.Left();
    618    if (rbp_mrr_t.IsRed()) {
    619      TreeNode rbp_mrr_u, rbp_mrr_v;
    620      rbp_mrr_u = rbp_mrr_t.Right();
    621      rbp_mrr_v = rbp_mrr_u.Left();
    622      if (rbp_mrr_v.IsRed()) {
    623        rbp_mrr_u.SetColor(aNode.Color());
    624        rbp_mrr_v.SetColor(NodeColor::Black);
    625        rbp_mrr_u = RotateLeft(rbp_mrr_t);
    626        aNode.SetLeft(rbp_mrr_u);
    627        node = RotateRight(aNode);
    628        rbp_mrr_t = RotateLeft(aNode);
    629        node.SetRight(rbp_mrr_t);
    630      } else {
    631        rbp_mrr_t.SetColor(aNode.Color());
    632        rbp_mrr_u.SetColor(NodeColor::Red);
    633        node = RotateRight(aNode);
    634        rbp_mrr_t = RotateLeft(aNode);
    635        node.SetRight(rbp_mrr_t);
    636      }
    637      aNode.SetColor(NodeColor::Red);
    638    } else {
    639      rbp_mrr_t.SetColor(NodeColor::Red);
    640      rbp_mrr_t = rbp_mrr_t.Left();
    641      if (rbp_mrr_t.IsRed()) {
    642        rbp_mrr_t.SetColor(NodeColor::Black);
    643        node = RotateRight(aNode);
    644        rbp_mrr_t = RotateLeft(aNode);
    645        node.SetRight(rbp_mrr_t);
    646      } else {
    647        node = RotateLeft(aNode);
    648      }
    649    }
    650    return node;
    651  }
    652 
    653  // The iterator simulates recursion via an array of pointers that store the
    654  // current path.  This is critical to performance, since a series of calls to
    655  // rb_{next,prev}() would require time proportional to (n lg n), whereas this
    656  // implementation only requires time proportional to (n).
    657  //
    658  // Since the iterator caches a path down the tree, any tree modification may
    659  // cause the cached path to become invalid. Don't modify the tree during an
    660  // iteration.
    661 
    662  // Size the path arrays such that they are always large enough, even if a
    663  // tree consumes all of memory.  Since each node must contain a minimum of
    664  // two pointers, there can never be more nodes than:
    665  //
    666  //   1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
    667  //
    668  // Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
    669  // is:
    670  //
    671  //   (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
    672  //
    673  // This works out to a maximum depth of 87 and 180 for 32- and 64-bit
    674  // systems, respectively (approximately 348 and 1440 bytes, respectively).
    675 public:
    676  class Iterator {
    677    TreeNode mPath[3 * ((sizeof(void*) << 3) - (LOG2(sizeof(void*)) + 1))];
    678 
    679    // Depth always points to the next empty place in mPath.  Therefore
    680    // mDepth == 0 means there are no items in mPath,
    681    // mDepth != 0 means that mPath[mDepth-1] is safe to dereference.
    682    unsigned mDepth;
    683 
    684   public:
    685    explicit Iterator(RedBlackTree<T, Trait>* aTree) : mDepth(0) {
    686      // Initialize the path to contain the left spine.
    687      if (aTree->mRoot) {
    688        TreeNode node;
    689        mPath[mDepth++] = aTree->mRoot;
    690        while ((node = mPath[mDepth - 1].Left())) {
    691          mPath[mDepth++] = node;
    692        }
    693      }
    694    }
    695 
    696    template <typename Iterator>
    697    class Item {
    698      Iterator* mIterator;
    699      T* mItem;
    700 
    701     public:
    702      Item(Iterator* aIterator, T* aItem)
    703          : mIterator(aIterator), mItem(aItem) {}
    704 
    705      bool operator!=(const Item& aOther) const {
    706        return (mIterator != aOther.mIterator) || (mItem != aOther.mItem);
    707      }
    708 
    709      T* operator*() const { return mItem; }
    710 
    711      const Item& operator++() {
    712        mItem = mIterator->Next();
    713        return *this;
    714      }
    715    };
    716 
    717    Item<Iterator> begin() { return Item<Iterator>(this, Current()); }
    718 
    719    Item<Iterator> end() { return Item<Iterator>(this, nullptr); }
    720 
    721    T* Next() {
    722      TreeNode node;
    723      if ((node = mPath[mDepth - 1].Right())) {
    724        // The successor is the left-most node in the right subtree.
    725        mPath[mDepth++] = node;
    726        while ((node = mPath[mDepth - 1].Left())) {
    727          mPath[mDepth++] = node;
    728        }
    729      } else {
    730        // The successor is above the current node.  Unwind until a
    731        // left-leaning edge is removed from the path, of the path is empty.
    732        for (mDepth--; mDepth > 0; mDepth--) {
    733          if (mPath[mDepth - 1].Left() == mPath[mDepth]) {
    734            break;
    735          }
    736        }
    737      }
    738      return Current();
    739    }
    740 
    741    T* Current() { return mDepth > 0 ? mPath[mDepth - 1].Get() : nullptr; }
    742 
    743    bool NotDone() { return !!mDepth; }
    744  };
    745 
    746  Iterator iter() { return Iterator(this); }
    747 };
    748 
    749 #endif  // RB_H_