LCOV - code coverage report
Current view: directory - content/xslt/src/xpath - txMozillaXPathTreeWalker.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 350 30 8.6 %
Date: 2012-06-02 Functions: 36 6 16.7 %

       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                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2003
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Peter Van der Beken <peterv@propagandism.org>
      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 "txXPathTreeWalker.h"
      40                 : #include "nsIAtom.h"
      41                 : #include "nsIAttribute.h"
      42                 : #include "nsIDOMAttr.h"
      43                 : #include "nsIDOMDocument.h"
      44                 : #include "nsIDOMNode.h"
      45                 : #include "nsIDOMElement.h"
      46                 : #include "nsIDOMProcessingInstruction.h"
      47                 : #include "nsINodeInfo.h"
      48                 : #include "nsPrintfCString.h"
      49                 : #include "nsReadableUtils.h"
      50                 : #include "nsString.h"
      51                 : #include "nsTextFragment.h"
      52                 : #include "txXMLUtils.h"
      53                 : #include "txLog.h"
      54                 : #include "nsUnicharUtils.h"
      55                 : #include "nsAttrName.h"
      56                 : #include "nsTArray.h"
      57                 : #include "mozilla/dom/Element.h"
      58                 : 
      59                 : const PRUint32 kUnknownIndex = PRUint32(-1);
      60                 : 
      61               0 : txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
      62                 :     : mPosition(aOther.mPosition),
      63               0 :       mCurrentIndex(aOther.mCurrentIndex)
      64                 : {
      65               0 : }
      66                 : 
      67              42 : txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
      68                 :     : mPosition(aNode),
      69              42 :       mCurrentIndex(kUnknownIndex)
      70                 : {
      71              42 : }
      72                 : 
      73                 : void
      74               0 : txXPathTreeWalker::moveToRoot()
      75                 : {
      76               0 :     if (mPosition.isDocument()) {
      77               0 :         return;
      78                 :     }
      79                 : 
      80               0 :     nsIDocument* root = mPosition.mNode->GetCurrentDoc();
      81               0 :     if (root) {
      82               0 :         mPosition.mIndex = txXPathNode::eDocument;
      83               0 :         mPosition.mNode = root;
      84                 :     }
      85                 :     else {
      86               0 :         nsINode *rootNode = mPosition.Root();
      87                 : 
      88               0 :         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
      89                 :                      "root of subtree wasn't an nsIContent");
      90                 : 
      91               0 :         mPosition.mIndex = txXPathNode::eContent;
      92               0 :         mPosition.mNode = rootNode;
      93                 :     }
      94                 : 
      95               0 :     mCurrentIndex = kUnknownIndex;
      96               0 :     mDescendants.Clear();
      97                 : }
      98                 : 
      99                 : bool
     100               0 : txXPathTreeWalker::moveToElementById(const nsAString& aID)
     101                 : {
     102               0 :     if (aID.IsEmpty()) {
     103               0 :         return false;
     104                 :     }
     105                 : 
     106               0 :     nsIDocument* doc = mPosition.mNode->GetCurrentDoc();
     107                 : 
     108               0 :     nsCOMPtr<nsIContent> content;
     109               0 :     if (doc) {
     110               0 :         content = doc->GetElementById(aID);
     111                 :     }
     112                 :     else {
     113                 :         // We're in a disconnected subtree, search only that subtree.
     114               0 :         nsINode *rootNode = mPosition.Root();
     115                 : 
     116               0 :         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
     117                 :                      "root of subtree wasn't an nsIContent");
     118                 : 
     119                 :         content = nsContentUtils::MatchElementId(
     120               0 :             static_cast<nsIContent*>(rootNode), aID);
     121                 :     }
     122                 : 
     123               0 :     if (!content) {
     124               0 :         return false;
     125                 :     }
     126                 : 
     127               0 :     mPosition.mIndex = txXPathNode::eContent;
     128               0 :     mPosition.mNode = content;
     129               0 :     mCurrentIndex = kUnknownIndex;
     130               0 :     mDescendants.Clear();
     131                 : 
     132               0 :     return true;
     133                 : }
     134                 : 
     135                 : bool
     136               0 : txXPathTreeWalker::moveToFirstAttribute()
     137                 : {
     138               0 :     if (!mPosition.isContent()) {
     139               0 :         return false;
     140                 :     }
     141                 : 
     142               0 :     return moveToValidAttribute(0);
     143                 : }
     144                 : 
     145                 : bool
     146               0 : txXPathTreeWalker::moveToNextAttribute()
     147                 : {
     148                 :     // XXX an assertion should be enough here with the current code
     149               0 :     if (!mPosition.isAttribute()) {
     150               0 :         return false;
     151                 :     }
     152                 : 
     153               0 :     return moveToValidAttribute(mPosition.mIndex + 1);
     154                 : }
     155                 : 
     156                 : bool
     157               0 : txXPathTreeWalker::moveToValidAttribute(PRUint32 aStartIndex)
     158                 : {
     159               0 :     NS_ASSERTION(!mPosition.isDocument(), "documents doesn't have attrs");
     160                 : 
     161               0 :     PRUint32 total = mPosition.Content()->GetAttrCount();
     162               0 :     if (aStartIndex >= total) {
     163               0 :         return false;
     164                 :     }
     165                 : 
     166                 :     PRUint32 index;
     167               0 :     for (index = aStartIndex; index < total; ++index) {
     168               0 :         const nsAttrName* name = mPosition.Content()->GetAttrNameAt(index);
     169                 : 
     170                 :         // We need to ignore XMLNS attributes.
     171               0 :         if (name->NamespaceID() != kNameSpaceID_XMLNS) {
     172               0 :             mPosition.mIndex = index;
     173                 : 
     174               0 :             return true;
     175                 :         }
     176                 :     }
     177               0 :     return false;
     178                 : }
     179                 : 
     180                 : bool
     181               0 : txXPathTreeWalker::moveToNamedAttribute(nsIAtom* aLocalName, PRInt32 aNSID)
     182                 : {
     183               0 :     if (!mPosition.isContent()) {
     184               0 :         return false;
     185                 :     }
     186                 : 
     187                 :     const nsAttrName* name;
     188                 :     PRUint32 i;
     189               0 :     for (i = 0; (name = mPosition.Content()->GetAttrNameAt(i)); ++i) {
     190               0 :         if (name->Equals(aLocalName, aNSID)) {
     191               0 :             mPosition.mIndex = i;
     192                 : 
     193               0 :             return true;
     194                 :         }
     195                 :     }
     196               0 :     return false;
     197                 : }
     198                 : 
     199                 : bool
     200               0 : txXPathTreeWalker::moveToFirstChild()
     201                 : {
     202               0 :     if (mPosition.isAttribute()) {
     203               0 :         return false;
     204                 :     }
     205                 : 
     206               0 :     NS_ASSERTION(!mPosition.isDocument() ||
     207                 :                  (mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
     208                 :                  "we shouldn't have any position info at the document");
     209               0 :     NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
     210                 :                  "Index should be known if parents index are");
     211                 : 
     212               0 :     nsIContent* child = mPosition.mNode->GetFirstChild();
     213               0 :     if (!child) {
     214               0 :         return false;
     215                 :     }
     216               0 :     mPosition.mIndex = txXPathNode::eContent;
     217               0 :     mPosition.mNode = child;
     218                 : 
     219               0 :     if (mCurrentIndex != kUnknownIndex &&
     220               0 :         !mDescendants.AppendValue(mCurrentIndex)) {
     221               0 :         mDescendants.Clear();
     222                 :     }
     223               0 :     mCurrentIndex = 0;
     224                 : 
     225               0 :     return true;
     226                 : }
     227                 : 
     228                 : bool
     229               0 : txXPathTreeWalker::moveToLastChild()
     230                 : {
     231               0 :     if (mPosition.isAttribute()) {
     232               0 :         return false;
     233                 :     }
     234                 : 
     235               0 :     NS_ASSERTION(!mPosition.isDocument() ||
     236                 :                  (mCurrentIndex == kUnknownIndex && mDescendants.IsEmpty()),
     237                 :                  "we shouldn't have any position info at the document");
     238               0 :     NS_ASSERTION(mCurrentIndex != kUnknownIndex || mDescendants.IsEmpty(),
     239                 :                  "Index should be known if parents index are");
     240                 : 
     241               0 :     PRUint32 total = mPosition.mNode->GetChildCount();
     242               0 :     if (!total) {
     243               0 :         return false;
     244                 :     }
     245               0 :     mPosition.mNode = mPosition.mNode->GetLastChild();
     246                 : 
     247               0 :     if (mCurrentIndex != kUnknownIndex &&
     248               0 :         !mDescendants.AppendValue(mCurrentIndex)) {
     249               0 :         mDescendants.Clear();
     250                 :     }
     251               0 :     mCurrentIndex = total - 1;
     252                 : 
     253               0 :     return true;
     254                 : }
     255                 : 
     256                 : bool
     257               0 : txXPathTreeWalker::moveToNextSibling()
     258                 : {
     259               0 :     if (!mPosition.isContent()) {
     260               0 :         return false;
     261                 :     }
     262                 : 
     263               0 :     return moveToSibling(1);
     264                 : }
     265                 : 
     266                 : bool
     267               0 : txXPathTreeWalker::moveToPreviousSibling()
     268                 : {
     269               0 :     if (!mPosition.isContent()) {
     270               0 :         return false;
     271                 :     }
     272                 : 
     273               0 :     return moveToSibling(-1);
     274                 : }
     275                 : 
     276                 : bool
     277               0 : txXPathTreeWalker::moveToParent()
     278                 : {
     279               0 :     if (mPosition.isDocument()) {
     280               0 :         return false;
     281                 :     }
     282                 : 
     283               0 :     if (mPosition.isAttribute()) {
     284               0 :         mPosition.mIndex = txXPathNode::eContent;
     285                 : 
     286               0 :         return true;
     287                 :     }
     288                 : 
     289               0 :     nsINode* parent = mPosition.mNode->GetNodeParent();
     290               0 :     if (!parent) {
     291               0 :         return false;
     292                 :     }
     293                 : 
     294               0 :     PRUint32 count = mDescendants.Length();
     295               0 :     if (count) {
     296               0 :         mCurrentIndex = mDescendants.ValueAt(--count);
     297               0 :         mDescendants.RemoveValueAt(count);
     298                 :     }
     299                 :     else {
     300               0 :         mCurrentIndex = kUnknownIndex;
     301                 :     }
     302                 : 
     303               0 :     mPosition.mIndex = mPosition.mNode->GetParent() ?
     304               0 :       txXPathNode::eContent : txXPathNode::eDocument;
     305               0 :     mPosition.mNode = parent;
     306                 : 
     307               0 :     return true;
     308                 : }
     309                 : 
     310                 : bool
     311               0 : txXPathTreeWalker::moveToSibling(PRInt32 aDir)
     312                 : {
     313               0 :     NS_ASSERTION(mPosition.isContent(),
     314                 :                  "moveToSibling should only be called for content");
     315                 : 
     316               0 :     nsINode* parent = mPosition.mNode->GetNodeParent();
     317               0 :     if (!parent) {
     318               0 :         return false;
     319                 :     }
     320               0 :     if (mCurrentIndex == kUnknownIndex) {
     321               0 :         mCurrentIndex = parent->IndexOf(mPosition.mNode);
     322                 :     }
     323                 : 
     324                 :     // if mCurrentIndex is 0 we rely on GetChildAt returning null for an
     325                 :     // index of PRUint32(-1).
     326               0 :     PRUint32 newIndex = mCurrentIndex + aDir;
     327               0 :     nsIContent* newChild = parent->GetChildAt(newIndex);
     328               0 :     if (!newChild) {
     329               0 :         return false;
     330                 :     }
     331                 : 
     332               0 :     mPosition.mNode = newChild;
     333               0 :     mCurrentIndex = newIndex;
     334                 : 
     335               0 :     return true;
     336                 : }
     337                 : 
     338              84 : txXPathNode::txXPathNode(const txXPathNode& aNode)
     339                 :   : mNode(aNode.mNode),
     340                 :     mRefCountRoot(aNode.mRefCountRoot),
     341              84 :     mIndex(aNode.mIndex)
     342                 : {
     343              84 :     MOZ_COUNT_CTOR(txXPathNode);
     344              84 :     if (mRefCountRoot) {
     345               0 :         NS_ADDREF(Root());
     346                 :     }
     347              84 : }
     348                 : 
     349             126 : txXPathNode::~txXPathNode()
     350                 : {
     351             126 :     MOZ_COUNT_DTOR(txXPathNode);
     352             126 :     if (mRefCountRoot) {
     353               0 :         nsINode *root = Root();
     354               0 :         NS_RELEASE(root);
     355                 :     }
     356             126 : }
     357                 : 
     358                 : /* static */
     359                 : bool
     360               0 : txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
     361                 :                           PRInt32 aNSID, nsAString& aValue)
     362                 : {
     363               0 :     if (aNode.isDocument() || aNode.isAttribute()) {
     364               0 :         return false;
     365                 :     }
     366                 : 
     367               0 :     return aNode.Content()->GetAttr(aNSID, aLocalName, aValue);
     368                 : }
     369                 : 
     370                 : /* static */
     371                 : already_AddRefed<nsIAtom>
     372               0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
     373                 : {
     374               0 :     if (aNode.isDocument()) {
     375               0 :         return nsnull;
     376                 :     }
     377                 : 
     378               0 :     if (aNode.isContent()) {
     379               0 :         if (aNode.mNode->IsElement()) {
     380               0 :             nsIAtom* localName = aNode.Content()->Tag();
     381               0 :             NS_ADDREF(localName);
     382                 : 
     383               0 :             return localName;
     384                 :         }
     385                 : 
     386               0 :         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     387               0 :             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
     388               0 :             nsAutoString target;
     389               0 :             node->GetNodeName(target);
     390                 : 
     391               0 :             return NS_NewAtom(target);
     392                 :         }
     393                 : 
     394               0 :         return nsnull;
     395                 :     }
     396                 : 
     397               0 :     nsIAtom* localName = aNode.Content()->
     398               0 :         GetAttrNameAt(aNode.mIndex)->LocalName();
     399               0 :     NS_ADDREF(localName);
     400                 : 
     401               0 :     return localName;
     402                 : }
     403                 : 
     404                 : nsIAtom*
     405               0 : txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
     406                 : {
     407               0 :     if (aNode.isDocument()) {
     408               0 :         return nsnull;
     409                 :     }
     410                 : 
     411               0 :     if (aNode.isContent()) {
     412                 :         // All other nsIContent node types but elements have a null prefix
     413                 :         // which is what we want here.
     414               0 :         return aNode.Content()->NodeInfo()->GetPrefixAtom();
     415                 :     }
     416                 : 
     417               0 :     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetPrefix();
     418                 : }
     419                 : 
     420                 : /* static */
     421                 : void
     422               0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)
     423                 : {
     424               0 :     if (aNode.isDocument()) {
     425               0 :         aLocalName.Truncate();
     426                 : 
     427               0 :         return;
     428                 :     }
     429                 : 
     430               0 :     if (aNode.isContent()) {
     431               0 :         if (aNode.mNode->IsElement()) {
     432               0 :             nsINodeInfo* nodeInfo = aNode.Content()->NodeInfo();
     433               0 :             nodeInfo->GetName(aLocalName);
     434               0 :             return;
     435                 :         }
     436                 : 
     437               0 :         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     438                 :             // PIs don't have a nodeinfo but do have a name
     439               0 :             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
     440               0 :             node->GetNodeName(aLocalName);
     441                 : 
     442                 :             return;
     443                 :         }
     444                 : 
     445               0 :         aLocalName.Truncate();
     446                 : 
     447               0 :         return;
     448                 :     }
     449                 : 
     450               0 :     aNode.Content()->GetAttrNameAt(aNode.mIndex)->LocalName()->
     451               0 :       ToString(aLocalName);
     452                 : 
     453                 :     // Check for html
     454               0 :     if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) &&
     455               0 :         aNode.Content()->IsHTML()) {
     456               0 :         nsContentUtils::ASCIIToUpper(aLocalName);
     457                 :     }
     458                 : }
     459                 : 
     460                 : /* static */
     461                 : void
     462               0 : txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName)
     463                 : {
     464               0 :     if (aNode.isDocument()) {
     465               0 :         aName.Truncate();
     466                 : 
     467               0 :         return;
     468                 :     }
     469                 : 
     470               0 :     if (aNode.isContent()) {
     471                 :         // Elements and PIs have a name
     472               0 :         if (aNode.mNode->IsElement() ||
     473               0 :             aNode.mNode->NodeType() ==
     474                 :             nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
     475               0 :             aName = aNode.Content()->NodeName();
     476               0 :             return;
     477                 :         }
     478                 : 
     479               0 :         aName.Truncate();
     480                 : 
     481               0 :         return;
     482                 :     }
     483                 : 
     484               0 :     aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetQualifiedName(aName);
     485                 : }
     486                 : 
     487                 : /* static */
     488                 : PRInt32
     489               0 : txXPathNodeUtils::getNamespaceID(const txXPathNode& aNode)
     490                 : {
     491               0 :     if (aNode.isDocument()) {
     492               0 :         return kNameSpaceID_None;
     493                 :     }
     494                 : 
     495               0 :     if (aNode.isContent()) {
     496               0 :         return aNode.Content()->GetNameSpaceID();
     497                 :     }
     498                 : 
     499               0 :     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->NamespaceID();
     500                 : }
     501                 : 
     502                 : /* static */
     503                 : void
     504               0 : txXPathNodeUtils::getNamespaceURI(const txXPathNode& aNode, nsAString& aURI)
     505                 : {
     506               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(getNamespaceID(aNode), aURI);
     507               0 : }
     508                 : 
     509                 : /* static */
     510                 : PRUint16
     511               0 : txXPathNodeUtils::getNodeType(const txXPathNode& aNode)
     512                 : {
     513               0 :     if (aNode.isDocument()) {
     514               0 :         return txXPathNodeType::DOCUMENT_NODE;
     515                 :     }
     516                 : 
     517               0 :     if (aNode.isContent()) {
     518               0 :         return aNode.mNode->NodeType();
     519                 :     }
     520                 : 
     521               0 :     return txXPathNodeType::ATTRIBUTE_NODE;
     522                 : }
     523                 : 
     524                 : /* static */
     525                 : void
     526              84 : txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
     527                 : {
     528              84 :     if (aNode.isAttribute()) {
     529               0 :         const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
     530                 : 
     531               0 :         if (aResult.IsEmpty()) {
     532               0 :             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
     533               0 :                                      aResult);
     534                 :         }
     535                 :         else {
     536               0 :             nsAutoString result;
     537               0 :             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
     538               0 :                                      result);
     539               0 :             aResult.Append(result);
     540                 :         }
     541                 : 
     542               0 :         return;
     543                 :     }
     544                 : 
     545             252 :     if (aNode.isDocument() ||
     546              84 :         aNode.mNode->IsElement() ||
     547              84 :         aNode.mNode->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
     548               0 :         nsContentUtils::AppendNodeTextContent(aNode.mNode, true, aResult);
     549                 : 
     550               0 :         return;
     551                 :     }
     552                 : 
     553              84 :     aNode.Content()->AppendTextTo(aResult);
     554                 : }
     555                 : 
     556                 : /* static */
     557                 : bool
     558               0 : txXPathNodeUtils::isWhitespace(const txXPathNode& aNode)
     559                 : {
     560               0 :     NS_ASSERTION(aNode.isContent() && isText(aNode), "Wrong type!");
     561                 : 
     562               0 :     return aNode.Content()->TextIsOnlyWhitespace();
     563                 : }
     564                 : 
     565                 : /* static */
     566                 : txXPathNode*
     567               0 : txXPathNodeUtils::getOwnerDocument(const txXPathNode& aNode)
     568                 : {
     569               0 :     return new txXPathNode(aNode.mNode->OwnerDoc());
     570                 : }
     571                 : 
     572                 : #ifndef HAVE_64BIT_OS
     573                 : #define kFmtSize 13
     574                 : #define kFmtSizeAttr 24
     575                 : const char gPrintfFmt[] = "id0x%08p";
     576                 : const char gPrintfFmtAttr[] = "id0x%08p-%010i";
     577                 : #else
     578                 : #define kFmtSize 21
     579                 : #define kFmtSizeAttr 32
     580                 : const char gPrintfFmt[] = "id0x%016p";
     581                 : const char gPrintfFmtAttr[] = "id0x%016p-%010i";
     582                 : #endif
     583                 : 
     584                 : /* static */
     585                 : nsresult
     586               0 : txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
     587                 :                             const txXPathNode& aBase,
     588                 :                             nsAString& aResult)
     589                 : {
     590               0 :     PRUword nodeid = ((PRUword)aNode.mNode) - ((PRUword)aBase.mNode);
     591               0 :     if (!aNode.isAttribute()) {
     592               0 :         CopyASCIItoUTF16(nsPrintfCString(kFmtSize, gPrintfFmt, nodeid),
     593               0 :                          aResult);
     594                 :     }
     595                 :     else {
     596                 :         CopyASCIItoUTF16(nsPrintfCString(kFmtSizeAttr, gPrintfFmtAttr,
     597               0 :                                          nodeid, aNode.mIndex), aResult);
     598                 :     }
     599                 : 
     600               0 :     return NS_OK;
     601                 : }
     602                 : 
     603                 : /* static */
     604                 : void
     605               0 : txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
     606                 : {
     607               0 :     aNode.mNode->GetDOMBaseURI(aURI);
     608               0 : }
     609                 : 
     610                 : /* static */
     611                 : PRIntn
     612               0 : txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
     613                 :                                   const txXPathNode& aOtherNode)
     614                 : {
     615                 :     // First check for equal nodes or attribute-nodes on the same element.
     616               0 :     if (aNode.mNode == aOtherNode.mNode) {
     617               0 :         if (aNode.mIndex == aOtherNode.mIndex) {
     618               0 :             return 0;
     619                 :         }
     620                 : 
     621               0 :         NS_ASSERTION(!aNode.isDocument() && !aOtherNode.isDocument(),
     622                 :                      "documents should always have a set index");
     623                 : 
     624               0 :         if (aNode.isContent() || (!aOtherNode.isContent() &&
     625                 :                                   aNode.mIndex < aOtherNode.mIndex)) {
     626               0 :             return -1;
     627                 :         }
     628                 : 
     629               0 :         return 1;
     630                 :     }
     631                 : 
     632                 :     // Get document for both nodes.
     633               0 :     nsIDocument* document = aNode.mNode->GetCurrentDoc();
     634               0 :     nsIDocument* otherDocument = aOtherNode.mNode->GetCurrentDoc();
     635                 : 
     636                 :     // If the nodes have different current documents, compare the document
     637                 :     // pointers.
     638               0 :     if (document != otherDocument) {
     639               0 :         return document < otherDocument ? -1 : 1;
     640                 :     }
     641                 : 
     642                 :     // Now either both nodes are in orphan trees, or they are both in the
     643                 :     // same tree.
     644                 : 
     645                 :     // Get parents up the tree.
     646               0 :     nsAutoTArray<nsINode*, 8> parents, otherParents;
     647               0 :     nsINode* node = aNode.mNode;
     648               0 :     nsINode* otherNode = aOtherNode.mNode;
     649                 :     nsINode* parent, *otherParent;
     650               0 :     while (node && otherNode) {
     651               0 :         parent = node->GetNodeParent();
     652               0 :         otherParent = otherNode->GetNodeParent();
     653                 : 
     654                 :         // Hopefully this is a common case.
     655               0 :         if (parent == otherParent) {
     656               0 :             if (!parent) {
     657                 :                 // Both node and otherNode are root nodes in respective orphan
     658                 :                 // tree.
     659               0 :                 return node < otherNode ? -1 : 1;
     660                 :             }
     661                 : 
     662               0 :             return parent->IndexOf(node) < parent->IndexOf(otherNode) ?
     663               0 :                    -1 : 1;
     664                 :         }
     665                 : 
     666               0 :         parents.AppendElement(node);
     667               0 :         otherParents.AppendElement(otherNode);
     668               0 :         node = parent;
     669               0 :         otherNode = otherParent;
     670                 :     }
     671                 : 
     672               0 :     while (node) {
     673               0 :         parents.AppendElement(node);
     674               0 :         node = node->GetNodeParent();
     675                 :     }
     676               0 :     while (otherNode) {
     677               0 :         otherParents.AppendElement(otherNode);
     678               0 :         otherNode = otherNode->GetNodeParent();
     679                 :     }
     680                 : 
     681                 :     // Walk back down along the parent-chains until we find where they split.
     682               0 :     PRInt32 total = parents.Length() - 1;
     683               0 :     PRInt32 otherTotal = otherParents.Length() - 1;
     684               0 :     NS_ASSERTION(total != otherTotal, "Can't have same number of parents");
     685                 : 
     686               0 :     PRInt32 lastIndex = NS_MIN(total, otherTotal);
     687                 :     PRInt32 i;
     688               0 :     parent = nsnull;
     689               0 :     for (i = 0; i <= lastIndex; ++i) {
     690               0 :         node = parents.ElementAt(total - i);
     691               0 :         otherNode = otherParents.ElementAt(otherTotal - i);
     692               0 :         if (node != otherNode) {
     693               0 :             if (!parent) {
     694                 :                 // The two nodes are in different orphan subtrees.
     695               0 :                 NS_ASSERTION(i == 0, "this shouldn't happen");
     696               0 :                 return node < otherNode ? -1 : 1;
     697                 :             }
     698                 : 
     699               0 :             PRInt32 index = parent->IndexOf(node);
     700               0 :             PRInt32 otherIndex = parent->IndexOf(otherNode);
     701               0 :             NS_ASSERTION(index != otherIndex && index >= 0 && otherIndex >= 0,
     702                 :                          "invalid index in compareTreePosition");
     703                 : 
     704               0 :             return index < otherIndex ? -1 : 1;
     705                 :         }
     706                 : 
     707               0 :         parent = node;
     708                 :     }
     709                 : 
     710                 :     // One node is a descendant of the other. The one with the shortest
     711                 :     // parent-chain is first in the document.
     712               0 :     return total < otherTotal ? -1 : 1;
     713                 : }
     714                 : 
     715                 : /* static */
     716                 : txXPathNode*
     717               0 : txXPathNativeNode::createXPathNode(nsIContent* aContent, bool aKeepRootAlive)
     718                 : {
     719               0 :     nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(aContent) : nsnull;
     720                 : 
     721               0 :     return new txXPathNode(aContent, txXPathNode::eContent, root);
     722                 : }
     723                 : 
     724                 : /* static */
     725                 : txXPathNode*
     726              42 : txXPathNativeNode::createXPathNode(nsIDOMNode* aNode, bool aKeepRootAlive)
     727                 : {
     728                 :     PRUint16 nodeType;
     729              42 :     aNode->GetNodeType(&nodeType);
     730                 : 
     731              42 :     if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
     732               0 :         nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
     733               0 :         NS_ASSERTION(attr, "doesn't implement nsIAttribute");
     734                 : 
     735               0 :         nsINodeInfo *nodeInfo = attr->NodeInfo();
     736               0 :         nsIContent *parent = attr->GetContent();
     737               0 :         if (!parent) {
     738               0 :             return nsnull;
     739                 :         }
     740                 : 
     741               0 :         nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(parent) : nsnull;
     742                 : 
     743               0 :         PRUint32 i, total = parent->GetAttrCount();
     744               0 :         for (i = 0; i < total; ++i) {
     745               0 :             const nsAttrName* name = parent->GetAttrNameAt(i);
     746               0 :             if (nodeInfo->Equals(name->LocalName(), name->NamespaceID())) {
     747               0 :                 return new txXPathNode(parent, i, root);
     748                 :             }
     749                 :         }
     750                 : 
     751               0 :         NS_ERROR("Couldn't find the attribute in its parent!");
     752                 : 
     753               0 :         return nsnull;
     754                 :     }
     755                 : 
     756              84 :     nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
     757                 :     PRUint32 index;
     758              42 :     nsINode* root = aKeepRootAlive ? node.get() : nsnull;
     759                 : 
     760              42 :     if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
     761               0 :         index = txXPathNode::eDocument;
     762                 :     }
     763                 :     else {
     764              42 :         index = txXPathNode::eContent;
     765              42 :         if (root) {
     766               0 :             root = txXPathNode::RootOf(root);
     767                 :         }
     768                 :     }
     769                 : 
     770              84 :     return new txXPathNode(node, index, root);
     771                 : }
     772                 : 
     773                 : /* static */
     774                 : txXPathNode*
     775               0 : txXPathNativeNode::createXPathNode(nsIDOMDocument* aDocument)
     776                 : {
     777               0 :     nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
     778               0 :     return new txXPathNode(document);
     779                 : }
     780                 : 
     781                 : /* static */
     782                 : nsresult
     783              42 : txXPathNativeNode::getNode(const txXPathNode& aNode, nsIDOMNode** aResult)
     784                 : {
     785              42 :     if (!aNode.isAttribute()) {
     786              42 :         return CallQueryInterface(aNode.mNode, aResult);
     787                 :     }
     788                 : 
     789               0 :     const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
     790                 : 
     791               0 :     nsAutoString namespaceURI;
     792               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(name->NamespaceID(), namespaceURI);
     793                 : 
     794               0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode.mNode);
     795               0 :     nsCOMPtr<nsIDOMAttr> attr;
     796               0 :     element->GetAttributeNodeNS(namespaceURI,
     797               0 :                                 nsDependentAtomString(name->LocalName()),
     798               0 :                                 getter_AddRefs(attr));
     799                 : 
     800               0 :     return CallQueryInterface(attr, aResult);
     801                 : }
     802                 : 
     803                 : /* static */
     804                 : nsIContent*
     805               0 : txXPathNativeNode::getContent(const txXPathNode& aNode)
     806                 : {
     807               0 :     NS_ASSERTION(aNode.isContent(),
     808                 :                  "Only call getContent on nsIContent wrappers!");
     809               0 :     return aNode.Content();
     810                 : }
     811                 : 
     812                 : /* static */
     813                 : nsIDocument*
     814               0 : txXPathNativeNode::getDocument(const txXPathNode& aNode)
     815                 : {
     816               0 :     NS_ASSERTION(aNode.isDocument(),
     817                 :                  "Only call getDocument on nsIDocument wrappers!");
     818               0 :     return aNode.Document();
     819                 : }

Generated by: LCOV version 1.7