src/gui/text/qfragmentmap_p.h
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QFRAGMENTMAP_P_H
       
    43 #define QFRAGMENTMAP_P_H
       
    44 
       
    45 //
       
    46 //  W A R N I N G
       
    47 //  -------------
       
    48 //
       
    49 // This file is not part of the Qt API.  It exists purely as an
       
    50 // implementation detail.  This header file may change from version to
       
    51 // version without notice, or even be removed.
       
    52 //
       
    53 // We mean it.
       
    54 //
       
    55 
       
    56 #include "QtCore/qglobal.h"
       
    57 #include <stdlib.h>
       
    58 #include <private/qtools_p.h>
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 
       
    63 template <int N = 1>
       
    64 class QFragment
       
    65 {
       
    66 public:
       
    67     quint32 parent;
       
    68     quint32 left;
       
    69     quint32 right;
       
    70     quint32 color;
       
    71     quint32 size_left_array[N];
       
    72     quint32 size_array[N];
       
    73     enum {size_array_max = N };
       
    74 };
       
    75 
       
    76 template <class Fragment>
       
    77 class QFragmentMapData
       
    78 {
       
    79     enum Color { Red, Black };
       
    80 public:
       
    81     QFragmentMapData();
       
    82     ~QFragmentMapData();
       
    83 
       
    84     void init();
       
    85 
       
    86     class Header
       
    87     {
       
    88     public:
       
    89         quint32 root; // this relies on being at the same position as parent in the fragment struct
       
    90         quint32 tag;
       
    91         quint32 freelist;
       
    92         quint32 node_count;
       
    93         quint32 allocated;
       
    94     };
       
    95 
       
    96 
       
    97     enum {fragmentSize = sizeof(Fragment) };
       
    98 
       
    99 
       
   100     int length(uint field = 0) const;
       
   101 
       
   102 
       
   103     inline Fragment *fragment(uint index) {
       
   104         return (fragments + index);
       
   105     }
       
   106     inline const Fragment *fragment(uint index) const {
       
   107         return (fragments + index);
       
   108     }
       
   109 
       
   110 
       
   111     inline Fragment &F(uint index) { return fragments[index] ; }
       
   112     inline const Fragment &F(uint index) const { return fragments[index] ; }
       
   113 
       
   114     inline bool isRoot(uint index) const {
       
   115         return !fragment(index)->parent;
       
   116     }
       
   117 
       
   118     inline uint position(uint node, uint field = 0) const {
       
   119         Q_ASSERT(field < Fragment::size_array_max);
       
   120         const Fragment *f = fragment(node);
       
   121         uint offset = f->size_left_array[field];
       
   122         while (f->parent) {
       
   123             uint p = f->parent;
       
   124             f = fragment(p);
       
   125             if (f->right == node)
       
   126                 offset += f->size_left_array[field] + f->size_array[field];
       
   127             node = p;
       
   128         }
       
   129         return offset;
       
   130     }
       
   131     inline uint sizeRight(uint node, uint field = 0) const {
       
   132         Q_ASSERT(field < Fragment::size_array_max);
       
   133         uint sr = 0;
       
   134         const Fragment *f = fragment(node);
       
   135         node = f->right;
       
   136         while (node) {
       
   137             f = fragment(node);
       
   138             sr += f->size_left_array[field] + f->size_array[field];
       
   139             node = f->right;
       
   140         }
       
   141         return sr;
       
   142     }
       
   143     inline uint sizeLeft(uint node, uint field = 0) const {
       
   144         Q_ASSERT(field < Fragment::size_array_max);
       
   145         return fragment(node)->size_left_array[field];
       
   146     }
       
   147 
       
   148 
       
   149     inline uint size(uint node, uint field = 0) const {
       
   150         Q_ASSERT(field < Fragment::size_array_max);
       
   151         return fragment(node)->size_array[field];
       
   152     }
       
   153 
       
   154     inline void setSize(uint node, int new_size, uint field = 0) {
       
   155         Q_ASSERT(field < Fragment::size_array_max);
       
   156         Fragment *f = fragment(node);
       
   157         int diff = new_size - f->size_array[field];
       
   158         f->size_array[field] = new_size;
       
   159         while (f->parent) {
       
   160             uint p = f->parent;
       
   161             f = fragment(p);
       
   162             if (f->left == node)
       
   163                 f->size_left_array[field] += diff;
       
   164             node = p;
       
   165         }
       
   166     }
       
   167 
       
   168 
       
   169     uint findNode(int k, uint field = 0) const;
       
   170 
       
   171     uint insert_single(int key, uint length);
       
   172     uint erase_single(uint f);
       
   173 
       
   174     uint minimum(uint n) const {
       
   175         while (n && fragment(n)->left)
       
   176             n = fragment(n)->left;
       
   177         return n;
       
   178     }
       
   179 
       
   180     uint maximum(uint n) const {
       
   181         while (n && fragment(n)->right)
       
   182             n = fragment(n)->right;
       
   183         return n;
       
   184     }
       
   185 
       
   186     uint next(uint n) const;
       
   187     uint previous(uint n) const;
       
   188 
       
   189     inline uint root() const {
       
   190         Q_ASSERT(!head->root || !fragment(head->root)->parent);
       
   191         return head->root;
       
   192     }
       
   193     inline void setRoot(uint new_root) {
       
   194         Q_ASSERT(!head->root || !fragment(new_root)->parent);
       
   195         head->root = new_root;
       
   196     }
       
   197 
       
   198     union {
       
   199         Header *head;
       
   200         Fragment *fragments;
       
   201     };
       
   202 
       
   203 private:
       
   204 
       
   205     void rotateLeft(uint x);
       
   206     void rotateRight(uint x);
       
   207     void rebalance(uint x);
       
   208     void removeAndRebalance(uint z);
       
   209 
       
   210     uint createFragment();
       
   211     void freeFragment(uint f);
       
   212 
       
   213 };
       
   214 
       
   215 template <class Fragment>
       
   216 QFragmentMapData<Fragment>::QFragmentMapData()
       
   217     : fragments(0)
       
   218 {
       
   219     init();
       
   220 }
       
   221 
       
   222 template <class Fragment>
       
   223 void QFragmentMapData<Fragment>::init()
       
   224 {
       
   225     // the following code will realloc an existing fragment or create a new one.
       
   226     // it will also ignore errors when shrinking an existing fragment.
       
   227     Fragment *newFragments = (Fragment *)realloc(fragments, 64*fragmentSize);
       
   228     if (newFragments) {
       
   229         fragments = newFragments;
       
   230         head->allocated = 64;
       
   231     }
       
   232     Q_CHECK_PTR(fragments);
       
   233 
       
   234     head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p');
       
   235     head->root = 0;
       
   236     head->freelist = 1;
       
   237     head->node_count = 0;
       
   238     // mark all items to the right as unused
       
   239     F(head->freelist).right = 0;
       
   240 }
       
   241 
       
   242 template <class Fragment>
       
   243 QFragmentMapData<Fragment>::~QFragmentMapData()
       
   244 {
       
   245     free(fragments);
       
   246 }
       
   247 
       
   248 template <class Fragment>
       
   249 uint QFragmentMapData<Fragment>::createFragment()
       
   250 {
       
   251     Q_ASSERT(head->freelist <= head->allocated);
       
   252 
       
   253     uint freePos = head->freelist;
       
   254     if (freePos == head->allocated) {
       
   255         // need to create some free space
       
   256         uint needed = qAllocMore((freePos+1)*fragmentSize, 0);
       
   257         Q_ASSERT(needed/fragmentSize > head->allocated);
       
   258         Fragment *newFragments = (Fragment *)realloc(fragments, needed);
       
   259         Q_CHECK_PTR(newFragments);
       
   260         fragments = newFragments;
       
   261         head->allocated = needed/fragmentSize;
       
   262         F(freePos).right = 0;
       
   263     }
       
   264 
       
   265     uint nextPos = F(freePos).right;
       
   266     if (!nextPos) {
       
   267         nextPos = freePos+1;
       
   268         if (nextPos < head->allocated)
       
   269             F(nextPos).right = 0;
       
   270     }
       
   271 
       
   272     head->freelist = nextPos;
       
   273 
       
   274     ++head->node_count;
       
   275 
       
   276     return freePos;
       
   277 }
       
   278 
       
   279 template <class Fragment>
       
   280 void QFragmentMapData<Fragment>::freeFragment(uint i)
       
   281 {
       
   282     F(i).right = head->freelist;
       
   283     head->freelist = i;
       
   284 
       
   285     --head->node_count;
       
   286 }
       
   287 
       
   288 
       
   289 template <class Fragment>
       
   290 uint QFragmentMapData<Fragment>::next(uint n) const {
       
   291     Q_ASSERT(n);
       
   292     if (F(n).right) {
       
   293         n = F(n).right;
       
   294         while (F(n).left)
       
   295             n = F(n).left;
       
   296     } else {
       
   297         uint y = F(n).parent;
       
   298         while (F(n).parent && n == F(y).right) {
       
   299             n = y;
       
   300             y = F(y).parent;
       
   301         }
       
   302         n = y;
       
   303     }
       
   304     return n;
       
   305 }
       
   306 
       
   307 template <class Fragment>
       
   308 uint QFragmentMapData<Fragment>::previous(uint n) const {
       
   309     if (!n)
       
   310         return maximum(root());
       
   311 
       
   312     if (F(n).left) {
       
   313         n = F(n).left;
       
   314         while (F(n).right)
       
   315             n = F(n).right;
       
   316     } else {
       
   317         uint y = F(n).parent;
       
   318         while (F(n).parent && n == F(y).left) {
       
   319             n = y;
       
   320             y = F(y).parent;
       
   321         }
       
   322         n = y;
       
   323     }
       
   324     return n;
       
   325 }
       
   326 
       
   327 
       
   328 /*
       
   329      x              y
       
   330       \            / \
       
   331        y    -->   x   b
       
   332       / \          \
       
   333      a   b          a
       
   334 */
       
   335 template <class Fragment>
       
   336 void QFragmentMapData<Fragment>::rotateLeft(uint x)
       
   337 {
       
   338     uint p = F(x).parent;
       
   339     uint y = F(x).right;
       
   340 
       
   341 
       
   342     if (y) {
       
   343         F(x).right = F(y).left;
       
   344         if (F(y).left)
       
   345             F(F(y).left).parent = x;
       
   346         F(y).left = x;
       
   347         F(y).parent = p;
       
   348     } else {
       
   349         F(x).right = 0;
       
   350     }
       
   351     if (!p) {
       
   352         Q_ASSERT(head->root == x);
       
   353         head->root = y;
       
   354     }
       
   355     else if (x == F(p).left)
       
   356         F(p).left = y;
       
   357     else
       
   358         F(p).right = y;
       
   359     F(x).parent = y;
       
   360     for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   361         F(y).size_left_array[field] += F(x).size_left_array[field] + F(x).size_array[field];
       
   362 }
       
   363 
       
   364 
       
   365 /*
       
   366          x          y
       
   367         /          / \
       
   368        y    -->   a   x
       
   369       / \            /
       
   370      a   b          b
       
   371 */
       
   372 template <class Fragment>
       
   373 void QFragmentMapData<Fragment>::rotateRight(uint x)
       
   374 {
       
   375     uint y = F(x).left;
       
   376     uint p = F(x).parent;
       
   377 
       
   378     if (y) {
       
   379         F(x).left = F(y).right;
       
   380         if (F(y).right)
       
   381             F(F(y).right).parent = x;
       
   382         F(y).right = x;
       
   383         F(y).parent = p;
       
   384     } else {
       
   385         F(x).left = 0;
       
   386     }
       
   387     if (!p) {
       
   388         Q_ASSERT(head->root == x);
       
   389         head->root = y;
       
   390     }
       
   391     else if (x == F(p).right)
       
   392         F(p).right = y;
       
   393     else
       
   394         F(p).left = y;
       
   395     F(x).parent = y;
       
   396     for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   397         F(x).size_left_array[field] -= F(y).size_left_array[field] + F(y).size_array[field];
       
   398 }
       
   399 
       
   400 
       
   401 template <class Fragment>
       
   402 void QFragmentMapData<Fragment>::rebalance(uint x)
       
   403 {
       
   404     F(x).color = Red;
       
   405 
       
   406     while (F(x).parent && F(F(x).parent).color == Red) {
       
   407         uint p = F(x).parent;
       
   408         uint pp = F(p).parent;
       
   409         Q_ASSERT(pp);
       
   410         if (p == F(pp).left) {
       
   411             uint y = F(pp).right;
       
   412             if (y && F(y).color == Red) {
       
   413                 F(p).color = Black;
       
   414                 F(y).color = Black;
       
   415                 F(pp).color = Red;
       
   416                 x = pp;
       
   417             } else {
       
   418                 if (x == F(p).right) {
       
   419                     x = p;
       
   420                     rotateLeft(x);
       
   421                     p = F(x).parent;
       
   422                     pp = F(p).parent;
       
   423                 }
       
   424                 F(p).color = Black;
       
   425                 if (pp) {
       
   426                     F(pp).color = Red;
       
   427                     rotateRight(pp);
       
   428                 }
       
   429             }
       
   430         } else {
       
   431             uint y = F(pp).left;
       
   432             if (y && F(y).color == Red) {
       
   433                 F(p).color = Black;
       
   434                 F(y).color = Black;
       
   435                 F(pp).color = Red;
       
   436                 x = pp;
       
   437             } else {
       
   438                 if (x == F(p).left) {
       
   439                     x = p;
       
   440                     rotateRight(x);
       
   441                     p = F(x).parent;
       
   442                     pp = F(p).parent;
       
   443                 }
       
   444                 F(p).color = Black;
       
   445                 if (pp) {
       
   446                     F(pp).color = Red;
       
   447                     rotateLeft(pp);
       
   448                 }
       
   449             }
       
   450         }
       
   451     }
       
   452     F(root()).color = Black;
       
   453 }
       
   454 
       
   455 
       
   456 template <class Fragment>
       
   457 uint QFragmentMapData<Fragment>::erase_single(uint z)
       
   458 {
       
   459     uint w = previous(z);
       
   460     uint y = z;
       
   461     uint x;
       
   462     uint p;
       
   463 
       
   464     if (!F(y).left) {
       
   465         x = F(y).right;
       
   466     } else if (!F(y).right) {
       
   467         x = F(y).left;
       
   468     } else {
       
   469         y = F(y).right;
       
   470         while (F(y).left)
       
   471             y = F(y).left;
       
   472         x = F(y).right;
       
   473     }
       
   474 
       
   475     if (y != z) {
       
   476         F(F(z).left).parent = y;
       
   477         F(y).left = F(z).left;
       
   478         for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   479             F(y).size_left_array[field] = F(z).size_left_array[field];
       
   480         if (y != F(z).right) {
       
   481             /*
       
   482                      z                y
       
   483                     / \              / \
       
   484                    a   b            a   b
       
   485                       /                /
       
   486                     ...     -->      ...
       
   487                     /                /
       
   488                    y                x
       
   489                   / \
       
   490                  0   x
       
   491              */
       
   492             p = F(y).parent;
       
   493             if (x)
       
   494                 F(x).parent = p;
       
   495             F(p).left = x;
       
   496             F(y).right = F(z).right;
       
   497             F(F(z).right).parent = y;
       
   498             uint n = p;
       
   499             while (n != y) {
       
   500                 for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   501                     F(n).size_left_array[field] -= F(y).size_array[field];
       
   502                 n = F(n).parent;
       
   503             }
       
   504         } else {
       
   505             /*
       
   506                      z                y
       
   507                     / \              / \
       
   508                    a   y     -->    a   x
       
   509                       / \
       
   510                      0   x
       
   511              */
       
   512             p = y;
       
   513         }
       
   514         uint zp = F(z).parent;
       
   515         if (!zp) {
       
   516             Q_ASSERT(head->root == z);
       
   517             head->root = y;
       
   518         } else if (F(zp).left == z) {
       
   519             F(zp).left = y;
       
   520             for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   521                 F(zp).size_left_array[field] -= F(z).size_array[field];
       
   522         } else {
       
   523             F(zp).right = y;
       
   524         }
       
   525         F(y).parent = zp;
       
   526         // Swap the colors
       
   527         uint c = F(y).color;
       
   528         F(y).color = F(z).color;
       
   529         F(z).color = c;
       
   530         y = z;
       
   531     } else {
       
   532         /*
       
   533                 p          p            p          p
       
   534                /          /              \          \
       
   535               z    -->   x                z  -->     x
       
   536               |                           |
       
   537               x                           x
       
   538          */
       
   539         p = F(z).parent;
       
   540         if (x)
       
   541             F(x).parent = p;
       
   542         if (!p) {
       
   543             Q_ASSERT(head->root == z);
       
   544             head->root = x;
       
   545         } else if (F(p).left == z) {
       
   546             F(p).left = x;
       
   547             for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   548                 F(p).size_left_array[field] -= F(z).size_array[field];
       
   549         } else {
       
   550             F(p).right = x;
       
   551         }
       
   552     }
       
   553     uint n = z;
       
   554     while (F(n).parent) {
       
   555         uint p = F(n).parent;
       
   556         if (F(p).left == n) {
       
   557             for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   558                 F(p).size_left_array[field] -= F(z).size_array[field];
       
   559         }
       
   560         n = p;
       
   561     }
       
   562 
       
   563     freeFragment(z);
       
   564 
       
   565 
       
   566     if (F(y).color != Red) {
       
   567         while (F(x).parent && (x == 0 || F(x).color == Black)) {
       
   568             if (x == F(p).left) {
       
   569                 uint w = F(p).right;
       
   570                 if (F(w).color == Red) {
       
   571                     F(w).color = Black;
       
   572                     F(p).color = Red;
       
   573                     rotateLeft(p);
       
   574                     w = F(p).right;
       
   575                 }
       
   576                 if ((F(w).left == 0 || F(F(w).left).color == Black) &&
       
   577                     (F(w).right == 0 || F(F(w).right).color == Black)) {
       
   578                     F(w).color = Red;
       
   579                     x = p;
       
   580                     p = F(x).parent;
       
   581                 } else {
       
   582                     if (F(w).right == 0 || F(F(w).right).color == Black) {
       
   583                         if (F(w).left)
       
   584                             F(F(w).left).color = Black;
       
   585                         F(w).color = Red;
       
   586                         rotateRight(F(p).right);
       
   587                         w = F(p).right;
       
   588                     }
       
   589                     F(w).color = F(p).color;
       
   590                     F(p).color = Black;
       
   591                     if (F(w).right)
       
   592                         F(F(w).right).color = Black;
       
   593                     rotateLeft(p);
       
   594                     break;
       
   595                 }
       
   596             } else {
       
   597                 uint w = F(p).left;
       
   598                 if (F(w).color == Red) {
       
   599                     F(w).color = Black;
       
   600                     F(p).color = Red;
       
   601                     rotateRight(p);
       
   602                     w = F(p).left;
       
   603                 }
       
   604                 if ((F(w).right == 0 || F(F(w).right).color == Black) &&
       
   605                     (F(w).left == 0 || F(F(w).left).color == Black)) {
       
   606                     F(w).color = Red;
       
   607                     x = p;
       
   608                     p = F(x).parent;
       
   609                 } else {
       
   610                     if (F(w).left == 0 || F(F(w).left).color == Black) {
       
   611                         if (F(w).right)
       
   612                             F(F(w).right).color = Black;
       
   613                         F(w).color = Red;
       
   614                         rotateLeft(F(p).left);
       
   615                         w = F(p).left;
       
   616                     }
       
   617                     F(w).color = F(p).color;
       
   618                     F(p).color = Black;
       
   619                     if (F(w).left)
       
   620                         F(F(w).left).color = Black;
       
   621                     rotateRight(p);
       
   622                     break;
       
   623                 }
       
   624             }
       
   625         }
       
   626         if (x)
       
   627             F(x).color = Black;
       
   628     }
       
   629 
       
   630     return w;
       
   631 }
       
   632 
       
   633 template <class Fragment>
       
   634 uint QFragmentMapData<Fragment>::findNode(int k, uint field) const
       
   635 {
       
   636     Q_ASSERT(field < Fragment::size_array_max);
       
   637     uint x = root();
       
   638 
       
   639     uint s = k;
       
   640     while (x) {
       
   641         if (sizeLeft(x, field) <= s) {
       
   642             if (s < sizeLeft(x, field) + size(x, field))
       
   643                 return x;
       
   644             s -= sizeLeft(x, field) + size(x, field);
       
   645             x = F(x).right;
       
   646         } else {
       
   647             x = F(x).left;
       
   648         }
       
   649     }
       
   650     return 0;
       
   651 }
       
   652 
       
   653 template <class Fragment>
       
   654 uint QFragmentMapData<Fragment>::insert_single(int key, uint length)
       
   655 {
       
   656     Q_ASSERT(!findNode(key) || (int)this->position(findNode(key)) == key);
       
   657 
       
   658     uint z = createFragment();
       
   659 
       
   660     F(z).left = 0;
       
   661     F(z).right = 0;
       
   662     F(z).size_array[0] = length;
       
   663     for (uint field = 1; field < Fragment::size_array_max; ++field)
       
   664         F(z).size_array[field] = 1;
       
   665     for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   666         F(z).size_left_array[field] = 0;
       
   667 
       
   668     uint y = 0;
       
   669     uint x = root();
       
   670 
       
   671     Q_ASSERT(!x || F(x).parent == 0);
       
   672 
       
   673     uint s = key;
       
   674     bool right = false;
       
   675     while (x) {
       
   676         y = x;
       
   677         if (s <= F(x).size_left_array[0]) {
       
   678             x = F(x).left;
       
   679             right = false;
       
   680         } else {
       
   681             s -= F(x).size_left_array[0] + F(x).size_array[0];
       
   682             x = F(x).right;
       
   683             right = true;
       
   684         }
       
   685     }
       
   686 
       
   687     F(z).parent = y;
       
   688     if (!y) {
       
   689         head->root = z;
       
   690     } else if (!right) {
       
   691         F(y).left = z;
       
   692         for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   693             F(y).size_left_array[field] = F(z).size_array[field];
       
   694     } else {
       
   695         F(y).right = z;
       
   696     }
       
   697     while (y && F(y).parent) {
       
   698         uint p = F(y).parent;
       
   699         if (F(p).left == y) {
       
   700             for (uint field = 0; field < Fragment::size_array_max; ++field)
       
   701                 F(p).size_left_array[field] += F(z).size_array[field];
       
   702         }
       
   703         y = p;
       
   704     }
       
   705     rebalance(z);
       
   706 
       
   707     return z;
       
   708 }
       
   709 
       
   710 
       
   711 template <class Fragment>
       
   712 int QFragmentMapData<Fragment>::length(uint field) const {
       
   713     uint root = this->root();
       
   714     return root ? sizeLeft(root, field) + size(root, field) + sizeRight(root, field) : 0;
       
   715 }
       
   716 
       
   717 
       
   718 template <class Fragment> // NOTE: must inherit QFragment
       
   719 class QFragmentMap
       
   720 {
       
   721 public:
       
   722     class Iterator
       
   723     {
       
   724     public:
       
   725         QFragmentMap *pt;
       
   726         quint32 n;
       
   727 
       
   728         Iterator() : pt(0), n(0) {}
       
   729         Iterator(QFragmentMap *p, int node) : pt(p), n(node) {}
       
   730         Iterator(const Iterator& it) : pt(it.pt), n(it.n) {}
       
   731 
       
   732         inline bool atEnd() const { return !n; }
       
   733 
       
   734         bool operator==(const Iterator& it) const { return pt == it.pt && n == it.n; }
       
   735         bool operator!=(const Iterator& it) const { return pt != it.pt || n != it.n; }
       
   736         bool operator<(const Iterator &it) const { return position() < it.position(); }
       
   737 
       
   738         Fragment *operator*() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   739         const Fragment *operator*() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   740         Fragment *operator->() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   741         const Fragment *operator->() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   742 
       
   743         int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); }
       
   744         const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   745         Fragment *value() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   746 
       
   747         Iterator& operator++() {
       
   748             n = pt->data.next(n);
       
   749             return *this;
       
   750         }
       
   751         Iterator& operator--() {
       
   752             n = pt->data.previous(n);
       
   753             return *this;
       
   754         }
       
   755 
       
   756     };
       
   757 
       
   758 
       
   759     class ConstIterator
       
   760     {
       
   761     public:
       
   762         const QFragmentMap *pt;
       
   763         quint32 n;
       
   764 
       
   765         /**
       
   766          * Functions
       
   767          */
       
   768         ConstIterator() : pt(0), n(0) {}
       
   769         ConstIterator(const QFragmentMap *p, int node) : pt(p), n(node) {}
       
   770         ConstIterator(const ConstIterator& it) : pt(it.pt), n(it.n) {}
       
   771         ConstIterator(const Iterator& it) : pt(it.pt), n(it.n) {}
       
   772 
       
   773         inline bool atEnd() const { return !n; }
       
   774 
       
   775         bool operator==(const ConstIterator& it) const { return pt == it.pt && n == it.n; }
       
   776         bool operator!=(const ConstIterator& it) const { return pt != it.pt || n != it.n; }
       
   777         bool operator<(const ConstIterator &it) const { return position() < it.position(); }
       
   778 
       
   779         const Fragment *operator*()  const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   780         const Fragment *operator->()  const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   781 
       
   782         int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); }
       
   783         int size() const { Q_ASSERT(!atEnd()); return pt->data.size(n); }
       
   784         const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
       
   785 
       
   786         ConstIterator& operator++() {
       
   787             n = pt->data.next(n);
       
   788             return *this;
       
   789         }
       
   790         ConstIterator& operator--() {
       
   791             n = pt->data.previous(n);
       
   792             return *this;
       
   793         }
       
   794     };
       
   795 
       
   796 
       
   797     QFragmentMap() {}
       
   798     ~QFragmentMap()
       
   799     {
       
   800         if (!data.fragments)
       
   801             return; // in case of out-of-memory, we won't have fragments
       
   802         for (Iterator it = begin(); !it.atEnd(); ++it)
       
   803             it.value()->free();
       
   804     }
       
   805 
       
   806     inline void clear() {
       
   807         for (Iterator it = begin(); !it.atEnd(); ++it)
       
   808             it.value()->free();
       
   809         data.init();
       
   810     }
       
   811 
       
   812     inline Iterator begin() { return Iterator(this, data.minimum(data.root())); }
       
   813     inline Iterator end() { return Iterator(this, 0); }
       
   814     inline ConstIterator begin() const { return ConstIterator(this, data.minimum(data.root())); }
       
   815     inline ConstIterator end() const { return ConstIterator(this, 0); }
       
   816 
       
   817     inline ConstIterator last() const { return ConstIterator(this, data.maximum(data.root())); }
       
   818 
       
   819     inline bool isEmpty() const { return data.head->node_count == 0; }
       
   820     inline int numNodes() const { return data.head->node_count; }
       
   821     int length(uint field = 0) const { return data.length(field); }
       
   822 
       
   823     Iterator find(int k, uint field = 0) { return Iterator(this, data.findNode(k, field)); }
       
   824     ConstIterator find(int k, uint field = 0) const { return ConstIterator(this, data.findNode(k, field)); }
       
   825 
       
   826     uint findNode(int k, uint field = 0) const { return data.findNode(k, field); }
       
   827 
       
   828     uint insert_single(int key, uint length)
       
   829     {
       
   830         uint f = data.insert_single(key, length);
       
   831         if (f != 0) {
       
   832             Fragment *frag = fragment(f);
       
   833             Q_ASSERT(frag);
       
   834             frag->initialize();
       
   835         }
       
   836         return f;
       
   837     }
       
   838     uint erase_single(uint f)
       
   839     {
       
   840       if (f != 0) {
       
   841           Fragment *frag = fragment(f);
       
   842           Q_ASSERT(frag);
       
   843           frag->free();
       
   844       }
       
   845       return data.erase_single(f);
       
   846     }
       
   847 
       
   848     inline Fragment *fragment(uint index) {
       
   849         Q_ASSERT(index != 0);
       
   850         return data.fragment(index);
       
   851     }
       
   852     inline const Fragment *fragment(uint index) const {
       
   853         Q_ASSERT(index != 0);
       
   854         return data.fragment(index);
       
   855     }
       
   856     inline uint position(uint node, uint field = 0) const { return data.position(node, field); }
       
   857     inline uint next(uint n) const { return data.next(n); }
       
   858     inline uint previous(uint n) const { return data.previous(n); }
       
   859     inline uint size(uint node, uint field = 0) const { return data.size(node, field); }
       
   860     inline void setSize(uint node, int new_size, uint field = 0)
       
   861         { data.setSize(node, new_size, field);
       
   862       if (node != 0 && field == 0) {
       
   863           Fragment *frag = fragment(node);
       
   864           Q_ASSERT(frag);
       
   865           frag->invalidate();
       
   866       }
       
   867     }
       
   868 
       
   869     inline int firstNode() const { return data.minimum(data.root()); }
       
   870 
       
   871 private:
       
   872     friend class Iterator;
       
   873     friend class ConstIterator;
       
   874 
       
   875     QFragmentMapData<Fragment> data;
       
   876 
       
   877     QFragmentMap(const QFragmentMap& m);
       
   878     QFragmentMap& operator= (const QFragmentMap& m);
       
   879 };
       
   880 
       
   881 QT_END_NAMESPACE
       
   882 
       
   883 #endif // QFRAGMENTMAP_P_H