LTP GCOV extension - code coverage report
Current view: directory - include/stx - btree.h
Test: STX B+ Tree Testsuite
Date: 2008-09-07 Instrumented lines: 1047
Code covered: 91.9 % Executed lines: 962
Legend: not executed executed

       1                 : // $Id: btree.h 113 2008-09-07 15:25:51Z tb $
       2                 : /** \file btree.h
       3                 :  * Contains the main B+ tree implementation template class btree.
       4                 :  */
       5                 : 
       6                 : /*
       7                 :  * STX B+ Tree Template Classes v0.8.3
       8                 :  * Copyright (C) 2008 Timo Bingmann
       9                 :  *
      10                 :  * This library is free software; you can redistribute it and/or modify it
      11                 :  * under the terms of the GNU Lesser General Public License as published by the
      12                 :  * Free Software Foundation; either version 2.1 of the License, or (at your
      13                 :  * option) any later version.
      14                 :  *
      15                 :  * This library is distributed in the hope that it will be useful, but WITHOUT
      16                 :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17                 :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
      18                 :  * for more details.
      19                 :  *
      20                 :  * You should have received a copy of the GNU Lesser General Public License
      21                 :  * along with this library; if not, write to the Free Software Foundation,
      22                 :  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      23                 :  */
      24                 : 
      25                 : #ifndef _STX_BTREE_H_
      26                 : #define _STX_BTREE_H_
      27                 : 
      28                 : // *** Required Headers from the STL
      29                 : 
      30                 : #include <algorithm>
      31                 : #include <functional>
      32                 : #include <istream>
      33                 : #include <ostream>
      34                 : #include <assert.h>
      35                 : 
      36                 : // *** Debugging Macros
      37                 : 
      38                 : #ifdef BTREE_DEBUG
      39                 : 
      40                 : #include <iostream>
      41                 : 
      42                 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
      43                 : #define BTREE_PRINT(x)          do { if (debug) (std::cout << x); } while(0)
      44                 : 
      45                 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
      46                 : #define BTREE_ASSERT(x)         do { assert(x); } while(0)
      47                 : 
      48                 : #else
      49                 : 
      50                 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
      51                 : #define BTREE_PRINT(x)          do { } while(0)
      52                 : 
      53                 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
      54                 : #define BTREE_ASSERT(x)         do { } while(0)
      55                 : 
      56                 : #endif
      57                 : 
      58                 : /// The maximum of a and b. Used in some compile-time formulas.
      59                 : #define BTREE_MAX(a,b)          ((a) < (b) ? (b) : (a))
      60                 : 
      61                 : #ifndef BTREE_FRIENDS
      62                 : /// The macro BTREE_FRIENDS can be used by outside class to access the B+
      63                 : /// tree internals. This was added for wxBTreeDemo to be able to draw the
      64                 : /// tree.
      65                 : #define BTREE_FRIENDS           friend class btree_friend;
      66                 : #endif
      67                 : 
      68                 : /// STX - Some Template Extensions namespace
      69                 : namespace stx {
      70                 : 
      71                 : /** Generates default traits for a B+ tree used as a set. It estimates leaf and
      72                 :  * inner node sizes by assuming a cache line size of 256 bytes. */
      73                 : template <typename _Key>
      74                 : struct btree_default_set_traits
      75                 : {
      76                 :     /// If true, the tree will self verify it's invariants after each insert()
      77                 :     /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
      78                 :     static const bool   selfverify = false;
      79                 : 
      80                 :     /// If true, the tree will print out debug information and a tree dump
      81                 :     /// during insert() or erase() operation. The header must have been
      82                 :     /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
      83                 :     /// printable.
      84                 :     static const bool   debug = false;
      85                 : 
      86                 :     /// Number of slots in each leaf of the tree. Estimated so that each node
      87                 :     /// has a size of about 256 bytes.
      88                 :     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
      89                 : 
      90                 :     /// Number of slots in each inner node of the tree. Estimated so that each node
      91                 :     /// has a size of about 256 bytes.
      92                 :     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
      93                 : };
      94                 : 
      95                 : /** Generates default traits for a B+ tree used as a map. It estimates leaf and
      96                 :  * inner node sizes by assuming a cache line size of 256 bytes. */
      97                 : template <typename _Key, typename _Data>
      98                 : struct btree_default_map_traits
      99                 : {
     100                 :     /// If true, the tree will self verify it's invariants after each insert()
     101                 :     /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
     102                 :     static const bool   selfverify = false;
     103                 : 
     104                 :     /// If true, the tree will print out debug information and a tree dump
     105                 :     /// during insert() or erase() operation. The header must have been
     106                 :     /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
     107                 :     /// printable.
     108                 :     static const bool   debug = false;
     109                 : 
     110                 :     /// Number of slots in each leaf of the tree. Estimated so that each node
     111                 :     /// has a size of about 256 bytes.
     112                 :     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
     113                 : 
     114                 :     /// Number of slots in each inner node of the tree. Estimated so that each node
     115                 :     /// has a size of about 256 bytes.
     116                 :     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
     117                 : };
     118                 : 
     119                 : /** @brief Basic class implementing a base B+ tree data structure in memory.
     120                 :  *
     121                 :  * The base implementation of a memory B+ tree. It is based on the
     122                 :  * implementation in Cormen's Introduction into Algorithms, Jan Jannink's paper
     123                 :  * and other algorithm resources. Almost all STL-required function calls are
     124                 :  * implemented. The asymptotic time requirements of the STL are not always
     125                 :  * fulfilled in theory, however in practice this B+ tree performs better than a
     126                 :  * red-black tree by using more memory. The insertion function splits the nodes
     127                 :  * on the recursion unroll. Erase is largely based on Jannink's ideas.
     128                 :  *
     129                 :  * This class is specialized into btree_set, btree_multiset, btree_map and
     130                 :  * btree_multimap using default template parameters and facade functions.
     131                 :  */
     132                 : template <typename _Key, typename _Data,
     133                 :           typename _Value = std::pair<_Key, _Data>,
     134                 :           typename _Compare = std::less<_Key>,
     135                 :           typename _Traits = btree_default_map_traits<_Key, _Data>,
     136                 :           bool _Duplicates = false>
     137                 : class btree
     138                 : {
     139                 : public:
     140                 :     // *** Template Parameter Types
     141                 : 
     142                 :     /// First template parameter: The key type of the B+ tree. This is stored
     143                 :     /// in inner nodes and leaves
     144                 :     typedef _Key                        key_type;
     145                 : 
     146                 :     /// Second template parameter: The data type associated with each
     147                 :     /// key. Stored in the B+ tree's leaves
     148                 :     typedef _Data                       data_type;
     149                 : 
     150                 :     /// Third template parameter: Composition pair of key and data types, this
     151                 :     /// is required by the STL standard. The B+ tree does not store key and
     152                 :     /// data together. If value_type == key_type then the B+ tree implements a
     153                 :     /// set.
     154                 :     typedef _Value                      value_type;
     155                 : 
     156                 :     /// Fourth template parameter: Key comparison function object
     157                 :     typedef _Compare                    key_compare;
     158                 : 
     159                 :     /// Fifth template parameter: Traits object used to define more parameters
     160                 :     /// of the B+ tree
     161                 :     typedef _Traits                     traits;
     162                 : 
     163                 :     /// Sixth template parameter: Allow duplicate keys in the B+ tree. Used to
     164                 :     /// implement multiset and multimap.
     165                 :     static const bool                   allow_duplicates = _Duplicates;
     166                 : 
     167                 :     // The macro BTREE_FRIENDS can be used by outside class to access the B+
     168                 :     // tree internals. This was added for wxBTreeDemo to be able to draw the
     169                 :     // tree.
     170                 :     BTREE_FRIENDS
     171                 : 
     172                 : public:
     173                 :     // *** Constructed Types
     174                 : 
     175                 :     /// Typedef of our own type
     176                 :     typedef btree<key_type, data_type, value_type,
     177                 :                   key_compare, traits, allow_duplicates>        btree_self;
     178                 : 
     179                 :     /// Size type used to count keys
     180                 :     typedef size_t                              size_type;
     181                 : 
     182                 :     /// The pair of key_type and data_type, this may be different from value_type.
     183                 :     typedef std::pair<key_type, data_type>      pair_type;
     184                 : 
     185                 : public:
     186                 :     // *** Static Constant Options and Values of the B+ Tree
     187                 : 
     188                 :     /// Base B+ tree parameter: The number of key/data slots in each leaf
     189                 :     static const unsigned short         leafslotmax =  traits::leafslots;
     190                 : 
     191                 :     /// Base B+ tree parameter: The number of key slots in each inner node,
     192                 :     /// this can differ from slots in each leaf.
     193                 :     static const unsigned short         innerslotmax =  traits::innerslots;
     194                 : 
     195                 :     /// Computed B+ tree parameter: The minimum number of key/data slots used
     196                 :     /// in a leaf. If fewer slots are used, the leaf will be merged or slots
     197                 :     /// shifted from it's siblings.
     198                 :     static const unsigned short minleafslots = (leafslotmax / 2);
     199                 : 
     200                 :     /// Computed B+ tree parameter: The minimum number of key slots used
     201                 :     /// in an inner node. If fewer slots are used, the inner node will be
     202                 :     /// merged or slots shifted from it's siblings.
     203                 :     static const unsigned short mininnerslots = (innerslotmax / 2);
     204                 : 
     205                 :     /// Debug parameter: Enables expensive and thorough checking of the B+ tree
     206                 :     /// invariants after each insert/erase operation.
     207                 :     static const bool                   selfverify = traits::selfverify;
     208                 : 
     209                 :     /// Debug parameter: Prints out lots of debug information about how the
     210                 :     /// algorithms change the tree. Requires the header file to be compiled
     211                 :     /// with BTREE_DEBUG and the key type must be std::ostream printable.
     212                 :     static const bool                   debug = traits::debug;
     213                 : 
     214                 : private:
     215                 :     // *** Node Classes for In-Memory Nodes
     216                 : 
     217                 :     /// The header structure of each node in-memory. This structure is extended
     218                 :     /// by inner_node or leaf_node.
     219                 :     struct node
     220             386 :     {
     221                 :         /// Level in the b-tree, if level == 0 -> leaf node
     222                 :         unsigned short  level;
     223                 : 
     224                 :         /// Number of key slotuse use, so number of valid children or data
     225                 :         /// pointers
     226                 :         unsigned short  slotuse;
     227                 : 
     228                 :         /// Delayed initialisation of constructed node
     229           11214 :         inline void initialize(const unsigned short l)
     230                 :         {
     231           11214 :             level = l;
     232           11214 :             slotuse = 0;
     233                 :         }
     234                 : 
     235                 :         /// True if this is a leaf node
     236        66459245 :         inline bool isleafnode() const
     237                 :         {
     238        66459245 :             return (level == 0);
     239                 :         }
     240                 :     };
     241                 : 
     242                 :     /// Extended structure of a inner node in-memory. Contains only keys and no
     243                 :     /// data items.
     244                 :     struct inner_node : public node
     245              89 :     {
     246                 :         /// Keys of children or data pointers
     247                 :         key_type        slotkey[innerslotmax];
     248                 : 
     249                 :         /// Pointers to children
     250                 :         node*           childid[innerslotmax+1];
     251                 : 
     252                 :         /// Set variables to initial values
     253            1943 :         inline void initialize(const unsigned short l)
     254                 :         {
     255            1943 :             node::initialize(l);
     256                 :         }
     257                 : 
     258                 :         /// True if the node's slots are full
     259           10268 :         inline bool isfull() const
     260                 :         {
     261           10268 :             return (node::slotuse == innerslotmax);
     262                 :         }
     263                 : 
     264                 :         /// True if few used entries, less than half full
     265            4808 :         inline bool isfew() const
     266                 :         {
     267            4808 :             return (node::slotuse <= mininnerslots);
     268                 :         }
     269                 : 
     270                 :         /// True if node has too few entries
     271        12488813 :         inline bool isunderflow() const
     272                 :         {
     273        12488813 :             return (node::slotuse < mininnerslots);
     274                 :         }
     275                 :     };
     276                 : 
     277                 :     /// Extended structure of a leaf node in memory. Contains pairs of keys and
     278                 :     /// data items. Key and data slots are kept in separate arrays, because the
     279                 :     /// key array is traversed very often compared to accessing the data items.
     280                 :     struct leaf_node : public node
     281             618 :     {
     282                 :         /// Double linked list pointers to traverse the leaves
     283                 :         leaf_node       *prevleaf;
     284                 : 
     285                 :         /// Double linked list pointers to traverse the leaves
     286                 :         leaf_node       *nextleaf;
     287                 : 
     288                 :         /// Keys of children or data pointers
     289                 :         key_type        slotkey[leafslotmax];
     290                 : 
     291                 :         /// Array of data
     292                 :         data_type       slotdata[leafslotmax];
     293                 : 
     294                 :         /// Set variables to initial values
     295            9271 :         inline void initialize()
     296                 :         {
     297            9271 :             node::initialize(0);
     298            9271 :             prevleaf = nextleaf = NULL;
     299                 :         }
     300                 : 
     301                 :         /// True if the node's slots are full
     302           40242 :         inline bool isfull() const
     303                 :         {
     304           40242 :             return (node::slotuse == leafslotmax);
     305                 :         }
     306                 : 
     307                 :         /// True if few used entries, less than half full
     308           21024 :         inline bool isfew() const
     309                 :         {
     310           21024 :             return (node::slotuse <= minleafslots);
     311                 :         }
     312                 : 
     313                 :         /// True if node has too few entries
     314        52872079 :         inline bool isunderflow() const
     315                 :         {
     316        52872079 :             return (node::slotuse < minleafslots);
     317                 :         }
     318                 :     };
     319                 : 
     320                 : private:
     321                 :     // *** Template Magic to Convert a pair or key/data types to a value_type
     322                 : 
     323                 :     /// \internal For sets the second pair_type is an empty struct, so the
     324                 :     /// value_type should only be the first.
     325                 :     template <typename value_type, typename pair_type>
     326                 :     struct btree_pair_to_value
     327                 :     {
     328                 :         /// Convert a fake pair type to just the first component
     329                 :         inline value_type operator()(pair_type& p) const {
     330                 :             return p.first;
     331                 :         }
     332                 :         /// Convert a fake pair type to just the first component
     333           32316 :         inline value_type operator()(const pair_type& p) const {
     334           32316 :             return p.first;
     335                 :         }
     336                 :     };
     337                 : 
     338                 :     /// \internal For maps value_type is the same as the pair_type
     339                 :     template <typename value_type>
     340                 :     struct btree_pair_to_value<value_type, value_type>
     341                 :     {
     342                 :         /// Identity "convert" a real pair type to just the first component
     343                 :         inline value_type operator()(pair_type& p) const {
     344                 :             return p;
     345                 :         }
     346                 :         /// Identity "convert" a real pair type to just the first component
     347           45476 :         inline value_type operator()(const pair_type& p) const {
     348           45476 :             return p;
     349                 :         }
     350                 :     };
     351                 : 
     352                 :     /// Using template specialization select the correct converter used by the
     353                 :     /// iterators
     354                 :     typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
     355                 : 
     356                 : public:
     357                 :     // *** Iterators and Reverse Iterators
     358                 : 
     359                 :     class iterator;
     360                 :     class const_iterator;
     361                 :     class reverse_iterator;
     362                 :     class const_reverse_iterator;
     363                 : 
     364                 :     /// STL-like iterator object for B+ tree items. The iterator points to a
     365                 :     /// specific slot number in a leaf.
     366                 :     class iterator
     367           13120 :     {
     368                 :     public:
     369                 :         // *** Types
     370                 : 
     371                 :         /// The key type of the btree. Returned by key().
     372                 :         typedef typename btree::key_type                key_type;
     373                 : 
     374                 :         /// The data type of the btree. Returned by data().
     375                 :         typedef typename btree::data_type               data_type;
     376                 : 
     377                 :         /// The value type of the btree. Returned by operator*().
     378                 :         typedef typename btree::value_type              value_type;
     379                 : 
     380                 :         /// The pair type of the btree.
     381                 :         typedef typename btree::pair_type               pair_type;
     382                 : 
     383                 :         /// Reference to the value_type. STL required.
     384                 :         typedef value_type&             reference;
     385                 : 
     386                 :         /// Pointer to the value_type. STL required.
     387                 :         typedef value_type*             pointer;
     388                 : 
     389                 :         /// STL-magic iterator category
     390                 :         typedef std::bidirectional_iterator_tag iterator_category;
     391                 : 
     392                 :         /// STL-magic
     393                 :         typedef ptrdiff_t               difference_type;
     394                 : 
     395                 :         /// Our own type
     396                 :         typedef iterator                self;
     397                 : 
     398                 :     private:
     399                 :         // *** Members
     400                 : 
     401                 :         /// The currently referenced leaf node of the tree
     402                 :         typename btree::leaf_node*      currnode;
     403                 : 
     404                 :         /// Current key/data slot referenced
     405                 :         unsigned short          currslot;
     406                 : 
     407                 :         /// Friendly to the const_iterator, so it may access the two data items directly.
     408                 :         friend class const_iterator;
     409                 : 
     410                 :         /// Also friendly to the reverse_iterator, so it may access the two data items directly.
     411                 :         friend class reverse_iterator;
     412                 : 
     413                 :         /// Also friendly to the const_reverse_iterator, so it may access the two data items directly.
     414                 :         friend class const_reverse_iterator;
     415                 : 
     416                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
     417                 :         /// operator->
     418                 :         mutable value_type              temp_value;
     419                 : 
     420                 :         // The macro BTREE_FRIENDS can be used by outside class to access the B+
     421                 :         // tree internals. This was added for wxBTreeDemo to be able to draw the
     422                 :         // tree.
     423                 :         BTREE_FRIENDS
     424                 : 
     425                 :     public:
     426                 :         // *** Methods
     427                 : 
     428                 :         /// Default-Constructor of a mutable iterator
     429               5 :         inline iterator()
     430               5 :             : currnode(NULL), currslot(0)
     431               5 :         { }
     432                 : 
     433                 :         /// Initializing-Constructor of a mutable iterator
     434          292786 :         inline iterator(typename btree::leaf_node *l, unsigned short s)
     435          292786 :             : currnode(l), currslot(s)
     436          292786 :         { }
     437                 : 
     438                 :         /// Copy-constructor from a reverse iterator
     439                 :         inline iterator(const reverse_iterator &it)
     440                 :             : currnode(it.currnode), currslot(it.currslot)
     441                 :         { }
     442                 : 
     443                 :         /// Dereference the iterator, this is not a value_type& because key and
     444                 :         /// value are not stored together
     445           10400 :         inline reference operator*() const
     446                 :         {
     447           10400 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     448                 :                                                          currnode->slotdata[currslot]) );
     449           10400 :             return temp_value;
     450                 :         }
     451                 : 
     452                 :         /// Dereference the iterator. Do not use this if possible, use key()
     453                 :         /// and data() instead. The B+ tree does not stored key and data
     454                 :         /// together.
     455            8676 :         inline pointer operator->() const
     456                 :         {
     457            8676 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     458                 :                                                          currnode->slotdata[currslot]) );
     459            8676 :             return &temp_value;
     460                 :         }
     461                 : 
     462                 :         /// Key of the current slot
     463           17360 :         inline const key_type& key() const
     464                 :         {
     465           17360 :             return currnode->slotkey[currslot];
     466                 :         }
     467                 : 
     468                 :         /// Writable reference to the current data object
     469               0 :         inline data_type& data() const
     470                 :         {
     471               0 :             return currnode->slotdata[currslot];
     472                 :         }
     473                 : 
     474                 :         /// Prefix++ advance the iterator to the next slot
     475           32161 :         inline self& operator++()
     476                 :         {
     477           32161 :             if (currslot + 1 < currnode->slotuse) {
     478           25125 :                 ++currslot;
     479                 :             }
     480            7036 :             else if (currnode->nextleaf != NULL) {
     481            7023 :                 currnode = currnode->nextleaf;
     482            7023 :                 currslot = 0;
     483                 :             }
     484                 :             else {
     485                 :                 // this is end()
     486              13 :                 currslot = currnode->slotuse;
     487                 :             }
     488                 : 
     489           32161 :             return *this;
     490                 :         }
     491                 : 
     492                 :         /// Postfix++ advance the iterator to the next slot
     493            2001 :         inline self operator++(int)
     494                 :         {
     495            2001 :             self tmp = *this;   // copy ourselves
     496                 : 
     497            2001 :             if (currslot + 1 < currnode->slotuse) {
     498            1502 :                 ++currslot;
     499                 :             }
     500             499 :             else if (currnode->nextleaf != NULL) {
     501             496 :                 currnode = currnode->nextleaf;
     502             496 :                 currslot = 0;
     503                 :             }
     504                 :             else {
     505                 :                 // this is end()
     506               3 :                 currslot = currnode->slotuse;
     507                 :             }
     508                 : 
     509                 :             return tmp;
     510                 :         }
     511                 : 
     512                 :         /// Prefix-- backstep the iterator to the last slot
     513            2007 :         inline self& operator--()
     514                 :         {
     515            2007 :             if (currslot > 0) {
     516            1510 :                 --currslot;
     517                 :             }
     518             497 :             else if (currnode->prevleaf != NULL) {
     519             496 :                 currnode = currnode->prevleaf;
     520             496 :                 currslot = currnode->slotuse - 1;
     521                 :             }
     522                 :             else {
     523                 :                 // this is begin()
     524               1 :                 currslot = 0;
     525                 :             }
     526                 : 
     527            2007 :             return *this;
     528                 :         }
     529                 : 
     530                 :         /// Postfix-- backstep the iterator to the last slot
     531            1999 :         inline self operator--(int)
     532                 :         {
     533            1999 :             self tmp = *this;   // copy ourselves
     534                 : 
     535            1999 :             if (currslot > 0) {
     536            1502 :                 --currslot;
     537                 :             }
     538             497 :             else if (currnode->prevleaf != NULL) {
     539             496 :                 currnode = currnode->prevleaf;
     540             496 :                 currslot = currnode->slotuse - 1;
     541                 :             }
     542                 :             else {
     543                 :                 // this is begin()
     544               1 :                 currslot = 0;
     545                 :             }
     546                 : 
     547                 :             return tmp;
     548                 :         }
     549                 : 
     550                 :         /// Equality of iterators
     551          100000 :         inline bool operator==(const self& x) const
     552                 :         {
     553          100000 :             return (x.currnode == currnode) && (x.currslot == currslot);
     554                 :         }
     555                 : 
     556                 :         /// Inequality of iterators
     557           38174 :         inline bool operator!=(const self& x) const
     558                 :         {
     559           38174 :             return (x.currnode != currnode) || (x.currslot != currslot);
     560                 :         }
     561                 :     };
     562                 : 
     563                 :     /// STL-like read-only iterator object for B+ tree items. The iterator
     564                 :     /// points to a specific slot number in a leaf.
     565                 :     class const_iterator
     566                 :     {
     567                 :     public:
     568                 :         // *** Types
     569                 : 
     570                 :         /// The key type of the btree. Returned by key().
     571                 :         typedef typename btree::key_type                key_type;
     572                 : 
     573                 :         /// The data type of the btree. Returned by data().
     574                 :         typedef typename btree::data_type               data_type;
     575                 : 
     576                 :         /// The value type of the btree. Returned by operator*().
     577                 :         typedef typename btree::value_type              value_type;
     578                 : 
     579                 :         /// The pair type of the btree.
     580                 :         typedef typename btree::pair_type               pair_type;
     581                 : 
     582                 :         /// Reference to the value_type. STL required.
     583                 :         typedef const value_type&               reference;
     584                 : 
     585                 :         /// Pointer to the value_type. STL required.
     586                 :         typedef const value_type*               pointer;
     587                 : 
     588                 :         /// STL-magic iterator category
     589                 :         typedef std::bidirectional_iterator_tag         iterator_category;
     590                 : 
     591                 :         /// STL-magic
     592                 :         typedef ptrdiff_t               difference_type;
     593                 : 
     594                 :         /// Our own type
     595                 :         typedef const_iterator          self;
     596                 : 
     597                 :     private:
     598                 :         // *** Members
     599                 : 
     600                 :         /// The currently referenced leaf node of the tree
     601                 :         const typename btree::leaf_node*        currnode;
     602                 : 
     603                 :         /// Current key/data slot referenced
     604                 :         unsigned short                  currslot;
     605                 : 
     606                 :         /// Friendly to the reverse_const_iterator, so it may access the two data items directly
     607                 :         friend class const_reverse_iterator;
     608                 : 
     609                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
     610                 :         /// operator->
     611                 :         mutable value_type              temp_value;
     612                 : 
     613                 :         // The macro BTREE_FRIENDS can be used by outside class to access the B+
     614                 :         // tree internals. This was added for wxBTreeDemo to be able to draw the
     615                 :         // tree.
     616                 :         BTREE_FRIENDS
     617                 : 
     618                 :     public:
     619                 :         // *** Methods
     620                 : 
     621                 :         /// Default-Constructor of a const iterator
     622               5 :         inline const_iterator()
     623               5 :             : currnode(NULL), currslot(0)
     624               5 :         { }
     625                 : 
     626                 :         /// Initializing-Constructor of a const iterator
     627              34 :         inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
     628              34 :             : currnode(l), currslot(s)
     629              34 :         { }
     630                 : 
     631                 :         /// Copy-constructor from a mutable iterator
     632           17700 :         inline const_iterator(const iterator &it)
     633           17700 :             : currnode(it.currnode), currslot(it.currslot)
     634           17700 :         { }
     635                 : 
     636                 :         /// Copy-constructor from a mutable reverse iterator
     637                 :         inline const_iterator(const reverse_iterator &it)
     638                 :             : currnode(it.currnode), currslot(it.currslot)
     639                 :         { }
     640                 : 
     641                 :         /// Copy-constructor from a const reverse iterator
     642                 :         inline const_iterator(const const_reverse_iterator &it)
     643                 :             : currnode(it.currnode), currslot(it.currslot)
     644                 :         { }
     645                 : 
     646                 :         /// Dereference the iterator. Do not use this if possible, use key()
     647                 :         /// and data() instead. The B+ tree does not stored key and data
     648                 :         /// together.
     649           10716 :         inline reference operator*() const
     650                 :         {
     651           10716 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     652                 :                                                          currnode->slotdata[currslot]) );
     653           10716 :             return temp_value;
     654                 :         }
     655                 : 
     656                 :         /// Dereference the iterator. Do not use this if possible, use key()
     657                 :         /// and data() instead. The B+ tree does not stored key and data
     658                 :         /// together.
     659            8000 :         inline pointer operator->() const
     660                 :         {
     661            8000 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
     662                 :                                                          currnode->slotdata[currslot]) );
     663            8000 :             return &temp_value;
     664                 :         }
     665                 : 
     666                 :         /// Key of the current slot
     667            4024 :         inline const key_type& key() const
     668                 :         {
     669            4024 :             return currnode->slotkey[currslot];
     670                 :         }
     671                 : 
     672                 :         /// Read-only reference to the current data object
     673                 :         inline const data_type& data() const
     674                 :         {
     675                 :             return currnode->slotdata[currslot];
     676                 :         }
     677                 : 
     678                 :         /// Prefix++ advance the iterator to the next slot
     679            6797 :         inline self& operator++()
     680                 :         {
     681            6797 :             if (currslot + 1 < currnode->slotuse) {
     682            5464 :                 ++currslot;
     683                 :             }
     684            1333 :             else if (currnode->nextleaf != NULL) {
     685            1318 :                 currnode = currnode->nextleaf;
     686            1318 :                 currslot = 0;
     687                 :             }
     688                 :             else {
     689                 :                 // this is end()
     690              15 :                 currslot = currnode->slotuse;
     691                 :             }
     692                 : 
     693            6797 :             return *this;
     694                 :         }
     695                 : 
     696                 :         /// Postfix++ advance the iterator to the next slot
     697            2001 :         inline self operator++(int)
     698                 :         {
     699            2001 :             self tmp = *this;   // copy ourselves
     700                 : 
     701            2001 :             if (currslot + 1 < currnode->slotuse) {
     702            1502 :                 ++currslot;
     703                 :             }
     704             499 :             else if (currnode->nextleaf != NULL) {
     705             496 :                 currnode = currnode->nextleaf;
     706             496 :                 currslot = 0;
     707                 :             }
     708                 :             else {
     709                 :                 // this is end()
     710               3 :                 currslot = currnode->slotuse;
     711                 :             }
     712                 : 
     713                 :             return tmp;
     714                 :         }
     715                 : 
     716                 :         /// Prefix-- backstep the iterator to the last slot
     717            1999 :         inline self& operator--()
     718                 :         {
     719            1999 :             if (currslot > 0) {
     720            1502 :                 --currslot;
     721                 :             }
     722             497 :             else if (currnode->prevleaf != NULL) {
     723             496 :                 currnode = currnode->prevleaf;
     724             496 :                 currslot = currnode->slotuse - 1;
     725                 :             }
     726                 :             else {
     727                 :                 // this is begin()
     728               1 :                 currslot = 0;
     729                 :             }
     730                 : 
     731            1999 :             return *this;
     732                 :         }
     733                 : 
     734                 :         /// Postfix-- backstep the iterator to the last slot
     735            1999 :         inline self operator--(int)
     736                 :         {
     737            1999 :             self tmp = *this;   // copy ourselves
     738                 : 
     739            1999 :             if (currslot > 0) {
     740            1502 :                 --currslot;
     741                 :             }
     742             497 :             else if (currnode->prevleaf != NULL) {
     743             496 :                 currnode = currnode->prevleaf;
     744             496 :                 currslot = currnode->slotuse - 1;
     745                 :             }
     746                 :             else {
     747                 :                 // this is begin()
     748               1 :                 currslot = 0;
     749                 :             }
     750                 : 
     751                 :             return tmp;
     752                 :         }
     753                 : 
     754                 :         /// Equality of iterators
     755            4846 :         inline bool operator==(const self& x) const
     756                 :         {
     757            4846 :             return (x.currnode == currnode) && (x.currslot == currslot);
     758                 :         }
     759                 : 
     760                 :         /// Inequality of iterators
     761           11372 :         inline bool operator!=(const self& x) const
     762                 :         {
     763           11372 :             return (x.currnode != currnode) || (x.currslot != currslot);
     764                 :         }
     765                 :     };
     766                 : 
     767                 :     /// STL-like mutable reverse iterator object for B+ tree items. The
     768                 :     /// iterator points to a specific slot number in a leaf.
     769                 :     class reverse_iterator
     770                 :     {
     771                 :     public:
     772                 :         // *** Types
     773                 : 
     774                 :         /// The key type of the btree. Returned by key().
     775                 :         typedef typename btree::key_type                key_type;
     776                 : 
     777                 :         /// The data type of the btree. Returned by data().
     778                 :         typedef typename btree::data_type               data_type;
     779                 : 
     780                 :         /// The value type of the btree. Returned by operator*().
     781                 :         typedef typename btree::value_type              value_type;
     782                 : 
     783                 :         /// The pair type of the btree.
     784                 :         typedef typename btree::pair_type               pair_type;
     785                 : 
     786                 :         /// Reference to the value_type. STL required.
     787                 :         typedef value_type&             reference;
     788                 : 
     789                 :         /// Pointer to the value_type. STL required.
     790                 :         typedef value_type*             pointer;
     791                 : 
     792                 :         /// STL-magic iterator category
     793                 :         typedef std::bidirectional_iterator_tag iterator_category;
     794                 : 
     795                 :         /// STL-magic
     796                 :         typedef ptrdiff_t               difference_type;
     797                 : 
     798                 :         /// Our own type
     799                 :         typedef reverse_iterator        self;
     800                 : 
     801                 :     private:
     802                 :         // *** Members
     803                 : 
     804                 :         /// The currently referenced leaf node of the tree
     805                 :         typename btree::leaf_node*      currnode;
     806                 : 
     807                 :         /// One slot past the current key/data slot referenced.
     808                 :         unsigned short          currslot;
     809                 : 
     810                 :         /// Friendly to the const_iterator, so it may access the two data items directly
     811                 :         friend class iterator;
     812                 : 
     813                 :         /// Also friendly to the const_iterator, so it may access the two data items directly
     814                 :         friend class const_iterator;
     815                 : 
     816                 :         /// Also friendly to the const_iterator, so it may access the two data items directly
     817                 :         friend class const_reverse_iterator;
     818                 : 
     819                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
     820                 :         /// operator->
     821                 :         mutable value_type              temp_value;
     822                 : 
     823                 :         // The macro BTREE_FRIENDS can be used by outside class to access the B+
     824                 :         // tree internals. This was added for wxBTreeDemo to be able to draw the
     825                 :         // tree.
     826                 :         BTREE_FRIENDS
     827                 : 
     828                 :     public:
     829                 :         // *** Methods
     830                 : 
     831                 :         /// Default-Constructor of a reverse iterator
     832               5 :         inline reverse_iterator()
     833               5 :             : currnode(NULL), currslot(0)
     834               5 :         { }
     835                 : 
     836                 :         /// Initializing-Constructor of a mutable reverse iterator
     837                 :         inline reverse_iterator(typename btree::leaf_node *l, unsigned short s)
     838                 :             : currnode(l), currslot(s)
     839                 :         { }
     840                 : 
     841                 :         /// Copy-constructor from a mutable iterator
     842           16048 :         inline reverse_iterator(const iterator &it)
     843           16048 :             : currnode(it.currnode), currslot(it.currslot)
     844           16048 :         { }
     845                 : 
     846                 :         /// Dereference the iterator, this is not a value_type& because key and
     847                 :         /// value are not stored together
     848           13600 :         inline reference operator*() const
     849                 :         {
     850           13600 :             BTREE_ASSERT(currslot > 0);
     851           13600 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1],
     852                 :                                                          currnode->slotdata[currslot - 1]) );
     853           13600 :             return temp_value;
     854                 :         }
     855                 : 
     856                 :         /// Dereference the iterator. Do not use this if possible, use key()
     857                 :         /// and data() instead. The B+ tree does not stored key and data
     858                 :         /// together.
     859           14400 :         inline pointer operator->() const
     860                 :         {
     861           14400 :             BTREE_ASSERT(currslot > 0);
     862           14400 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1],
     863                 :                                                          currnode->slotdata[currslot - 1]) );
     864           14400 :             return &temp_value;
     865                 :         }
     866                 : 
     867                 :         /// Key of the current slot
     868                 :         inline const key_type& key() const
     869                 :         {
     870                 :             BTREE_ASSERT(currslot > 0);
     871                 :             return currnode->slotkey[currslot - 1];
     872                 :         }
     873                 : 
     874                 :         /// Writable reference to the current data object
     875                 :         inline data_type& data() const
     876                 :         {
     877                 :             BTREE_ASSERT(currslot > 0);
     878                 :             return currnode->slotdata[currslot - 1];
     879                 :         }
     880                 : 
     881                 :         /// Prefix++ advance the iterator to the next slot
     882           18001 :         inline self& operator++()
     883                 :         {
     884           18001 :             if (currslot > 1) {
     885           14647 :                 --currslot;
     886                 :             }
     887            3354 :             else if (currnode->prevleaf != NULL) {
     888            3346 :                 currnode = currnode->prevleaf;
     889            3346 :                 currslot = currnode->slotuse;
     890                 :             }
     891                 :             else {
     892                 :                 // this is begin() == rend()
     893               8 :                 currslot = 0;
     894                 :             }
     895                 : 
     896           18001 :             return *this;
     897                 :         }
     898                 : 
     899                 :         /// Postfix++ advance the iterator to the next slot
     900            5201 :         inline self operator++(int)
     901                 :         {
     902            5201 :             self tmp = *this;   // copy ourselves
     903                 : 
     904            5201 :             if (currslot > 1) {
     905            4131 :                 --currslot;
     906                 :             }
     907            1070 :             else if (currnode->prevleaf != NULL) {
     908            1066 :                 currnode = currnode->prevleaf;
     909            1066 :                 currslot = currnode->slotuse;
     910                 :             }
     911                 :             else {
     912                 :                 // this is begin() == rend()
     913               4 :                 currslot = 0;
     914                 :             }
     915                 : 
     916                 :             return tmp;
     917                 :         }
     918                 : 
     919                 :         /// Prefix-- backstep the iterator to the last slot
     920            2007 :         inline self& operator--()
     921                 :         {
     922            2007 :             if (currslot < currnode->slotuse) {
     923            1510 :                 ++currslot;
     924                 :             }
     925             497 :             else if (currnode->nextleaf != NULL) {
     926             496 :                 currnode = currnode->nextleaf;
     927             496 :                 currslot = 1;
     928                 :             }
     929                 :             else {
     930                 :                 // this is end() == rbegin()
     931               1 :                 currslot = currnode->slotuse;
     932                 :             }
     933                 : 
     934            2007 :             return *this;
     935                 :         }
     936                 : 
     937                 :         /// Postfix-- backstep the iterator to the last slot
     938            1999 :         inline self operator--(int)
     939                 :         {
     940            1999 :             self tmp = *this;   // copy ourselves
     941                 : 
     942            1999 :             if (currslot < currnode->slotuse) {
     943            1502 :                 ++currslot;
     944                 :             }
     945             497 :             else if (currnode->nextleaf != NULL) {
     946             496 :                 currnode = currnode->nextleaf;
     947             496 :                 currslot = 1;
     948                 :             }
     949                 :             else {
     950                 :                 // this is end() == rbegin()
     951               1 :                 currslot = currnode->slotuse;
     952                 :             }
     953                 : 
     954                 :             return tmp;
     955                 :         }
     956                 : 
     957                 :         /// Equality of iterators
     958               6 :         inline bool operator==(const self& x) const
     959                 :         {
     960               6 :             return (x.currnode == currnode) && (x.currslot == currslot);
     961                 :         }
     962                 : 
     963                 :         /// Inequality of iterators
     964           20810 :         inline bool operator!=(const self& x) const
     965                 :         {
     966           20810 :             return (x.currnode != currnode) || (x.currslot != currslot);
     967                 :         }
     968                 :     };
     969                 : 
     970                 :     /// STL-like read-only reverse iterator object for B+ tree items. The
     971                 :     /// iterator points to a specific slot number in a leaf.
     972                 :     class const_reverse_iterator
     973                 :     {
     974                 :     public:
     975                 :         // *** Types
     976                 : 
     977                 :         /// The key type of the btree. Returned by key().
     978                 :         typedef typename btree::key_type                key_type;
     979                 : 
     980                 :         /// The data type of the btree. Returned by data().
     981                 :         typedef typename btree::data_type               data_type;
     982                 : 
     983                 :         /// The value type of the btree. Returned by operator*().
     984                 :         typedef typename btree::value_type              value_type;
     985                 : 
     986                 :         /// The pair type of the btree.
     987                 :         typedef typename btree::pair_type               pair_type;
     988                 : 
     989                 :         /// Reference to the value_type. STL required.
     990                 :         typedef const value_type&               reference;
     991                 : 
     992                 :         /// Pointer to the value_type. STL required.
     993                 :         typedef const value_type*               pointer;
     994                 : 
     995                 :         /// STL-magic iterator category
     996                 :         typedef std::bidirectional_iterator_tag         iterator_category;
     997                 : 
     998                 :         /// STL-magic
     999                 :         typedef ptrdiff_t               difference_type;
    1000                 : 
    1001                 :         /// Our own type
    1002                 :         typedef const_reverse_iterator  self;
    1003                 : 
    1004                 :     private:
    1005                 :         // *** Members
    1006                 : 
    1007                 :         /// The currently referenced leaf node of the tree
    1008                 :         const typename btree::leaf_node*        currnode;
    1009                 : 
    1010                 :         /// One slot past the current key/data slot referenced.
    1011                 :         unsigned short                          currslot;
    1012                 : 
    1013                 :         /// Friendly to the const_iterator, so it may access the two data items directly.
    1014                 :         friend class reverse_iterator;
    1015                 : 
    1016                 :         /// Evil! A temporary value_type to STL-correctly deliver operator* and
    1017                 :         /// operator->
    1018                 :         mutable value_type              temp_value;
    1019                 : 
    1020                 :         // The macro BTREE_FRIENDS can be used by outside class to access the B+
    1021                 :         // tree internals. This was added for wxBTreeDemo to be able to draw the
    1022                 :         // tree.
    1023                 :         BTREE_FRIENDS
    1024                 : 
    1025                 :     public:
    1026                 :         // *** Methods
    1027                 : 
    1028                 :         /// Default-Constructor of a const reverse iterator
    1029               5 :         inline const_reverse_iterator()
    1030               5 :             : currnode(NULL), currslot(0)
    1031               5 :         { }
    1032                 : 
    1033                 :         /// Initializing-Constructor of a const reverse iterator
    1034                 :         inline const_reverse_iterator(const typename btree::leaf_node *l, unsigned short s)
    1035                 :             : currnode(l), currslot(s)
    1036                 :         { }
    1037                 : 
    1038                 :         /// Copy-constructor from a mutable iterator
    1039                 :         inline const_reverse_iterator(const iterator &it)
    1040                 :             : currnode(it.currnode), currslot(it.currslot)
    1041                 :         { }
    1042                 : 
    1043                 :         /// Copy-constructor from a const iterator
    1044               0 :         inline const_reverse_iterator(const const_iterator &it)
    1045               0 :             : currnode(it.currnode), currslot(it.currslot)
    1046               0 :         { }
    1047                 : 
    1048                 :         /// Copy-constructor from a mutable reverse iterator
    1049            8020 :         inline const_reverse_iterator(const reverse_iterator &it)
    1050            8020 :             : currnode(it.currnode), currslot(it.currslot)
    1051            8020 :         { }
    1052                 : 
    1053                 :         /// Dereference the iterator. Do not use this if possible, use key()
    1054                 :         /// and data() instead. The B+ tree does not stored key and data
    1055                 :         /// together.
    1056            4000 :         inline reference operator*() const
    1057                 :         {
    1058            4000 :             BTREE_ASSERT(currslot > 0);
    1059            4000 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1],
    1060                 :                                                          currnode->slotdata[currslot - 1]) );
    1061            4000 :             return temp_value;
    1062                 :         }
    1063                 : 
    1064                 :         /// Dereference the iterator. Do not use this if possible, use key()
    1065                 :         /// and data() instead. The B+ tree does not stored key and data
    1066                 :         /// together.
    1067            8000 :         inline pointer operator->() const
    1068                 :         {
    1069            8000 :             BTREE_ASSERT(currslot > 0);
    1070            8000 :             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1],
    1071                 :                                                          currnode->slotdata[currslot - 1]) );
    1072            8000 :             return &temp_value;
    1073                 :         }
    1074                 : 
    1075                 :         /// Key of the current slot
    1076                 :         inline const key_type& key() const
    1077                 :         {
    1078                 :             BTREE_ASSERT(currslot > 0);
    1079                 :             return currnode->slotkey[currslot - 1];
    1080                 :         }
    1081                 : 
    1082                 :         /// Read-only reference to the current data object
    1083                 :         inline const data_type& data() const
    1084                 :         {
    1085                 :             BTREE_ASSERT(currslot > 0);
    1086                 :             return currnode->slotdata[currslot - 1];
    1087                 :         }
    1088                 : 
    1089                 :         /// Prefix++ advance the iterator to the previous slot
    1090            2001 :         inline self& operator++()
    1091                 :         {
    1092            2001 :             if (currslot > 1) {
    1093            1502 :                 --currslot;
    1094                 :             }
    1095             499 :             else if (currnode->prevleaf != NULL) {
    1096             496 :                 currnode = currnode->prevleaf;
    1097             496 :                 currslot = currnode->slotuse;
    1098                 :             }
    1099                 :             else {
    1100                 :                 // this is begin() == rend()
    1101               3 :                 currslot = 0;
    1102                 :             }
    1103                 : 
    1104            2001 :             return *this;
    1105                 :         }
    1106                 : 
    1107                 :         /// Postfix++ advance the iterator to the previous slot
    1108            2001 :         inline self operator++(int)
    1109                 :         {
    1110            2001 :             self tmp = *this;   // copy ourselves
    1111                 : 
    1112            2001 :             if (currslot > 1) {
    1113            1502 :                 --currslot;
    1114                 :             }
    1115             499 :             else if (currnode->prevleaf != NULL) {
    1116             496 :                 currnode = currnode->prevleaf;
    1117             496 :                 currslot = currnode->slotuse;
    1118                 :             }
    1119                 :             else {
    1120                 :                 // this is begin() == rend()
    1121               3 :                 currslot = 0;
    1122                 :             }
    1123                 : 
    1124                 :             return tmp;
    1125                 :         }
    1126                 : 
    1127                 :         /// Prefix-- backstep the iterator to the next slot
    1128            1999 :         inline self& operator--()
    1129                 :         {
    1130            1999 :             if (currslot < currnode->slotuse) {
    1131            1502 :                 ++currslot;
    1132                 :             }
    1133             497 :             else if (currnode->nextleaf != NULL) {
    1134             496 :                 currnode = currnode->nextleaf;
    1135             496 :                 currslot = 1;
    1136                 :             }
    1137                 :             else {
    1138                 :                 // this is end() == rbegin()
    1139               1 :                 currslot = currnode->slotuse;
    1140                 :             }
    1141                 : 
    1142            1999 :             return *this;
    1143                 :         }
    1144                 : 
    1145                 :         /// Postfix-- backstep the iterator to the next slot
    1146            1999 :         inline self operator--(int)
    1147                 :         {
    1148            1999 :             self tmp = *this;   // copy ourselves
    1149                 : 
    1150            1999 :             if (currslot < currnode->slotuse) {
    1151            1502 :                 ++currslot;
    1152                 :             }
    1153             497 :             else if (currnode->nextleaf != NULL) {
    1154             496 :                 currnode = currnode->nextleaf;
    1155             496 :                 currslot = 1;
    1156                 :             }
    1157                 :             else {
    1158                 :                 // this is end() == rbegin()
    1159               1 :                 currslot = currnode->slotuse;
    1160                 :             }
    1161                 : 
    1162                 :             return tmp;
    1163                 :         }
    1164                 : 
    1165                 :         /// Equality of iterators
    1166               4 :         inline bool operator==(const self& x) const
    1167                 :         {
    1168               4 :             return (x.currnode == currnode) && (x.currslot == currslot);
    1169                 :         }
    1170                 : 
    1171                 :         /// Inequality of iterators
    1172            8004 :         inline bool operator!=(const self& x) const
    1173                 :         {
    1174            8004 :             return (x.currnode != currnode) || (x.currslot != currslot);
    1175                 :         }
    1176                 :     };
    1177                 : 
    1178                 : public:
    1179                 :     // *** Small Statistics Structure
    1180                 : 
    1181                 :     /** A small struct containing basic statistics about the B+ tree. It can be
    1182                 :      * fetched using get_stats(). */
    1183                 :     struct tree_stats
    1184                 :     {
    1185                 :         /// Number of items in the B+ tree
    1186                 :         size_type       itemcount;
    1187                 : 
    1188                 :         /// Number of leaves in the B+ tree
    1189                 :         size_type       leaves;
    1190                 : 
    1191                 :         /// Number of inner nodes in the B+ tree
    1192                 :         size_type       innernodes;
    1193                 : 
    1194                 :         /// Base B+ tree parameter: The number of key/data slots in each leaf
    1195                 :         static const unsigned short     leafslots = btree_self::leafslotmax;
    1196                 : 
    1197                 :         /// Base B+ tree parameter: The number of key slots in each inner node.
    1198                 :         static const unsigned short     innerslots = btree_self::innerslotmax;
    1199                 : 
    1200                 :         /// Zero initialized
    1201           84101 :         inline tree_stats()
    1202                 :             : itemcount(0),
    1203           84101 :               leaves(0), innernodes(0)
    1204           84101 :         {
    1205                 :         }
    1206                 : 
    1207                 :         /// Return the total number of nodes
    1208                 :         inline size_type nodes() const
    1209                 :         {
    1210                 :             return innernodes + leaves;
    1211                 :         }
    1212                 : 
    1213                 :         /// Return the average fill of leaves
    1214                 :         inline double avgfill_leaves() const
    1215                 :         {
    1216                 :             return static_cast<double>(itemcount) / (leaves * leafslots);
    1217                 :         }
    1218                 :     };
    1219                 : 
    1220                 : private:
    1221                 :     // *** Tree Object Data Members
    1222                 : 
    1223                 :     /// Pointer to the B+ tree's root node, either leaf or inner node
    1224                 :     node*       root;
    1225                 : 
    1226                 :     /// Pointer to first leaf in the double linked leaf chain
    1227                 :     leaf_node   *headleaf;
    1228                 : 
    1229                 :     /// Pointer to last leaf in the double linked leaf chain
    1230                 :     leaf_node   *tailleaf;
    1231                 : 
    1232                 :     /// Other small statistics about the B+ tree
    1233                 :     tree_stats  stats;
    1234                 : 
    1235                 :     /// Key comparison object. More comparison functions are generated from
    1236                 :     /// this < relation.
    1237                 :     key_compare key_less;
    1238                 : 
    1239                 : public:
    1240                 :     // *** Constructors and Destructor
    1241                 : 
    1242                 :     /// Default constructor initializing an empty B+ tree with the standard key
    1243                 :     /// comparison function
    1244              24 :     inline btree()
    1245              24 :         : root(NULL), headleaf(NULL), tailleaf(NULL)
    1246              24 :     {
    1247                 :     }
    1248                 : 
    1249                 :     /// Constructor initializing an empty B+ tree with a special key
    1250                 :     /// comparison object
    1251               1 :     inline btree(const key_compare &kcf)
    1252                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
    1253               1 :           key_less(kcf)
    1254               1 :     {
    1255                 :     }
    1256                 : 
    1257                 :     /// Constructor initializing a B+ tree with the range [first,last)
    1258                 :     template <class InputIterator>
    1259               1 :     inline btree(InputIterator first, InputIterator last)
    1260               1 :         : root(NULL), headleaf(NULL), tailleaf(NULL)
    1261                 :     {
    1262               1 :         insert(first, last);
    1263                 :     }
    1264                 : 
    1265                 :     /// Constructor initializing a B+ tree with the range [first,last) and a
    1266                 :     /// special key comparison object
    1267                 :     template <class InputIterator>
    1268                 :     inline btree(InputIterator first, InputIterator last, const key_compare &kcf)
    1269                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
    1270                 :           key_less(kcf)
    1271                 :     {
    1272                 :         insert(first, last);
    1273                 :     }
    1274                 : 
    1275                 :     /// Frees up all used B+ tree memory pages
    1276              29 :     inline ~btree()
    1277                 :     {
    1278              29 :         clear();
    1279                 :     }
    1280                 : 
    1281                 :     /// Fast swapping of two identical B+ tree objects.
    1282                 :     void swap(btree_self& from)
    1283                 :     {
    1284                 :         std::swap(root, from.root);
    1285                 :         std::swap(headleaf, from.headleaf);
    1286                 :         std::swap(tailleaf, from.tailleaf);
    1287                 :         std::swap(stats, from.stats);
    1288                 :         std::swap(key_less, from.key_less);
    1289                 :     }
    1290                 : 
    1291                 : public:
    1292                 :     // *** Key and Value Comparison Function Objects
    1293                 : 
    1294                 :     /// Function class to compare value_type objects. Required by the STL
    1295                 :     class value_compare
    1296                 :     {
    1297                 :     protected:
    1298                 :         /// Key comparison function from the template parameter
    1299                 :         key_compare     key_comp;
    1300                 : 
    1301                 :         /// Constructor called from btree::value_comp()
    1302               0 :         inline value_compare(key_compare kc)
    1303               0 :             : key_comp(kc)
    1304               0 :         { }
    1305                 : 
    1306                 :         /// Friendly to the btree class so it may call the constructor
    1307                 :         friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>;
    1308                 : 
    1309                 :     public:
    1310                 :         /// Function call "less"-operator resulting in true if x < y.
    1311                 :         inline bool operator()(const value_type& x, const value_type& y) const
    1312                 :         {
    1313                 :             return key_comp(x.first, y.first);
    1314                 :         }
    1315                 :     };
    1316                 : 
    1317                 :     /// Constant access to the key comparison object sorting the B+ tree
    1318               4 :     inline key_compare key_comp() const
    1319                 :     {
    1320               4 :         return key_less;
    1321                 :     }
    1322                 : 
    1323                 :     /// Constant access to a constructed value_type comparison object. Required
    1324                 :     /// by the STL
    1325               0 :     inline value_compare value_comp() const
    1326                 :     {
    1327               0 :         return value_compare(key_less);
    1328                 :     }
    1329                 : 
    1330                 : private:
    1331                 :     // *** Convenient Key Comparison Functions Generated From key_less
    1332                 : 
    1333                 :     /// True if a <= b ? constructed from key_less()
    1334       431410653 :     inline bool key_lessequal(const key_type &a, const key_type b) const
    1335                 :     {
    1336       431410653 :         return !key_less(b, a);
    1337                 :     }
    1338                 : 
    1339                 :     /// True if a > b ? constructed from key_less()
    1340                 :     inline bool key_greater(const key_type &a, const key_type &b) const
    1341                 :     {
    1342                 :         return key_less(b, a);
    1343                 :     }
    1344                 : 
    1345                 :     /// True if a >= b ? constructed from key_less()
    1346        52762356 :     inline bool key_greaterequal(const key_type &a, const key_type b) const
    1347                 :     {
    1348        52762356 :         return !key_less(a, b);
    1349                 :     }
    1350                 : 
    1351                 :     /// True if a == b ? constructed from key_less(). This requires the <
    1352                 :     /// relation to be a total order, otherwise the B+ tree cannot be sorted.
    1353        56085267 :     inline bool key_equal(const key_type &a, const key_type &b) const
    1354                 :     {
    1355        56085267 :         return !key_less(a, b) && !key_less(b, a);
    1356                 :     }
    1357                 : 
    1358                 : private:
    1359                 :     // *** Node Object Allocation and Deallocation Functions
    1360                 : 
    1361                 :     /// Allocate and initialize a leaf node
    1362            9271 :     inline leaf_node* allocate_leaf()
    1363                 :     {
    1364            9271 :         leaf_node* n = new leaf_node;
    1365            9271 :         n->initialize();
    1366            9271 :         stats.leaves++;
    1367            9271 :         return n;
    1368                 :     }
    1369                 : 
    1370                 :     /// Allocate and initialize an inner node
    1371            1943 :     inline inner_node* allocate_inner(unsigned short l)
    1372                 :     {
    1373            1943 :         inner_node* n = new inner_node;
    1374            1943 :         n->initialize(l);
    1375            1943 :         stats.innernodes++;
    1376            1943 :         return n;
    1377                 :     }
    1378                 : 
    1379                 :     /// Correctly free either inner or leaf node, destructs all contained key
    1380                 :     /// and value objects
    1381           11214 :     inline void free_node(node *n)
    1382                 :     {
    1383           11214 :         if (n->isleafnode()) {
    1384            9271 :             delete static_cast<leaf_node*>(n);
    1385            9271 :             stats.leaves--;
    1386                 :         }
    1387                 :         else {
    1388            1943 :             delete static_cast<inner_node*>(n);
    1389            1943 :             stats.innernodes--;
    1390                 :         }
    1391                 :     }
    1392                 : 
    1393                 : public:
    1394                 :     // *** Fast Destruction of the B+ Tree
    1395                 : 
    1396                 :     /// Frees all key/data pairs and all nodes of the tree
    1397              31 :     void clear()
    1398                 :     {
    1399              31 :         if (root)
    1400                 :         {
    1401              12 :             clear_recursive(root);
    1402              12 :             free_node(root);
    1403                 : 
    1404              12 :             root = NULL;
    1405              12 :             headleaf = tailleaf = NULL;
    1406                 : 
    1407              12 :             stats = tree_stats();
    1408                 :         }
    1409                 : 
    1410              31 :         BTREE_ASSERT(stats.itemcount == 0);
    1411                 :     }
    1412                 : 
    1413                 : private:
    1414                 :     /// Recursively free up nodes
    1415            4060 :     void clear_recursive(node *n)
    1416                 :     {
    1417            4060 :         if (n->isleafnode())
    1418                 :         {
    1419            3426 :             leaf_node *leafnode = static_cast<leaf_node*>(n);
    1420                 : 
    1421            3426 :             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
    1422                 :             {
    1423                 :                 // data objects are deleted by leaf_node's destructor
    1424                 :             }
    1425                 :         }
    1426                 :         else
    1427                 :         {
    1428             634 :             inner_node *innernode = static_cast<inner_node*>(n);
    1429                 : 
    1430            4682 :             for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
    1431                 :             {
    1432            4048 :                 clear_recursive(innernode->childid[slot]);
    1433            8108 :                 free_node(innernode->childid[slot]);
    1434                 :             }
    1435                 :         }
    1436                 :     }
    1437                 : 
    1438                 : public:
    1439                 :     // *** STL Iterator Construction Functions
    1440                 : 
    1441                 :     /// Constructs a read/data-write iterator that points to the first slot in
    1442                 :     /// the first leaf of the B+ tree.
    1443           16052 :     inline iterator begin()
    1444                 :     {
    1445           16052 :         return iterator(headleaf, 0);
    1446                 :     }
    1447                 : 
    1448                 :     /// Constructs a read/data-write iterator that points to the first invalid
    1449                 :     /// slot in the last leaf of the B+ tree.
    1450          139248 :     inline iterator end()
    1451                 :     {
    1452          139248 :         return iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0);
    1453                 :     }
    1454                 : 
    1455                 :     /// Constructs a read-only constant iterator that points to the first slot
    1456                 :     /// in the first leaf of the B+ tree.
    1457              20 :     inline const_iterator begin() const
    1458                 :     {
    1459              20 :         return const_iterator(headleaf, 0);
    1460                 :     }
    1461                 : 
    1462                 :     /// Constructs a read-only constant iterator that points to the first
    1463                 :     /// invalid slot in the last leaf of the B+ tree.
    1464              14 :     inline const_iterator end() const
    1465                 :     {
    1466              14 :         return const_iterator(tailleaf, tailleaf ? tailleaf->slotuse : 0);
    1467                 :     }
    1468                 : 
    1469                 :     /// Constructs a read/data-write reverse iterator that points to the first
    1470                 :     /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
    1471            8020 :     inline reverse_iterator rbegin()
    1472                 :     {
    1473            8020 :         return reverse_iterator(end());
    1474                 :     }
    1475                 : 
    1476                 :     /// Constructs a read/data-write reverse iterator that points to the first
    1477                 :     /// slot in the first leaf of the B+ tree. Uses STL magic.
    1478            8028 :     inline reverse_iterator rend()
    1479                 :     {
    1480            8028 :         return reverse_iterator(begin());
    1481                 :     }
    1482                 : 
    1483                 :     /// Constructs a read-only reverse iterator that points to the first
    1484                 :     /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
    1485               0 :     inline const_reverse_iterator rbegin() const
    1486                 :     {
    1487               0 :         return const_reverse_iterator(end());
    1488                 :     }
    1489                 : 
    1490                 :     /// Constructs a read-only reverse iterator that points to the first slot
    1491                 :     /// in the first leaf of the B+ tree. Uses STL magic.
    1492               0 :     inline const_reverse_iterator rend() const
    1493                 :     {
    1494               0 :         return const_reverse_iterator(begin());
    1495                 :     }
    1496                 : 
    1497                 : private:
    1498                 :     // *** B+ Tree Node Binary Search Functions
    1499                 : 
    1500                 :     /// Searches for the first key in the node n less or equal to key. Uses
    1501                 :     /// binary search with an optional linear self-verification. This is a
    1502                 :     /// template function, because the slotkey array is located at different
    1503                 :     /// places in leaf_node and inner_node.
    1504                 :     template <typename node_type>
    1505         1090374 :     inline int find_lower(const node_type *n, const key_type& key) const
    1506                 :     {
    1507         1090374 :         if (n->slotuse == 0) return 0;
    1508                 : 
    1509         1090353 :         int lo = 0,
    1510         1090353 :             hi = n->slotuse - 1;
    1511                 : 
    1512         4345083 :         while(lo < hi)
    1513                 :         {
    1514         2164377 :             int mid = (lo + hi) >> 1;
    1515                 : 
    1516         2164377 :             if (key_lessequal(key, n->slotkey[mid])) {
    1517          969644 :                 hi = mid - 1;
    1518                 :             }
    1519                 :             else {
    1520         1194733 :                 lo = mid + 1;
    1521                 :             }
    1522                 :         }
    1523                 : 
    1524         1090353 :         if (hi < 0 || key_less(n->slotkey[hi], key))
    1525          655730 :             hi++;
    1526                 : 
    1527                 :         BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
    1528                 : 
    1529                 :         // verify result using simple linear search
    1530                 :         if (selfverify)
    1531                 :         {
    1532          788089 :             int i = n->slotuse - 1;
    1533         3711262 :             while(i >= 0 && key_lessequal(key, n->slotkey[i]))
    1534         2135084 :                 i--;
    1535          788089 :             i++;
    1536                 : 
    1537                 :             BTREE_PRINT("testfind: " << i << std::endl);
    1538          788089 :             BTREE_ASSERT(i == hi);
    1539                 :         }
    1540                 :         else {
    1541                 :             BTREE_PRINT(std::endl);
    1542                 :         }
    1543                 : 
    1544         1090353 :         return hi;
    1545                 :     }
    1546                 : 
    1547                 :     /// Searches for the first key in the node n greater than key. Uses binary
    1548                 :     /// search with an optional linear self-verification. This is a template
    1549                 :     /// function, because the slotkey array is located at different places in
    1550                 :     /// leaf_node and inner_node.
    1551                 :     template <typename node_type>
    1552            7700 :     inline int find_upper(const node_type *n, const key_type& key) const
    1553                 :     {
    1554            7700 :         if (n->slotuse == 0) return 0;
    1555                 : 
    1556            7700 :         int lo = 0,
    1557            7700 :             hi = n->slotuse - 1;
    1558                 : 
    1559           30732 :         while(lo < hi)
    1560                 :         {
    1561           15332 :             int mid = (lo + hi) >> 1;
    1562                 : 
    1563           15332 :             if (key_less(key, n->slotkey[mid])) {
    1564            6026 :                 hi = mid - 1;
    1565                 :             }
    1566                 :             else {
    1567            9306 :                 lo = mid + 1;
    1568                 :             }
    1569                 :         }
    1570                 : 
    1571            7700 :         if (hi < 0 || key_lessequal(n->slotkey[hi], key))
    1572            4748 :             hi++;
    1573                 : 
    1574                 :         BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
    1575                 : 
    1576                 :         // verify result using simple linear search
    1577                 :         if (selfverify)
    1578                 :         {
    1579            7700 :             int i = n->slotuse - 1;
    1580           36122 :             while(i >= 0 && key_less(key, n->slotkey[i]))
    1581           20722 :                 i--;
    1582            7700 :             i++;
    1583                 : 
    1584                 :             BTREE_PRINT("btree::find_upper testfind: " << i << std::endl);
    1585            7700 :             BTREE_ASSERT(i == hi);
    1586                 :         }
    1587                 :         else {
    1588                 :             BTREE_PRINT(std::endl);
    1589                 :         }
    1590                 : 
    1591            7700 :         return hi;
    1592                 :     }
    1593                 : 
    1594                 : public:
    1595                 :     // *** Access Functions to the Item Count
    1596                 : 
    1597                 :     /// Return the number of key/data pairs in the B+ tree
    1598          172724 :     inline size_type size() const
    1599                 :     {
    1600          172724 :         return stats.itemcount;
    1601                 :     }
    1602                 : 
    1603                 :     /// Returns true if there is at least one key/data pair in the B+ tree
    1604              13 :     inline bool empty() const
    1605                 :     {
    1606              13 :         return (size() == size_type(0));
    1607                 :     }
    1608                 : 
    1609                 :     /// Returns the largest possible size of the B+ Tree. This is just a
    1610                 :     /// function required by the STL standard, the B+ Tree can hold more items.
    1611               0 :     inline size_type max_size() const
    1612                 :     {
    1613               0 :         return size_type(-1);
    1614                 :     }
    1615                 : 
    1616                 :     /// Return a const reference to the current statistics.
    1617               0 :     inline const struct tree_stats& get_stats() const
    1618                 :     {
    1619               0 :         return stats;
    1620                 :     }
    1621                 : 
    1622                 : public:
    1623                 :     // *** Standard Access Functions Querying the Tree by Descending to a Leaf
    1624                 : 
    1625                 :     /// Non-STL function checking whether a key is in the B+ tree. The same as
    1626                 :     /// (find(k) != end()) or (count() != 0).
    1627           69900 :     bool exists(const key_type &key) const
    1628                 :     {
    1629           69900 :         const node *n = root;
    1630           69900 :         if (!n) return false;
    1631                 : 
    1632          406817 :         while(!n->isleafnode())
    1633                 :         {
    1634          267017 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1635          267017 :             int slot = find_lower(inner, key);
    1636                 : 
    1637          267017 :             n = inner->childid[slot];
    1638                 :         }
    1639                 : 
    1640           69900 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1641                 : 
    1642           69900 :         int slot = find_lower(leaf, key);
    1643           69900 :         return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot]));
    1644                 :     }
    1645                 : 
    1646                 :     /// Tries to locate a key in the B+ tree and returns an iterator to the
    1647                 :     /// key/data slot if found. If unsuccessful it returns end().
    1648          100666 :     iterator find(const key_type &key)
    1649                 :     {
    1650          100666 :         node *n = root;
    1651          100666 :         if (!n) return end();
    1652                 : 
    1653          402693 :         while(!n->isleafnode())
    1654                 :         {
    1655          201363 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1656          201363 :             int slot = find_lower(inner, key);
    1657                 : 
    1658          201363 :             n = inner->childid[slot];
    1659                 :         }
    1660                 : 
    1661          100665 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1662                 : 
    1663          100665 :         int slot = find_lower(leaf, key);
    1664                 :         return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot]))
    1665          100665 :             ? iterator(leaf, slot) : end();
    1666                 :     }
    1667                 : 
    1668                 :     /// Tries to locate a key in the B+ tree and returns an constant iterator
    1669                 :     /// to the key/data slot if found. If unsuccessful it returns end().
    1670               0 :     const_iterator find(const key_type &key) const
    1671                 :     {
    1672               0 :         const node *n = root;
    1673               0 :         if (!n) return end();
    1674                 : 
    1675               0 :         while(!n->isleafnode())
    1676                 :         {
    1677               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1678               0 :             int slot = find_lower(inner, key);
    1679                 : 
    1680               0 :             n = inner->childid[slot];
    1681                 :         }
    1682                 : 
    1683               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1684                 : 
    1685               0 :         int slot = find_lower(leaf, key);
    1686                 :         return (slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot]))
    1687               0 :             ? const_iterator(leaf, slot) : end();
    1688                 :     }
    1689                 : 
    1690                 :     /// Tries to locate a key in the B+ tree and returns the number of
    1691                 :     /// identical key entries found.
    1692           34720 :     size_type count(const key_type &key) const
    1693                 :     {
    1694           34720 :         const node *n = root;
    1695           34720 :         if (!n) return 0;
    1696                 : 
    1697          214767 :         while(!n->isleafnode())
    1698                 :         {
    1699          145327 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1700          145327 :             int slot = find_lower(inner, key);
    1701                 : 
    1702          145327 :             n = inner->childid[slot];
    1703                 :         }
    1704                 : 
    1705           34720 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1706                 : 
    1707           34720 :         int slot = find_lower(leaf, key);
    1708           34720 :         size_type num = 0;
    1709                 : 
    1710         3173397 :         while (leaf && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot]))
    1711                 :         {
    1712         3103957 :             ++num;
    1713         3103957 :             if (++slot >= leaf->slotuse)
    1714                 :             {
    1715          775421 :                 leaf = leaf->nextleaf;
    1716          775421 :                 slot = 0;
    1717                 :             }
    1718                 :         }
    1719                 : 
    1720           34720 :         return num;
    1721                 :     }
    1722                 : 
    1723                 :     /// Searches the B+ tree and returns an iterator to the first key less or
    1724                 :     /// equal to the parameter. If unsuccessful it returns end().
    1725            2420 :     iterator lower_bound(const key_type& key)
    1726                 :     {
    1727            2420 :         node *n = root;
    1728            2420 :         if (!n) return end();
    1729                 : 
    1730           10120 :         while(!n->isleafnode())
    1731                 :         {
    1732            5280 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1733            5280 :             int slot = find_lower(inner, key);
    1734                 : 
    1735            5280 :             n = inner->childid[slot];
    1736                 :         }
    1737                 : 
    1738            2420 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1739                 : 
    1740            2420 :         int slot = find_lower(leaf, key);
    1741            2420 :         return iterator(leaf, slot);
    1742                 :     }
    1743                 : 
    1744                 :     /// Searches the B+ tree and returns an constant iterator to the first key less or
    1745                 :     /// equal to the parameter. If unsuccessful it returns end().
    1746               0 :     const_iterator lower_bound(const key_type& key) const
    1747                 :     {
    1748               0 :         const node *n = root;
    1749               0 :         if (!n) return end();
    1750                 : 
    1751               0 :         while(!n->isleafnode())
    1752                 :         {
    1753               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1754               0 :             int slot = find_lower(inner, key);
    1755                 : 
    1756               0 :             n = inner->childid[slot];
    1757                 :         }
    1758                 : 
    1759               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1760                 : 
    1761               0 :         int slot = find_lower(leaf, key);
    1762               0 :         return const_iterator(leaf, slot);
    1763                 :     }
    1764                 : 
    1765                 :     /// Searches the B+ tree and returns an iterator to the first key greater
    1766                 :     /// than the parameter. If unsuccessful it returns end().
    1767            2420 :     iterator upper_bound(const key_type& key)
    1768                 :     {
    1769            2420 :         node *n = root;
    1770            2420 :         if (!n) return end();
    1771                 : 
    1772           10120 :         while(!n->isleafnode())
    1773                 :         {
    1774            5280 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1775            5280 :             int slot = find_upper(inner, key);
    1776                 : 
    1777            5280 :             n = inner->childid[slot];
    1778                 :         }
    1779                 : 
    1780            2420 :         leaf_node *leaf = static_cast<leaf_node*>(n);
    1781                 : 
    1782            2420 :         int slot = find_upper(leaf, key);
    1783            2420 :         return iterator(leaf, slot);
    1784                 :     }
    1785                 : 
    1786                 :     /// Searches the B+ tree and returns an constant iterator to the first key
    1787                 :     /// greater than the parameter. If unsuccessful it returns end().
    1788               0 :     const_iterator upper_bound(const key_type& key) const
    1789                 :     {
    1790               0 :         const node *n = root;
    1791               0 :         if (!n) return end();
    1792                 : 
    1793               0 :         while(!n->isleafnode())
    1794                 :         {
    1795               0 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1796               0 :             int slot = find_upper(inner, key);
    1797                 : 
    1798               0 :             n = inner->childid[slot];
    1799                 :         }
    1800                 : 
    1801               0 :         const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1802                 : 
    1803               0 :         int slot = find_upper(leaf, key);
    1804               0 :         return const_iterator(leaf, slot);
    1805                 :     }
    1806                 : 
    1807                 :     /// Searches the B+ tree and returns both lower_bound() and upper_bound().
    1808            1210 :     inline std::pair<iterator, iterator> equal_range(const key_type& key)
    1809                 :     {
    1810            1210 :         return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
    1811                 :     }
    1812                 : 
    1813                 :     /// Searches the B+ tree and returns both lower_bound() and upper_bound().
    1814               0 :     inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
    1815                 :     {
    1816               0 :         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
    1817                 :     }
    1818                 : 
    1819                 : public:
    1820                 :     // *** B+ Tree Object Comparison Functions
    1821                 : 
    1822                 :     /// Equality relation of B+ trees of the same type. B+ trees of the same
    1823                 :     /// size and equal elements (both key and data) are considered
    1824                 :     /// equal. Beware of the random ordering of duplicate keys.
    1825               6 :     inline bool operator==(const btree_self &other) const
    1826                 :     {
    1827               6 :         return (size() == other.size()) && std::equal(begin(), end(), other.begin());
    1828                 :     }
    1829                 : 
    1830                 :     /// Inequality relation. Based on operator==.
    1831               1 :     inline bool operator!=(const btree_self &other) const
    1832                 :     {
    1833               1 :         return !(*this == other);
    1834                 :     }
    1835                 : 
    1836                 :     /// Total ordering relation of B+ trees of the same type. It uses
    1837                 :     /// std::lexicographical_compare() for the actual comparison of elements.
    1838               4 :     inline bool operator<(const btree_self &other) const
    1839                 :     {
    1840               4 :         return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    1841                 :     }
    1842                 : 
    1843                 :     /// Greater relation. Based on operator<.
    1844               1 :     inline bool operator>(const btree_self &other) const
    1845                 :     {
    1846               1 :         return other < *this;
    1847                 :     }
    1848                 : 
    1849                 :     /// Less-equal relation. Based on operator<.
    1850               1 :     inline bool operator<=(const btree_self &other) const
    1851                 :     {
    1852               1 :         return !(other < *this);
    1853                 :     }
    1854                 : 
    1855                 :     /// Greater-equal relation. Based on operator<.
    1856               1 :     inline bool operator>=(const btree_self &other) const
    1857                 :     {
    1858               1 :         return !(*this < other);
    1859                 :     }
    1860                 : 
    1861                 : public:
    1862                 :     /// *** Fast Copy: Assign Operator and Copy Constructors
    1863                 : 
    1864                 :     /// Assignment operator. All the key/data pairs are copied
    1865               1 :     inline btree_self& operator= (const btree_self &other)
    1866                 :     {
    1867               1 :         if (this != &other)
    1868                 :         {
    1869               1 :             clear();
    1870                 : 
    1871               1 :             key_less = other.key_comp();
    1872               1 :             if (other.size() != 0)
    1873                 :             {
    1874               1 :                 stats.leaves = stats.innernodes = 0;
    1875               1 :                 if (other.root) {
    1876               1 :                     root = copy_recursive(other.root);
    1877                 :                 }
    1878               1 :                 stats = other.stats;
    1879                 :             }
    1880                 : 
    1881               1 :             if (selfverify) verify();
    1882                 :         }
    1883               1 :         return *this;
    1884                 :     }
    1885                 : 
    1886                 :     /// Copy constructor. The newly initialized B+ tree object will contain a
    1887                 :     /// copy of all key/data pairs.
    1888               3 :     inline btree(const btree_self &other)
    1889                 :         : root(NULL), headleaf(NULL), tailleaf(NULL),
    1890                 :           stats( other.stats ),
    1891               3 :           key_less( other.key_comp() )
    1892                 :     {
    1893               3 :         if (size() > 0)
    1894                 :         {
    1895               3 :             stats.leaves = stats.innernodes = 0;
    1896               3 :             if (other.root) {
    1897               3 :                 root = copy_recursive(other.root);
    1898                 :             }
    1899               3 :             if (selfverify) verify();
    1900                 :         }
    1901                 :     }
    1902                 : 
    1903                 : private:
    1904                 :     /// Recursively copy nodes from another B+ tree object
    1905            1474 :     struct node* copy_recursive(const node *n)
    1906                 :     {
    1907            1474 :         if (n->isleafnode())
    1908                 :         {
    1909            1254 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    1910            1254 :             leaf_node *newleaf = allocate_leaf();
    1911                 : 
    1912            1254 :             newleaf->slotuse = leaf->slotuse;
    1913            1254 :             std::copy(leaf->slotkey, leaf->slotkey + leaf->slotuse, newleaf->slotkey);
    1914            1254 :             std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse, newleaf->slotdata);
    1915                 : 
    1916            1254 :             if (headleaf == NULL)
    1917                 :             {
    1918               4 :                 headleaf = tailleaf = newleaf;
    1919               4 :                 newleaf->prevleaf = newleaf->nextleaf = NULL;
    1920                 :             }
    1921                 :             else
    1922                 :             {
    1923            1250 :                 newleaf->prevleaf = tailleaf;
    1924            1250 :                 tailleaf->nextleaf = newleaf;
    1925            1250 :                 tailleaf = newleaf;
    1926                 :             }
    1927                 : 
    1928            1254 :             return newleaf;
    1929                 :         }
    1930                 :         else
    1931                 :         {
    1932             220 :             const inner_node *inner = static_cast<const inner_node*>(n);
    1933             220 :             inner_node *newinner = allocate_inner(inner->level);
    1934                 : 
    1935             220 :             newinner->slotuse = inner->slotuse;
    1936             220 :             std::copy(inner->slotkey, inner->slotkey + inner->slotuse, newinner->slotkey);
    1937                 : 
    1938            1690 :             for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    1939                 :             {
    1940            1470 :                 newinner->childid[slot] = copy_recursive(inner->childid[slot]);
    1941                 :             }
    1942                 : 
    1943             220 :             return newinner;
    1944                 :         }
    1945                 :     }
    1946                 : 
    1947                 : public:
    1948                 :     // *** Public Insertion Functions
    1949                 : 
    1950                 :     /// Attempt to insert a key/data pair into the B+ tree. If the tree does not
    1951                 :     /// allow duplicate keys, then the insert may fail if it is already
    1952                 :     /// present.
    1953            3200 :     inline std::pair<iterator, bool> insert(const pair_type& x)
    1954                 :     {
    1955            3200 :         return insert_start(x.first, x.second);
    1956                 :     }
    1957                 : 
    1958                 :     /// Attempt to insert a key/data pair into the B+ tree. Beware that if
    1959                 :     /// key_type == data_type, then the template iterator insert() is called
    1960                 :     /// instead. If the tree does not allow duplicate keys, then the insert may
    1961                 :     /// fail if it is already present.
    1962                 :     inline std::pair<iterator, bool> insert(const key_type& key, const data_type& data)
    1963                 :     {
    1964                 :         return insert_start(key, data);
    1965                 :     }
    1966                 : 
    1967                 :     /// Attempt to insert a key/data pair into the B+ tree. This function is the
    1968                 :     /// same as the other insert, however if key_type == data_type then the
    1969                 :     /// non-template function cannot be called. If the tree does not allow
    1970                 :     /// duplicate keys, then the insert may fail if it is already present.
    1971           29780 :     inline std::pair<iterator, bool> insert2(const key_type& key, const data_type& data)
    1972                 :     {
    1973           29780 :         return insert_start(key, data);
    1974                 :     }
    1975                 : 
    1976                 :     /// Attempt to insert a key/data pair into the B+ tree. The iterator hint
    1977                 :     /// is currently ignored by the B+ tree insertion routine.
    1978                 :     inline iterator insert(iterator /* hint */, const pair_type &x)
    1979                 :     {
    1980                 :         return insert_start(x.first, x.second).first;
    1981                 :     }
    1982                 : 
    1983                 :     /// Attempt to insert a key/data pair into the B+ tree. The iterator hint is
    1984                 :     /// currently ignored by the B+ tree insertion routine.
    1985               0 :     inline iterator insert2(iterator /* hint */, const key_type& key, const data_type& data)
    1986                 :     {
    1987               0 :         return insert_start(key, data).first;
    1988                 :     }
    1989                 : 
    1990                 :     /// Attempt to insert the range [first,last) of value_type pairs into the B+
    1991                 :     /// tree. Each key/data pair is inserted individually.
    1992                 :     template <typename InputIterator>
    1993               1 :     inline void insert(InputIterator first, InputIterator last)
    1994                 :     {
    1995               1 :         InputIterator iter = first;
    1996            3202 :         while(iter != last)
    1997                 :         {
    1998            3200 :             insert(*iter);
    1999            3201 :             ++iter;
    2000                 :         }
    2001                 :     }
    2002                 : 
    2003                 : private:
    2004                 :     // *** Private Insertion Functions
    2005                 : 
    2006                 :     /// Start the insertion descent at the current root and handle root
    2007                 :     /// splits. Returns true if the item was inserted
    2008           32980 :     std::pair<iterator, bool> insert_start(const key_type& key, const data_type& value)
    2009                 :     {
    2010           32980 :         node *newchild = NULL;
    2011           32980 :         key_type newkey = key_type();
    2012                 : 
    2013           32980 :         if (root == NULL) {
    2014              21 :             root = headleaf = tailleaf = allocate_leaf();
    2015                 :         }
    2016                 : 
    2017           32980 :         std::pair<iterator, bool> r = insert_descend(root, key, value, &newkey, &newchild);
    2018                 : 
    2019           32980 :         if (newchild)
    2020                 :         {
    2021              58 :             inner_node *newroot = allocate_inner(root->level + 1);
    2022              58 :             newroot->slotkey[0] = newkey;
    2023                 : 
    2024              58 :             newroot->childid[0] = root;
    2025              58 :             newroot->childid[1] = newchild;
    2026                 : 
    2027              58 :             newroot->slotuse = 1;
    2028                 : 
    2029              58 :             root = newroot;
    2030                 :         }
    2031                 : 
    2032                 :         // increment itemcount if the item was inserted
    2033           32980 :         if (r.second) ++stats.itemcount;
    2034                 : 
    2035                 : #ifdef BTREE_DEBUG
    2036                 :         if (debug) print(std::cout);
    2037                 : #endif
    2038                 : 
    2039                 :         if (selfverify) {
    2040           31980 :             verify();
    2041           31980 :             BTREE_ASSERT(exists(key));
    2042                 :         }
    2043                 : 
    2044             676 :         return r;
    2045                 :     }
    2046                 : 
    2047                 :     /**
    2048                 :      * @brief Insert an item into the B+ tree.
    2049                 :      *
    2050                 :      * Descend down the nodes to a leaf, insert the key/data pair in a free
    2051                 :      * slot. If the node overflows, then it must be split and the new split
    2052                 :      * node inserted into the parent. Unroll / this splitting up to the root.
    2053                 :     */
    2054                 :     std::pair<iterator, bool> insert_descend(node* n,
    2055                 :                                              const key_type& key, const data_type& value,
    2056          143928 :                                              key_type* splitkey, node** splitnode)
    2057                 :     {
    2058          143928 :         if (!n->isleafnode())
    2059                 :         {
    2060          110948 :             inner_node *inner = static_cast<inner_node*>(n);
    2061                 : 
    2062          110948 :             key_type newkey = key_type();
    2063          110948 :             node *newchild = NULL;
    2064                 : 
    2065          110948 :             int slot = find_lower(inner, key);
    2066                 : 
    2067                 :             BTREE_PRINT("btree::insert_descend into " << inner->childid[slot] << std::endl);
    2068                 : 
    2069                 :             std::pair<iterator, bool> r = insert_descend(inner->childid[slot],
    2070          110948 :                                                          key, value, &newkey, &newchild);
    2071                 : 
    2072          110948 :             if (newchild)
    2073                 :             {
    2074                 :                 BTREE_PRINT("btree::insert_descend newchild with key " << newkey << " node " << newchild << " at slot " << slot << std::endl);
    2075                 : 
    2076            8736 :                 if (inner->isfull())
    2077                 :                 {
    2078            1532 :                     split_inner_node(inner, splitkey, splitnode, slot);
    2079                 : 
    2080                 :                     BTREE_PRINT("btree::insert_descend done split_inner: putslot: " << slot << " putkey: " << newkey << " upkey: " << *splitkey << std::endl);
    2081                 : 
    2082                 : #ifdef BTREE_DEBUG
    2083                 :                     if (debug)
    2084                 :                     {
    2085                 :                         print_node(std::cout, inner);
    2086                 :                         print_node(std::cout, *splitnode);
    2087                 :                     }
    2088                 : #endif
    2089                 : 
    2090                 :                     // check if insert slot is in the split sibling node
    2091                 :                     BTREE_PRINT("btree::insert_descend switch: " << slot << " > " << inner->slotuse+1 << std::endl);
    2092                 : 
    2093            1532 :                     if (slot == inner->slotuse+1 && inner->slotuse < (*splitnode)->slotuse)
    2094                 :                     {
    2095                 :                         // special case when the insert slot matches the split
    2096                 :                         // place between the two nodes, then the insert key
    2097                 :                         // becomes the split key.
    2098                 : 
    2099              53 :                         BTREE_ASSERT(inner->slotuse + 1 < innerslotmax);
    2100                 : 
    2101              53 :                         inner_node *splitinner = static_cast<inner_node*>(*splitnode);
    2102                 : 
    2103                 :                         // move the split key and it's datum into the left node
    2104              53 :                         inner->slotkey[inner->slotuse] = *splitkey;
    2105              53 :                         inner->childid[inner->slotuse+1] = splitinner->childid[0];
    2106              53 :                         inner->slotuse++;
    2107                 : 
    2108                 :                         // set new split key and move corresponding datum into right node
    2109              53 :                         splitinner->childid[0] = newchild;
    2110              53 :                         *splitkey = newkey;
    2111                 : 
    2112            2985 :                         return r;
    2113                 :                     }
    2114            1479 :                     else if (slot >= inner->slotuse+1)
    2115                 :                     {
    2116                 :                         // in case the insert slot is in the newly create split
    2117                 :                         // node, we reuse the code below.
    2118                 : 
    2119             961 :                         slot -= inner->slotuse+1;
    2120             961 :                         inner = static_cast<inner_node*>(*splitnode);
    2121                 :                         BTREE_PRINT("btree::insert_descend switching to splitted node " << inner << " slot " << slot <<std::endl);
    2122                 :                     }
    2123                 :                 }
    2124                 : 
    2125                 :                 // put pointer to child node into correct slot
    2126            8683 :                 BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
    2127                 : 
    2128            8683 :                 int i = inner->slotuse;
    2129                 : 
    2130           31719 :                 while(i > slot) {
    2131           14353 :                     inner->slotkey[i] = inner->slotkey[i - 1];
    2132           14353 :                     inner->childid[i + 1] = inner->childid[i];
    2133           14353 :                     i--;
    2134                 :                 }
    2135                 : 
    2136            8683 :                 inner->slotkey[slot] = newkey;
    2137            8683 :                 inner->childid[slot + 1] = newchild;
    2138            8683 :                 inner->slotuse++;
    2139                 :             }
    2140                 : 
    2141          110895 :             return r;
    2142                 :         }
    2143                 :         else // n->isleafnode() == true
    2144                 :         {
    2145           32980 :             leaf_node *leaf = static_cast<leaf_node*>(n);
    2146                 : 
    2147           32980 :             int slot = find_lower(leaf, key);
    2148                 : 
    2149            3100 :             if (!allow_duplicates && slot < leaf->slotuse && key_equal(key, leaf->slotkey[slot])) {
    2150               0 :                 return std::pair<iterator, bool>(iterator(leaf, slot), false);
    2151                 :             }
    2152                 : 
    2153           32980 :             if (leaf->isfull())
    2154                 :             {
    2155            7262 :                 split_leaf_node(leaf, splitkey, splitnode);
    2156                 : 
    2157                 :                 // check if insert slot is in the split sibling node
    2158            7262 :                 if (slot >= leaf->slotuse)
    2159                 :                 {
    2160            4020 :                     slot -= leaf->slotuse;
    2161            4020 :                     leaf = static_cast<leaf_node*>(*splitnode);
    2162                 :                 }
    2163                 :             }
    2164                 : 
    2165                 :             // put data item into correct data slot
    2166                 : 
    2167           32980 :             int i = leaf->slotuse - 1;
    2168           32980 :             BTREE_ASSERT(i + 1 < leafslotmax);
    2169                 : 
    2170           88366 :             while(i >= 0 && key_less(key, leaf->slotkey[i])) {
    2171           22406 :                 leaf->slotkey[i + 1] = leaf->slotkey[i];
    2172           22406 :                 leaf->slotdata[i + 1] = leaf->slotdata[i];
    2173           22406 :                 i--;
    2174                 :             }
    2175                 : 
    2176           32980 :             leaf->slotkey[i + 1] = key;
    2177           32980 :             leaf->slotdata[i + 1] = value;
    2178           32980 :             leaf->slotuse++;
    2179                 : 
    2180           32980 :             if (splitnode && leaf != *splitnode && slot == leaf->slotuse-1)
    2181                 :             {
    2182                 :                 // special case: the node was split, and the insert is at the
    2183                 :                 // last slot of the old node. then the splitkey must be
    2184                 :                 // updated.
    2185           10587 :                 *splitkey = key;
    2186                 :             }
    2187                 : 
    2188           32980 :             return std::pair<iterator, bool>(iterator(leaf, i + 1), true);
    2189                 :         }
    2190                 :     }
    2191                 : 
    2192                 :     /// Split up a leaf node into two equally-filled sibling leaves. Returns
    2193                 :     /// the new nodes and it's insertion key in the two parameters.
    2194            7262 :     void split_leaf_node(leaf_node* leaf, key_type* _newkey, node** _newleaf)
    2195                 :     {
    2196            7262 :         BTREE_ASSERT(leaf->isfull());
    2197                 : 
    2198            7262 :         unsigned int mid = (leaf->slotuse >> 1);
    2199                 : 
    2200                 :         BTREE_PRINT("btree::split_leaf_node on " << leaf << std::endl);
    2201                 : 
    2202            7262 :         leaf_node *newleaf = allocate_leaf();
    2203                 : 
    2204            7262 :         newleaf->slotuse = leaf->slotuse - mid;
    2205                 : 
    2206            7262 :         newleaf->nextleaf = leaf->nextleaf;
    2207            7262 :         if (newleaf->nextleaf == NULL) {
    2208            3351 :             BTREE_ASSERT(leaf == tailleaf);
    2209            3351 :             tailleaf = newleaf;
    2210                 :         }
    2211                 :         else {
    2212            3911 :             newleaf->nextleaf->prevleaf = newleaf;
    2213                 :         }
    2214                 : 
    2215           37000 :         for(unsigned int slot = mid; slot < leaf->slotuse; ++slot)
    2216                 :         {
    2217           29738 :             unsigned int ni = slot - mid;
    2218           29738 :             newleaf->slotkey[ni] = leaf->slotkey[slot];
    2219           29738 :             newleaf->slotdata[ni] = leaf->slotdata[slot];
    2220                 :         }
    2221                 : 
    2222            7262 :         leaf->slotuse = mid;
    2223            7262 :         leaf->nextleaf = newleaf;
    2224            7262 :         newleaf->prevleaf = leaf;
    2225                 : 
    2226            7262 :         *_newkey = leaf->slotkey[leaf->slotuse-1];
    2227            7262 :         *_newleaf = newleaf;
    2228                 :     }
    2229                 : 
    2230                 :     /// Split up an inner node into two equally-filled sibling nodes. Returns
    2231                 :     /// the new nodes and it's insertion key in the two parameters. Requires
    2232                 :     /// the slot of the item will be inserted, so the nodes will be the same
    2233                 :     /// size after the insert.
    2234            1532 :     void split_inner_node(inner_node* inner, key_type* _newkey, node** _newinner, unsigned int addslot)
    2235                 :     {
    2236            1532 :         BTREE_ASSERT(inner->isfull());
    2237                 : 
    2238            1532 :         unsigned int mid = (inner->slotuse >> 1);
    2239                 : 
    2240                 :         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
    2241                 : 
    2242                 :         // if the split is uneven and the overflowing item will be put into the
    2243                 :         // larger node, then the smaller split node may underflow
    2244            1532 :         if (addslot <= mid && mid > inner->slotuse - (mid + 1))
    2245             571 :             mid--;
    2246                 : 
    2247                 :         BTREE_PRINT("btree::split_inner: mid " << mid << " addslot " << addslot << std::endl);
    2248                 : 
    2249                 :         BTREE_PRINT("btree::split_inner_node on " << inner << " into two nodes " << mid << " and " << inner->slotuse - (mid + 1) << " sized" << std::endl);
    2250                 : 
    2251            1532 :         inner_node *newinner = allocate_inner(inner->level);
    2252                 : 
    2253            1532 :         newinner->slotuse = inner->slotuse - (mid + 1);
    2254                 : 
    2255            6734 :         for(unsigned int slot = mid + 1; slot < inner->slotuse; ++slot)
    2256                 :         {
    2257            5202 :             unsigned int ni = slot - (mid + 1);
    2258            5202 :             newinner->slotkey[ni] = inner->slotkey[slot];
    2259            5202 :             newinner->childid[ni] = inner->childid[slot];
    2260                 :         }
    2261            1532 :         newinner->childid[newinner->slotuse] = inner->childid[inner->slotuse];
    2262                 : 
    2263            1532 :         inner->slotuse = mid;
    2264                 : 
    2265            1532 :         *_newkey = inner->slotkey[mid];
    2266            1532 :         *_newinner = newinner;
    2267                 :     }
    2268                 : 
    2269                 : private:
    2270                 :     // *** Support Class Encapsulating Deletion Results
    2271                 : 
    2272                 :     /// Result flags of recursive deletion.
    2273                 :     enum result_flags_t
    2274                 :     {
    2275                 :         /// Deletion successful and no fix-ups necessary.
    2276                 :         btree_ok = 0,
    2277                 : 
    2278                 :         /// Deletion not successful because key was not found.
    2279                 :         btree_not_found = 1,
    2280                 : 
    2281                 :         /// Deletion successful, the last key was updated so parent slotkeys
    2282                 :         /// need updates.
    2283                 :         btree_update_lastkey = 2,
    2284                 : 
    2285                 :         /// Deletion successful, children nodes were merged and the parent
    2286                 :         /// needs to remove the empty node.
    2287                 :         btree_fixmerge = 4
    2288                 :     };
    2289                 : 
    2290                 :     /// \internal B+ tree recursive deletion has much information which is
    2291                 :     /// needs to be passed upward.
    2292                 :     struct result_t
    2293            7494 :     {
    2294                 :         /// Merged result flags
    2295                 :         result_flags_t  flags;
    2296                 : 
    2297                 :         /// The key to be updated at the parent's slot
    2298                 :         key_type        lastkey;
    2299                 : 
    2300                 :         /// Constructor of a result with a specific flag, this can also be used
    2301                 :         /// as for implicit conversion.
    2302          128102 :         inline result_t(result_flags_t f = btree_ok)
    2303          128102 :             : flags(f), lastkey()
    2304          128102 :         { }
    2305                 : 
    2306                 :         /// Constructor with a lastkey value.
    2307             505 :         inline result_t(result_flags_t f, const key_type &k)
    2308             505 :             : flags(f), lastkey(k)
    2309             505 :         { }
    2310                 : 
    2311                 :         /// Test if this result object has a given flag set.
    2312          342025 :         inline bool has(result_flags_t f) const
    2313                 :         {
    2314          342025 :             return (flags & f) != 0;
    2315                 :         }
    2316                 : 
    2317                 :         /// Merge two results OR-ing the result flags and overwriting lastkeys.
    2318            8799 :         inline result_t& operator|= (const result_t &other)
    2319                 :         {
    2320            8799 :             flags = result_flags_t(flags | other.flags);
    2321                 : 
    2322                 :             // we overwrite existing lastkeys on purpose
    2323            8799 :             if (other.has(btree_update_lastkey))
    2324             505 :                 lastkey = other.lastkey;
    2325                 : 
    2326            8799 :             return *this;
    2327                 :         }
    2328                 :     };
    2329                 : 
    2330                 : public:
    2331                 :     // *** Public Erase Functions
    2332                 : 
    2333                 :     /// Erases one (the first) of the key/data pairs associated with the given
    2334                 :     /// key.
    2335           26037 :     bool erase_one(const key_type &key)
    2336                 :     {
    2337                 :         BTREE_PRINT("btree::erase_one(" << key << ") on btree size " << size() << std::endl);
    2338                 : 
    2339           26037 :         if (selfverify) verify();
    2340                 : 
    2341           26037 :         if (!root) return false;
    2342                 : 
    2343           26036 :         result_t result = erase_one_descend(key, root, NULL, NULL, NULL, NULL, NULL, 0);
    2344                 : 
    2345           26036 :         if (!result.has(btree_not_found))
    2346           26036 :             --stats.itemcount;
    2347                 : 
    2348                 : #ifdef BTREE_DEBUG
    2349                 :         if (debug) print(std::cout);
    2350                 : #endif
    2351           26036 :         if (selfverify) verify();
    2352                 : 
    2353           26036 :         return !result.has(btree_not_found);
    2354                 :     }
    2355                 : 
    2356                 :     /// Erases all the key/data pairs associated with the given key. This is
    2357                 :     /// implemented using erase_one().
    2358               1 :     size_type erase(const key_type &key)
    2359                 :     {
    2360               1 :         size_type c = 0;
    2361                 : 
    2362               2 :         while( erase_one(key) )
    2363                 :         {
    2364               0 :             ++c;
    2365               0 :             if (!allow_duplicates) break;
    2366                 :         }
    2367                 : 
    2368               1 :         return c;
    2369                 :     }
    2370                 : 
    2371                 : #ifdef BTREE_TODO
    2372                 :     /// Erase the key/data pair referenced by the iterator.
    2373                 :     void erase(iterator iter)
    2374                 :     {
    2375                 : 
    2376                 :     }
    2377                 : #endif
    2378                 : 
    2379                 : #ifdef BTREE_TODO
    2380                 :     /// Erase all key/data pairs in the range [first,last). This function is
    2381                 :     /// currently not implemented by the B+ Tree.
    2382                 :     void erase(iterator /* first */, iterator /* last */)
    2383                 :     {
    2384                 :         abort();
    2385                 :     }
    2386                 : #endif
    2387                 : 
    2388                 : private:
    2389                 :     // *** Private Erase Functions
    2390                 : 
    2391                 :     /** @brief Erase one (the first) key/data pair in the B+ tree matching key.
    2392                 :      *
    2393                 :      * Descends down the tree in search of key. During the descent the parent,
    2394                 :      * left and right siblings and their parents are computed and passed
    2395                 :      * down. Once the key/data pair is found, it is removed from the leaf. If
    2396                 :      * the leaf underflows 6 different cases are handled. These cases resolve
    2397                 :      * the underflow by shifting key/data pairs from adjacent sibling nodes,
    2398                 :      * merging two sibling nodes or trimming the tree.
    2399                 :      */
    2400                 :     result_t erase_one_descend(const key_type& key,
    2401                 :                                node *curr,
    2402                 :                                node *left, node *right,
    2403                 :                                inner_node *leftparent, inner_node *rightparent,
    2404          119754 :                                inner_node *parent, unsigned int parentslot)
    2405                 :     {
    2406          119754 :         if (curr->isleafnode())
    2407                 :         {
    2408           26036 :             leaf_node *leaf = static_cast<leaf_node*>(curr);
    2409           26036 :             leaf_node *leftleaf = static_cast<leaf_node*>(left);
    2410           26036 :             leaf_node *rightleaf = static_cast<leaf_node*>(right);
    2411                 : 
    2412           26036 :             int slot = find_lower(leaf, key);
    2413                 : 
    2414           26036 :             if (slot >= leaf->slotuse || !key_equal(key, leaf->slotkey[slot]))
    2415                 :             {
    2416                 :                 BTREE_PRINT("Could not find key " << key << " to erase." << std::endl);
    2417                 : 
    2418               0 :                 return btree_not_found;
    2419                 :             }
    2420                 : 
    2421                 :             BTREE_PRINT("Found key in leaf " << curr << " at slot " << slot << std::endl);
    2422                 : 
    2423          112159 :             for (int i = slot; i < leaf->slotuse - 1; i++)
    2424                 :             {
    2425           86123 :                 leaf->slotkey[i] = leaf->slotkey[i + 1];
    2426           86123 :                 leaf->slotdata[i] = leaf->slotdata[i + 1];
    2427                 :             }
    2428           26036 :             leaf->slotuse--;
    2429                 : 
    2430           26036 :             result_t myres = btree_ok;
    2431                 : 
    2432                 :             // if the last key of the leaf was changed, the parent is notified
    2433                 :             // and updates the key of this leaf
    2434           26036 :             if (slot == leaf->slotuse)
    2435                 :             {
    2436            4338 :                 if (parent && parentslot < parent->slotuse)
    2437                 :                 {
    2438            1957 :                     BTREE_ASSERT(parent->childid[parentslot] == curr);
    2439            1957 :                     parent->slotkey[parentslot] = leaf->slotkey[leaf->slotuse - 1];
    2440                 :                 }
    2441                 :                 else
    2442                 :                 {
    2443             424 :                     if (leaf->slotuse >= 1)
    2444                 :                     {
    2445                 :                         BTREE_PRINT("Scheduling lastkeyupdate: key " << leaf->slotkey[leaf->slotuse - 1] << std::endl);
    2446             410 :                         myres |= result_t(btree_update_lastkey, leaf->slotkey[leaf->slotuse - 1]);
    2447                 :                     }
    2448                 :                     else
    2449                 :                     {
    2450              14 :                         BTREE_ASSERT(leaf == root);
    2451                 :                     }
    2452                 :                 }
    2453                 :             }
    2454                 : 
    2455           26036 :             if (leaf->isunderflow() && !(leaf == root && leaf->slotuse >= 1))
    2456                 :             {
    2457                 :                 // determine what to do about the underflow
    2458                 : 
    2459                 :                 // case : if this empty leaf is the root, then delete all nodes
    2460                 :                 // and set root to NULL.
    2461            8768 :                 if (leftleaf == NULL && rightleaf == NULL)
    2462                 :                 {
    2463              14 :                     BTREE_ASSERT(leaf == root);
    2464              14 :                     BTREE_ASSERT(leaf->slotuse == 0);
    2465                 : 
    2466              14 :                     free_node(root);
    2467                 : 
    2468              14 :                     root = leaf = NULL;
    2469              14 :                     headleaf = tailleaf = NULL;
    2470                 : 
    2471                 :                     // will be decremented soon by insert_start()
    2472              14 :                     BTREE_ASSERT(stats.itemcount == 1);
    2473              14 :                     BTREE_ASSERT(stats.leaves == 0);
    2474              14 :                     BTREE_ASSERT(stats.innernodes == 0);
    2475                 : 
    2476             690 :                     return btree_ok;
    2477                 :                 }
    2478                 :                 // case : if both left and right leaves would underflow in case of
    2479                 :                 // a shift, then merging is necessary. choose the more local merger
    2480                 :                 // with our parent
    2481            8754 :                 else if ( (leftleaf == NULL || leftleaf->isfew()) && (rightleaf == NULL || rightleaf->isfew()) )
    2482                 :                 {
    2483            5543 :                     if (leftparent == parent)
    2484            1958 :                         myres |= merge_leaves(leftleaf, leaf, leftparent);
    2485                 :                     else
    2486            3585 :                         myres |= merge_leaves(leaf, rightleaf, rightparent);
    2487                 :                 }
    2488                 :                 // case : the right leaf has extra data, so balance right with current
    2489            3211 :                 else if ( (leftleaf != NULL && leftleaf->isfew()) && (rightleaf != NULL && !rightleaf->isfew()) )
    2490                 :                 {
    2491             837 :                     if (rightparent == parent)
    2492             675 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    2493                 :                     else
    2494             162 :                         myres |= merge_leaves(leftleaf, leaf, leftparent);
    2495                 :                 }
    2496                 :                 // case : the left leaf has extra data, so balance left with current
    2497            2374 :                 else if ( (leftleaf != NULL && !leftleaf->isfew()) && (rightleaf != NULL && rightleaf->isfew()) )
    2498                 :                 {
    2499            1488 :                     if (leftparent == parent)
    2500            1362 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2501                 :                     else
    2502             126 :                         myres |= merge_leaves(leaf, rightleaf, rightparent);
    2503                 :                 }
    2504                 :                 // case : both the leaf and right leaves have extra data and our
    2505                 :                 // parent, choose the leaf with more data
    2506             886 :                 else if (leftparent == rightparent)
    2507                 :                 {
    2508             587 :                     if (leftleaf->slotuse <= rightleaf->slotuse)
    2509             382 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    2510                 :                     else
    2511             205 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2512                 :                 }
    2513                 :                 else
    2514                 :                 {
    2515             299 :                     if (leftparent == parent)
    2516             162 :                         shift_right_leaf(leftleaf, leaf, leftparent, parentslot - 1);
    2517                 :                     else
    2518             137 :                         myres |= shift_left_leaf(leaf, rightleaf, rightparent, parentslot);
    2519                 :                 }
    2520                 :             }
    2521                 : 
    2522           26022 :             return myres;
    2523                 :         }
    2524                 :         else // !curr->isleafnode()
    2525                 :         {
    2526           93718 :             inner_node *inner = static_cast<inner_node*>(curr);
    2527           93718 :             inner_node *leftinner = static_cast<inner_node*>(left);
    2528           93718 :             inner_node *rightinner = static_cast<inner_node*>(right);
    2529                 : 
    2530                 :             node *myleft, *myright;
    2531                 :             inner_node *myleftparent, *myrightparent;
    2532                 : 
    2533           93718 :             int slot = find_lower(inner, key);
    2534                 : 
    2535           93718 :             if (slot == 0) {
    2536           58213 :                 myleft = (left == NULL) ? NULL : (static_cast<inner_node*>(left))->childid[left->slotuse - 1];
    2537           58213 :                 myleftparent = leftparent;
    2538                 :             }
    2539                 :             else {
    2540           35505 :                 myleft = inner->childid[slot - 1];
    2541           35505 :                 myleftparent = inner;
    2542                 :             }
    2543                 : 
    2544           93718 :             if (slot == inner->slotuse) {
    2545            9011 :                 myright = (right == NULL) ? NULL : (static_cast<inner_node*>(right))->childid[0];
    2546            9011 :                 myrightparent = rightparent;
    2547                 :             }
    2548                 :             else {
    2549           84707 :                 myright = inner->childid[slot + 1];
    2550           84707 :                 myrightparent = inner;
    2551                 :             }
    2552                 : 
    2553                 :             BTREE_PRINT("erase_one_descend into " << inner->childid[slot] << std::endl);
    2554                 : 
    2555                 :             result_t result = erase_one_descend(key,
    2556                 :                                                 inner->childid[slot],
    2557                 :                                                 myleft, myright,
    2558                 :                                                 myleftparent, myrightparent,
    2559           93718 :                                                 inner, slot);
    2560                 : 
    2561           93718 :             result_t myres = btree_ok;
    2562                 : 
    2563           93718 :             if (result.has(btree_not_found))
    2564                 :             {
    2565            1735 :                 return result;
    2566                 :             }
    2567                 : 
    2568           93718 :             if (result.has(btree_update_lastkey))
    2569                 :             {
    2570             845 :                 if (parent && parentslot < parent->slotuse)
    2571                 :                 {
    2572                 :                     BTREE_PRINT("Fixing lastkeyupdate: key " << result.lastkey << " into parent " << parent << " at parentslot " << parentslot << std::endl);
    2573                 : 
    2574             375 :                     BTREE_ASSERT(parent->childid[parentslot] == curr);
    2575             375 :                     parent->slotkey[parentslot] = result.lastkey;
    2576                 :                 }
    2577                 :                 else
    2578                 :                 {
    2579                 :                     BTREE_PRINT("Forwarding lastkeyupdate: key " << result.lastkey << std::endl);
    2580              95 :                     myres |= result_t(btree_update_lastkey, result.lastkey);
    2581                 :                 }
    2582                 :             }
    2583                 : 
    2584           93718 :             if (result.has(btree_fixmerge))
    2585                 :             {
    2586                 :                 // either the current node or the next is empty and should be removed
    2587            7100 :                 if (inner->childid[slot]->slotuse != 0)
    2588            4547 :                     slot++;
    2589                 : 
    2590                 :                 // this is the child slot invalidated by the merge
    2591            7100 :                 BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
    2592                 : 
    2593            7100 :                 free_node(inner->childid[slot]);
    2594                 : 
    2595           33229 :                 for(int i = slot; i < inner->slotuse; i++)
    2596                 :                 {
    2597           26129 :                     inner->slotkey[i - 1] = inner->slotkey[i];
    2598           26129 :                     inner->childid[i] = inner->childid[i + 1];
    2599                 :                 }
    2600            7100 :                 inner->slotuse--;
    2601                 : 
    2602            7100 :                 if (inner->level == 1)
    2603                 :                 {
    2604                 :                     // fix split key for children leaves
    2605            5831 :                     slot--;
    2606            5831 :                     leaf_node *child = static_cast<leaf_node*>(inner->childid[slot]);
    2607            5831 :                     inner->slotkey[slot] = child->slotkey[ child->slotuse-1 ];
    2608                 :                 }
    2609                 :             }
    2610                 : 
    2611           93718 :             if (inner->isunderflow() && !(inner == root && inner->slotuse >= 1))
    2612                 :             {
    2613                 :                 // case: the inner node is the root and has just one child. that child becomes the new root
    2614            2106 :                 if (leftinner == NULL && rightinner == NULL)
    2615                 :                 {
    2616              40 :                     BTREE_ASSERT(inner == root);
    2617              40 :                     BTREE_ASSERT(inner->slotuse == 0);
    2618                 : 
    2619              40 :                     root = inner->childid[0];
    2620                 : 
    2621              40 :                     inner->slotuse = 0;
    2622              40 :                     free_node(inner);
    2623                 : 
    2624              40 :                     return btree_ok;
    2625                 :                 }
    2626                 :                 // case : if both left and right leaves would underflow in case of
    2627                 :                 // a shift, then merging is necessary. choose the more local merger
    2628                 :                 // with our parent
    2629            2066 :                 else if ( (leftinner == NULL || leftinner->isfew()) && (rightinner == NULL || rightinner->isfew()) )
    2630                 :                 {
    2631            1242 :                     if (leftparent == parent)
    2632             421 :                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
    2633                 :                     else
    2634             821 :                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
    2635                 :                 }
    2636                 :                 // case : the right leaf has extra data, so balance right with current
    2637             824 :                 else if ( (leftinner != NULL && leftinner->isfew()) && (rightinner != NULL && !rightinner->isfew()) )
    2638                 :                 {
    2639             170 :                     if (rightparent == parent)
    2640             158 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2641                 :                     else
    2642              12 :                         myres |= merge_inner(leftinner, inner, leftparent, parentslot - 1);
    2643                 :                 }
    2644                 :                 // case : the left leaf has extra data, so balance left with current
    2645             654 :                 else if ( (leftinner != NULL && !leftinner->isfew()) && (rightinner != NULL && rightinner->isfew()) )
    2646                 :                 {
    2647             379 :                     if (leftparent == parent)
    2648             364 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2649                 :                     else
    2650              15 :                         myres |= merge_inner(inner, rightinner, rightparent, parentslot);
    2651                 :                 }
    2652                 :                 // case : both the leaf and right leaves have extra data and our
    2653                 :                 // parent, choose the leaf with more data
    2654             275 :                 else if (leftparent == rightparent)
    2655                 :                 {
    2656             138 :                     if (leftinner->slotuse <= rightinner->slotuse)
    2657              84 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2658                 :                     else
    2659              54 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2660                 :                 }
    2661                 :                 else
    2662                 :                 {
    2663             137 :                     if (leftparent == parent)
    2664              72 :                         shift_right_inner(leftinner, inner, leftparent, parentslot - 1);
    2665                 :                     else
    2666              65 :                         shift_left_inner(inner, rightinner, rightparent, parentslot);
    2667                 :                 }
    2668                 :             }
    2669                 : 
    2670           93678 :             return myres;
    2671                 :         }
    2672                 :     }
    2673                 : 
    2674                 :     /// Merge two leaf nodes. The function moves all key/data pairs from right
    2675                 :     /// to left and sets right's slotuse to zero. The right slot is then
    2676                 :     /// removed by the calling parent node.
    2677            5831 :     result_t merge_leaves(leaf_node* left, leaf_node* right, inner_node* parent)
    2678                 :     {
    2679                 :         BTREE_PRINT("Merge leaf nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
    2680                 :         (void)parent;
    2681                 : 
    2682            5831 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2683            5831 :         BTREE_ASSERT(parent->level == 1);
    2684                 : 
    2685            5831 :         BTREE_ASSERT(left->slotuse + right->slotuse < leafslotmax);
    2686                 : 
    2687           27035 :         for (unsigned int i = 0; i < right->slotuse; i++)
    2688                 :         {
    2689           21204 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2690           21204 :             left->slotdata[left->slotuse + i] = right->slotdata[i];
    2691                 :         }
    2692            5831 :         left->slotuse += right->slotuse;
    2693                 : 
    2694            5831 :         left->nextleaf = right->nextleaf;
    2695            5831 :         if (left->nextleaf)
    2696            5774 :             left->nextleaf->prevleaf = left;
    2697                 :         else
    2698              57 :             tailleaf = left;
    2699                 : 
    2700            5831 :         right->slotuse = 0;
    2701                 : 
    2702            5831 :         return btree_fixmerge;
    2703                 :     }
    2704                 : 
    2705                 :     /// Merge two inner nodes. The function moves all key/childid pairs from
    2706                 :     /// right to left and sets right's slotuse to zero. The right slot is then
    2707                 :     /// removed by the calling parent node.
    2708            1269 :     static result_t merge_inner(inner_node* left, inner_node* right, inner_node* parent, unsigned int parentslot)
    2709                 :     {
    2710                 :         BTREE_PRINT("Merge inner nodes " << left << " and " << right << " with common parent " << parent << "." << std::endl);
    2711                 : 
    2712            1269 :         BTREE_ASSERT(left->level == right->level);
    2713            1269 :         BTREE_ASSERT(parent->level == left->level + 1);
    2714                 : 
    2715            1269 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2716                 : 
    2717            1269 :         BTREE_ASSERT(left->slotuse + right->slotuse < innerslotmax);
    2718                 : 
    2719                 :         if (selfverify)
    2720                 :         {
    2721                 :             // find the left node's slot in the parent's children
    2722            1269 :             unsigned int leftslot = 0;
    2723            3481 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2724             943 :                 ++leftslot;
    2725                 : 
    2726            1269 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2727            1269 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2728            1269 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2729                 : 
    2730            1269 :             BTREE_ASSERT(parentslot == leftslot);
    2731                 :         }
    2732                 : 
    2733                 :         // retrieve the decision key from parent
    2734            1269 :         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
    2735            1269 :         left->slotuse++;
    2736                 : 
    2737                 :         // copy over keys and children from right
    2738            5912 :         for (unsigned int i = 0; i < right->slotuse; i++)
    2739                 :         {
    2740            4643 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2741            4643 :             left->childid[left->slotuse + i] = right->childid[i];
    2742                 :         }
    2743            1269 :         left->slotuse += right->slotuse;
    2744                 : 
    2745            1269 :         left->childid[left->slotuse] = right->childid[right->slotuse];
    2746                 : 
    2747            1269 :         right->slotuse = 0;
    2748                 : 
    2749            1269 :         return btree_fixmerge;
    2750                 :     }
    2751                 : 
    2752                 :     /// Balance two leaf nodes. The function moves key/data pairs from right to
    2753                 :     /// left so that both nodes are equally filled. The parent node is updated
    2754                 :     /// if possible.
    2755            1194 :     static result_t shift_left_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
    2756                 :     {
    2757            1194 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2758            1194 :         BTREE_ASSERT(parent->level == 1);
    2759                 : 
    2760            1194 :         BTREE_ASSERT(left->nextleaf == right);
    2761            1194 :         BTREE_ASSERT(left == right->prevleaf);
    2762                 : 
    2763            1194 :         BTREE_ASSERT(left->slotuse < right->slotuse);
    2764            1194 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2765                 : 
    2766            1194 :         unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
    2767                 : 
    2768                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
    2769                 : 
    2770            1194 :         BTREE_ASSERT(left->slotuse + shiftnum < leafslotmax);
    2771                 : 
    2772                 :         // copy the first items from the right node to the last slot in the left node.
    2773            2733 :         for(unsigned int i = 0; i < shiftnum; i++)
    2774                 :         {
    2775            1539 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2776            1539 :             left->slotdata[left->slotuse + i] = right->slotdata[i];
    2777                 :         }
    2778            1194 :         left->slotuse += shiftnum;
    2779                 : 
    2780                 :         // shift all slots in the right node to the left
    2781                 : 
    2782            1194 :         right->slotuse -= shiftnum;
    2783            6583 :         for(int i = 0; i < right->slotuse; i++)
    2784                 :         {
    2785            5389 :             right->slotkey[i] = right->slotkey[i + shiftnum];
    2786            5389 :             right->slotdata[i] = right->slotdata[i + shiftnum];
    2787                 :         }
    2788                 : 
    2789                 :         // fixup parent
    2790            1194 :         if (parentslot < parent->slotuse) {
    2791            1194 :             parent->slotkey[parentslot] = left->slotkey[left->slotuse - 1];
    2792            1194 :             return btree_ok;
    2793                 :         }
    2794                 :         else { // the update is further up the tree
    2795               0 :             return result_t(btree_update_lastkey, left->slotkey[left->slotuse - 1]);
    2796                 :         }
    2797                 :     }
    2798                 : 
    2799                 :     /// Balance two inner nodes. The function moves key/data pairs from right
    2800                 :     /// to left so that both nodes are equally filled. The parent node is
    2801                 :     /// updated if possible.
    2802             307 :     static void shift_left_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
    2803                 :     {
    2804             307 :         BTREE_ASSERT(left->level == right->level);
    2805             307 :         BTREE_ASSERT(parent->level == left->level + 1);
    2806                 : 
    2807             307 :         BTREE_ASSERT(left->slotuse < right->slotuse);
    2808             307 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2809                 : 
    2810             307 :         unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
    2811                 : 
    2812                 :         BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left " << left << " from right " << right << " with common parent " << parent << "." << std::endl);
    2813                 : 
    2814             307 :         BTREE_ASSERT(left->slotuse + shiftnum < innerslotmax);
    2815                 : 
    2816                 :         if (selfverify)
    2817                 :         {
    2818                 :             // find the left node's slot in the parent's children and compare to parentslot
    2819                 : 
    2820             307 :             unsigned int leftslot = 0;
    2821            1208 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2822             594 :                 ++leftslot;
    2823                 : 
    2824             307 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2825             307 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2826             307 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2827                 : 
    2828             307 :             BTREE_ASSERT(leftslot == parentslot);
    2829                 :         }
    2830                 : 
    2831                 :         // copy the parent's decision slotkey and childid to the first new key on the left
    2832             307 :         left->slotkey[left->slotuse] = parent->slotkey[parentslot];
    2833             307 :         left->slotuse++;
    2834                 : 
    2835                 :         // copy the other items from the right node to the last slots in the left node.
    2836             431 :         for(unsigned int i = 0; i < shiftnum - 1; i++)
    2837                 :         {
    2838             124 :             left->slotkey[left->slotuse + i] = right->slotkey[i];
    2839             124 :             left->childid[left->slotuse + i] = right->childid[i];
    2840                 :         }
    2841             307 :         left->slotuse += shiftnum - 1;
    2842                 : 
    2843                 :         // fixup parent
    2844             307 :         parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
    2845                 :         // last pointer in left
    2846             307 :         left->childid[left->slotuse] = right->childid[shiftnum - 1];
    2847                 : 
    2848                 :         // shift all slots in the right node
    2849                 : 
    2850             307 :         right->slotuse -= shiftnum;
    2851            1801 :         for(int i = 0; i < right->slotuse; i++)
    2852                 :         {
    2853            1494 :             right->slotkey[i] = right->slotkey[i + shiftnum];
    2854            1494 :             right->childid[i] = right->childid[i + shiftnum];
    2855                 :         }
    2856             307 :         right->childid[right->slotuse] = right->childid[right->slotuse + shiftnum];
    2857                 :     }
    2858                 : 
    2859                 :     /// Balance two leaf nodes. The function moves key/data pairs from left to
    2860                 :     /// right so that both nodes are equally filled. The parent node is updated
    2861                 :     /// if possible.
    2862            1729 :     static void shift_right_leaf(leaf_node *left, leaf_node *right, inner_node *parent, unsigned int parentslot)
    2863                 :     {
    2864            1729 :         BTREE_ASSERT(left->isleafnode() && right->isleafnode());
    2865            1729 :         BTREE_ASSERT(parent->level == 1);
    2866                 : 
    2867            1729 :         BTREE_ASSERT(left->nextleaf == right);
    2868            1729 :         BTREE_ASSERT(left == right->prevleaf);
    2869            1729 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2870                 : 
    2871            1729 :         BTREE_ASSERT(left->slotuse > right->slotuse);
    2872                 : 
    2873            1729 :         unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
    2874                 : 
    2875                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
    2876                 : 
    2877                 :         if (selfverify)
    2878                 :         {
    2879                 :             // find the left node's slot in the parent's children
    2880            1729 :             unsigned int leftslot = 0;
    2881            7793 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2882            4335 :                 ++leftslot;
    2883                 : 
    2884            1729 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2885            1729 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2886            1729 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2887                 : 
    2888            1729 :             BTREE_ASSERT(leftslot == parentslot);
    2889                 :         }
    2890                 : 
    2891                 :         // shift all slots in the right node
    2892                 : 
    2893            1729 :         BTREE_ASSERT(right->slotuse + shiftnum < leafslotmax);
    2894                 : 
    2895            8645 :         for(int i = right->slotuse; i >= 0; i--)
    2896                 :         {
    2897            6916 :             right->slotkey[i + shiftnum] = right->slotkey[i];
    2898            6916 :             right->slotdata[i + shiftnum] = right->slotdata[i];
    2899                 :         }
    2900            1729 :         right->slotuse += shiftnum;
    2901                 : 
    2902                 :         // copy the last items from the left node to the first slot in the right node.
    2903            3840 :         for(unsigned int i = 0; i < shiftnum; i++)
    2904                 :         {
    2905            2111 :             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i];
    2906            2111 :             right->slotdata[i] = left->slotdata[left->slotuse - shiftnum + i];
    2907                 :         }
    2908            1729 :         left->slotuse -= shiftnum;
    2909                 : 
    2910            1729 :         parent->slotkey[parentslot] = left->slotkey[left->slotuse-1];
    2911                 :     }
    2912                 : 
    2913                 :     /// Balance two inner nodes. The function moves key/data pairs from left to
    2914                 :     /// right so that both nodes are equally filled. The parent node is updated
    2915                 :     /// if possible.
    2916             490 :     static void shift_right_inner(inner_node *left, inner_node *right, inner_node *parent, unsigned int parentslot)
    2917                 :     {
    2918             490 :         BTREE_ASSERT(left->level == right->level);
    2919             490 :         BTREE_ASSERT(parent->level == left->level + 1);
    2920                 : 
    2921             490 :         BTREE_ASSERT(left->slotuse > right->slotuse);
    2922             490 :         BTREE_ASSERT(parent->childid[parentslot] == left);
    2923                 : 
    2924             490 :         unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
    2925                 : 
    2926                 :         BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right " << right << " from left " << left << " with common parent " << parent << "." << std::endl);
    2927                 : 
    2928                 :         if (selfverify)
    2929                 :         {
    2930                 :             // find the left node's slot in the parent's children
    2931             490 :             unsigned int leftslot = 0;
    2932            1999 :             while(leftslot <= parent->slotuse && parent->childid[leftslot] != left)
    2933            1019 :                 ++leftslot;
    2934                 : 
    2935             490 :             BTREE_ASSERT(leftslot < parent->slotuse);
    2936             490 :             BTREE_ASSERT(parent->childid[leftslot] == left);
    2937             490 :             BTREE_ASSERT(parent->childid[leftslot+1] == right);
    2938                 : 
    2939             490 :             BTREE_ASSERT(leftslot == parentslot);
    2940                 :         }
    2941                 : 
    2942                 :         // shift all slots in the right node
    2943                 : 
    2944             490 :         BTREE_ASSERT(right->slotuse + shiftnum < innerslotmax);
    2945                 : 
    2946             490 :         right->childid[right->slotuse + shiftnum] = right->childid[right->slotuse];
    2947            1960 :         for(int i = right->slotuse-1; i >= 0; i--)
    2948                 :         {
    2949            1470 :             right->slotkey[i + shiftnum] = right->slotkey[i];
    2950            1470 :             right->childid[i + shiftnum] = right->childid[i];
    2951                 :         }
    2952                 : 
    2953             490 :         right->slotuse += shiftnum;
    2954                 : 
    2955                 :         // copy the parent's decision slotkey and childid to the last new key on the right
    2956             490 :         right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
    2957             490 :         right->childid[shiftnum - 1] = left->childid[left->slotuse];
    2958                 : 
    2959                 :         // copy the remaining last items from the left node to the first slot in the right node.
    2960             676 :         for(unsigned int i = 0; i < shiftnum - 1; i++)
    2961                 :         {
    2962             186 :             right->slotkey[i] = left->slotkey[left->slotuse - shiftnum + i + 1];
    2963             186 :             right->childid[i] = left->childid[left->slotuse - shiftnum + i + 1];
    2964                 :         }
    2965                 : 
    2966                 :         // copy the first to-be-removed key from the left node to the parent's decision slot
    2967             490 :         parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
    2968                 : 
    2969             490 :         left->slotuse -= shiftnum;
    2970                 :     }
    2971                 : 
    2972                 : #ifdef BTREE_DEBUG
    2973                 : public:
    2974                 :     // *** Debug Printing
    2975                 : 
    2976                 :     /// Print out the B+ tree structure with keys onto the given ostream. This
    2977                 :     /// function requires that the header is compiled with BTREE_DEBUG and that
    2978                 :     /// key_type is printable via std::ostream.
    2979               0 :     void print(std::ostream &os) const
    2980                 :     {
    2981               0 :         if (root) {
    2982               0 :             print_node(os, root, 0, true);
    2983                 :         }
    2984                 :     }
    2985                 : 
    2986                 :     /// Print out only the leaves via the double linked list.
    2987               0 :     void print_leaves(std::ostream &os) const
    2988                 :     {
    2989               0 :         os << "leaves:" << std::endl;
    2990                 : 
    2991               0 :         const leaf_node *n = headleaf;
    2992                 : 
    2993               0 :         while(n)
    2994                 :         {
    2995               0 :             os << "  " << n << std::endl;
    2996                 : 
    2997               0 :             n = n->nextleaf;
    2998                 :         }
    2999                 :     }
    3000                 : 
    3001                 : private:
    3002                 : 
    3003                 :     /// Recursively descend down the tree and print out nodes.
    3004               0 :     static void print_node(std::ostream &os, const node* node, unsigned int depth=0, bool recursive=false)
    3005                 :     {
    3006               0 :         for(unsigned int i = 0; i < depth; i++) os << "  ";
    3007                 : 
    3008               0 :         os << "node " << node << " level " << node->level << " slotuse " << node->slotuse << std::endl;
    3009                 : 
    3010               0 :         if (node->isleafnode())
    3011                 :         {
    3012               0 :             const leaf_node *leafnode = static_cast<const leaf_node*>(node);
    3013                 : 
    3014               0 :             for(unsigned int i = 0; i < depth; i++) os << "  ";
    3015               0 :             os << "  leaf prev " << leafnode->prevleaf << " next " << leafnode->nextleaf << std::endl;
    3016                 : 
    3017               0 :             for(unsigned int i = 0; i < depth; i++) os << "  ";
    3018                 : 
    3019               0 :             for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
    3020                 :             {
    3021               0 :                 os << leafnode->slotkey[slot] << "  "; // << "(data: " << leafnode->slotdata[slot] << ") ";
    3022                 :             }
    3023               0 :             os << std::endl;
    3024                 :         }
    3025                 :         else
    3026                 :         {
    3027               0 :             const inner_node *innernode = static_cast<const inner_node*>(node);
    3028                 : 
    3029               0 :             for(unsigned int i = 0; i < depth; i++) os << "  ";
    3030                 : 
    3031               0 :             for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
    3032                 :             {
    3033               0 :                 os << "(" << innernode->childid[slot] << ") " << innernode->slotkey[slot] << " ";
    3034                 :             }
    3035               0 :             os << "(" << innernode->childid[innernode->slotuse] << ")" << std::endl;
    3036                 : 
    3037               0 :             if (recursive)
    3038                 :             {
    3039               0 :                 for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
    3040                 :                 {
    3041               0 :                     print_node(os, innernode->childid[slot], depth + 1, recursive);
    3042                 :                 }
    3043                 :             }
    3044                 :         }
    3045                 :     }
    3046                 : #endif
    3047                 : 
    3048                 : public:
    3049                 :     // *** Verification of B+ Tree Invariants
    3050                 : 
    3051                 :     /// Run a thorough verification of all B+ tree invariants. The program
    3052                 :     /// aborts via assert() if something is wrong.
    3053           84063 :     void verify() const
    3054                 :     {
    3055            2989 :         key_type minkey, maxkey;
    3056           84063 :         tree_stats vstats;
    3057                 : 
    3058           84063 :         if (root)
    3059                 :         {
    3060           84043 :             verify_node(root, &minkey, &maxkey, vstats);
    3061                 : 
    3062           84043 :             assert( vstats.itemcount == stats.itemcount );
    3063           84043 :             assert( vstats.leaves == stats.leaves );
    3064           84043 :             assert( vstats.innernodes == stats.innernodes );
    3065                 : 
    3066           84043 :             verify_leaflinks();
    3067                 :         }
    3068                 :     }
    3069                 : 
    3070                 : private:
    3071                 : 
    3072                 :     /// Recursively descend down the tree and verify each node
    3073        65325181 :     void verify_node(const node* n, key_type* minkey, key_type* maxkey, tree_stats &vstats) const
    3074                 :     {
    3075                 :         BTREE_PRINT("verifynode " << n << std::endl);
    3076                 : 
    3077        65325181 :         if (n->isleafnode())
    3078                 :         {
    3079        52846399 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    3080                 : 
    3081        52846399 :             assert( leaf == root || !leaf->isunderflow() );
    3082        52846399 :             assert( leaf->slotuse > 0 );
    3083                 : 
    3084       220294984 :             for(unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
    3085                 :             {
    3086       166762783 :                 assert(key_lessequal(leaf->slotkey[slot], leaf->slotkey[slot + 1]));
    3087                 :             }
    3088                 : 
    3089        52846399 :             *minkey = leaf->slotkey[0];
    3090        52846399 :             *maxkey = leaf->slotkey[leaf->slotuse - 1];
    3091                 : 
    3092        52846399 :             vstats.leaves++;
    3093        52846399 :             vstats.itemcount += leaf->slotuse;
    3094                 :         }
    3095                 :         else // !n->isleafnode()
    3096                 :         {
    3097        12478782 :             const inner_node *inner = static_cast<const inner_node*>(n);
    3098        12478782 :             vstats.innernodes++;
    3099                 : 
    3100        12478782 :             assert( inner == root || !inner->isunderflow() );
    3101        12478782 :             assert( inner->slotuse > 0 );
    3102                 : 
    3103        52918043 :             for(unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
    3104                 :             {
    3105        40283574 :                 assert(key_lessequal(inner->slotkey[slot], inner->slotkey[slot + 1]));
    3106                 :             }
    3107                 : 
    3108        77719920 :             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    3109                 :             {
    3110        65241138 :                 const node *subnode = inner->childid[slot];
    3111        65241138 :                 key_type subminkey = key_type();
    3112        65241138 :                 key_type submaxkey = key_type();
    3113                 : 
    3114        65241138 :                 assert(subnode->level + 1 == inner->level);
    3115        65241138 :                 verify_node(subnode, &subminkey, &submaxkey, vstats);
    3116                 : 
    3117                 :                 BTREE_PRINT("verify subnode " << subnode << ": " << subminkey << " - " << submaxkey << std::endl);
    3118                 : 
    3119        65241138 :                 if (slot == 0)
    3120        12478782 :                     *minkey = subminkey;
    3121                 :                 else
    3122        52762356 :                     assert(key_greaterequal(subminkey, inner->slotkey[slot-1]));
    3123                 : 
    3124        65241138 :                 if (slot == inner->slotuse)
    3125        12478782 :                     *maxkey = submaxkey;
    3126                 :                 else
    3127        52762356 :                     assert(key_equal(inner->slotkey[slot], submaxkey));
    3128                 : 
    3129        65241138 :                 if (inner->level == 1 && slot < inner->slotuse)
    3130                 :                 {
    3131                 :                     // children are leaves and must be linked together in the
    3132                 :                     // correct order
    3133        42692204 :                     const leaf_node *leafa = static_cast<const leaf_node*>(inner->childid[slot]);
    3134        42692204 :                     const leaf_node *leafb = static_cast<const leaf_node*>(inner->childid[slot + 1]);
    3135                 : 
    3136        42692204 :                     assert(leafa->nextleaf == leafb);
    3137        42692204 :                     assert(leafa == leafb->prevleaf);
    3138                 :                     (void)leafa; (void)leafb;
    3139                 :                 }
    3140        65241138 :                 if (inner->level == 2 && slot < inner->slotuse)
    3141                 :                 {
    3142                 :                     // verify leaf links between the adjacent inner nodes
    3143         8246953 :                     const inner_node *parenta = static_cast<const inner_node*>(inner->childid[slot]);
    3144         8246953 :                     const inner_node *parentb = static_cast<const inner_node*>(inner->childid[slot+1]);
    3145                 : 
    3146         8246953 :                     const leaf_node *leafa = static_cast<const leaf_node*>(parenta->childid[parenta->slotuse]);
    3147         8246953 :                     const leaf_node *leafb = static_cast<const leaf_node*>(parentb->childid[0]);
    3148                 : 
    3149         8246953 :                     assert(leafa->nextleaf == leafb);
    3150         8246953 :                     assert(leafa == leafb->prevleaf);
    3151        65325181 :                     (void)leafa; (void)leafb;
    3152                 :                 }
    3153                 :             }
    3154                 :         }
    3155                 :     }
    3156                 : 
    3157                 :     /// Verify the double linked list of leaves.
    3158           84043 :     void verify_leaflinks() const
    3159                 :     {
    3160           84043 :         const leaf_node *n = headleaf;
    3161                 : 
    3162           84043 :         assert(n->level == 0);
    3163           84043 :         assert(!n || n->prevleaf == NULL);
    3164                 : 
    3165           84043 :         unsigned int testcount = 0;
    3166                 : 
    3167        53014485 :         while(n)
    3168                 :         {
    3169        52846399 :             assert(n->level == 0);
    3170        52846399 :             assert(n->slotuse > 0);
    3171                 : 
    3172       220294984 :             for(unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
    3173                 :             {
    3174       166762783 :                 assert(key_lessequal(n->slotkey[slot], n->slotkey[slot + 1]));
    3175                 :             }
    3176                 : 
    3177        52846399 :             testcount += n->slotuse;
    3178                 : 
    3179        52846399 :             if (n->nextleaf)
    3180                 :             {
    3181        52762356 :                 assert(key_lessequal(n->slotkey[n->slotuse-1], n->nextleaf->slotkey[0]));
    3182                 : 
    3183        52762356 :                 assert(n == n->nextleaf->prevleaf);
    3184                 :             }
    3185                 :             else
    3186                 :             {
    3187           84043 :                 assert(tailleaf == n);
    3188                 :             }
    3189                 : 
    3190        52846399 :             n = n->nextleaf;
    3191                 :         }
    3192                 : 
    3193           84043 :         assert(testcount == size());
    3194                 :     }
    3195                 : 
    3196                 : private:
    3197                 :     // *** Dump and Restore of B+ Trees
    3198                 : 
    3199                 :     /// \internal A header for the binary image containing the base properties
    3200                 :     /// of the B+ tree. These properties have to match the current template
    3201                 :     /// instantiation.
    3202                 :     struct dump_header
    3203                 :     {
    3204                 :         /// "stx-btree", just to stop the restore() function from loading garbage
    3205                 :         char            signature[12];
    3206                 : 
    3207                 :         /// Currently 0
    3208                 :         unsigned short  version;
    3209                 : 
    3210                 :         /// sizeof(key_type)
    3211                 :         unsigned short  key_type_size;
    3212                 : 
    3213                 :         /// sizeof(data_type)
    3214                 :         unsigned short  data_type_size;
    3215                 : 
    3216                 :         /// Number of slots in the leaves
    3217                 :         unsigned short  leafslots;
    3218                 : 
    3219                 :         /// Number of slots in the inner nodes
    3220                 :         unsigned short  innerslots;
    3221                 : 
    3222                 :         /// Allow duplicates
    3223                 :         bool            allow_duplicates;
    3224                 : 
    3225                 :         /// The item count of the tree
    3226                 :         size_type       itemcount;
    3227                 : 
    3228                 :         /// Fill the struct with the current B+ tree's properties, itemcount is
    3229                 :         /// not filled.
    3230               3 :         inline void fill()
    3231                 :         {
    3232                 :             // don't want to include string.h just for this signature
    3233               3 :             *reinterpret_cast<unsigned int*>(signature+0) = 0x2d787473;
    3234               3 :             *reinterpret_cast<unsigned int*>(signature+4) = 0x65727462;
    3235               3 :             *reinterpret_cast<unsigned int*>(signature+8) = 0x00000065;
    3236                 : 
    3237               3 :             version = 0;
    3238               3 :             key_type_size = sizeof(typename btree_self::key_type);
    3239               3 :             data_type_size = sizeof(typename btree_self::data_type);
    3240               3 :             leafslots = btree_self::leafslotmax;
    3241               3 :             innerslots = btree_self::innerslotmax;
    3242               3 :             allow_duplicates = btree_self::allow_duplicates;
    3243                 :         }
    3244                 : 
    3245                 :         /// Returns true if the headers have the same vital properties
    3246               2 :         inline bool same(const struct dump_header &o) const
    3247                 :         {
    3248                 :             return (*reinterpret_cast<const unsigned int*>(signature+0) ==
    3249                 :                     *reinterpret_cast<const unsigned int*>(o.signature+0))
    3250                 :                 && (*reinterpret_cast<const unsigned int*>(signature+4) ==
    3251                 :                     *reinterpret_cast<const unsigned int*>(o.signature+4))
    3252                 :                 && (*reinterpret_cast<const unsigned int*>(signature+8) ==
    3253                 :                     *reinterpret_cast<const unsigned int*>(o.signature+8))
    3254                 : 
    3255                 :                 && (version == o.version)
    3256                 :                 && (key_type_size == o.key_type_size)
    3257                 :                 && (data_type_size == o.data_type_size)
    3258                 :                 && (leafslots == o.leafslots)
    3259                 :                 && (innerslots == o.innerslots)
    3260               2 :                 && (allow_duplicates == o.allow_duplicates);
    3261                 :         }
    3262                 :     };
    3263                 : 
    3264                 : public:
    3265                 : 
    3266                 :     /// Dump the contents of the B+ tree out onto an ostream as a binary
    3267                 :     /// image. The image contains memory pointers which will be fixed when the
    3268                 :     /// image is restored. For this to work your key_type and data_type must be
    3269                 :     /// integral types and contain no pointers or references.
    3270               1 :     void dump(std::ostream &os) const
    3271                 :     {
    3272                 :         struct dump_header header;
    3273               1 :         header.fill();
    3274               1 :         header.itemcount = size();
    3275                 : 
    3276               1 :         os.write(reinterpret_cast<char*>(&header), sizeof(header));
    3277                 : 
    3278               1 :         if (root) {
    3279               1 :             dump_node(os, root);
    3280                 :         }
    3281                 :     }
    3282                 : 
    3283                 :     /// Restore a binary image of a dumped B+ tree from an istream. The B+ tree
    3284                 :     /// pointers are fixed using the dump order. For dump and restore to work
    3285                 :     /// your key_type and data_type must be integral types and contain no
    3286                 :     /// pointers or references. Returns true if the restore was successful.
    3287               2 :     bool restore(std::istream &is)
    3288                 :     {
    3289                 :         struct dump_header fileheader;
    3290               2 :         is.read(reinterpret_cast<char*>(&fileheader), sizeof(fileheader));
    3291               2 :         if (!is.good()) return false;
    3292                 : 
    3293                 :         struct dump_header myheader;
    3294               2 :         myheader.fill();
    3295               2 :         myheader.itemcount = fileheader.itemcount;
    3296                 : 
    3297               2 :         if (!myheader.same(fileheader))
    3298                 :         {
    3299                 :             BTREE_PRINT("btree::restore: file header does not match instantiation signature." << std::endl);
    3300               1 :             return false;
    3301                 :         }
    3302                 : 
    3303               1 :         clear();
    3304                 : 
    3305               1 :         if (fileheader.itemcount > 0)
    3306                 :         {
    3307               1 :             root = restore_node(is);
    3308               1 :             if (root == NULL) return false;
    3309                 : 
    3310               1 :             stats.itemcount = fileheader.itemcount;
    3311                 :         }
    3312                 : 
    3313                 : #ifdef BTREE_DEBUG
    3314                 :         if (debug) print(std::cout);
    3315                 : #endif
    3316               1 :         if (selfverify) verify();
    3317                 : 
    3318               1 :         return true;
    3319                 :     }
    3320                 : 
    3321                 : private:
    3322                 : 
    3323                 :     /// Recursively descend down the tree and dump each node in a precise order
    3324             867 :     void dump_node(std::ostream &os, const node* n) const
    3325                 :     {
    3326                 :         BTREE_PRINT("dump_node " << n << std::endl);
    3327                 : 
    3328             867 :         if (n->isleafnode())
    3329                 :         {
    3330             734 :             const leaf_node *leaf = static_cast<const leaf_node*>(n);
    3331                 : 
    3332             734 :             os.write(reinterpret_cast<const char*>(leaf), sizeof(*leaf));
    3333                 :         }
    3334                 :         else // !n->isleafnode()
    3335                 :         {
    3336             133 :             const inner_node *inner = static_cast<const inner_node*>(n);
    3337                 : 
    3338             133 :             os.write(reinterpret_cast<const char*>(inner), sizeof(*inner));
    3339                 : 
    3340             999 :             for(unsigned short slot = 0; slot <= inner->slotuse; ++slot)
    3341                 :             {
    3342             866 :                 const node *subnode = inner->childid[slot];
    3343                 : 
    3344            1733 :                 dump_node(os, subnode);
    3345                 :             }
    3346                 :         }
    3347                 :     }
    3348                 : 
    3349                 :     /// Read the dump image and construct a tree from the node order in the
    3350                 :     /// serialization.
    3351             867 :     node* restore_node(std::istream &is)
    3352                 :     {
    3353                 :         union {
    3354                 :             node        top;
    3355                 :             leaf_node   leaf;
    3356                 :             inner_node  inner;
    3357                 :         } nu;
    3358                 : 
    3359                 :         // first read only the top of the node
    3360             867 :         is.read(reinterpret_cast<char*>(&nu.top), sizeof(nu.top));
    3361             867 :         if (!is.good()) return NULL;
    3362                 : 
    3363             867 :         if (nu.top.isleafnode())
    3364                 :         {
    3365                 :             // read remaining data of leaf node
    3366             734 :             is.read(reinterpret_cast<char*>(&nu.leaf) + sizeof(nu.top), sizeof(nu.leaf) - sizeof(nu.top));
    3367             734 :             if (!is.good()) return NULL;
    3368                 : 
    3369             734 :             leaf_node *newleaf = allocate_leaf();
    3370                 : 
    3371                 :             // copy over all data, the leaf nodes contain only their double linked list pointers
    3372             734 :             *newleaf = nu.leaf;
    3373                 : 
    3374                 :             // reconstruct the linked list from the order in the file
    3375             734 :             if (headleaf == NULL) {
    3376               1 :                 BTREE_ASSERT(newleaf->prevleaf == NULL);
    3377               1 :                 headleaf = tailleaf = newleaf;
    3378                 :             }
    3379                 :             else {
    3380             733 :                 newleaf->prevleaf = tailleaf;
    3381             733 :                 tailleaf->nextleaf = newleaf;
    3382             733 :                 tailleaf = newleaf;
    3383                 :             }
    3384                 : 
    3385             734 :             return newleaf;
    3386                 :         }
    3387                 :         else
    3388                 :         {
    3389                 :             // read remaining data of inner node
    3390             133 :             is.read(reinterpret_cast<char*>(&nu.inner) + sizeof(nu.top), sizeof(nu.inner) - sizeof(nu.top));
    3391             133 :             if (!is.good()) return NULL;
    3392                 : 
    3393             133 :             inner_node *newinner = allocate_inner(0);
    3394                 : 
    3395                 :             // copy over all data, the inner nodes contain only pointers to their children
    3396             133 :             *newinner = nu.inner;
    3397                 : 
    3398             999 :             for(unsigned short slot = 0; slot <= newinner->slotuse; ++slot)
    3399                 :             {
    3400             866 :                 newinner->childid[slot] = restore_node(is);
    3401                 :             }
    3402                 : 
    3403             133 :             return newinner;
    3404                 :         }
    3405                 :     }
    3406                 : };
    3407                 : 
    3408                 : } // namespace stx
    3409                 : 
    3410                 : #endif // _STX_BTREE_H_

Generated by: LTP GCOV extension version 1.6