LCOV - app.info - content/xslt/src/xpath/txNodeSet.cpp

LCOV - code coverage report
| Current view: | directory - content/xslt/src/xpath - txNodeSet.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 254 | 58 | 22.8 %
| Date: | 2012-06-02 | Functions: | 25 | 11 | 44.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is TransforMiiX XSLT processor code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * The MITRE Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1999
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Keith Visco <kvisco@ziplink.net> (Original Author)
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "txNodeSet.h"
          40                 : #include "txLog.h"
          41                 : #include "nsMemory.h"
          42                 : #include "txXPathTreeWalker.h"
          43                 :
          44                 : /**
          45                 :  * Implementation of an XPath nodeset
          46                 :  */
          47                 :
          48                 : #ifdef NS_BUILD_REFCNT_LOGGING
          49                 : #define LOG_CHUNK_MOVE(_start, _new_start, _count)            \
          50                 : {                                                             \
          51                 :     txXPathNode *start = const_cast<txXPathNode*>(_start);    \
          52                 :     while (start < _start + _count) {                         \
          53                 :         NS_LogDtor(start, "txXPathNode", sizeof(*start));     \
          54                 :         ++start;                                              \
          55                 :     }                                                         \
          56                 :     start = const_cast<txXPathNode*>(_new_start);             \
          57                 :     while (start < _new_start + _count) {                     \
          58                 :         NS_LogCtor(start, "txXPathNode", sizeof(*start));     \
          59                 :         ++start;                                              \
          60                 :     }                                                         \
          61                 : }
          62                 : #else
          63                 : #define LOG_CHUNK_MOVE(_start, _new_start, _count)
          64                 : #endif
          65                 :
          66                 : static const PRInt32 kTxNodeSetMinSize = 4;
          67                 : static const PRInt32 kTxNodeSetGrowFactor = 2;
          68                 :
          69                 : #define kForward   1
          70                 : #define kReversed -1
          71                 :
          72               2 : txNodeSet::txNodeSet(txResultRecycler* aRecycler)
          73                 :     : txAExprResult(aRecycler),
          74                 :       mStart(nsnull),
          75                 :       mEnd(nsnull),
          76                 :       mStartBuffer(nsnull),
          77                 :       mEndBuffer(nsnull),
          78                 :       mDirection(kForward),
          79               2 :       mMarks(nsnull)
          80                 : {
          81               2 : }
          82                 :
          83               0 : txNodeSet::txNodeSet(const txXPathNode& aNode, txResultRecycler* aRecycler)
          84                 :     : txAExprResult(aRecycler),
          85                 :       mStart(nsnull),
          86                 :       mEnd(nsnull),
          87                 :       mStartBuffer(nsnull),
          88                 :       mEndBuffer(nsnull),
          89                 :       mDirection(kForward),
          90               0 :       mMarks(nsnull)
          91                 : {
          92               0 :     if (!ensureGrowSize(1)) {
          93               0 :         return;
          94                 :     }
          95                 :
          96               0 :     new(mStart) txXPathNode(aNode);
          97               0 :     ++mEnd;
          98                 : }
          99                 :
         100               0 : txNodeSet::txNodeSet(const txNodeSet& aSource, txResultRecycler* aRecycler)
         101                 :     : txAExprResult(aRecycler),
         102                 :       mStart(nsnull),
         103                 :       mEnd(nsnull),
         104                 :       mStartBuffer(nsnull),
         105                 :       mEndBuffer(nsnull),
         106                 :       mDirection(kForward),
         107               0 :       mMarks(nsnull)
         108                 : {
         109               0 :     append(aSource);
         110               0 : }
         111                 :
         112               6 : txNodeSet::~txNodeSet()
         113                 : {
         114               2 :     delete [] mMarks;
         115                 :
         116               2 :     if (mStartBuffer) {
         117               2 :         destroyElements(mStart, mEnd);
         118                 :
         119               2 :         nsMemory::Free(mStartBuffer);
         120                 :     }
         121               8 : }
         122                 :
         123               0 : nsresult txNodeSet::add(const txXPathNode& aNode)
         124                 : {
         125               0 :     NS_ASSERTION(mDirection == kForward,
         126                 :                  "only append(aNode) is supported on reversed nodesets");
         127                 :
         128               0 :     if (isEmpty()) {
         129               0 :         return append(aNode);
         130                 :     }
         131                 :
         132                 :     bool dupe;
         133               0 :     txXPathNode* pos = findPosition(aNode, mStart, mEnd, dupe);
         134                 :
         135               0 :     if (dupe) {
         136               0 :         return NS_OK;
         137                 :     }
         138                 :
         139                 :     // save pos, ensureGrowSize messes with the pointers
         140               0 :     PRInt32 moveSize = mEnd - pos;
         141               0 :     PRInt32 offset = pos - mStart;
         142               0 :     if (!ensureGrowSize(1)) {
         143               0 :         return NS_ERROR_OUT_OF_MEMORY;
         144                 :     }
         145                 :     // set pos to where it was
         146               0 :     pos = mStart + offset;
         147                 :
         148               0 :     if (moveSize > 0) {
         149               0 :         LOG_CHUNK_MOVE(pos, pos + 1, moveSize);
         150               0 :         memmove(pos + 1, pos, moveSize * sizeof(txXPathNode));
         151                 :     }
         152                 :
         153               0 :     new(pos) txXPathNode(aNode);
         154               0 :     ++mEnd;
         155                 :
         156               0 :     return NS_OK;
         157                 : }
         158                 :
         159               0 : nsresult txNodeSet::add(const txNodeSet& aNodes)
         160                 : {
         161               0 :     return add(aNodes, copyElements, nsnull);
         162                 : }
         163                 :
         164               0 : nsresult txNodeSet::addAndTransfer(txNodeSet* aNodes)
         165                 : {
         166                 :     // failure is out-of-memory, transfer didn't happen
         167               0 :     nsresult rv = add(*aNodes, transferElements, destroyElements);
         168               0 :     NS_ENSURE_SUCCESS(rv, rv);
         169                 :
         170                 : #ifdef TX_DONT_RECYCLE_BUFFER
         171                 :     if (aNodes->mStartBuffer) {
         172                 :         nsMemory::Free(aNodes->mStartBuffer);
         173                 :         aNodes->mStartBuffer = aNodes->mEndBuffer = nsnull;
         174                 :     }
         175                 : #endif
         176               0 :     aNodes->mStart = aNodes->mEnd = aNodes->mStartBuffer;
         177                 :
         178               0 :     return NS_OK;
         179                 : }
         180                 :
         181                 : /**
         182                 :  * add(aNodeSet, aTransferOp)
         183                 :  *
         184                 :  * The code is optimized to make a minimum number of calls to
         185                 :  * Node::compareDocumentPosition. The idea is this:
         186                 :  * We have the two nodesets (number indicate "document position")
         187                 :  *
         188                 :  * 1 3 7             <- source 1
         189                 :  * 2 3 6 8 9         <- source 2
         190                 :  * _ _ _ _ _ _ _ _   <- result
         191                 :  *
         192                 :  *
         193                 :  * When merging these nodesets into the result, the nodes are transfered
         194                 :  * in chunks to the end of the buffer so that each chunk does not contain
         195                 :  * a node from the other nodeset, in document order.
         196                 :  *
         197                 :  * We select the last non-transfered node in the first nodeset and find
         198                 :  * where in the other nodeset it would be inserted. In this case we would
         199                 :  * take the 7 from the first nodeset and find the position between the
         200                 :  * 6 and 8 in the second. We then take the nodes after the insert-position
         201                 :  * and transfer them to the end of the resulting nodeset. Which in this case
         202                 :  * means that we first transfered the 8 and 9 nodes, giving us the following:
         203                 :  *
         204                 :  * 1 3 7             <- source 1
         205                 :  * 2 3 6             <- source 2
         206                 :  * _ _ _ _ _ _ 8 9   <- result
         207                 :  *
         208                 :  * The corresponding procedure is done for the second nodeset, that is
         209                 :  * the insertion position of the 6 in the first nodeset is found, which
         210                 :  * is between the 3 and the 7. The 7 is memmoved (as it stays within
         211                 :  * the same nodeset) to the result buffer.
         212                 :  *
         213                 :  * As the result buffer is filled from the end, it is safe to share the
         214                 :  * buffer between this nodeset and the result.
         215                 :  *
         216                 :  * This is repeated until both of the nodesets are empty.
         217                 :  *
         218                 :  * If we find a duplicate node when searching for where insertposition we
         219                 :  * check for sequences of duplicate nodes, which can be optimized.
         220                 :  *
         221                 :  */
         222               0 : nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer,
         223                 :                         destroyOp aDestroy)
         224                 : {
         225               0 :     NS_ASSERTION(mDirection == kForward,
         226                 :                  "only append(aNode) is supported on reversed nodesets");
         227                 :
         228               0 :     if (aNodes.isEmpty()) {
         229               0 :         return NS_OK;
         230                 :     }
         231                 :
         232               0 :     if (!ensureGrowSize(aNodes.size())) {
         233               0 :         return NS_ERROR_OUT_OF_MEMORY;
         234                 :     }
         235                 :
         236                 :     // This is probably a rather common case, so lets try to shortcut.
         237               0 :     if (mStart == mEnd ||
         238               0 :         txXPathNodeUtils::comparePosition(mEnd[-1], *aNodes.mStart) < 0) {
         239               0 :         aTransfer(mEnd, aNodes.mStart, aNodes.mEnd);
         240               0 :         mEnd += aNodes.size();
         241                 :
         242               0 :         return NS_OK;
         243                 :     }
         244                 :
         245                 :     // Last element in this nodeset
         246               0 :     txXPathNode* thisPos = mEnd;
         247                 :
         248                 :     // Last element of the other nodeset
         249               0 :     txXPathNode* otherPos = aNodes.mEnd;
         250                 :
         251                 :     // Pointer to the insertion point in this nodeset
         252               0 :     txXPathNode* insertPos = mEndBuffer;
         253                 :
         254                 :     bool dupe;
         255                 :     txXPathNode* pos;
         256                 :     PRInt32 count;
         257               0 :     while (thisPos > mStart || otherPos > aNodes.mStart) {
         258                 :         // Find where the last remaining node of this nodeset would
         259                 :         // be inserted in the other nodeset.
         260               0 :         if (thisPos > mStart) {
         261               0 :             pos = findPosition(thisPos[-1], aNodes.mStart, otherPos, dupe);
         262                 :
         263               0 :             if (dupe) {
         264               0 :                 const txXPathNode *deletePos = thisPos;
         265               0 :                 --thisPos; // this is already added
         266                 :                 // check dupe sequence
         267               0 :                 while (thisPos > mStart && pos > aNodes.mStart &&
         268               0 :                        thisPos[-1] == pos[-1]) {
         269               0 :                     --thisPos;
         270               0 :                     --pos;
         271                 :                 }
         272                 :
         273               0 :                 if (aDestroy) {
         274               0 :                     aDestroy(thisPos, deletePos);
         275                 :                 }
         276                 :             }
         277                 :         }
         278                 :         else {
         279               0 :             pos = aNodes.mStart;
         280                 :         }
         281                 :
         282                 :         // Transfer the otherNodes after the insertion point to the result
         283               0 :         count = otherPos - pos;
         284               0 :         if (count > 0) {
         285               0 :             insertPos -= count;
         286               0 :             aTransfer(insertPos, pos, otherPos);
         287               0 :             otherPos -= count;
         288                 :         }
         289                 :
         290                 :         // Find where the last remaining node of the otherNodeset would
         291                 :         // be inserted in this nodeset.
         292               0 :         if (otherPos > aNodes.mStart) {
         293               0 :             pos = findPosition(otherPos[-1], mStart, thisPos, dupe);
         294                 :
         295               0 :             if (dupe) {
         296               0 :                 const txXPathNode *deletePos = otherPos;
         297               0 :                 --otherPos; // this is already added
         298                 :                 // check dupe sequence
         299               0 :                 while (otherPos > aNodes.mStart && pos > mStart &&
         300               0 :                        otherPos[-1] == pos[-1]) {
         301               0 :                     --otherPos;
         302               0 :                     --pos;
         303                 :                 }
         304                 :
         305               0 :                 if (aDestroy) {
         306               0 :                     aDestroy(otherPos, deletePos);
         307                 :                 }
         308                 :             }
         309                 :         }
         310                 :         else {
         311               0 :             pos = mStart;
         312                 :         }
         313                 :
         314                 :         // Move the nodes from this nodeset after the insertion point
         315                 :         // to the result
         316               0 :         count = thisPos - pos;
         317               0 :         if (count > 0) {
         318               0 :             insertPos -= count;
         319               0 :             LOG_CHUNK_MOVE(pos, insertPos, count);
         320               0 :             memmove(insertPos, pos, count * sizeof(txXPathNode));
         321               0 :             thisPos -= count;
         322                 :         }
         323                 :     }
         324               0 :     mStart = insertPos;
         325               0 :     mEnd = mEndBuffer;
         326                 :
         327               0 :     return NS_OK;
         328                 : }
         329                 :
         330                 : /**
         331                 :  * Append API
         332                 :  * These functions should be used with care.
         333                 :  * They are intended to be used when the caller assures that the resulting
         334                 :  * nodeset remains in document order.
         335                 :  * Abuse will break document order, and cause errors in the result.
         336                 :  * These functions are significantly faster than the add API, as no
         337                 :  * order info operations will be performed.
         338                 :  */
         339                 :
         340                 : nsresult
         341              42 : txNodeSet::append(const txXPathNode& aNode)
         342                 : {
         343              42 :     if (!ensureGrowSize(1)) {
         344               0 :         return NS_ERROR_OUT_OF_MEMORY;
         345                 :     }
         346                 :
         347              42 :     if (mDirection == kForward) {
         348              42 :         new(mEnd) txXPathNode(aNode);
         349              42 :         ++mEnd;
         350                 :
         351              42 :         return NS_OK;
         352                 :     }
         353                 :
         354               0 :     new(--mStart) txXPathNode(aNode);
         355                 :
         356               0 :     return NS_OK;
         357                 : }
         358                 :
         359                 : nsresult
         360               0 : txNodeSet::append(const txNodeSet& aNodes)
         361                 : {
         362               0 :     NS_ASSERTION(mDirection == kForward,
         363                 :                  "only append(aNode) is supported on reversed nodesets");
         364                 :
         365               0 :     if (aNodes.isEmpty()) {
         366               0 :         return NS_OK;
         367                 :     }
         368                 :
         369               0 :     PRInt32 appended = aNodes.size();
         370               0 :     if (!ensureGrowSize(appended)) {
         371               0 :         return NS_ERROR_OUT_OF_MEMORY;
         372                 :     }
         373                 :
         374               0 :     copyElements(mEnd, aNodes.mStart, aNodes.mEnd);
         375               0 :     mEnd += appended;
         376                 :
         377               0 :     return NS_OK;
         378                 : }
         379                 :
         380                 : nsresult
         381               0 : txNodeSet::mark(PRInt32 aIndex)
         382                 : {
         383               0 :     NS_ASSERTION(aIndex >= 0 && mStart && mEnd - mStart > aIndex,
         384                 :                  "index out of bounds");
         385               0 :     if (!mMarks) {
         386               0 :         PRInt32 length = size();
         387               0 :         mMarks = new bool[length];
         388               0 :         NS_ENSURE_TRUE(mMarks, NS_ERROR_OUT_OF_MEMORY);
         389               0 :         memset(mMarks, 0, length * sizeof(bool));
         390                 :     }
         391               0 :     if (mDirection == kForward) {
         392               0 :         mMarks[aIndex] = true;
         393                 :     }
         394                 :     else {
         395               0 :         mMarks[size() - aIndex - 1] = true;
         396                 :     }
         397                 :
         398               0 :     return NS_OK;
         399                 : }
         400                 :
         401                 : nsresult
         402               0 : txNodeSet::sweep()
         403                 : {
         404               0 :     if (!mMarks) {
         405                 :         // sweep everything
         406               0 :         clear();
         407                 :     }
         408                 :
         409               0 :     PRInt32 chunk, pos = 0;
         410               0 :     PRInt32 length = size();
         411               0 :     txXPathNode* insertion = mStartBuffer;
         412                 :
         413               0 :     while (pos < length) {
         414               0 :         while (pos < length && !mMarks[pos]) {
         415                 :             // delete unmarked
         416               0 :             mStart[pos].~txXPathNode();
         417               0 :             ++pos;
         418                 :         }
         419                 :         // find chunk to move
         420               0 :         chunk = 0;
         421               0 :         while (pos < length && mMarks[pos]) {
         422               0 :             ++pos;
         423               0 :             ++chunk;
         424                 :         }
         425                 :         // move chunk
         426               0 :         if (chunk > 0) {
         427               0 :             LOG_CHUNK_MOVE(mStart + pos - chunk, insertion, chunk);
         428               0 :             memmove(insertion, mStart + pos - chunk,
         429               0 :                     chunk * sizeof(txXPathNode));
         430               0 :             insertion += chunk;
         431                 :         }
         432                 :     }
         433               0 :     mStart = mStartBuffer;
         434               0 :     mEnd = insertion;
         435               0 :     delete [] mMarks;
         436               0 :     mMarks = nsnull;
         437                 :
         438               0 :     return NS_OK;
         439                 : }
         440                 :
         441                 : void
         442              42 : txNodeSet::clear()
         443                 : {
         444              42 :     destroyElements(mStart, mEnd);
         445                 : #ifdef TX_DONT_RECYCLE_BUFFER
         446                 :     if (mStartBuffer) {
         447                 :         nsMemory::Free(mStartBuffer);
         448                 :         mStartBuffer = mEndBuffer = nsnull;
         449                 :     }
         450                 : #endif
         451              42 :     mStart = mEnd = mStartBuffer;
         452              42 :     delete [] mMarks;
         453              42 :     mMarks = nsnull;
         454              42 :     mDirection = kForward;
         455              42 : }
         456                 :
         457                 : PRInt32
         458               0 : txNodeSet::indexOf(const txXPathNode& aNode, PRUint32 aStart) const
         459                 : {
         460               0 :     NS_ASSERTION(mDirection == kForward,
         461                 :                  "only append(aNode) is supported on reversed nodesets");
         462                 :
         463               0 :     if (!mStart || mStart == mEnd) {
         464               0 :         return -1;
         465                 :     }
         466                 :
         467               0 :     txXPathNode* pos = mStart + aStart;
         468               0 :     for (; pos < mEnd; ++pos) {
         469               0 :         if (*pos == aNode) {
         470               0 :             return pos - mStart;
         471                 :         }
         472                 :     }
         473                 :
         474               0 :     return -1;
         475                 : }
         476                 :
         477                 : const txXPathNode&
         478             126 : txNodeSet::get(PRInt32 aIndex) const
         479                 : {
         480             126 :     if (mDirection == kForward) {
         481             126 :         return mStart[aIndex];
         482                 :     }
         483                 :
         484               0 :     return mEnd[-aIndex - 1];
         485                 : }
         486                 :
         487                 : short
         488             126 : txNodeSet::getResultType()
         489                 : {
         490             126 :     return txAExprResult::NODESET;
         491                 : }
         492                 :
         493                 : bool
         494              42 : txNodeSet::booleanValue()
         495                 : {
         496              42 :     return !isEmpty();
         497                 : }
         498                 : double
         499              42 : txNodeSet::numberValue()
         500                 : {
         501              84 :     nsAutoString str;
         502              42 :     stringValue(str);
         503                 :
         504              42 :     return txDouble::toDouble(str);
         505                 : }
         506                 :
         507                 : void
         508              84 : txNodeSet::stringValue(nsString& aStr)
         509                 : {
         510              84 :     NS_ASSERTION(mDirection == kForward,
         511                 :                  "only append(aNode) is supported on reversed nodesets");
         512              84 :     if (isEmpty()) {
         513               0 :         return;
         514                 :     }
         515              84 :     txXPathNodeUtils::appendNodeValue(get(0), aStr);
         516                 : }
         517                 :
         518                 : const nsString*
         519               0 : txNodeSet::stringValuePointer()
         520                 : {
         521               0 :     return nsnull;
         522                 : }
         523                 :
         524              42 : bool txNodeSet::ensureGrowSize(PRInt32 aSize)
         525                 : {
         526                 :     // check if there is enough place in the buffer as is
         527              42 :     if (mDirection == kForward && aSize <= mEndBuffer - mEnd) {
         528              40 :         return true;
         529                 :     }
         530                 :
         531               2 :     if (mDirection == kReversed && aSize <= mStart - mStartBuffer) {
         532               0 :         return true;
         533                 :     }
         534                 :
         535                 :     // check if we just have to align mStart to have enough space
         536               2 :     PRInt32 oldSize = mEnd - mStart;
         537               2 :     PRInt32 oldLength = mEndBuffer - mStartBuffer;
         538               2 :     PRInt32 ensureSize = oldSize + aSize;
         539               2 :     if (ensureSize <= oldLength) {
         540                 :         // just move the buffer
         541               0 :         txXPathNode* dest = mStartBuffer;
         542               0 :         if (mDirection == kReversed) {
         543               0 :             dest = mEndBuffer - oldSize;
         544                 :         }
         545               0 :         LOG_CHUNK_MOVE(mStart, dest, oldSize);
         546               0 :         memmove(dest, mStart, oldSize * sizeof(txXPathNode));
         547               0 :         mStart = dest;
         548               0 :         mEnd = dest + oldSize;
         549                 :
         550               0 :         return true;
         551                 :     }
         552                 :
         553                 :     // This isn't 100% safe. But until someone manages to make a 1gig nodeset
         554                 :     // it should be ok.
         555               2 :     PRInt32 newLength = NS_MAX(oldLength, kTxNodeSetMinSize);
         556                 :
         557               4 :     while (newLength < ensureSize) {
         558               0 :         newLength *= kTxNodeSetGrowFactor;
         559                 :     }
         560                 :
         561                 :     txXPathNode* newArr = static_cast<txXPathNode*>
         562                 :                                      (nsMemory::Alloc(newLength *
         563               2 :                                                          sizeof(txXPathNode)));
         564               2 :     if (!newArr) {
         565               0 :         return false;
         566                 :     }
         567                 :
         568               2 :     txXPathNode* dest = newArr;
         569               2 :     if (mDirection == kReversed) {
         570               0 :         dest += newLength - oldSize;
         571                 :     }
         572                 :
         573               2 :     if (oldSize > 0) {
         574               0 :         LOG_CHUNK_MOVE(mStart, dest, oldSize);
         575               0 :         memcpy(dest, mStart, oldSize * sizeof(txXPathNode));
         576                 :     }
         577                 :
         578               2 :     if (mStartBuffer) {
         579                 : #ifdef DEBUG
         580                 :         memset(mStartBuffer, 0,
         581               0 :                (mEndBuffer - mStartBuffer) * sizeof(txXPathNode));
         582                 : #endif
         583               0 :         nsMemory::Free(mStartBuffer);
         584                 :     }
         585                 :
         586               2 :     mStartBuffer = newArr;
         587               2 :     mEndBuffer = mStartBuffer + newLength;
         588               2 :     mStart = dest;
         589               2 :     mEnd = dest + oldSize;
         590                 :
         591               2 :     return true;
         592                 : }
         593                 :
         594                 : txXPathNode*
         595               0 : txNodeSet::findPosition(const txXPathNode& aNode, txXPathNode* aFirst,
         596                 :                         txXPathNode* aLast, bool& aDupe) const
         597                 : {
         598               0 :     aDupe = false;
         599               0 :     if (aLast - aFirst <= 2) {
         600                 :         // If we search 2 nodes or less there is no point in further divides
         601               0 :         txXPathNode* pos = aFirst;
         602               0 :         for (; pos < aLast; ++pos) {
         603               0 :             PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *pos);
         604               0 :             if (cmp < 0) {
         605               0 :                 return pos;
         606                 :             }
         607                 :
         608               0 :             if (cmp == 0) {
         609               0 :                 aDupe = true;
         610                 :
         611               0 :                 return pos;
         612                 :             }
         613                 :         }
         614               0 :         return pos;
         615                 :     }
         616                 :
         617                 :     // (cannot add two pointers)
         618               0 :     txXPathNode* midpos = aFirst + (aLast - aFirst) / 2;
         619               0 :     PRIntn cmp = txXPathNodeUtils::comparePosition(aNode, *midpos);
         620               0 :     if (cmp == 0) {
         621               0 :         aDupe = true;
         622                 :
         623               0 :         return midpos;
         624                 :     }
         625                 :
         626               0 :     if (cmp > 0) {
         627               0 :         return findPosition(aNode, midpos + 1, aLast, aDupe);
         628                 :     }
         629                 :
         630                 :     // midpos excluded as end of range
         631                 :
         632               0 :     return findPosition(aNode, aFirst, midpos, aDupe);
         633                 : }
         634                 :
         635                 : /* static */
         636                 : void
         637               0 : txNodeSet::copyElements(txXPathNode* aDest,
         638                 :                         const txXPathNode* aStart, const txXPathNode* aEnd)
         639                 : {
         640               0 :     const txXPathNode* pos = aStart;
         641               0 :     while (pos < aEnd) {
         642               0 :         new(aDest) txXPathNode(*pos);
         643               0 :         ++aDest;
         644               0 :         ++pos;
         645                 :     }
         646               0 : }
         647                 :
         648                 : /* static */
         649                 : void
         650               0 : txNodeSet::transferElements(txXPathNode* aDest,
         651                 :                             const txXPathNode* aStart, const txXPathNode* aEnd)
         652                 : {
         653               0 :     LOG_CHUNK_MOVE(aStart, aDest, (aEnd - aStart));
         654               0 :     memcpy(aDest, aStart, (aEnd - aStart) * sizeof(txXPathNode));
         655               0 : }

Generated by: LCOV version 1.7