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