• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

util

convenientfreelist.h

00001 /* This file is part of KDevelop
00002     Copyright 2008 David Nolden <david.nolden.kdevelop@art-master.de>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #ifndef CONVENIENTFREELIST_H
00020 #define CONVENIENTFREELIST_H
00021 
00022 #include <QtCore/QVector>
00023 #include <QtCore/QPair>
00024 
00025 #include <KDE/KDebug>
00026 
00027 #include "embeddedfreetree.h"
00028 #include "kdevvarlengtharray.h"
00029 
00030 namespace KDevelop {
00031     
00032     template<class Data, class Handler>
00033     class ConvenientEmbeddedSetIterator;
00034     template<class Data, class Handler, class Data2, class Handler2, class KeyExtractor>
00035     class ConvenientEmbeddedSetFilterIterator;
00036     
00038     template<class Data, class Handler>
00039     class ConstantConvenientEmbeddedSet {
00040         public:
00041             ConstantConvenientEmbeddedSet() : m_data(0), m_dataSize(0), m_centralFreeItem(-1) {
00042             }
00043             ConstantConvenientEmbeddedSet(const Data* data, uint count, int centralFreeItem) : m_data(data), m_dataSize(count), m_centralFreeItem(centralFreeItem) {
00044             }
00045             
00047             bool contains(const Data& data) const {
00048                 return indexOf(data) != -1;
00049             }
00050             
00052             int indexOf(const Data& data) const {
00053                 EmbeddedTreeAlgorithms<Data, Handler> alg(m_data, m_dataSize, m_centralFreeItem);
00054                 return alg.indexOf(data);
00055             }
00056             
00058             uint dataSize() const {
00059                 return m_dataSize;
00060             }
00061             
00062             uint countFreeItems() {
00063                 EmbeddedTreeAlgorithms<Data, Handler> alg(m_data, m_dataSize, m_centralFreeItem);
00064                 return alg.countFreeItems();
00065             }
00066             
00067             void verify() {
00068                 EmbeddedTreeAlgorithms<Data, Handler> alg(m_data, m_dataSize, m_centralFreeItem);
00069                 alg.verifyTreeConsistent();
00070                 alg.verifyOrder();
00071             }
00072             
00074             const Data* data() const {
00075                 return m_data;
00076             }
00077             
00080             int lowerBound(const Data& data) const {
00081                 EmbeddedTreeAlgorithms<Data, Handler> alg(m_data, m_dataSize, m_centralFreeItem);
00082                 return alg.lowerBound(data, 0, m_dataSize);
00083             }
00084 
00088             int lowerBound(const Data& data, uint start, uint end) const {
00089                 EmbeddedTreeAlgorithms<Data, Handler> alg(m_data, m_dataSize, m_centralFreeItem);
00090                 return alg.lowerBound(data, start, end);
00091             }
00092 
00095             int validMiddle(uint start, uint end) {
00096                 if(end <= start)
00097                     return -1;
00098                 
00099                 int firstTry = ((end-start)/2) + start;
00100                 
00101                 int thisTry = firstTry;
00102                 while(thisTry < (int)end && Handler::isFree(m_data[thisTry]))
00103                     ++thisTry;
00104                 
00105                 if(thisTry != (int)end)
00106                     return thisTry;
00107                 
00108                 //Nothing find on right side of middle, try the other direction
00109                 thisTry = firstTry-1;
00110                 while(thisTry >= (int)start && Handler::isFree(m_data[thisTry]))
00111                     --thisTry;
00112                 
00113                 if(thisTry >= (int)start)
00114                     return thisTry;
00115                 else
00116                     return -1;
00117             }
00118             
00120             int firstValidItem(int start, int end = -1) const {
00121                 if(end == -1)
00122                     end = (int)m_dataSize;
00123                 for(; start < end; ++start)
00124                     if(!Handler::isFree(m_data[start]))
00125                         return start;
00126 
00127                 return -1;
00128             }
00129             
00131             int lastValidItem(int start = 0, int end = -1) const {
00132                 if(end == -1)
00133                     end = (int)m_dataSize;
00134                 --end;
00135                 for(; end >= start; --end)
00136                     if(!Handler::isFree(m_data[end]))
00137                         return end;
00138 
00139                 return -1;
00140             }
00141             
00142             typedef ConvenientEmbeddedSetIterator<Data, Handler> Iterator;
00143             
00144             ConvenientEmbeddedSetIterator<Data, Handler> iterator() const;
00145             
00146 //         protected:
00147             const Data* m_data;
00148             uint m_dataSize;
00149             int m_centralFreeItem;
00150     };
00151     
00153     template<class Data, class Handler>
00154     class ConvenientEmbeddedSetIterator : public ConstantConvenientEmbeddedSet<Data, Handler> {
00155         public:
00156         ConvenientEmbeddedSetIterator(const Data* data = 0, uint count = 0, int centralFreeItem = -1) : ConstantConvenientEmbeddedSet<Data, Handler>(data, count, centralFreeItem), m_pos(0) {
00157             //Move to first valid position
00158             moveToValid();
00159         }
00160         
00162         operator bool() const {
00163             return m_pos != this->m_dataSize;
00164         }
00165         
00166         const Data* operator->() const {
00167             return &this->m_data[m_pos];
00168         }
00169         
00170         const Data& operator*() const {
00171             return this->m_data[m_pos];
00172         }
00173         
00174         ConvenientEmbeddedSetIterator& operator++() {
00175             ++m_pos;
00176             moveToValid();
00177             return *this;
00178         }
00179         
00180         protected:
00181             inline void moveToValid() {
00182                 while(this->m_pos < this->m_dataSize && (Handler::isFree(this->m_data[this->m_pos])))
00183                     ++this->m_pos;
00184             }
00185             uint m_pos;
00186     };
00187     
00188     
00195     template<class Data, class Handler, class Data2, class Handler2, class KeyExtractor>
00196     class ConvenientEmbeddedSetFilterIterator : public ConvenientEmbeddedSetIterator<Data, Handler> {
00197         public:
00198         ConvenientEmbeddedSetFilterIterator() : m_match(-1) {
00199         }
00200         ConvenientEmbeddedSetFilterIterator(const ConvenientEmbeddedSetIterator<Data, Handler>& base, const ConvenientEmbeddedSetIterator<Data2, Handler2>& rhs) : ConvenientEmbeddedSetIterator<Data, Handler>(base), m_rhs(rhs), m_match(-1) {
00201             boundStack.append( qMakePair( qMakePair(0u, this->m_dataSize), qMakePair(0u, rhs.m_dataSize) ) );
00202             go();
00203         }
00204         
00205         operator bool() const {
00206             return m_match != -1;
00207         }
00208         
00209         const Data* operator->() const {
00210             Q_ASSERT(m_match != -1);
00211             return &this->m_data[m_match];
00212         }
00213 
00214         const Data& operator*() const {
00215             Q_ASSERT(m_match != -1);
00216             return this->m_data[m_match];
00217         }
00218         
00219         ConvenientEmbeddedSetFilterIterator& operator++() {
00220             Q_ASSERT(m_match != -1);
00221             go();
00222             return *this;
00223         }
00224         #define CHECK_BOUNDS Q_ASSERT(boundStack.back().first.first < 100000 && boundStack.back().first.second < 10000  && boundStack.back().second.first < 100000 && boundStack.back().second.second < 10000 );
00225 
00226         private:
00227         void go() {
00228             m_match = -1;
00229             
00230             boundsUp:
00231             if(boundStack.isEmpty())
00232                 return;
00233             CHECK_BOUNDS
00234             QPair<QPair<uint, uint>, QPair<uint, uint> > currentBounds = boundStack.back();
00235             boundStack.pop_back();
00236 
00237             uint ownStart = currentBounds.first.first, ownEnd = currentBounds.first.second;
00238             uint rhsStart = currentBounds.second.first, rhsEnd = currentBounds.second.second;
00239 #if 0
00240             //This code works, but it doesn't give a speedup
00241             int ownFirstValid = this->firstValidItem(ownStart, ownEnd), ownLastValid = this->lastValidItem(ownStart, ownEnd);
00242             int rhsFirstValid = m_rhs.firstValidItem(rhsStart, rhsEnd), rhsLastValid = m_rhs.lastValidItem(rhsStart, rhsEnd);
00243             
00244             if(ownFirstValid == -1 || rhsFirstValid == -1)
00245                 goto boundsUp;
00246             
00247             
00248             Data2 ownFirstValidData = KeyExtractor::extract(this->m_data[ownFirstValid]);
00249             Data2 ownLastValidData = KeyExtractor::extract(this->m_data[ownLastValid]);
00250             
00251             Data2 commonStart = ownFirstValidData;
00252             Data2 commonLast = ownLastValidData; //commonLast is also still valid
00253             
00254             if(commonStart < m_rhs.m_data[rhsFirstValid])
00255                 commonStart = m_rhs.m_data[rhsFirstValid];
00256             
00257             if(m_rhs.m_data[rhsLastValid] < commonLast)
00258                 commonLast = m_rhs.m_data[rhsLastValid];
00259             
00260             if(commonLast < commonStart)
00261                 goto boundsUp;
00262 #endif
00263             
00264             while(true) {
00265                 if(ownStart == ownEnd)
00266                     goto boundsUp;
00267                 
00268                 int ownMiddle = this->validMiddle(ownStart, ownEnd);
00269                 Q_ASSERT(ownMiddle < 100000);
00270                 if(ownMiddle == -1)
00271                     goto boundsUp; //No valid items in the range
00272                 
00273                 Data2 currentData2 = KeyExtractor::extract(this->m_data[ownMiddle]);
00274                 Q_ASSERT(!Handler2::isFree(currentData2));
00275                 
00276                 int bound = m_rhs.lowerBound(currentData2, rhsStart, rhsEnd);
00277                 if(bound == -1) {
00278                     //Release second half of the own range
00279 //                     Q_ASSERT(ownEnd > ownMiddle);
00280                     ownEnd = ownMiddle;
00281                     continue;
00282                 }
00283 
00284                 if(currentData2 == m_rhs.m_data[bound]) {
00285                     //We have a match
00286                     this->m_match = ownMiddle;
00287                     //Append the ranges that need to be matched next, without the matched item
00288                     boundStack.append( qMakePair( qMakePair( (uint)ownMiddle+1, ownEnd ), qMakePair((uint)bound, rhsEnd)) );
00289                     if(ownMiddle)
00290                         boundStack.append( qMakePair( qMakePair( ownStart, (uint)ownMiddle ), qMakePair(rhsStart, (uint)bound+1)) );
00291                     return;
00292                 }
00293 
00294                 if(bound == m_rhs.firstValidItem(rhsStart)) {
00295                     //The bound is the first valid item of the second range.
00296                     //Discard left side and the matched left item, and continue.
00297                     
00298                     ownStart = ownMiddle+1;
00299                     rhsStart = bound;
00300                     continue;
00301                 }
00302                 
00303                 //Standard: Split both sides into 2 ranges that will be checked next
00304                 boundStack.append( qMakePair( qMakePair( (uint)ownMiddle+1, ownEnd ), qMakePair((uint)bound, rhsEnd)) );
00305 //                 Q_ASSERT(ownMiddle <= ownEnd);
00306                 ownEnd = ownMiddle; //We loose the item at 'middle' here, but that's fine, since it hasn't found a match.
00307                 rhsEnd = bound+1;
00308             }
00309         }
00310 
00311         //Bounds that yet need to be matched.
00312         KDevVarLengthArray<QPair<QPair<uint, uint>, QPair<uint, uint> > > boundStack;
00313         ConvenientEmbeddedSetIterator<Data2, Handler2> m_rhs;
00314         int m_match;
00315     };
00316 
00318     template<class Data, class Handler, class Data2, class TreeSet, class KeyExtractor>
00319     class ConvenientEmbeddedSetTreeFilterIterator : public ConvenientEmbeddedSetIterator<Data, Handler> {
00320         public:
00321         ConvenientEmbeddedSetTreeFilterIterator() : m_match(-1) {
00322         }
00324         ConvenientEmbeddedSetTreeFilterIterator(const ConvenientEmbeddedSetIterator<Data, Handler>& base, const TreeSet& rhs, bool noFiltering = false) : ConvenientEmbeddedSetIterator<Data, Handler>(base), m_rhs(rhs), m_match(-1), m_noFiltering(noFiltering) {
00325             if(rhs.node().isValid()) {
00326                 //Correctly initialize the initial bounds
00327                 int ownStart = lowerBound(rhs.node().firstItem(), 0, this->m_dataSize);
00328                 if(ownStart == -1)
00329                     return;
00330                 int ownEnd = lowerBound(rhs.node().lastItem(), ownStart, this->m_dataSize);
00331                 if(ownEnd == -1)
00332                     ownEnd = this->m_dataSize;
00333                 else
00334                     ownEnd += 1;
00335                 boundStack.append( qMakePair( qMakePair((uint)ownStart, (uint)ownEnd), rhs.node() ) );
00336             }
00337             go();
00338         }
00339         
00340         operator bool() const {
00341             return m_match != -1;
00342         }
00343         
00344         const Data* operator->() const {
00345             Q_ASSERT(m_match != -1);
00346             return &this->m_data[m_match];
00347         }
00348 
00349         const Data& operator*() const {
00350             Q_ASSERT(m_match != -1);
00351             return this->m_data[m_match];
00352         }
00353         
00354         ConvenientEmbeddedSetTreeFilterIterator& operator++() {
00355             Q_ASSERT(m_match != -1);
00356             go();
00357             return *this;
00358         }
00359         #define CHECK_BOUNDS Q_ASSERT(boundStack.back().first.first < 100000 && boundStack.back().first.second < 10000  && boundStack.back().second.first < 100000 && boundStack.back().second.second < 10000 );
00360 
00361         private:
00362         void go() {
00363             if(m_noFiltering) {
00364                 ++m_match;
00365                 if((uint)m_match >= this->m_dataSize)
00366                     m_match = -1;
00367                 return;
00368             }
00369 
00370             if(m_match != -1) {
00371                 //Match multiple items in this list to one in the tree
00372                 m_match = this->firstValidItem(m_match+1, this->m_dataSize);
00373                 if(m_match != -1 && KeyExtractor::extract(this->m_data[m_match]) == m_matchingTo)
00374                     return;
00375             }
00376             m_match = -1;
00377             
00378             boundsUp:
00379             if(boundStack.isEmpty())
00380                 return;
00381             QPair<QPair<uint, uint>, typename TreeSet::Node > currentBounds = boundStack.back();
00382             boundStack.pop_back();
00383 
00384             uint ownStart = currentBounds.first.first, ownEnd = currentBounds.first.second;
00385             typename TreeSet::Node currentNode = currentBounds.second;
00386 
00387             if(ownStart >= ownEnd)
00388                 goto boundsUp;
00389             if(!currentNode.isValid())
00390                 goto boundsUp;
00391             
00392             while(true) {
00393                 if(ownStart == ownEnd)
00394                     goto boundsUp;
00395                 
00396                 if(currentNode.isFinalNode()) {
00397 //                      kDebug() << ownStart << ownEnd << "final node" << currentNode.start() * extractor_div_with << currentNode.end() * extractor_div_with;
00398                     //Check whether the item is contained
00399                     int bound = lowerBound(*currentNode, ownStart, ownEnd);
00400 //                      kDebug() << "bound:" << bound << (KeyExtractor::extract(this->m_data[bound]) == *currentNode);
00401                     if(bound != -1 && KeyExtractor::extract(this->m_data[bound]) == *currentNode) {
00402                         //Got a match
00403                         m_match = bound;
00404                         m_matchingTo = *currentNode;
00405                         m_matchBound = ownEnd;
00406                         return;
00407                     }else{
00408                         //Mismatch
00409                         goto boundsUp;
00410                     }
00411                 }else{
00412 //                     kDebug() << ownStart << ownEnd << "node" << currentNode.start() * extractor_div_with << currentNode.end() * extractor_div_with;
00413                     //This is not a final node, split up the search into the sub-nodes
00414                     typename TreeSet::Node leftNode = currentNode.leftChild();
00415                     typename TreeSet::Node rightNode = currentNode.rightChild();
00416                     Q_ASSERT(leftNode.isValid());
00417                     Q_ASSERT(rightNode.isValid());
00418                     
00419                     
00420                     Data2 leftLastItem = leftNode.lastItem();
00421                     
00422                     int rightSearchStart = lowerBound(rightNode.firstItem(), ownStart, ownEnd);
00423                     if(rightSearchStart == -1)
00424                         rightSearchStart = ownEnd;
00425                     int leftSearchLast = lowerBound(leftLastItem, ownStart, rightSearchStart != -1 ? rightSearchStart : ownEnd);
00426                     if(leftSearchLast == -1)
00427                         leftSearchLast = rightSearchStart-1;
00428                     
00429                     bool recurseLeft = false;
00430                     if(leftSearchLast > (int)ownStart) {
00431                         recurseLeft = true; //There must be something in the range ownStart -> leftSearchLast that matches the range
00432                     }else if((int)ownStart == leftSearchLast) {
00433                         //Check if the one item item under leftSearchStart is contained in the range
00434                         Data2 leftFoundStartData = KeyExtractor::extract(this->m_data[ownStart]);
00435                         recurseLeft = leftFoundStartData < leftLastItem || leftFoundStartData == leftLastItem;
00436                     }
00437                     
00438                     bool recurseRight = false;
00439                     if(rightSearchStart < (int)ownEnd)
00440                         recurseRight = true;
00441                     
00442                     if(recurseLeft && recurseRight) {
00443                         //Push the right branch onto the stack, and work in the left one
00444                         boundStack.append( qMakePair( qMakePair( (uint)rightSearchStart, ownEnd ), rightNode) );
00445                     }
00446                     
00447                     if(recurseLeft) {
00448                         currentNode = leftNode;
00449                         if(leftSearchLast != -1)
00450                             ownEnd = leftSearchLast+1;
00451                     }else if(recurseRight) {
00452                         currentNode = rightNode;
00453                         ownStart = rightSearchStart;
00454                     }else{
00455                         goto boundsUp;
00456                     }
00457                 }
00458             }
00459         }
00460         
00463         int lowerBound(const Data2& data, int start, int end) {
00464             int currentBound = -1;
00465             while(1) {
00466                 if(start >= end)
00467                     return currentBound;
00468                 
00469                 int center = (start + end)/2;
00470                 
00471                 //Skip free items, since they cannot be used for ordering
00472                 for(; center < end; ) {
00473                     if(!Handler::isFree(this->m_data[center]))
00474                         break;
00475                     ++center;
00476                 }
00477                 
00478                 if(center == end) {
00479                     end = (start + end)/2; //No non-free items found in second half, so continue search in the other
00480                 }else{
00481                     Data2 centerData = KeyExtractor::extract(this->m_data[center]);
00482                     //Even if the data equals we must continue searching to the left, since there may be multiple matching
00483                     if(data == centerData || data < centerData) {
00484                         currentBound = center;
00485                         end = (start + end)/2;
00486                     }else{
00487                         //Continue search in second half
00488                         start = center+1;
00489                     }
00490                 }
00491             }
00492         }
00493         
00494         //Bounds that yet need to be matched. Always a range in the own vector, and a node that all items in the range are contained in
00495         KDevVarLengthArray<QPair<QPair<uint, uint>, typename TreeSet::Node > > boundStack;
00496         TreeSet m_rhs;
00497         int m_match, m_matchBound;
00498         Data2 m_matchingTo;
00499         bool m_noFiltering;
00500     };
00501 
00504     template<class Data, class Handler, class Data2, class TreeSet, class KeyExtractor, class Visitor>
00505     class ConvenientEmbeddedSetTreeFilterVisitor : public ConvenientEmbeddedSetIterator<Data, Handler> {
00506         public:
00507         ConvenientEmbeddedSetTreeFilterVisitor() {
00508         }
00509         
00510         typedef QPair<QPair<uint, uint>, typename TreeSet::Node > Bounds;
00511         
00512         struct Bound {
00513             inline Bound(uint s, uint e, const typename TreeSet::Node& n) : start(s), end(e), node(n) {
00514             }
00515             Bound() {
00516             }
00517             uint start;
00518             uint end;
00519             typename TreeSet::Node node;
00520         };
00521         
00523         ConvenientEmbeddedSetTreeFilterVisitor(Visitor& visitor, const ConvenientEmbeddedSetIterator<Data, Handler>& base, const TreeSet& rhs, bool noFiltering = false) : ConvenientEmbeddedSetIterator<Data, Handler>(base), m_visitor(visitor), m_rhs(rhs), m_noFiltering(noFiltering) {
00524             
00525             if(m_noFiltering) {
00526                 for(uint a = 0; a < this->m_dataSize; ++a)
00527                     visitor(this->m_data[a]);
00528                 return;
00529             }
00530             
00531             if(rhs.node().isValid())  {
00532                 //Correctly initialize the initial bounds
00533                 int ownStart = lowerBound(rhs.node().firstItem(), 0, this->m_dataSize);
00534                 if(ownStart == -1)
00535                     return;
00536                 int ownEnd = lowerBound(rhs.node().lastItem(), ownStart, this->m_dataSize);
00537                 if(ownEnd == -1)
00538                     ownEnd = this->m_dataSize;
00539                 else
00540                     ownEnd += 1;
00541                 
00542                 go( Bound((uint)ownStart, (uint)ownEnd, rhs.node()) );
00543             }
00544         }
00545         
00546         private:
00547         void go( Bound bound ) {
00548 
00549             KDevVarLengthArray<Bound> bounds;
00550             
00551             while(true) {
00552                 if(bound.start >= bound.end)
00553                     goto nextBound;
00554                 
00555                 if(bound.node.isFinalNode()) {
00556                     //Check whether the item is contained
00557                     int b = lowerBound(*bound.node, bound.start, bound.end);
00558                     if(b != -1) {
00559                         const Data2& matchTo(*bound.node);
00560                     
00561                         if(KeyExtractor::extract(this->m_data[b]) == matchTo) {
00562                             while(1) {
00563                                 m_visitor(this->m_data[b]);
00564                                 b = this->firstValidItem(b+1, this->m_dataSize);
00565                                 if(b < (int)this->m_dataSize && b != -1 && KeyExtractor::extract(this->m_data[b]) == matchTo)
00566                                     continue;
00567                                 else
00568                                     break;
00569                             }
00570                         }
00571                     }
00572                     goto nextBound;
00573                 }else{
00574                     //This is not a final node, split up the search into the sub-nodes
00575                     typename TreeSet::Node leftNode = bound.node.leftChild();
00576                     typename TreeSet::Node rightNode = bound.node.rightChild();
00577                     Q_ASSERT(leftNode.isValid());
00578                     Q_ASSERT(rightNode.isValid());
00579                     
00580                     
00581                     Data2 leftLastItem = leftNode.lastItem();
00582                     
00583                     int rightSearchStart = lowerBound(rightNode.firstItem(), bound.start, bound.end);
00584                     if(rightSearchStart == -1)
00585                         rightSearchStart = bound.end;
00586                     int leftSearchLast = lowerBound(leftLastItem, bound.start, rightSearchStart != -1 ? rightSearchStart : bound.end);
00587                     if(leftSearchLast == -1)
00588                         leftSearchLast = rightSearchStart-1;
00589                     
00590                     bool recurseLeft = false;
00591                     if(leftSearchLast > (int)bound.start) {
00592                         recurseLeft = true; //There must be something in the range bound.start -> leftSearchLast that matches the range
00593                     }else if((int)bound.start == leftSearchLast) {
00594                         //Check if the one item item under leftSearchStart is contained in the range
00595                         Data2 leftFoundStartData = KeyExtractor::extract(this->m_data[bound.start]);
00596                         recurseLeft = leftFoundStartData < leftLastItem || leftFoundStartData == leftLastItem;
00597                     }
00598                     
00599                     bool recurseRight = false;
00600                     if(rightSearchStart < (int)bound.end)
00601                         recurseRight = true;
00602                     
00603                     if(recurseLeft && recurseRight)
00604                         bounds.append( Bound(rightSearchStart, bound.end, rightNode) );
00605                     
00606                     if(recurseLeft) {
00607                         bound.node = leftNode;
00608                         if(leftSearchLast != -1)
00609                             bound.end = leftSearchLast+1;
00610                     }else if(recurseRight) {
00611                         bound.node = rightNode;
00612                         bound.start = rightSearchStart;
00613                     }else{
00614                         goto nextBound;
00615                     }
00616                     continue;
00617                 }
00618                 nextBound:
00619                     if(bounds.isEmpty()) {
00620                         return;
00621                     }else{
00622                         bound = bounds.back();
00623                         bounds.pop_back();
00624                     }
00625             }
00626         }
00627         
00630         int lowerBound(const Data2& data, int start, int end) {
00631             int currentBound = -1;
00632             while(1) {
00633                 if(start >= end)
00634                     return currentBound;
00635                 
00636                 int center = (start + end)/2;
00637                 
00638                 //Skip free items, since they cannot be used for ordering
00639                 for(; center < end; ) {
00640                     if(!Handler::isFree(this->m_data[center]))
00641                         break;
00642                     ++center;
00643                 }
00644                 
00645                 if(center == end) {
00646                     end = (start + end)/2; //No non-free items found in second half, so continue search in the other
00647                 }else{
00648                     Data2 centerData = KeyExtractor::extract(this->m_data[center]);
00649                     //Even if the data equals we must continue searching to the left, since there may be multiple matching
00650                     if(data == centerData || data < centerData) {
00651                         currentBound = center;
00652                         end = (start + end)/2;
00653                     }else{
00654                         //Continue search in second half
00655                         start = center+1;
00656                     }
00657                 }
00658             }
00659         }
00660         
00661         //Bounds that yet need to be matched. Always a range in the own vector, and a node that all items in the range are contained in
00662         Visitor& m_visitor;
00663         TreeSet m_rhs;
00664         bool m_noFiltering;
00665     };
00666     
00667     template<class Data, class Handler>
00668     ConvenientEmbeddedSetIterator<Data, Handler> ConstantConvenientEmbeddedSet<Data, Handler>::iterator() const {
00669         return ConvenientEmbeddedSetIterator<Data, Handler>(m_data, m_dataSize, m_centralFreeItem);
00670     }
00671 
00683     
00684     template<class Data, class Handler>
00685     class ConvenientFreeListSet {
00686         public:
00687             
00688             typedef ConvenientEmbeddedSetIterator<Data, Handler> Iterator;
00689             
00690             ConvenientFreeListSet() : m_centralFree(-1) {
00691             }
00692             
00694             ConvenientFreeListSet(int centralFreeItem, QVector<Data> data) : m_data(data), m_centralFree(centralFreeItem) {
00695             }
00696             
00698             int centralFreeItem() const {
00699                 return m_centralFree;
00700             }
00701             
00702             const QVector<Data>& data() const {
00703                 return m_data;
00704             }
00705             
00706             void insert(const Data& item) {
00707                 if(contains(item))
00708                     return;
00709                 KDevelop::EmbeddedTreeAddItem<Data, Handler> add(m_data.data(), m_data.size(), m_centralFree, item);
00710                 
00711                 if((int)add.newItemCount() != (int)m_data.size()) {
00712                     QVector<Data> newData;
00713                     newData.resize(add.newItemCount());
00714                     add.transferData(newData.data(), newData.size());
00715                     m_data = newData;
00716                 }
00717             }
00718             
00719             Iterator iterator() const {
00720                 return Iterator(m_data.data(), m_data.size(), m_centralFree);
00721             }
00722             
00723             bool contains(const Data& item) const {
00724                 KDevelop::EmbeddedTreeAlgorithms<Data, Handler> alg(m_data.data(), m_data.size(), m_centralFree);
00725                 return alg.indexOf(Data(item)) != -1;
00726             }
00727             
00728             void remove(const Data& item) {
00729                 KDevelop::EmbeddedTreeRemoveItem<Data, Handler> remove(m_data.data(), m_data.size(), m_centralFree, item);
00730                 
00731                 if((int)remove.newItemCount() != (int)m_data.size()) {
00732                     QVector<Data> newData;
00733                     newData.resize(remove.newItemCount());
00734                     remove.transferData(newData.data(), newData.size());
00735                     m_data = newData;
00736                 }
00737             }
00738                  
00739         private:
00740             int m_centralFree;
00741             QVector<Data> m_data;
00742     };
00743 }
00744 
00745 #endif

util

Skip menu "util"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   codegen
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal