dom/xslt/xpath/txLocationStep.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 Implementation of an XPath LocationStep
michael@0 8 */
michael@0 9
michael@0 10 #include "txExpr.h"
michael@0 11 #include "txIXPathContext.h"
michael@0 12 #include "txNodeSet.h"
michael@0 13 #include "txXPathTreeWalker.h"
michael@0 14
michael@0 15 //-----------------------------/
michael@0 16 //- Virtual methods from Expr -/
michael@0 17 //-----------------------------/
michael@0 18
michael@0 19 /**
michael@0 20 * Evaluates this Expr based on the given context node and processor state
michael@0 21 * @param context the context node for evaluation of this Expr
michael@0 22 * @param ps the ProcessorState containing the stack information needed
michael@0 23 * for evaluation
michael@0 24 * @return the result of the evaluation
michael@0 25 * @see Expr
michael@0 26 **/
michael@0 27 nsresult
michael@0 28 LocationStep::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
michael@0 29 {
michael@0 30 NS_ASSERTION(aContext, "internal error");
michael@0 31 *aResult = nullptr;
michael@0 32
michael@0 33 nsRefPtr<txNodeSet> nodes;
michael@0 34 nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
michael@0 35 NS_ENSURE_SUCCESS(rv, rv);
michael@0 36
michael@0 37 txXPathTreeWalker walker(aContext->getContextNode());
michael@0 38
michael@0 39 switch (mAxisIdentifier) {
michael@0 40 case ANCESTOR_AXIS:
michael@0 41 {
michael@0 42 if (!walker.moveToParent()) {
michael@0 43 break;
michael@0 44 }
michael@0 45 // do not break here
michael@0 46 }
michael@0 47 case ANCESTOR_OR_SELF_AXIS:
michael@0 48 {
michael@0 49 nodes->setReverse();
michael@0 50
michael@0 51 do {
michael@0 52 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 53 nodes->append(walker.getCurrentPosition());
michael@0 54 }
michael@0 55 } while (walker.moveToParent());
michael@0 56
michael@0 57 break;
michael@0 58 }
michael@0 59 case ATTRIBUTE_AXIS:
michael@0 60 {
michael@0 61 if (!walker.moveToFirstAttribute()) {
michael@0 62 break;
michael@0 63 }
michael@0 64
michael@0 65 do {
michael@0 66 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 67 nodes->append(walker.getCurrentPosition());
michael@0 68 }
michael@0 69 } while (walker.moveToNextAttribute());
michael@0 70 break;
michael@0 71 }
michael@0 72 case DESCENDANT_OR_SELF_AXIS:
michael@0 73 {
michael@0 74 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 75 nodes->append(walker.getCurrentPosition());
michael@0 76 }
michael@0 77 // do not break here
michael@0 78 }
michael@0 79 case DESCENDANT_AXIS:
michael@0 80 {
michael@0 81 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
michael@0 82 break;
michael@0 83 }
michael@0 84 case FOLLOWING_AXIS:
michael@0 85 {
michael@0 86 if (txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) {
michael@0 87 walker.moveToParent();
michael@0 88 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
michael@0 89 }
michael@0 90 bool cont = true;
michael@0 91 while (!walker.moveToNextSibling()) {
michael@0 92 if (!walker.moveToParent()) {
michael@0 93 cont = false;
michael@0 94 break;
michael@0 95 }
michael@0 96 }
michael@0 97 while (cont) {
michael@0 98 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 99 nodes->append(walker.getCurrentPosition());
michael@0 100 }
michael@0 101
michael@0 102 fromDescendants(walker.getCurrentPosition(), aContext, nodes);
michael@0 103
michael@0 104 while (!walker.moveToNextSibling()) {
michael@0 105 if (!walker.moveToParent()) {
michael@0 106 cont = false;
michael@0 107 break;
michael@0 108 }
michael@0 109 }
michael@0 110 }
michael@0 111 break;
michael@0 112 }
michael@0 113 case FOLLOWING_SIBLING_AXIS:
michael@0 114 {
michael@0 115 while (walker.moveToNextSibling()) {
michael@0 116 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 117 nodes->append(walker.getCurrentPosition());
michael@0 118 }
michael@0 119 }
michael@0 120 break;
michael@0 121 }
michael@0 122 case NAMESPACE_AXIS: //-- not yet implemented
michael@0 123 #if 0
michael@0 124 // XXX DEBUG OUTPUT
michael@0 125 cout << "namespace axis not yet implemented"<<endl;
michael@0 126 #endif
michael@0 127 break;
michael@0 128 case PARENT_AXIS :
michael@0 129 {
michael@0 130 if (walker.moveToParent() &&
michael@0 131 mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 132 nodes->append(walker.getCurrentPosition());
michael@0 133 }
michael@0 134 break;
michael@0 135 }
michael@0 136 case PRECEDING_AXIS:
michael@0 137 {
michael@0 138 nodes->setReverse();
michael@0 139
michael@0 140 bool cont = true;
michael@0 141 while (!walker.moveToPreviousSibling()) {
michael@0 142 if (!walker.moveToParent()) {
michael@0 143 cont = false;
michael@0 144 break;
michael@0 145 }
michael@0 146 }
michael@0 147 while (cont) {
michael@0 148 fromDescendantsRev(walker.getCurrentPosition(), aContext, nodes);
michael@0 149
michael@0 150 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 151 nodes->append(walker.getCurrentPosition());
michael@0 152 }
michael@0 153
michael@0 154 while (!walker.moveToPreviousSibling()) {
michael@0 155 if (!walker.moveToParent()) {
michael@0 156 cont = false;
michael@0 157 break;
michael@0 158 }
michael@0 159 }
michael@0 160 }
michael@0 161 break;
michael@0 162 }
michael@0 163 case PRECEDING_SIBLING_AXIS:
michael@0 164 {
michael@0 165 nodes->setReverse();
michael@0 166
michael@0 167 while (walker.moveToPreviousSibling()) {
michael@0 168 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 169 nodes->append(walker.getCurrentPosition());
michael@0 170 }
michael@0 171 }
michael@0 172 break;
michael@0 173 }
michael@0 174 case SELF_AXIS:
michael@0 175 {
michael@0 176 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 177 nodes->append(walker.getCurrentPosition());
michael@0 178 }
michael@0 179 break;
michael@0 180 }
michael@0 181 default: // Children Axis
michael@0 182 {
michael@0 183 if (!walker.moveToFirstChild()) {
michael@0 184 break;
michael@0 185 }
michael@0 186
michael@0 187 do {
michael@0 188 if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
michael@0 189 nodes->append(walker.getCurrentPosition());
michael@0 190 }
michael@0 191 } while (walker.moveToNextSibling());
michael@0 192 break;
michael@0 193 }
michael@0 194 }
michael@0 195
michael@0 196 // Apply predicates
michael@0 197 if (!isEmpty()) {
michael@0 198 rv = evaluatePredicates(nodes, aContext);
michael@0 199 NS_ENSURE_SUCCESS(rv, rv);
michael@0 200 }
michael@0 201
michael@0 202 nodes->unsetReverse();
michael@0 203
michael@0 204 NS_ADDREF(*aResult = nodes);
michael@0 205
michael@0 206 return NS_OK;
michael@0 207 }
michael@0 208
michael@0 209 void LocationStep::fromDescendants(const txXPathNode& aNode,
michael@0 210 txIMatchContext* aCs,
michael@0 211 txNodeSet* aNodes)
michael@0 212 {
michael@0 213 txXPathTreeWalker walker(aNode);
michael@0 214 if (!walker.moveToFirstChild()) {
michael@0 215 return;
michael@0 216 }
michael@0 217
michael@0 218 do {
michael@0 219 const txXPathNode& child = walker.getCurrentPosition();
michael@0 220 if (mNodeTest->matches(child, aCs)) {
michael@0 221 aNodes->append(child);
michael@0 222 }
michael@0 223 fromDescendants(child, aCs, aNodes);
michael@0 224 } while (walker.moveToNextSibling());
michael@0 225 }
michael@0 226
michael@0 227 void LocationStep::fromDescendantsRev(const txXPathNode& aNode,
michael@0 228 txIMatchContext* aCs,
michael@0 229 txNodeSet* aNodes)
michael@0 230 {
michael@0 231 txXPathTreeWalker walker(aNode);
michael@0 232 if (!walker.moveToLastChild()) {
michael@0 233 return;
michael@0 234 }
michael@0 235
michael@0 236 do {
michael@0 237 const txXPathNode& child = walker.getCurrentPosition();
michael@0 238 fromDescendantsRev(child, aCs, aNodes);
michael@0 239
michael@0 240 if (mNodeTest->matches(child, aCs)) {
michael@0 241 aNodes->append(child);
michael@0 242 }
michael@0 243
michael@0 244 } while (walker.moveToPreviousSibling());
michael@0 245 }
michael@0 246
michael@0 247 Expr::ExprType
michael@0 248 LocationStep::getType()
michael@0 249 {
michael@0 250 return LOCATIONSTEP_EXPR;
michael@0 251 }
michael@0 252
michael@0 253
michael@0 254 TX_IMPL_EXPR_STUBS_BASE(LocationStep, NODESET_RESULT)
michael@0 255
michael@0 256 Expr*
michael@0 257 LocationStep::getSubExprAt(uint32_t aPos)
michael@0 258 {
michael@0 259 return PredicateList::getSubExprAt(aPos);
michael@0 260 }
michael@0 261
michael@0 262 void
michael@0 263 LocationStep::setSubExprAt(uint32_t aPos, Expr* aExpr)
michael@0 264 {
michael@0 265 PredicateList::setSubExprAt(aPos, aExpr);
michael@0 266 }
michael@0 267
michael@0 268 bool
michael@0 269 LocationStep::isSensitiveTo(ContextSensitivity aContext)
michael@0 270 {
michael@0 271 return (aContext & NODE_CONTEXT) ||
michael@0 272 mNodeTest->isSensitiveTo(aContext) ||
michael@0 273 PredicateList::isSensitiveTo(aContext);
michael@0 274 }
michael@0 275
michael@0 276 #ifdef TX_TO_STRING
michael@0 277 void
michael@0 278 LocationStep::toString(nsAString& str)
michael@0 279 {
michael@0 280 switch (mAxisIdentifier) {
michael@0 281 case ANCESTOR_AXIS :
michael@0 282 str.AppendLiteral("ancestor::");
michael@0 283 break;
michael@0 284 case ANCESTOR_OR_SELF_AXIS :
michael@0 285 str.AppendLiteral("ancestor-or-self::");
michael@0 286 break;
michael@0 287 case ATTRIBUTE_AXIS:
michael@0 288 str.Append(char16_t('@'));
michael@0 289 break;
michael@0 290 case DESCENDANT_AXIS:
michael@0 291 str.AppendLiteral("descendant::");
michael@0 292 break;
michael@0 293 case DESCENDANT_OR_SELF_AXIS:
michael@0 294 str.AppendLiteral("descendant-or-self::");
michael@0 295 break;
michael@0 296 case FOLLOWING_AXIS :
michael@0 297 str.AppendLiteral("following::");
michael@0 298 break;
michael@0 299 case FOLLOWING_SIBLING_AXIS:
michael@0 300 str.AppendLiteral("following-sibling::");
michael@0 301 break;
michael@0 302 case NAMESPACE_AXIS:
michael@0 303 str.AppendLiteral("namespace::");
michael@0 304 break;
michael@0 305 case PARENT_AXIS :
michael@0 306 str.AppendLiteral("parent::");
michael@0 307 break;
michael@0 308 case PRECEDING_AXIS :
michael@0 309 str.AppendLiteral("preceding::");
michael@0 310 break;
michael@0 311 case PRECEDING_SIBLING_AXIS :
michael@0 312 str.AppendLiteral("preceding-sibling::");
michael@0 313 break;
michael@0 314 case SELF_AXIS :
michael@0 315 str.AppendLiteral("self::");
michael@0 316 break;
michael@0 317 default:
michael@0 318 break;
michael@0 319 }
michael@0 320 NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
michael@0 321 mNodeTest->toString(str);
michael@0 322
michael@0 323 PredicateList::toString(str);
michael@0 324 }
michael@0 325 #endif

mercurial