/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef txXPathTreeWalker_h__
#define txXPathTreeWalker_h__
#include "txCore.h"
#include "txXPathNode.h"
#include "nsIContentInlines.h"
#include "nsTArray.h"
class nsAtom;
class txXPathTreeWalker {
public:
txXPathTreeWalker(
const txXPathTreeWalker& aOther);
explicit txXPathTreeWalker(
const txXPathNode& aNode);
bool getAttr(nsAtom* aLocalName, int32_t aNSID, nsAString& aValue)
const;
int32_t getNamespaceID()
const;
uint16_t getNodeType()
const;
void appendNodeValue(nsAString& aResult)
const;
void getNodeName(nsAString& aName)
const;
void moveTo(
const txXPathTreeWalker& aWalker);
void moveToRoot();
bool moveToParent();
bool moveToElementById(
const nsAString& aID);
bool moveToFirstAttribute();
bool moveToNextAttribute();
bool moveToNamedAttribute(nsAtom* aLocalName, int32_t aNSID);
bool moveToFirstChild();
bool moveToLastChild();
bool moveToNextSibling();
bool moveToPreviousSibling();
bool isOnNode(
const txXPathNode& aNode)
const;
const txXPathNode& getCurrentPosition()
const;
private:
txXPathNode mPosition;
bool moveToValidAttribute(uint32_t aStartIndex);
};
class txXPathNodeUtils {
public:
static bool getAttr(
const txXPathNode& aNode, nsAtom* aLocalName,
int32_t aNSID, nsAString& aValue);
static already_AddRefed<nsAtom> getLocalName(
const txXPathNode& aNode);
static nsAtom* getPrefix(
const txXPathNode& aNode);
static void getLocalName(
const txXPathNode& aNode, nsAString& aLocalName);
static void getNodeName(
const txXPathNode& aNode, nsAString& aName);
static int32_t getNamespaceID(
const txXPathNode& aNode);
static void getNamespaceURI(
const txXPathNode& aNode, nsAString& aURI);
static uint16_t getNodeType(
const txXPathNode& aNode);
static void appendNodeValue(
const txXPathNode& aNode, nsAString& aResult);
static bool isWhitespace(
const txXPathNode& aNode);
static txXPathNode* getOwnerDocument(
const txXPathNode& aNode);
static int32_t getUniqueIdentifier(
const txXPathNode& aNode);
static nsresult getXSLTId(
const txXPathNode& aNode,
const txXPathNode& aBase,
nsAString& aResult);
static void release(txXPathNode* aNode);
static nsresult getBaseURI(
const txXPathNode& aNode, nsAString& aURI);
static int comparePosition(
const txXPathNode& aNode,
const txXPathNode& aOtherNode);
static bool localNameEquals(
const txXPathNode& aNode, nsAtom* aLocalName);
static bool isRoot(
const txXPathNode& aNode);
static bool isElement(
const txXPathNode& aNode);
static bool isAttribute(
const txXPathNode& aNode);
static bool isProcessingInstruction(
const txXPathNode& aNode);
static bool isComment(
const txXPathNode& aNode);
static bool isText(
const txXPathNode& aNode);
static inline bool isHTMLElementInHTMLDocument(
const txXPathNode& aNode) {
if (!aNode.isContent()) {
return false;
}
nsIContent* content = aNode.Content();
return content->IsHTMLElement() && content->IsInHTMLDocument();
}
};
class txXPathNativeNode {
public:
static txXPathNode* createXPathNode(nsINode* aNode,
bool aKeepRootAlive =
false);
static txXPathNode* createXPathNode(nsIContent* aContent,
bool aKeepRootAlive =
false);
static txXPathNode* createXPathNode(mozilla::dom::Document* aDocument);
static nsINode* getNode(
const txXPathNode& aNode);
static nsIContent* getContent(
const txXPathNode& aNode);
static mozilla::dom::Document* getDocument(
const txXPathNode& aNode);
static void addRef(
const txXPathNode& aNode) { NS_ADDREF(aNode.mNode); }
static void release(
const txXPathNode& aNode) {
nsINode* node = aNode.mNode;
NS_RELEASE(node);
}
};
inline const txXPathNode& txXPathTreeWalker::getCurrentPosition()
const {
return mPosition;
}
inline bool txXPathTreeWalker::getAttr(nsAtom* aLocalName, int32_t aNSID,
nsAString& aValue)
const {
return txXPathNodeUtils::getAttr(mPosition, aLocalName, aNSID, aValue);
}
inline int32_t txXPathTreeWalker::getNamespaceID()
const {
return txXPathNodeUtils::getNamespaceID(mPosition);
}
inline void txXPathTreeWalker::appendNodeValue(nsAString& aResult)
const {
txXPathNodeUtils::appendNodeValue(mPosition, aResult);
}
inline void txXPathTreeWalker::getNodeName(nsAString& aName)
const {
txXPathNodeUtils::getNodeName(mPosition, aName);
}
inline void txXPathTreeWalker::moveTo(
const txXPathTreeWalker& aWalker) {
nsINode* root = nullptr;
if (mPosition.mRefCountRoot) {
root = mPosition.Root();
}
mPosition.mIndex = aWalker.mPosition.mIndex;
mPosition.mRefCountRoot = aWalker.mPosition.mRefCountRoot;
mPosition.mNode = aWalker.mPosition.mNode;
nsINode* newRoot = nullptr;
if (mPosition.mRefCountRoot) {
newRoot = mPosition.Root();
}
if (root != newRoot) {
NS_IF_ADDREF(newRoot);
NS_IF_RELEASE(root);
}
}
inline bool txXPathTreeWalker::isOnNode(
const txXPathNode& aNode)
const {
return (mPosition == aNode);
}
/* static */
inline int32_t txXPathNodeUtils::getUniqueIdentifier(
const txXPathNode& aNode) {
MOZ_ASSERT(!aNode.isAttribute(),
"Not implemented for attributes.");
return NS_PTR_TO_INT32(aNode.mNode);
}
/* static */
inline void txXPathNodeUtils::release(txXPathNode* aNode) {
NS_RELEASE(aNode->mNode);
}
/* static */
inline bool txXPathNodeUtils::localNameEquals(
const txXPathNode& aNode,
nsAtom* aLocalName) {
if (aNode.isContent() && aNode.Content()->IsElement()) {
return aNode.Content()->NodeInfo()->Equals(aLocalName);
}
RefPtr<nsAtom> localName = txXPathNodeUtils::getLocalName(aNode);
return localName == aLocalName;
}
/* static */
inline bool txXPathNodeUtils::isRoot(
const txXPathNode& aNode) {
return !aNode.isAttribute() && !aNode.mNode->GetParentNode();
}
/* static */
inline bool txXPathNodeUtils::isElement(
const txXPathNode& aNode) {
return aNode.isContent() && aNode.Content()->IsElement();
}
/* static */
inline bool txXPathNodeUtils::isAttribute(
const txXPathNode& aNode) {
return aNode.isAttribute();
}
/* static */
inline bool txXPathNodeUtils::isProcessingInstruction(
const txXPathNode& aNode) {
return aNode.isContent() && aNode.Content()->IsProcessingInstruction();
}
/* static */
inline bool txXPathNodeUtils::isComment(
const txXPathNode& aNode) {
return aNode.isContent() && aNode.Content()->IsComment();
}
/* static */
inline bool txXPathNodeUtils::isText(
const txXPathNode& aNode) {
return aNode.isContent() && aNode.Content()->IsText();
}
#endif /* txXPathTreeWalker_h__ */