1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 // Class header file.
20 #include "XPath.hpp"
21
22
23
24 #include <cassert>
25 #include <cfloat>
26
27
28
29 #include <xalanc/Include/STLHelper.hpp>
30
31
32
33 #include <xalanc/XalanDOM/XalanNamedNodeMap.hpp>
34
35
36
37 #include <xalanc/PlatformSupport/DoubleSupport.hpp>
38 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
39 #include <xalanc/PlatformSupport/PrefixResolver.hpp>
40
41
42
43 #include <xalanc/DOMSupport/DOMServices.hpp>
44
45
46
47 #include "FormatterStringLengthCounter.hpp"
48 #include "MutableNodeRefList.hpp"
49 #include "XalanQNameByReference.hpp"
50 #include "XObject.hpp"
51 #include "XObjectFactory.hpp"
52 #include "XPathConstructionContext.hpp"
53 #include "XPathEnvSupport.hpp"
54
55
56
57 namespace XALAN_CPP_NAMESPACE {
58
59
60
61
62 const XalanDOMString XPath::s_emptyString(XalanMemMgrs::getDummyMemMgr());
63
64
65
XPath(MemoryManager & theManager,const Locator * theLocator)66 XPath::XPath(
67 MemoryManager& theManager,
68 const Locator* theLocator) :
69 m_expression(theManager),
70 m_locator(theLocator),
71 m_inStylesheet(false)
72 {
73 }
74
75
76
77 XPath*
create(MemoryManager & theManager,const Locator * theLocator)78 XPath::create(
79 MemoryManager& theManager,
80 const Locator* theLocator)
81 {
82 typedef XPath ThisType;
83
84 XalanAllocationGuard theGuard(theManager, theManager.allocate(sizeof(ThisType)));
85
86 ThisType* const theResult =
87 new (theGuard.get()) ThisType(
88 theManager,
89 theLocator);
90
91 theGuard.release();
92
93 return theResult;
94 }
95
96
97
~XPath()98 XPath::~XPath()
99 {
100 }
101
102
103
104 void
unknownOpCodeError(XalanNode * context,XPathExecutionContext & executionContext,OpCodeMapPositionType opPos) const105 XPath::unknownOpCodeError(
106 XalanNode* context,
107 XPathExecutionContext& executionContext,
108 OpCodeMapPositionType opPos) const
109 {
110 const GetCachedString theGuard1(executionContext);
111
112 XalanDOMString& theOpCode = theGuard1.get();
113
114 NumberToDOMString(
115 m_expression.getOpCodeMapValue(opPos),
116 theOpCode);
117
118 const GetCachedString theGuard2(executionContext);
119
120 executionContext.problem(
121 XPathExecutionContext::eXPath,
122 XPathExecutionContext::eError,
123 XalanMessageLoader::getMessage(
124 theGuard2.get(),
125 XalanMessages::InvalidOpcodeWasDetected_1Param,
126 theOpCode),
127 m_locator,
128 context);
129 }
130
131
132
133 void
notNodeSetError(XalanNode * context,XPathExecutionContext & executionContext) const134 XPath::notNodeSetError(
135 XalanNode* context,
136 XPathExecutionContext& executionContext) const
137 {
138 GetCachedString theGuard(executionContext);
139
140 XalanDOMString& theBuffer = theGuard.get();
141
142 executionContext.problem(
143 XPathExecutionContext::eXPath,
144 XPathExecutionContext::eError,
145 XalanMessageLoader::getMessage(
146 theBuffer,
147 XalanMessages::ExpressionDoesNotEvaluateToNodeSet),
148 m_locator,
149 context);
150 }
151
152
153
154 const XObjectPtr
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext) const155 XPath::execute(
156 XalanNode* context,
157 const PrefixResolver& prefixResolver,
158 XPathExecutionContext& executionContext) const
159 {
160 // Push and pop the PrefixResolver...
161 const PrefixResolverSetAndRestore theResolverSetAndRestore(
162 executionContext,
163 &prefixResolver);
164
165 // Push and pop the current node...
166 const CurrentNodePushAndPop theNodePushAndPop(
167 executionContext,
168 context);
169
170 return executeMore(
171 context,
172 getInitialOpCodePosition(),
173 executionContext);
174 }
175
176
177
178 void
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext,bool & result) const179 XPath::execute(
180 XalanNode* context,
181 const PrefixResolver& prefixResolver,
182 XPathExecutionContext& executionContext,
183 bool& result) const
184 {
185 assert(context != 0);
186
187 // Push and pop the PrefixResolver...
188 const PrefixResolverSetAndRestore theResolverSetAndRestore(
189 executionContext,
190 &prefixResolver);
191
192 // Push and pop the current node...
193 const CurrentNodePushAndPop theNodePushAndPop(
194 executionContext,
195 context);
196
197 executeMore(
198 context,
199 getInitialOpCodePosition(),
200 executionContext,
201 result);
202 }
203
204
205
206 void
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext,double & result) const207 XPath::execute(
208 XalanNode* context,
209 const PrefixResolver& prefixResolver,
210 XPathExecutionContext& executionContext,
211 double& result) const
212 {
213 assert(context != 0);
214
215 // Push and pop the PrefixResolver...
216 const PrefixResolverSetAndRestore theResolverSetAndRestore(
217 executionContext,
218 &prefixResolver);
219
220 // Push and pop the current node...
221 const CurrentNodePushAndPop theNodePushAndPop(
222 executionContext,
223 context);
224
225 executeMore(
226 context,
227 getInitialOpCodePosition(),
228 executionContext,
229 result);
230 }
231
232
233
234 void
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext,XalanDOMString & result) const235 XPath::execute(
236 XalanNode* context,
237 const PrefixResolver& prefixResolver,
238 XPathExecutionContext& executionContext,
239 XalanDOMString& result) const
240 {
241 assert(context != 0);
242
243 // Push and pop the PrefixResolver...
244 const PrefixResolverSetAndRestore theResolverSetAndRestore(
245 executionContext,
246 &prefixResolver);
247
248 // Push and pop the current node...
249 const CurrentNodePushAndPop theNodePushAndPop(
250 executionContext,
251 context);
252
253 executeMore(
254 context,
255 getInitialOpCodePosition(),
256 executionContext,
257 result);
258 }
259
260
261
262 void
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const263 XPath::execute(
264 XalanNode* context,
265 const PrefixResolver& prefixResolver,
266 XPathExecutionContext& executionContext,
267 FormatterListener& formatterListener,
268 MemberFunctionPtr function) const
269 {
270 assert(context != 0);
271
272 // Push and pop the PrefixResolver...
273 const PrefixResolverSetAndRestore theResolverSetAndRestore(
274 executionContext,
275 &prefixResolver);
276
277 // Push and pop the current node...
278 const CurrentNodePushAndPop theNodePushAndPop(
279 executionContext,
280 context);
281
282 executeMore(
283 context,
284 getInitialOpCodePosition(),
285 executionContext,
286 formatterListener,
287 function);
288 }
289
290
291
292 const XObjectPtr
execute(XalanNode * context,const PrefixResolver & prefixResolver,XPathExecutionContext & executionContext,MutableNodeRefList & result) const293 XPath::execute(
294 XalanNode* context,
295 const PrefixResolver& prefixResolver,
296 XPathExecutionContext& executionContext,
297 MutableNodeRefList& result) const
298 {
299 assert(context != 0);
300 assert(result.empty() == true);
301
302 // Push and pop the PrefixResolver...
303 const PrefixResolverSetAndRestore theResolverSetAndRestore(
304 executionContext,
305 &prefixResolver);
306
307 // Push and pop the current node...
308 const CurrentNodePushAndPop theNodePushAndPop(
309 executionContext,
310 context);
311
312 return executeMore(
313 context,
314 getInitialOpCodePosition(),
315 executionContext,
316 result);
317 }
318
319
320
321 const XObjectPtr
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const322 XPath::executeMore(
323 XalanNode* context,
324 OpCodeMapPositionType opPos,
325 XPathExecutionContext& executionContext) const
326 {
327 switch(m_expression.getOpCodeMapValue(opPos))
328 {
329 case XPathExpression::eOP_OR:
330 return executionContext.getXObjectFactory().createBoolean(Or(context, opPos, executionContext));
331 break;
332
333 case XPathExpression::eOP_AND:
334 return executionContext.getXObjectFactory().createBoolean(And(context, opPos, executionContext));
335 break;
336
337 case XPathExpression::eOP_NOTEQUALS:
338 return executionContext.getXObjectFactory().createBoolean(notequals(context, opPos, executionContext));
339 break;
340
341 case XPathExpression::eOP_EQUALS:
342 return executionContext.getXObjectFactory().createBoolean(equals(context, opPos, executionContext));
343 break;
344
345 case XPathExpression::eOP_LTE:
346 return executionContext.getXObjectFactory().createBoolean(lte(context, opPos, executionContext));
347 break;
348
349 case XPathExpression::eOP_LT:
350 return executionContext.getXObjectFactory().createBoolean(lt(context, opPos, executionContext));
351 break;
352
353 case XPathExpression::eOP_GTE:
354 return executionContext.getXObjectFactory().createBoolean(gte(context, opPos, executionContext));
355 break;
356
357 case XPathExpression::eOP_GT:
358 return executionContext.getXObjectFactory().createBoolean(gt(context, opPos, executionContext));
359 break;
360
361 case XPathExpression::eOP_PLUS:
362 return executionContext.getXObjectFactory().createNumber(plus(context, opPos, executionContext));
363 break;
364
365 case XPathExpression::eOP_MINUS:
366 return executionContext.getXObjectFactory().createNumber(minus(context, opPos, executionContext));
367 break;
368
369 case XPathExpression::eOP_MULT:
370 return executionContext.getXObjectFactory().createNumber(mult(context, opPos, executionContext));
371 break;
372
373 case XPathExpression::eOP_DIV:
374 return executionContext.getXObjectFactory().createNumber(div(context, opPos, executionContext));
375 break;
376
377 case XPathExpression::eOP_MOD:
378 return executionContext.getXObjectFactory().createNumber(mod(context, opPos, executionContext));
379 break;
380
381 case XPathExpression::eOP_NEG:
382 return executionContext.getXObjectFactory().createNumber(neg(context, opPos, executionContext));
383 break;
384
385 case XPathExpression::eOP_UNION:
386 return Union(context, opPos, executionContext);
387 break;
388
389 case XPathExpression::eOP_LITERAL:
390 return literal(opPos, executionContext);
391 break;
392
393 case XPathExpression::eOP_VARIABLE:
394 return variable(opPos, executionContext);
395 break;
396
397 case XPathExpression::eOP_GROUP:
398 return group(context, opPos, executionContext);
399 break;
400
401 case XPathExpression::eOP_NUMBERLIT:
402 return numberlit(opPos, executionContext);
403 break;
404
405 case XPathExpression::eOP_EXTFUNCTION:
406 return runExtFunction(context, opPos, executionContext);
407 break;
408
409 case XPathExpression::eOP_FUNCTION:
410 return runFunction(context, opPos, executionContext);
411 break;
412
413 case XPathExpression::eOP_LOCATIONPATH:
414 return locationPath(context, opPos, executionContext);
415 break;
416
417 case XPathExpression::eOP_FUNCTION_POSITION:
418 return executionContext.getXObjectFactory().createNumber(functionPosition(context, executionContext));
419 break;
420
421 case XPathExpression::eOP_FUNCTION_LAST:
422 return executionContext.getXObjectFactory().createNumber(functionLast(executionContext));
423 break;
424
425 case XPathExpression::eOP_FUNCTION_COUNT:
426 return executionContext.getXObjectFactory().createNumber(functionCount(context, opPos, executionContext));
427 break;
428
429 case XPathExpression::eOP_FUNCTION_NOT:
430 return executionContext.getXObjectFactory().createBoolean(functionNot(context, opPos, executionContext));
431 break;
432
433 case XPathExpression::eOP_FUNCTION_TRUE:
434 return executionContext.getXObjectFactory().createBoolean(true);
435 break;
436
437 case XPathExpression::eOP_FUNCTION_FALSE:
438 return executionContext.getXObjectFactory().createBoolean(false);
439 break;
440
441 case XPathExpression::eOP_FUNCTION_BOOLEAN:
442 return executionContext.getXObjectFactory().createBoolean(functionBoolean(context, opPos, executionContext));
443 break;
444
445 case XPathExpression::eOP_FUNCTION_NAME_0:
446 return executionContext.getXObjectFactory().createStringReference(functionName(context));
447 break;
448
449 case XPathExpression::eOP_FUNCTION_NAME_1:
450 return executionContext.getXObjectFactory().createStringReference(functionName(context, opPos, executionContext));
451 break;
452
453 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
454 return executionContext.getXObjectFactory().createStringReference(functionLocalName(context));
455 break;
456
457 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
458 return executionContext.getXObjectFactory().createStringReference(functionLocalName(context, opPos, executionContext));
459 break;
460
461 case XPathExpression::eOP_FUNCTION_FLOOR:
462 return executionContext.getXObjectFactory().createNumber(functionFloor(context, opPos, executionContext));
463 break;
464
465 case XPathExpression::eOP_FUNCTION_CEILING:
466 return executionContext.getXObjectFactory().createNumber(functionCeiling(context, opPos, executionContext));
467 break;
468
469 case XPathExpression::eOP_FUNCTION_ROUND:
470 return executionContext.getXObjectFactory().createNumber(functionRound(context, opPos, executionContext));
471 break;
472
473 case XPathExpression::eOP_FUNCTION_NUMBER_0:
474 return executionContext.getXObjectFactory().createNumber(functionNumber(context, executionContext));
475 break;
476
477 case XPathExpression::eOP_FUNCTION_NUMBER_1:
478 return executionContext.getXObjectFactory().createNumber(functionNumber(context, opPos, executionContext));
479 break;
480
481 // case XPathExpression::eOP_FUNCTION_STRING_0:
482 // return functionString(context);
483 // break;
484
485 // case XPathExpression::eOP_FUNCTION_STRING_1:
486 // return functionString(context, opPos, executionContext);
487 // break;
488
489 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
490 return executionContext.getXObjectFactory().createNumber(functionStringLength(context, executionContext));
491 break;
492
493 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
494 return executionContext.getXObjectFactory().createNumber(functionStringLength(context, opPos, executionContext));
495 break;
496
497 case XPathExpression::eOP_FUNCTION_SUM:
498 return executionContext.getXObjectFactory().createNumber(functionSum(context, opPos, executionContext));
499 break;
500
501 default:
502 unknownOpCodeError(context, executionContext, opPos);
503 break;
504 }
505
506 return XObjectPtr();
507 }
508
509
510
511 void
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,bool & result) const512 XPath::executeMore(
513 XalanNode* context,
514 OpCodeMapPositionType opPos,
515 XPathExecutionContext& executionContext,
516 bool& result) const
517 {
518 switch(m_expression.getOpCodeMapValue(opPos))
519 {
520 case XPathExpression::eOP_OR:
521 result = Or(context, opPos, executionContext);
522 break;
523
524 case XPathExpression::eOP_AND:
525 result = And(context, opPos, executionContext);
526 break;
527
528 case XPathExpression::eOP_NOTEQUALS:
529 result = notequals(context, opPos, executionContext);
530 break;
531
532 case XPathExpression::eOP_EQUALS:
533 result = equals(context, opPos, executionContext);
534 break;
535
536 case XPathExpression::eOP_LTE:
537 result = lte(context, opPos, executionContext);
538 break;
539
540 case XPathExpression::eOP_LT:
541 result = lt(context, opPos, executionContext);
542 break;
543
544 case XPathExpression::eOP_GTE:
545 result = gte(context, opPos, executionContext);
546 break;
547
548 case XPathExpression::eOP_GT:
549 result = gt(context, opPos, executionContext);
550 break;
551
552 case XPathExpression::eOP_PLUS:
553 result = XObject::boolean(plus(context, opPos, executionContext));
554 break;
555
556 case XPathExpression::eOP_MINUS:
557 result = XObject::boolean(minus(context, opPos, executionContext));
558 break;
559
560 case XPathExpression::eOP_MULT:
561 result = XObject::boolean(mult(context, opPos, executionContext));
562 break;
563
564 case XPathExpression::eOP_DIV:
565 result = XObject::boolean(div(context, opPos, executionContext));
566 break;
567
568 case XPathExpression::eOP_MOD:
569 result = XObject::boolean(mod(context, opPos, executionContext));
570 break;
571
572 case XPathExpression::eOP_NEG:
573 result = XObject::boolean(neg(context, opPos, executionContext));
574 break;
575
576 case XPathExpression::eOP_UNION:
577 Union(context, opPos, executionContext, result);
578 break;
579
580 case XPathExpression::eOP_LITERAL:
581 literal(opPos, result);
582 break;
583
584 case XPathExpression::eOP_VARIABLE:
585 result = variable(opPos, executionContext)->boolean(executionContext);
586 break;
587
588 case XPathExpression::eOP_GROUP:
589 group(context, opPos, executionContext, result);
590 break;
591
592 case XPathExpression::eOP_NUMBERLIT:
593 numberlit(opPos, result);
594 break;
595
596 case XPathExpression::eOP_EXTFUNCTION:
597 result = runExtFunction(context, opPos, executionContext)->boolean(executionContext);
598 break;
599
600 case XPathExpression::eOP_FUNCTION:
601 result = runFunction(context, opPos, executionContext)->boolean(executionContext);
602 break;
603
604 case XPathExpression::eOP_LOCATIONPATH:
605 locationPath(context, opPos, executionContext, result);
606 break;
607
608 case XPathExpression::eOP_FUNCTION_POSITION:
609 result = XObject::boolean(functionPosition(context, executionContext));
610 break;
611
612 case XPathExpression::eOP_FUNCTION_LAST:
613 result = XObject::boolean(functionLast(executionContext));
614 break;
615
616 case XPathExpression::eOP_FUNCTION_COUNT:
617 result = XObject::boolean(functionCount(context, opPos, executionContext));
618 break;
619
620 case XPathExpression::eOP_FUNCTION_NOT:
621 result = functionNot(context, opPos, executionContext);
622 break;
623
624 case XPathExpression::eOP_FUNCTION_TRUE:
625 result = true;
626 break;
627
628 case XPathExpression::eOP_FUNCTION_FALSE:
629 result = false;
630 break;
631
632 case XPathExpression::eOP_FUNCTION_BOOLEAN:
633 result = functionBoolean(context, opPos, executionContext);
634 break;
635
636 case XPathExpression::eOP_FUNCTION_NAME_0:
637 result = XObject::boolean(functionName(context));
638 break;
639
640 case XPathExpression::eOP_FUNCTION_NAME_1:
641 result = XObject::boolean(functionName(context, opPos, executionContext));
642 break;
643
644 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
645 result = XObject::boolean(functionLocalName(context));
646 break;
647
648 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
649 result = XObject::boolean(functionLocalName(context, opPos, executionContext));
650 break;
651
652 case XPathExpression::eOP_FUNCTION_FLOOR:
653 result = XObject::boolean(functionFloor(context, opPos, executionContext));
654 break;
655
656 case XPathExpression::eOP_FUNCTION_CEILING:
657 result = XObject::boolean(functionCeiling(context, opPos, executionContext));
658 break;
659
660 case XPathExpression::eOP_FUNCTION_ROUND:
661 result = XObject::boolean(functionRound(context, opPos, executionContext));
662 break;
663
664 case XPathExpression::eOP_FUNCTION_NUMBER_0:
665 result = XObject::boolean(functionNumber(context, executionContext));
666 break;
667
668 case XPathExpression::eOP_FUNCTION_NUMBER_1:
669 result = XObject::boolean(functionNumber(context, opPos, executionContext));
670 break;
671
672 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
673 result = XObject::boolean(functionStringLength(context, executionContext));
674 break;
675
676 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
677 result = XObject::boolean(functionStringLength(context, opPos, executionContext));
678 break;
679
680 case XPathExpression::eOP_FUNCTION_SUM:
681 result = XObject::boolean(functionSum(context, opPos, executionContext));
682 break;
683
684 default:
685 unknownOpCodeError(context, executionContext, opPos);
686 break;
687 }
688 }
689
690
691
692 void
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,double & result) const693 XPath::executeMore(
694 XalanNode* context,
695 OpCodeMapPositionType opPos,
696 XPathExecutionContext& executionContext,
697 double& result) const
698 {
699 switch(m_expression.getOpCodeMapValue(opPos))
700 {
701 case XPathExpression::eOP_OR:
702 result = XObject::number(Or(context, opPos, executionContext));
703 break;
704
705 case XPathExpression::eOP_AND:
706 result = XObject::number(And(context, opPos, executionContext));
707 break;
708
709 case XPathExpression::eOP_NOTEQUALS:
710 result = XObject::number(notequals(context, opPos, executionContext));
711 break;
712
713 case XPathExpression::eOP_EQUALS:
714 result = XObject::number(equals(context, opPos, executionContext));
715 break;
716
717 case XPathExpression::eOP_LTE:
718 result = XObject::number(lte(context, opPos, executionContext));
719 break;
720
721 case XPathExpression::eOP_LT:
722 result = XObject::number(lt(context, opPos, executionContext));
723 break;
724
725 case XPathExpression::eOP_GTE:
726 result = XObject::number(gte(context, opPos, executionContext));
727 break;
728
729 case XPathExpression::eOP_GT:
730 result = XObject::number(gt(context, opPos, executionContext));
731 break;
732
733 case XPathExpression::eOP_PLUS:
734 result = plus(context, opPos, executionContext);
735 break;
736
737 case XPathExpression::eOP_MINUS:
738 result = minus(context, opPos, executionContext);
739 break;
740
741 case XPathExpression::eOP_MULT:
742 result = mult(context, opPos, executionContext);
743 break;
744
745 case XPathExpression::eOP_DIV:
746 result = div(context, opPos, executionContext);
747 break;
748
749 case XPathExpression::eOP_MOD:
750 result = mod(context, opPos, executionContext);
751 break;
752
753 case XPathExpression::eOP_NEG:
754 result = neg(context, opPos, executionContext);
755 break;
756
757 case XPathExpression::eOP_UNION:
758 Union(context, opPos, executionContext, result);
759 break;
760
761 case XPathExpression::eOP_LITERAL:
762 literal(opPos, result);
763 break;
764
765 case XPathExpression::eOP_VARIABLE:
766 result = variable(opPos, executionContext)->num(executionContext);
767 break;
768
769 case XPathExpression::eOP_GROUP:
770 group(context, opPos, executionContext, result);
771 break;
772
773 case XPathExpression::eOP_NUMBERLIT:
774 result = numberlit(opPos);
775 break;
776
777 case XPathExpression::eOP_EXTFUNCTION:
778 result = runExtFunction(context, opPos, executionContext)->num(executionContext);
779 break;
780
781 case XPathExpression::eOP_FUNCTION:
782 result = runFunction(context, opPos, executionContext)->num(executionContext);
783 break;
784
785 case XPathExpression::eOP_LOCATIONPATH:
786 locationPath(context, opPos, executionContext, result);
787 break;
788
789 case XPathExpression::eOP_FUNCTION_POSITION:
790 result = functionPosition(context, executionContext);
791 break;
792
793 case XPathExpression::eOP_FUNCTION_LAST:
794 result = functionLast(executionContext);
795 break;
796
797 case XPathExpression::eOP_FUNCTION_COUNT:
798 result = functionCount(context, opPos, executionContext);
799 break;
800
801 case XPathExpression::eOP_FUNCTION_NOT:
802 result = XObject::number(functionNot(context, opPos, executionContext));
803 break;
804
805 case XPathExpression::eOP_FUNCTION_TRUE:
806 result = XObject::number(true);
807 break;
808
809 case XPathExpression::eOP_FUNCTION_FALSE:
810 result = XObject::number(false);
811 break;
812
813 case XPathExpression::eOP_FUNCTION_BOOLEAN:
814 result = XObject::number(functionBoolean(context, opPos, executionContext));
815 break;
816
817 case XPathExpression::eOP_FUNCTION_NAME_0:
818 result = XObject::number(functionName(context),executionContext.getMemoryManager());
819 break;
820
821 case XPathExpression::eOP_FUNCTION_NAME_1:
822 result = XObject::number(functionName(context, opPos, executionContext),executionContext.getMemoryManager());
823 break;
824
825 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
826 result = XObject::number(functionLocalName(context),executionContext.getMemoryManager());
827 break;
828
829 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
830 result = XObject::number(functionLocalName(context, opPos, executionContext),executionContext.getMemoryManager());
831 break;
832
833 case XPathExpression::eOP_FUNCTION_FLOOR:
834 result = functionFloor(context, opPos, executionContext);
835 break;
836
837 case XPathExpression::eOP_FUNCTION_CEILING:
838 result = functionCeiling(context, opPos, executionContext);
839 break;
840
841 case XPathExpression::eOP_FUNCTION_ROUND:
842 result = functionRound(context, opPos, executionContext);
843 break;
844
845 case XPathExpression::eOP_FUNCTION_NUMBER_0:
846 result = functionNumber(context, executionContext);
847 break;
848
849 case XPathExpression::eOP_FUNCTION_NUMBER_1:
850 result = functionNumber(context, opPos, executionContext);
851 break;
852
853 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
854 result = functionStringLength(context, executionContext);
855 break;
856
857 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
858 result = functionStringLength(context, opPos, executionContext);
859 break;
860
861 case XPathExpression::eOP_FUNCTION_SUM:
862 result = functionSum(context, opPos, executionContext);
863 break;
864
865 default:
866 unknownOpCodeError(context, executionContext, opPos);
867 break;
868 }
869 }
870
871
872
873 void
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,XalanDOMString & result) const874 XPath::executeMore(
875 XalanNode* context,
876 OpCodeMapPositionType opPos,
877 XPathExecutionContext& executionContext,
878 XalanDOMString& result) const
879 {
880 switch(m_expression.getOpCodeMapValue(opPos))
881 {
882 case XPathExpression::eOP_OR:
883 XObject::string(Or(context, opPos, executionContext), result);
884 break;
885
886 case XPathExpression::eOP_AND:
887 XObject::string(And(context, opPos, executionContext), result);
888 break;
889
890 case XPathExpression::eOP_NOTEQUALS:
891 XObject::string(notequals(context, opPos, executionContext), result);
892 break;
893
894 case XPathExpression::eOP_EQUALS:
895 XObject::string(equals(context, opPos, executionContext), result);
896 break;
897
898 case XPathExpression::eOP_LTE:
899 XObject::string(lte(context, opPos, executionContext), result);
900 break;
901
902 case XPathExpression::eOP_LT:
903 XObject::string(lt(context, opPos, executionContext), result);
904 break;
905
906 case XPathExpression::eOP_GTE:
907 XObject::string(gte(context, opPos, executionContext), result);
908 break;
909
910 case XPathExpression::eOP_GT:
911 XObject::string(gt(context, opPos, executionContext), result);
912 break;
913
914 case XPathExpression::eOP_PLUS:
915 XObject::string(plus(context, opPos, executionContext), result);
916 break;
917
918 case XPathExpression::eOP_MINUS:
919 XObject::string(minus(context, opPos, executionContext), result);
920 break;
921
922 case XPathExpression::eOP_MULT:
923 XObject::string(mult(context, opPos, executionContext), result);
924 break;
925
926 case XPathExpression::eOP_DIV:
927 XObject::string(div(context, opPos, executionContext), result);
928 break;
929
930 case XPathExpression::eOP_MOD:
931 XObject::string(mod(context, opPos, executionContext), result);
932 break;
933
934 case XPathExpression::eOP_NEG:
935 XObject::string(neg(context, opPos, executionContext), result);
936 break;
937
938 case XPathExpression::eOP_UNION:
939 Union(context, opPos, executionContext, result);
940 break;
941
942 case XPathExpression::eOP_LITERAL:
943 literal(opPos, result);
944 break;
945
946 case XPathExpression::eOP_VARIABLE:
947 variable(opPos, executionContext)->str(executionContext, result);
948 break;
949
950 case XPathExpression::eOP_GROUP:
951 group(context, opPos, executionContext, result);
952 break;
953
954 case XPathExpression::eOP_NUMBERLIT:
955 numberlit(opPos, result);
956 break;
957
958 case XPathExpression::eOP_EXTFUNCTION:
959 runExtFunction(context, opPos, executionContext)->str(executionContext, result);
960 break;
961
962 case XPathExpression::eOP_FUNCTION:
963 runFunction(context, opPos, executionContext)->str(executionContext, result);
964 break;
965
966 case XPathExpression::eOP_LOCATIONPATH:
967 locationPath(context, opPos, executionContext, result);
968 break;
969
970 case XPathExpression::eOP_FUNCTION_POSITION:
971 XObject::string(functionPosition(context, executionContext), result);
972 break;
973
974 case XPathExpression::eOP_FUNCTION_LAST:
975 XObject::string(functionLast(executionContext), result);
976 break;
977
978 case XPathExpression::eOP_FUNCTION_COUNT:
979 XObject::string(functionCount(context, opPos, executionContext), result);
980 break;
981
982 case XPathExpression::eOP_FUNCTION_NOT:
983 XObject::string(functionNot(context, opPos, executionContext), result);
984 break;
985
986 case XPathExpression::eOP_FUNCTION_TRUE:
987 XObject::string(true, result);
988 break;
989
990 case XPathExpression::eOP_FUNCTION_FALSE:
991 XObject::string(false, result);
992 break;
993
994 case XPathExpression::eOP_FUNCTION_BOOLEAN:
995 XObject::string(functionBoolean(context, opPos, executionContext), result);
996 break;
997
998 case XPathExpression::eOP_FUNCTION_NAME_0:
999 result.append(functionName(context));
1000 break;
1001
1002 case XPathExpression::eOP_FUNCTION_NAME_1:
1003 result.append(functionName(context, opPos, executionContext));
1004 break;
1005
1006 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
1007 result.append(functionLocalName(context));
1008 break;
1009
1010 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
1011 result.append(functionLocalName(context, opPos, executionContext));
1012 break;
1013
1014 case XPathExpression::eOP_FUNCTION_FLOOR:
1015 XObject::string(functionFloor(context, opPos, executionContext), result);
1016 break;
1017
1018 case XPathExpression::eOP_FUNCTION_CEILING:
1019 XObject::string(functionCeiling(context, opPos, executionContext), result);
1020 break;
1021
1022 case XPathExpression::eOP_FUNCTION_ROUND:
1023 XObject::string(functionRound(context, opPos, executionContext), result);
1024 break;
1025
1026 case XPathExpression::eOP_FUNCTION_NUMBER_0:
1027 XObject::string(functionNumber(context, executionContext), result);
1028 break;
1029
1030 case XPathExpression::eOP_FUNCTION_NUMBER_1:
1031 XObject::string(functionNumber(context, opPos, executionContext), result);
1032 break;
1033
1034 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
1035 XObject::string(functionStringLength(context, executionContext), result);
1036 break;
1037
1038 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
1039 XObject::string(functionStringLength(context, opPos, executionContext), result);
1040 break;
1041
1042 case XPathExpression::eOP_FUNCTION_SUM:
1043 XObject::string(functionSum(context, opPos, executionContext), result);
1044 break;
1045
1046 default:
1047 unknownOpCodeError(context, executionContext, opPos);
1048 break;
1049 }
1050 }
1051
1052
1053
1054 inline void
stringToCharacters(const XalanDOMString & str,FormatterListener & formatterListener,XPath::MemberFunctionPtr function)1055 stringToCharacters(
1056 const XalanDOMString& str,
1057 FormatterListener& formatterListener,
1058 XPath::MemberFunctionPtr function)
1059 {
1060 const XalanDOMString::size_type theLength = str.length();
1061
1062 if (theLength != 0)
1063 {
1064 assert(theLength == FormatterListener::size_type(theLength));
1065
1066 (formatterListener.*function)(
1067 str.c_str(),
1068 FormatterListener::size_type(theLength));
1069 }
1070 }
1071
1072
1073
1074 void
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const1075 XPath::executeMore(
1076 XalanNode* context,
1077 OpCodeMapPositionType opPos,
1078 XPathExecutionContext& executionContext,
1079 FormatterListener& formatterListener,
1080 MemberFunctionPtr function) const
1081 {
1082 switch(m_expression.getOpCodeMapValue(opPos))
1083 {
1084 case XPathExpression::eOP_OR:
1085 XObject::string(
1086 Or(context, opPos, executionContext),
1087 formatterListener,
1088 function);
1089 break;
1090
1091 case XPathExpression::eOP_AND:
1092 XObject::string(
1093 And(context, opPos, executionContext),
1094 formatterListener,
1095 function);
1096 break;
1097
1098 case XPathExpression::eOP_NOTEQUALS:
1099 XObject::string(
1100 notequals(context, opPos, executionContext),
1101 formatterListener,
1102 function);
1103 break;
1104
1105 case XPathExpression::eOP_EQUALS:
1106 XObject::string(
1107 equals(context, opPos, executionContext),
1108 formatterListener,
1109 function);
1110 break;
1111
1112 case XPathExpression::eOP_LTE:
1113 XObject::string(
1114 lte(context, opPos, executionContext),
1115 formatterListener,
1116 function);
1117 break;
1118
1119 case XPathExpression::eOP_LT:
1120 XObject::string(
1121 lt(context, opPos, executionContext),
1122 formatterListener,
1123 function);
1124 break;
1125
1126 case XPathExpression::eOP_GTE:
1127 XObject::string(
1128 gte(context, opPos, executionContext),
1129 formatterListener,
1130 function);
1131 break;
1132
1133 case XPathExpression::eOP_GT:
1134 XObject::string(
1135 gt(context, opPos, executionContext),
1136 formatterListener,
1137 function);
1138 break;
1139
1140 case XPathExpression::eOP_PLUS:
1141 plus(context, opPos, executionContext, formatterListener, function);
1142 break;
1143
1144 case XPathExpression::eOP_MINUS:
1145 minus(context, opPos, executionContext, formatterListener, function);
1146 break;
1147
1148 case XPathExpression::eOP_MULT:
1149 mult(context, opPos, executionContext, formatterListener, function);
1150 break;
1151
1152 case XPathExpression::eOP_DIV:
1153 div(context, opPos, executionContext, formatterListener, function);
1154 break;
1155
1156 case XPathExpression::eOP_MOD:
1157 mod(context, opPos, executionContext, formatterListener, function);
1158 break;
1159
1160 case XPathExpression::eOP_NEG:
1161 neg(context, opPos, executionContext, formatterListener, function);
1162 break;
1163
1164 case XPathExpression::eOP_UNION:
1165 Union(context, opPos, executionContext, formatterListener, function);
1166 break;
1167
1168 case XPathExpression::eOP_LITERAL:
1169 literal(opPos, formatterListener, function);
1170 break;
1171
1172 case XPathExpression::eOP_VARIABLE:
1173 variable(opPos, executionContext)->str(executionContext, formatterListener, function);
1174 break;
1175
1176 case XPathExpression::eOP_GROUP:
1177 group(context, opPos, executionContext, formatterListener, function);
1178 break;
1179
1180 case XPathExpression::eOP_NUMBERLIT:
1181 numberlit(opPos, formatterListener, function);
1182 break;
1183
1184 case XPathExpression::eOP_EXTFUNCTION:
1185 runExtFunction(context, opPos, executionContext)->str(executionContext, formatterListener, function);
1186 break;
1187
1188 case XPathExpression::eOP_FUNCTION:
1189 runFunction(context, opPos, executionContext)->str(executionContext, formatterListener, function);
1190 break;
1191
1192 case XPathExpression::eOP_LOCATIONPATH:
1193 locationPath(context, opPos, executionContext, formatterListener, function);
1194 break;
1195
1196 case XPathExpression::eOP_FUNCTION_POSITION:
1197 XObject::string(functionPosition(context, executionContext), formatterListener, function);
1198 break;
1199
1200 case XPathExpression::eOP_FUNCTION_LAST:
1201 XObject::string(functionLast(executionContext), formatterListener, function);
1202 break;
1203
1204 case XPathExpression::eOP_FUNCTION_COUNT:
1205 XObject::string(functionCount(context, opPos, executionContext), formatterListener, function);
1206 break;
1207
1208 case XPathExpression::eOP_FUNCTION_NOT:
1209 XObject::string(functionNot(context, opPos, executionContext), formatterListener, function);
1210 break;
1211
1212 case XPathExpression::eOP_FUNCTION_TRUE:
1213 XObject::string(true, formatterListener, function);
1214 break;
1215
1216 case XPathExpression::eOP_FUNCTION_FALSE:
1217 XObject::string(false, formatterListener, function);
1218 break;
1219
1220 case XPathExpression::eOP_FUNCTION_BOOLEAN:
1221 XObject::string(functionBoolean(context, opPos, executionContext), formatterListener, function);
1222 break;
1223
1224 case XPathExpression::eOP_FUNCTION_NAME_0:
1225 stringToCharacters(functionName(context), formatterListener, function);
1226 break;
1227
1228 case XPathExpression::eOP_FUNCTION_NAME_1:
1229 stringToCharacters(functionName(context, opPos, executionContext), formatterListener, function);
1230 break;
1231
1232 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
1233 stringToCharacters(functionLocalName(context), formatterListener, function);
1234 break;
1235
1236 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
1237 stringToCharacters(functionLocalName(context, opPos, executionContext), formatterListener, function);
1238 break;
1239
1240 case XPathExpression::eOP_FUNCTION_FLOOR:
1241 XObject::string(functionFloor(context, opPos, executionContext), formatterListener, function);
1242 break;
1243
1244 case XPathExpression::eOP_FUNCTION_CEILING:
1245 XObject::string(functionCeiling(context, opPos, executionContext), formatterListener, function);
1246 break;
1247
1248 case XPathExpression::eOP_FUNCTION_ROUND:
1249 XObject::string(functionRound(context, opPos, executionContext), formatterListener, function);
1250 break;
1251
1252 case XPathExpression::eOP_FUNCTION_NUMBER_0:
1253 XObject::string(functionNumber(context, executionContext), formatterListener, function);
1254 break;
1255
1256 case XPathExpression::eOP_FUNCTION_NUMBER_1:
1257 XObject::string(functionNumber(context, opPos, executionContext), formatterListener, function);
1258 break;
1259
1260 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
1261 XObject::string(functionStringLength(context, executionContext), formatterListener, function);
1262 break;
1263
1264 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
1265 XObject::string(functionStringLength(context, opPos, executionContext), formatterListener, function);
1266 break;
1267
1268 case XPathExpression::eOP_FUNCTION_SUM:
1269 XObject::string(functionSum(context, opPos, executionContext), formatterListener, function);
1270 break;
1271
1272 default:
1273 unknownOpCodeError(context, executionContext, opPos);
1274 break;
1275 }
1276 }
1277
1278
1279
1280 const XObjectPtr
executeMore(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,MutableNodeRefList & result) const1281 XPath::executeMore(
1282 XalanNode* context,
1283 OpCodeMapPositionType opPos,
1284 XPathExecutionContext& executionContext,
1285 MutableNodeRefList& result) const
1286 {
1287 XObjectPtr theXObject;
1288
1289 switch(m_expression.getOpCodeMapValue(opPos))
1290 {
1291 case XPathExpression::eOP_XPATH:
1292 theXObject = executeMore(context, opPos + 2, executionContext, result);
1293 break;
1294
1295 case XPathExpression::eOP_OR:
1296 case XPathExpression::eOP_AND:
1297 case XPathExpression::eOP_NOTEQUALS:
1298 case XPathExpression::eOP_EQUALS:
1299 case XPathExpression::eOP_LTE:
1300 case XPathExpression::eOP_LT:
1301 case XPathExpression::eOP_GTE:
1302 case XPathExpression::eOP_GT:
1303 case XPathExpression::eOP_PLUS:
1304 case XPathExpression::eOP_MINUS:
1305 case XPathExpression::eOP_MULT:
1306 case XPathExpression::eOP_DIV:
1307 case XPathExpression::eOP_MOD:
1308 case XPathExpression::eOP_NEG:
1309 case XPathExpression::eOP_LITERAL:
1310 case XPathExpression::eOP_NUMBERLIT:
1311 case XPathExpression::eOP_FUNCTION_POSITION:
1312 case XPathExpression::eOP_FUNCTION_LAST:
1313 case XPathExpression::eOP_FUNCTION_COUNT:
1314 case XPathExpression::eOP_FUNCTION_NOT:
1315 case XPathExpression::eOP_FUNCTION_TRUE:
1316 case XPathExpression::eOP_FUNCTION_FALSE:
1317 case XPathExpression::eOP_FUNCTION_BOOLEAN:
1318 case XPathExpression::eOP_FUNCTION_NAME_0:
1319 case XPathExpression::eOP_FUNCTION_NAME_1:
1320 case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
1321 case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
1322 case XPathExpression::eOP_FUNCTION_FLOOR:
1323 case XPathExpression::eOP_FUNCTION_CEILING:
1324 case XPathExpression::eOP_FUNCTION_ROUND:
1325 case XPathExpression::eOP_FUNCTION_NUMBER_0:
1326 case XPathExpression::eOP_FUNCTION_NUMBER_1:
1327 case XPathExpression::eOP_FUNCTION_STRING_0:
1328 case XPathExpression::eOP_FUNCTION_STRING_1:
1329 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
1330 case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
1331 case XPathExpression::eOP_FUNCTION_NAMESPACEURI_0:
1332 case XPathExpression::eOP_FUNCTION_NAMESPACEURI_1:
1333 case XPathExpression::eOP_FUNCTION_SUM:
1334 notNodeSetError(context, executionContext);
1335 break;
1336
1337 case XPathExpression::eOP_UNION:
1338 Union(context, opPos, executionContext, result);
1339 break;
1340
1341 case XPathExpression::eOP_VARIABLE:
1342 theXObject = variable(opPos, executionContext);
1343 break;
1344
1345 case XPathExpression::eOP_GROUP:
1346 group(context, opPos, executionContext, result);
1347 break;
1348
1349 case XPathExpression::eOP_EXTFUNCTION:
1350 theXObject = runExtFunction(context, opPos, executionContext);
1351 break;
1352
1353 case XPathExpression::eOP_FUNCTION:
1354 theXObject = runFunction(context, opPos, executionContext);
1355 break;
1356
1357 case XPathExpression::eOP_LOCATIONPATH:
1358 locationPath(context, opPos, executionContext, result);
1359 break;
1360
1361 default:
1362 unknownOpCodeError(context, executionContext, opPos);
1363 break;
1364 }
1365
1366 if (theXObject.null() == false && theXObject->getType() != XObject::eTypeNodeSet)
1367 {
1368 notNodeSetError(context, executionContext);
1369 }
1370
1371 return theXObject;
1372 }
1373
1374
1375
1376 inline void
doGetMatchScore(XalanNode * context,XPathExecutionContext & executionContext,eMatchScore & score) const1377 XPath::doGetMatchScore(
1378 XalanNode* context,
1379 XPathExecutionContext& executionContext,
1380 eMatchScore& score) const
1381 {
1382 assert(context != 0);
1383
1384 OpCodeMapPositionType opPos =
1385 m_expression.getInitialOpCodePosition() + 2;
1386
1387 while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN)
1388 {
1389 const OpCodeMapPositionType nextOpPos = m_expression.getNextOpCodePosition(opPos);
1390
1391 score = locationPathPattern(executionContext, *context, opPos);
1392
1393 if(score == eMatchScoreNone)
1394 {
1395 opPos = nextOpPos;
1396 }
1397 else
1398 {
1399 break;
1400 }
1401 }
1402 }
1403
1404
1405
1406 XPath::eMatchScore
getMatchScore(XalanNode * node,XPathExecutionContext & executionContext) const1407 XPath::getMatchScore(
1408 XalanNode* node,
1409 XPathExecutionContext& executionContext) const
1410 {
1411 eMatchScore score = eMatchScoreNone;
1412
1413 if(m_expression.getOpCodeMapValue(0) != XPathExpression::eOP_MATCHPATTERN)
1414 {
1415 GetCachedString theGuard(executionContext);
1416
1417 XalanDOMString& theBuffer = theGuard.get();
1418
1419 executionContext.problem(
1420 XPathExecutionContext::eXPath,
1421 XPathExecutionContext::eError,
1422 XalanMessageLoader::getMessage(
1423 theBuffer,
1424 XalanMessages::CannotEvaluateXPathExpressionAsMatchPattern),
1425 m_locator,
1426 node);
1427 }
1428 else
1429 {
1430 assert(node != 0);
1431
1432 doGetMatchScore(node, executionContext, score);
1433 }
1434
1435 return score;
1436 }
1437
1438
1439
1440 XPath::eMatchScore
getMatchScore(XalanNode * node,const PrefixResolver & resolver,XPathExecutionContext & executionContext) const1441 XPath::getMatchScore(
1442 XalanNode* node,
1443 const PrefixResolver& resolver,
1444 XPathExecutionContext& executionContext) const
1445 {
1446 const PrefixResolver* const theCurrentResolver =
1447 executionContext.getPrefixResolver();
1448
1449 if (theCurrentResolver == &resolver)
1450 {
1451 return getMatchScore(node, executionContext);
1452 }
1453 else
1454 {
1455 // Push and pop the PrefixResolver...
1456 const PrefixResolverSetAndRestore theSetAndRestore(
1457 executionContext,
1458 theCurrentResolver,
1459 &resolver);
1460
1461 return getMatchScore(node, executionContext);
1462 }
1463 }
1464
1465
1466
1467 inline const XalanDOMString*
getStringFromTokenQueue(const XPathExpression & expression,XPath::OpCodeMapPositionType opPos)1468 getStringFromTokenQueue(
1469 const XPathExpression& expression,
1470 XPath::OpCodeMapPositionType opPos)
1471 {
1472 const XPath::OpCodeMapValueType tokenPosition =
1473 expression.getOpCodeMapValue(opPos);
1474
1475 if (tokenPosition == XPathExpression::eEMPTY ||
1476 tokenPosition == XPathExpression::eELEMWILDCARD)
1477 {
1478 return 0;
1479 }
1480 else
1481 {
1482 assert(tokenPosition != XPathExpression::eENDOP);
1483
1484 const XToken* const token =
1485 expression.getToken(tokenPosition);
1486 assert(token != 0);
1487
1488 return &token->str();
1489 }
1490 }
1491
1492
1493
1494 void
getTargetData(TargetDataVectorType & targetData) const1495 XPath::getTargetData(TargetDataVectorType& targetData) const
1496 {
1497 OpCodeMapPositionType opPos =
1498 m_expression.getInitialOpCodePosition() + 2;
1499
1500 targetData.reserve(eDefaultTargetDataSize);
1501
1502 while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN)
1503 {
1504 const OpCodeMapPositionType nextOpPos = m_expression.getNextOpCodePosition(opPos);
1505
1506 opPos += 2;
1507
1508 unsigned long stepCount = 0;
1509
1510 while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP)
1511 {
1512 ++stepCount;
1513
1514 const OpCodeMapPositionType nextStepPos =
1515 m_expression.getNextOpCodePosition(opPos);
1516
1517 const OpCodeMapValueType nextOp = m_expression.getOpCodeMapValue(nextStepPos);
1518
1519 if(nextOp == XPathExpression::eENDOP)
1520 {
1521 eMatchScore score = eMatchScoreNone;
1522
1523 const XalanDOMChar* targetLocalName = 0;
1524
1525 TargetData::eTargetType targetType = TargetData::eOther;
1526
1527 bool fIsAttribute = false;
1528
1529 const OpCodeMapValueType stepType = m_expression.getOpCodeMapValue(opPos);
1530
1531 opPos += 3;
1532
1533 switch(stepType)
1534 {
1535 case XPathExpression::eOP_FUNCTION:
1536 targetLocalName = PSEUDONAME_ANY;
1537 score = eMatchScoreOther;
1538 targetType = TargetData::eAny;
1539 break;
1540
1541 case XPathExpression::eFROM_ROOT:
1542 targetLocalName = PSEUDONAME_ROOT;
1543 score = eMatchScoreOther;
1544 break;
1545
1546 case XPathExpression::eMATCH_ATTRIBUTE:
1547 fIsAttribute = true;
1548 // fall through on purpose...
1549
1550 case XPathExpression::eMATCH_ANY_ANCESTOR:
1551 case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
1552 {
1553 const OpCodeMapValueType tok = m_expression.getOpCodeMapValue(opPos);
1554
1555 switch(tok)
1556 {
1557 case XPathExpression::eNODETYPE_COMMENT:
1558 targetLocalName = PSEUDONAME_COMMENT;
1559 score = eMatchScoreNodeTest;
1560 break;
1561
1562 case XPathExpression::eNODETYPE_TEXT:
1563 targetLocalName = PSEUDONAME_TEXT;
1564 score = eMatchScoreNodeTest;
1565 break;
1566
1567 case XPathExpression::eNODETYPE_NODE:
1568 targetLocalName = PSEUDONAME_NODE;
1569 score = eMatchScoreNodeTest;
1570 break;
1571
1572 case XPathExpression::eNODETYPE_ROOT:
1573 targetLocalName = PSEUDONAME_ROOT;
1574 score = eMatchScoreNodeTest;
1575 break;
1576
1577 case XPathExpression::eNODETYPE_ANYELEMENT:
1578 targetLocalName = PSEUDONAME_ANY;
1579 score = eMatchScoreNodeTest;
1580 targetType = TargetData::eElement;
1581 break;
1582
1583 case XPathExpression::eNODETYPE_PI:
1584 {
1585 const OpCodeMapValueType argLen =
1586 m_expression.getOpCodeArgumentLength(opPos - 3);
1587
1588 targetLocalName = PSEUDONAME_PI;
1589
1590 if (argLen == 1)
1591 {
1592 score = eMatchScoreNodeTest;
1593 }
1594 else if (argLen == 2)
1595 {
1596 score = eMatchScoreQName;
1597 }
1598 }
1599 break;
1600
1601 case XPathExpression::eNODENAME:
1602 {
1603 const XalanDOMString* const targetNamespace =
1604 getStringFromTokenQueue(m_expression, opPos + 1);
1605
1606 const XalanDOMString* const targetLocal =
1607 getStringFromTokenQueue(m_expression, opPos + 2);
1608
1609 if (targetLocal == 0)
1610 {
1611 targetLocalName = 0;
1612 }
1613 else
1614 {
1615 targetLocalName = targetLocal->c_str();
1616 }
1617
1618 targetType = fIsAttribute ?
1619 TargetData::eAttribute :
1620 TargetData::eElement;
1621
1622 if(targetLocalName != 0)
1623 {
1624 if(targetLocalName == PSEUDONAME_ANY)
1625 {
1626 targetLocalName = PSEUDONAME_ANY;
1627
1628 if (targetNamespace == 0 ||
1629 *targetNamespace == PSEUDONAME_ANY)
1630 {
1631 score = eMatchScoreNodeTest;
1632 }
1633 else
1634 {
1635 score = eMatchScoreNSWild;
1636 }
1637 }
1638 else
1639 {
1640 score = eMatchScoreQName;
1641 }
1642 }
1643 else
1644 {
1645 targetLocalName = PSEUDONAME_ANY;
1646
1647 if (targetNamespace == 0 ||
1648 *targetNamespace == PSEUDONAME_ANY)
1649 {
1650 score = eMatchScoreNodeTest;
1651 }
1652 else
1653 {
1654 score = eMatchScoreNSWild;
1655 }
1656 }
1657 }
1658
1659 break;
1660
1661 default:
1662 targetLocalName = PSEUDONAME_ANY;
1663 score = eMatchScoreNodeTest;
1664 break;
1665 }
1666 }
1667 break;
1668 }
1669
1670 assert(targetLocalName != 0);
1671
1672 // If there are multiple steps, or a predicate,
1673 // the priority is always eMatchScoreOther.
1674 if (stepCount > 1 ||
1675 opPos + 3 < nextStepPos)
1676 {
1677 score = eMatchScoreOther;
1678 }
1679
1680 targetData.push_back(TargetData(targetLocalName, score, targetType));
1681 }
1682
1683 opPos = nextStepPos;
1684 }
1685
1686 opPos = nextOpPos;
1687 }
1688 }
1689
1690
1691
1692 bool
Or(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1693 XPath::Or(
1694 XalanNode* context,
1695 OpCodeMapPositionType opPos,
1696 XPathExecutionContext& executionContext) const
1697 {
1698 opPos += 2;
1699
1700 bool theResult;
1701
1702 executeMore(context, opPos, executionContext, theResult);
1703
1704 if(theResult == false)
1705 {
1706 opPos = m_expression.getNextOpCodePosition(opPos);
1707
1708 executeMore(context, opPos, executionContext, theResult);
1709 }
1710
1711 return theResult;
1712 }
1713
1714
1715
1716 bool
And(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1717 XPath::And(
1718 XalanNode* context,
1719 OpCodeMapPositionType opPos,
1720 XPathExecutionContext& executionContext) const
1721 {
1722 opPos += 2;
1723
1724 bool fResult;
1725
1726 executeMore(context, opPos, executionContext, fResult);
1727
1728 if (fResult == true)
1729 {
1730 opPos = m_expression.getNextOpCodePosition(opPos);
1731
1732 executeMore(context, opPos, executionContext, fResult);
1733 }
1734
1735 return fResult;
1736 }
1737
1738
1739
1740 bool
notequals(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1741 XPath::notequals(
1742 XalanNode* context,
1743 OpCodeMapPositionType opPos,
1744 XPathExecutionContext& executionContext) const
1745 {
1746 opPos += 2;
1747
1748 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1749 assert(expr1.get() != 0);
1750
1751 opPos = m_expression.getNextOpCodePosition(opPos);
1752
1753 return expr1->notEquals(
1754 *executeMore(context, opPos, executionContext).get(),
1755 executionContext);
1756 }
1757
1758
1759
1760 bool
equals(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1761 XPath::equals(
1762 XalanNode* context,
1763 OpCodeMapPositionType opPos,
1764 XPathExecutionContext& executionContext) const
1765 {
1766 opPos += 2;
1767
1768 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1769 assert(expr1.get() != 0);
1770
1771 opPos = m_expression.getNextOpCodePosition(opPos);
1772
1773 return expr1->equals(
1774 *executeMore(context, opPos, executionContext).get(),
1775 executionContext);
1776 }
1777
1778
1779
1780 bool
lte(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1781 XPath::lte(
1782 XalanNode* context,
1783 OpCodeMapPositionType opPos,
1784 XPathExecutionContext& executionContext) const
1785 {
1786 opPos += 2;
1787
1788 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1789 assert(expr1.get() != 0);
1790
1791 opPos = m_expression.getNextOpCodePosition(opPos);
1792
1793 return expr1->lessThanOrEquals(
1794 *executeMore(context, opPos, executionContext).get(),
1795 executionContext);
1796 }
1797
1798
1799
1800 bool
lt(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1801 XPath::lt(
1802 XalanNode* context,
1803 OpCodeMapPositionType opPos,
1804 XPathExecutionContext& executionContext) const
1805 {
1806 opPos += 2;
1807
1808 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1809 assert(expr1.get() != 0);
1810
1811 opPos = m_expression.getNextOpCodePosition(opPos);
1812
1813 return expr1->lessThan(
1814 *executeMore(context, opPos, executionContext).get(),
1815 executionContext);
1816 }
1817
1818
1819
1820 bool
gte(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1821 XPath::gte(
1822 XalanNode* context,
1823 OpCodeMapPositionType opPos,
1824 XPathExecutionContext& executionContext) const
1825 {
1826 opPos += 2;
1827
1828 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1829 assert(expr1.get() != 0);
1830
1831 opPos = m_expression.getNextOpCodePosition(opPos);
1832
1833 return expr1->greaterThanOrEquals(
1834 *executeMore(context, opPos, executionContext).get(),
1835 executionContext);
1836 }
1837
1838
1839
1840 bool
gt(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1841 XPath::gt(
1842 XalanNode* context,
1843 OpCodeMapPositionType opPos,
1844 XPathExecutionContext& executionContext) const
1845 {
1846 opPos += 2;
1847
1848 const XObjectPtr expr1(executeMore(context, opPos, executionContext));
1849 assert(expr1.get() != 0);
1850
1851 opPos = m_expression.getNextOpCodePosition(opPos);
1852
1853 return expr1->greaterThan(
1854 *executeMore(context, opPos, executionContext).get(),
1855 executionContext);
1856 }
1857
1858
1859
1860 double
getNumericOperand(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1861 XPath::getNumericOperand(
1862 XalanNode* context,
1863 OpCodeMapPositionType opPos,
1864 XPathExecutionContext& executionContext) const
1865 {
1866 if (m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_NUMBERLIT)
1867 {
1868 assert(m_expression.tokenQueueSize() >
1869 m_expression.getOpCodeMapValue(opPos + 3));
1870
1871 return m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(opPos + 2));
1872 }
1873 else
1874 {
1875 double theResult;
1876
1877 executeMore(context, opPos, executionContext, theResult);
1878
1879 return theResult;
1880 }
1881 }
1882
1883
1884
1885 double
plus(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1886 XPath::plus(
1887 XalanNode* context,
1888 OpCodeMapPositionType opPos,
1889 XPathExecutionContext& executionContext) const
1890 {
1891 opPos += 2;
1892
1893 const double expr1 = getNumericOperand(context, opPos, executionContext);
1894
1895 opPos = m_expression.getNextOpCodePosition(opPos);
1896
1897 const double expr2 = getNumericOperand(context, opPos, executionContext);
1898
1899 return DoubleSupport::add(expr1, expr2);
1900 }
1901
1902
1903
1904 void
plus(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const1905 XPath::plus(
1906 XalanNode* context,
1907 OpCodeMapPositionType opPos,
1908 XPathExecutionContext& executionContext,
1909 FormatterListener& formatterListener,
1910 MemberFunctionPtr function) const
1911 {
1912 const double theResult = plus(context, opPos, executionContext);
1913
1914 XObject::string(theResult, formatterListener, function);
1915 }
1916
1917
1918
1919 double
minus(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1920 XPath::minus(
1921 XalanNode* context,
1922 OpCodeMapPositionType opPos,
1923 XPathExecutionContext& executionContext) const
1924 {
1925 opPos += 2;
1926
1927 const double expr1 = getNumericOperand(context, opPos, executionContext);
1928
1929 opPos = m_expression.getNextOpCodePosition(opPos);
1930
1931 const double expr2 = getNumericOperand(context, opPos, executionContext);
1932
1933 return DoubleSupport::subtract(expr1, expr2);
1934 }
1935
1936
1937
1938 void
minus(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const1939 XPath::minus(
1940 XalanNode* context,
1941 OpCodeMapPositionType opPos,
1942 XPathExecutionContext& executionContext,
1943 FormatterListener& formatterListener,
1944 MemberFunctionPtr function) const
1945 {
1946 const double theResult = minus(context, opPos, executionContext);
1947
1948 XObject::string(theResult, formatterListener, function);
1949 }
1950
1951
1952
1953 double
mult(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1954 XPath::mult(
1955 XalanNode* context,
1956 OpCodeMapPositionType opPos,
1957 XPathExecutionContext& executionContext) const
1958 {
1959 opPos += 2;
1960
1961 const double expr1 = getNumericOperand(context, opPos, executionContext);
1962
1963 opPos = m_expression.getNextOpCodePosition(opPos);
1964
1965 const double expr2 = getNumericOperand(context, opPos, executionContext);
1966
1967 return DoubleSupport::multiply(expr1, expr2);
1968 }
1969
1970
1971
1972 void
mult(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const1973 XPath::mult(
1974 XalanNode* context,
1975 OpCodeMapPositionType opPos,
1976 XPathExecutionContext& executionContext,
1977 FormatterListener& formatterListener,
1978 MemberFunctionPtr function) const
1979 {
1980 const double theResult = mult(context, opPos, executionContext);
1981
1982 XObject::string(theResult, formatterListener, function);
1983 }
1984
1985
1986
1987 double
div(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const1988 XPath::div(
1989 XalanNode* context,
1990 OpCodeMapPositionType opPos,
1991 XPathExecutionContext& executionContext) const
1992 {
1993 opPos += 2;
1994
1995 const double expr1 = getNumericOperand(context, opPos, executionContext);
1996
1997 opPos = m_expression.getNextOpCodePosition(opPos);
1998
1999 const double expr2 = getNumericOperand(context, opPos, executionContext);
2000
2001 return DoubleSupport::divide(expr1, expr2);
2002 }
2003
2004
2005
2006 void
div(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const2007 XPath::div(
2008 XalanNode* context,
2009 OpCodeMapPositionType opPos,
2010 XPathExecutionContext& executionContext,
2011 FormatterListener& formatterListener,
2012 MemberFunctionPtr function) const
2013 {
2014 const double theResult = div(context, opPos, executionContext);
2015
2016 XObject::string(theResult, formatterListener, function);
2017 }
2018
2019
2020
2021 double
mod(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2022 XPath::mod(
2023 XalanNode* context,
2024 OpCodeMapPositionType opPos,
2025 XPathExecutionContext& executionContext) const
2026 {
2027 opPos += 2;
2028
2029 const double expr1 = getNumericOperand(context, opPos, executionContext);
2030
2031 opPos = m_expression.getNextOpCodePosition(opPos);
2032
2033 const double expr2 = getNumericOperand(context, opPos, executionContext);
2034
2035 return DoubleSupport::modulus(expr1, expr2);
2036 }
2037
2038
2039
2040 void
mod(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const2041 XPath::mod(
2042 XalanNode* context,
2043 OpCodeMapPositionType opPos,
2044 XPathExecutionContext& executionContext,
2045 FormatterListener& formatterListener,
2046 MemberFunctionPtr function) const
2047 {
2048 const double theResult = mod(context, opPos, executionContext);
2049
2050 XObject::string(theResult, formatterListener, function);
2051 }
2052
2053
2054
2055 double
neg(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2056 XPath::neg(
2057 XalanNode* context,
2058 OpCodeMapPositionType opPos,
2059 XPathExecutionContext& executionContext) const
2060 {
2061 return DoubleSupport::negative(getNumericOperand(context, opPos + 2, executionContext));
2062 }
2063
2064
2065
2066 void
neg(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const2067 XPath::neg(
2068 XalanNode* context,
2069 OpCodeMapPositionType opPos,
2070 XPathExecutionContext& executionContext,
2071 FormatterListener& formatterListener,
2072 MemberFunctionPtr function) const
2073 {
2074 const double theResult = neg(context, opPos, executionContext);
2075
2076 XObject::string(theResult, formatterListener, function);
2077 }
2078
2079
2080
2081 const XObjectPtr
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2082 XPath::Union(
2083 XalanNode* context,
2084 OpCodeMapPositionType opPos,
2085 XPathExecutionContext& executionContext) const
2086 {
2087 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2088
2089 BorrowReturnMutableNodeRefList resultNodeList(executionContext);
2090
2091 Union(context, opPos, executionContext, *resultNodeList);
2092
2093 return executionContext.getXObjectFactory().createNodeSet(resultNodeList);
2094 }
2095
2096
2097
2098 void
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,bool & result) const2099 XPath::Union(
2100 XalanNode* context,
2101 OpCodeMapPositionType opPos,
2102 XPathExecutionContext& executionContext,
2103 bool& result) const
2104 {
2105 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2106
2107 BorrowReturnMutableNodeRefList resultNodeList(executionContext);
2108
2109 Union(context, opPos, executionContext, *resultNodeList);
2110
2111 result = XObject::boolean(*resultNodeList);
2112 }
2113
2114
2115
2116 void
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,double & result) const2117 XPath::Union(
2118 XalanNode* context,
2119 OpCodeMapPositionType opPos,
2120 XPathExecutionContext& executionContext,
2121 double& result) const
2122 {
2123 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2124
2125 BorrowReturnMutableNodeRefList resultNodeList(executionContext);
2126
2127 Union(context, opPos, executionContext, *resultNodeList);
2128
2129 result = XObject::number(executionContext, *resultNodeList);
2130 }
2131
2132
2133
2134 void
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,XalanDOMString & result) const2135 XPath::Union(
2136 XalanNode* context,
2137 OpCodeMapPositionType opPos,
2138 XPathExecutionContext& executionContext,
2139 XalanDOMString& result) const
2140 {
2141 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2142
2143 BorrowReturnMutableNodeRefList resultNodeList(executionContext);
2144
2145 Union(context, opPos, executionContext, *resultNodeList);
2146
2147 XObject::string(*resultNodeList, executionContext, result);
2148 }
2149
2150
2151
2152 void
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const2153 XPath::Union(
2154 XalanNode* context,
2155 OpCodeMapPositionType opPos,
2156 XPathExecutionContext& executionContext,
2157 FormatterListener& formatterListener,
2158 MemberFunctionPtr function) const
2159 {
2160 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2161
2162 BorrowReturnMutableNodeRefList resultNodeList(executionContext);
2163
2164 Union(context, opPos, executionContext, *resultNodeList);
2165
2166 XObject::string(*resultNodeList, executionContext, formatterListener, function);
2167 }
2168
2169
2170
2171 void
Union(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,MutableNodeRefList & result) const2172 XPath::Union(
2173 XalanNode* context,
2174 OpCodeMapPositionType opPos,
2175 XPathExecutionContext& executionContext,
2176 MutableNodeRefList& result) const
2177 {
2178 assert(result.empty() == true);
2179
2180 opPos += 2;
2181
2182 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2183
2184 BorrowReturnMutableNodeRefList theGuard(executionContext);
2185
2186 MutableNodeRefList& tempNodeList = *theGuard;
2187
2188 while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP)
2189 {
2190 const XObjectPtr nodesetResult(executeMore(context, opPos, executionContext, tempNodeList));
2191
2192 if (nodesetResult.null() == false)
2193 {
2194 result.addNodesInDocOrder(nodesetResult->nodeset(), executionContext);
2195 }
2196 else
2197 {
2198 result.addNodesInDocOrder(tempNodeList, executionContext);
2199
2200 tempNodeList.clear();
2201 }
2202
2203 opPos = m_expression.getNextOpCodePosition(opPos);
2204 }
2205
2206 result.setDocumentOrder();
2207 }
2208
2209
2210
2211 const XObjectPtr
literal(OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2212 XPath::literal(
2213 OpCodeMapPositionType opPos,
2214 XPathExecutionContext& executionContext) const
2215 {
2216 assert(m_expression.isValidOpCodePosition(opPos + 2));
2217 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
2218
2219 const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2220 assert(theLiteral != 0);
2221
2222 if (m_inStylesheet == true)
2223 {
2224 return executionContext.getXObjectFactory().createString(*theLiteral);
2225 }
2226 else
2227 {
2228 return executionContext.getXObjectFactory().createString(theLiteral->str());
2229 }
2230 }
2231
2232
2233
2234 void
literal(OpCodeMapPositionType opPos,bool & theResult) const2235 XPath::literal(
2236 OpCodeMapPositionType opPos,
2237 bool& theResult) const
2238 {
2239 assert(m_expression.isValidOpCodePosition(opPos + 2));
2240 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
2241
2242 const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2243 assert(theLiteral != 0);
2244
2245 theResult = theLiteral->boolean();
2246 }
2247
2248
2249
2250 void
literal(OpCodeMapPositionType opPos,double & theResult) const2251 XPath::literal(
2252 OpCodeMapPositionType opPos,
2253 double& theResult) const
2254 {
2255 assert(m_expression.isValidOpCodePosition(opPos + 2));
2256 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
2257
2258 const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2259 assert(theLiteral != 0);
2260
2261 theResult = theLiteral->num();
2262 }
2263
2264
2265
2266 void
literal(OpCodeMapPositionType opPos,XalanDOMString & theString) const2267 XPath::literal(
2268 OpCodeMapPositionType opPos,
2269 XalanDOMString& theString) const
2270 {
2271 assert(m_expression.isValidOpCodePosition(opPos + 2));
2272 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
2273
2274 const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2275 assert(theLiteral != 0);
2276
2277 theString = theLiteral->str();
2278 }
2279
2280
2281
2282 void
literal(OpCodeMapPositionType opPos,FormatterListener & formatterListener,MemberFunctionPtr function) const2283 XPath::literal(
2284 OpCodeMapPositionType opPos,
2285 FormatterListener& formatterListener,
2286 MemberFunctionPtr function) const
2287 {
2288 assert(m_expression.isValidOpCodePosition(opPos + 2));
2289 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
2290
2291 const XToken* const theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2292 assert(theLiteral != 0);
2293
2294 theLiteral->str(formatterListener, function);
2295 }
2296
2297
2298
2299 const XObjectPtr
variable(OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2300 XPath::variable(
2301 OpCodeMapPositionType opPos,
2302 XPathExecutionContext& executionContext) const
2303 {
2304 assert(m_expression.isValidOpCodePosition(opPos + 3));
2305 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2306
2307 const XToken* const ns =
2308 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
2309 assert(ns != 0);
2310
2311 const XToken* const varName =
2312 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2313 assert(varName != 0);
2314
2315 return executionContext.getVariable(XalanQNameByReference(ns->str(), varName->str()), m_locator);
2316 }
2317
2318
2319
2320 const XObjectPtr
numberlit(OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2321 XPath::numberlit(
2322 OpCodeMapPositionType opPos,
2323 XPathExecutionContext& executionContext) const
2324 {
2325 assert(m_expression.isValidOpCodePosition(opPos + 3));
2326 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2327
2328 const XToken* const theLiteral =
2329 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2330 assert(theLiteral != 0);
2331
2332 if (m_inStylesheet == true)
2333 {
2334 return executionContext.getXObjectFactory().createNumber(*theLiteral);
2335 }
2336 else
2337 {
2338 return executionContext.getXObjectFactory().createNumber(theLiteral->num());
2339 }
2340 }
2341
2342
2343
2344 double
numberlit(OpCodeMapPositionType opPos) const2345 XPath::numberlit(OpCodeMapPositionType opPos) const
2346 {
2347 assert(m_expression.isValidOpCodePosition(opPos + 3));
2348 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2349
2350 const XToken* const theLiteral =
2351 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2352 assert(theLiteral != 0);
2353
2354 return theLiteral->num();
2355 }
2356
2357
2358
2359 void
numberlit(OpCodeMapPositionType opPos,bool & theResult) const2360 XPath::numberlit(
2361 OpCodeMapPositionType opPos,
2362 bool& theResult) const
2363 {
2364 assert(m_expression.isValidOpCodePosition(opPos + 3));
2365 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2366
2367 const XToken* const theLiteral =
2368 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2369 assert(theLiteral != 0);
2370
2371 theResult = theLiteral->boolean();
2372 }
2373
2374
2375
2376 void
numberlit(OpCodeMapPositionType opPos,XalanDOMString & theString) const2377 XPath::numberlit(
2378 OpCodeMapPositionType opPos,
2379 XalanDOMString& theString) const
2380 {
2381 assert(m_expression.isValidOpCodePosition(opPos + 3));
2382 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2383
2384 const XToken* const theLiteral =
2385 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2386 assert(theLiteral != 0);
2387
2388 theString = theLiteral->str();
2389 }
2390
2391
2392
2393 void
numberlit(OpCodeMapPositionType opPos,FormatterListener & formatterListener,MemberFunctionPtr function) const2394 XPath::numberlit(
2395 OpCodeMapPositionType opPos,
2396 FormatterListener& formatterListener,
2397 MemberFunctionPtr function) const
2398 {
2399 assert(m_expression.isValidOpCodePosition(opPos + 3));
2400 assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
2401
2402 const XToken* const theLiteral =
2403 m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
2404 assert(theLiteral != 0);
2405
2406 theLiteral->str( formatterListener, function);
2407 }
2408
2409
2410
2411 const XObjectPtr
locationPath(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2412 XPath::locationPath(
2413 XalanNode* context,
2414 OpCodeMapPositionType opPos,
2415 XPathExecutionContext& executionContext) const
2416 {
2417 assert(context != 0);
2418
2419 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2420
2421 BorrowReturnMutableNodeRefList mnl(executionContext);
2422
2423 locationPath(context, opPos, executionContext, *mnl.get());
2424
2425 return executionContext.getXObjectFactory().createNodeSet(mnl);
2426 }
2427
2428
2429
2430 void
locationPath(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,bool & theResult) const2431 XPath::locationPath(
2432 XalanNode* context,
2433 OpCodeMapPositionType opPos,
2434 XPathExecutionContext& executionContext,
2435 bool& theResult) const
2436 {
2437 assert(context != 0);
2438
2439 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2440
2441 BorrowReturnMutableNodeRefList mnl(executionContext);
2442
2443 locationPath(context, opPos, executionContext, *mnl.get());
2444
2445 theResult = XObject::boolean(*mnl.get());
2446 }
2447
2448
2449
2450 void
locationPath(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,double & theResult) const2451 XPath::locationPath(
2452 XalanNode* context,
2453 OpCodeMapPositionType opPos,
2454 XPathExecutionContext& executionContext,
2455 double& theResult) const
2456 {
2457 assert(context != 0);
2458
2459 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2460
2461 BorrowReturnMutableNodeRefList mnl(executionContext);
2462
2463 locationPath(context, opPos, executionContext, *mnl.get());
2464
2465 theResult = XObject::number(executionContext, *mnl.get());
2466 }
2467
2468
2469
2470 void
locationPath(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,XalanDOMString & theResult) const2471 XPath::locationPath(
2472 XalanNode* context,
2473 OpCodeMapPositionType opPos,
2474 XPathExecutionContext& executionContext,
2475 XalanDOMString& theResult) const
2476 {
2477 assert(context != 0);
2478
2479 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2480
2481 BorrowReturnMutableNodeRefList mnl(executionContext);
2482
2483 locationPath(context, opPos, executionContext, *mnl.get());
2484
2485 XObject::string(*mnl.get(), executionContext, theResult);
2486 }
2487
2488
2489
2490 void
locationPath(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext,FormatterListener & formatterListener,MemberFunctionPtr function) const2491 XPath::locationPath(
2492 XalanNode* context,
2493 OpCodeMapPositionType opPos,
2494 XPathExecutionContext& executionContext,
2495 FormatterListener& formatterListener,
2496 MemberFunctionPtr function) const
2497 {
2498 assert(context != 0);
2499
2500 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2501
2502 BorrowReturnMutableNodeRefList mnl(executionContext);
2503
2504 locationPath(context, opPos, executionContext, *mnl.get());
2505
2506 XObject::string(*mnl, executionContext, formatterListener, function);
2507 }
2508
2509
2510
2511 const XObjectPtr
runExtFunction(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2512 XPath::runExtFunction(
2513 XalanNode* context,
2514 OpCodeMapPositionType opPos,
2515 XPathExecutionContext& executionContext) const
2516 {
2517 assert(context != 0);
2518
2519 const OpCodeMapPositionType endExtFunc =
2520 opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1;
2521
2522 opPos += 2;
2523
2524 const XToken* const ns = m_expression.getToken(m_expression.getOpCodeMapValue(opPos));
2525 assert(ns != 0);
2526
2527 ++opPos;
2528
2529 const XToken* const funcName = m_expression.getToken(m_expression.getOpCodeMapValue(opPos));
2530 assert(funcName != 0);
2531
2532 ++opPos;
2533
2534 typedef XPathExecutionContext::XObjectArgVectorType XObjectArgVectorType;
2535
2536 XObjectArgVectorType args(executionContext.getMemoryManager());
2537
2538 while(opPos < endExtFunc)
2539 {
2540 const OpCodeMapPositionType nextOpPos =
2541 m_expression.getNextOpCodePosition(opPos);
2542
2543 args.push_back(executeMore(context, opPos, executionContext));
2544
2545 opPos = nextOpPos;
2546 }
2547
2548 return extfunction(context, opPos, ns->str(), funcName->str(), args, executionContext);
2549 }
2550
2551
2552
2553 const XObjectPtr
runFunction(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2554 XPath::runFunction(
2555 XalanNode* context,
2556 OpCodeMapPositionType opPos,
2557 XPathExecutionContext& executionContext) const
2558 {
2559 const OpCodeMapPositionType endFunc =
2560 opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1;
2561
2562 opPos += 2;
2563
2564 // This is index into the function table for the
2565 // function.
2566 const OpCodeMapValueType funcID = m_expression.getOpCodeMapValue(opPos);
2567
2568 opPos++;
2569
2570 // Number of args is next.
2571 const OpCodeMapValueType argCount = m_expression.getOpCodeMapValue(opPos);
2572
2573 opPos++;
2574
2575 if (argCount == 0)
2576 {
2577 assert(opPos == endFunc);
2578
2579 return s_functions[funcID].execute(executionContext, context, m_locator);
2580 }
2581 else if (argCount == 1)
2582 {
2583 return s_functions[funcID].execute(
2584 executionContext,
2585 context,
2586 executeMore(context, opPos, executionContext),
2587 m_locator);
2588 }
2589 else if (argCount == 2)
2590 {
2591 const XObjectPtr theArg1(executeMore(context, opPos, executionContext));
2592
2593 opPos = m_expression.getNextOpCodePosition(opPos);
2594
2595 assert(m_expression.getNextOpCodePosition(opPos) == endFunc);
2596
2597 return s_functions[funcID].execute(
2598 executionContext,
2599 context,
2600 theArg1,
2601 executeMore(context, opPos, executionContext),
2602 m_locator);
2603 }
2604 else if (argCount == 3)
2605 {
2606 const XObjectPtr theArg1(executeMore(context, opPos, executionContext));
2607
2608 opPos = m_expression.getNextOpCodePosition(opPos);
2609
2610 const XObjectPtr theArg2(executeMore(context, opPos, executionContext));
2611
2612 opPos = m_expression.getNextOpCodePosition(opPos);
2613
2614 assert(m_expression.getNextOpCodePosition(opPos) == endFunc);
2615
2616 return s_functions[funcID].execute(
2617 executionContext,
2618 context,
2619 theArg1,
2620 theArg2,
2621 executeMore(context, opPos, executionContext),
2622 m_locator);
2623 }
2624 else
2625 {
2626 typedef XPathExecutionContext::XObjectArgVectorType XObjectArgVectorType;
2627
2628 XObjectArgVectorType args(executionContext.getMemoryManager());
2629
2630 args.reserve(argCount);
2631
2632 while(opPos < endFunc)
2633 {
2634 args.push_back(executeMore(context, opPos, executionContext));
2635
2636 opPos = m_expression.getNextOpCodePosition(opPos);
2637 }
2638
2639 return function(context, funcID, args, executionContext);
2640 }
2641 }
2642
2643
2644
2645 double
functionCount(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2646 XPath::functionCount(
2647 XalanNode* context,
2648 OpCodeMapPositionType opPos,
2649 XPathExecutionContext& executionContext) const
2650 {
2651 assert(context != 0);
2652
2653 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2654
2655 BorrowReturnMutableNodeRefList result(executionContext);
2656
2657 const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
2658
2659 const XPathExecutionContext::size_type theResult =
2660 nodesetResult.null() == false ?
2661 nodesetResult->nodeset().getLength() :
2662 result->getLength();
2663 assert(static_cast<double>(theResult) == theResult);
2664
2665 return static_cast<double>(theResult);
2666 }
2667
2668
2669
2670 const XalanDOMString&
functionName(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2671 XPath::functionName(
2672 XalanNode* context,
2673 OpCodeMapPositionType opPos,
2674 XPathExecutionContext& executionContext) const
2675 {
2676 assert(context != 0);
2677
2678 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2679
2680 BorrowReturnMutableNodeRefList result(executionContext);
2681
2682 const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
2683
2684 const NodeRefListBase* const theNodeList = nodesetResult.null() == false ?
2685 &nodesetResult->nodeset() : &*result;
2686 assert(theNodeList != 0);
2687
2688 if (theNodeList->getLength() == 0)
2689 {
2690 return s_emptyString;
2691 }
2692 else
2693 {
2694 assert(theNodeList->item(0) != 0);
2695
2696 return functionName(theNodeList->item(0));
2697 }
2698 }
2699
2700
2701
2702 const XalanDOMString&
functionLocalName(XalanNode * context) const2703 XPath::functionLocalName(XalanNode* context) const
2704 {
2705 assert(context != 0);
2706
2707 const XalanDOMString* theResult = &s_emptyString;
2708
2709 const XalanNode::NodeType theType = context->getNodeType();
2710
2711 if(theType == XalanNode::ELEMENT_NODE ||
2712 theType == XalanNode::PROCESSING_INSTRUCTION_NODE)
2713 {
2714 theResult = &DOMServices::getLocalNameOfNode(*context);
2715 }
2716 else if (theType == XalanNode::ATTRIBUTE_NODE)
2717 {
2718 const XalanDOMString& theLocalName = DOMServices::getLocalNameOfNode(*context);
2719
2720 if (theLocalName != DOMServices::s_XMLNamespace)
2721 {
2722 theResult = &theLocalName;
2723 }
2724 }
2725
2726 return *theResult;
2727 }
2728
2729
2730
2731 const XalanDOMString&
functionLocalName(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2732 XPath::functionLocalName(
2733 XalanNode* context,
2734 OpCodeMapPositionType opPos,
2735 XPathExecutionContext& executionContext) const
2736 {
2737 assert(context != 0);
2738
2739 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2740
2741 BorrowReturnMutableNodeRefList result(executionContext);
2742
2743 const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
2744
2745 const NodeRefListBase* const theNodeList = nodesetResult.null() == false ?
2746 &nodesetResult->nodeset() : &*result;
2747 assert(theNodeList != 0);
2748
2749 if (theNodeList->getLength() == 0)
2750 {
2751 return s_emptyString;
2752 }
2753 else
2754 {
2755 assert(theNodeList->item(0) != 0);
2756
2757 return functionLocalName(theNodeList->item(0));
2758 }
2759 }
2760
2761
2762
2763 double
functionStringLength(XalanNode * context,XPathExecutionContext & executionContext) const2764 XPath::functionStringLength(
2765 XalanNode* context,
2766 XPathExecutionContext& executionContext) const
2767 {
2768 assert(context != 0);
2769
2770 FormatterStringLengthCounter theCounter;
2771
2772 DOMServices::getNodeData(*context, executionContext, theCounter, &FormatterListener::characters);
2773
2774 const FormatterListener::size_type theResult = theCounter.getCount();
2775 assert(static_cast<double>(theResult) == theResult);
2776
2777 return static_cast<double>(theResult);
2778 }
2779
2780
2781
2782 double
functionStringLength(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2783 XPath::functionStringLength(
2784 XalanNode* context,
2785 OpCodeMapPositionType opPos,
2786 XPathExecutionContext& executionContext) const
2787 {
2788 assert(context != 0);
2789
2790 FormatterStringLengthCounter theCounter;
2791
2792 executeMore(context, opPos + 2, executionContext, theCounter, &FormatterListener::characters);
2793
2794 const FormatterListener::size_type theResult = theCounter.getCount();
2795 assert(static_cast<double>(theResult) == theResult);
2796
2797 return static_cast<double>(theResult);
2798 }
2799
2800
2801
2802 double
functionSum(XalanNode * context,OpCodeMapPositionType opPos,XPathExecutionContext & executionContext) const2803 XPath::functionSum(
2804 XalanNode* context,
2805 OpCodeMapPositionType opPos,
2806 XPathExecutionContext& executionContext) const
2807 {
2808 assert(context != 0);
2809
2810 double sum = 0.0;
2811
2812 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2813
2814 BorrowReturnMutableNodeRefList result(executionContext);
2815
2816 const XObjectPtr nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
2817
2818 const NodeRefListBase* const theNodeList = nodesetResult.null() == false ?
2819 &nodesetResult->nodeset() : &*result;
2820 assert(theNodeList != 0);
2821
2822 const NodeRefListBase::size_type theLength = theNodeList->getLength();
2823
2824 if (theLength != 0)
2825 {
2826 assert(theNodeList->item(0) != 0);
2827
2828 const GetCachedString theData(executionContext);
2829
2830 XalanDOMString& theString = theData.get();
2831
2832 for (NodeRefListBase::size_type i = 0; i < theLength; i++)
2833 {
2834 DOMServices::getNodeData(*theNodeList->item(i), executionContext, theString);
2835
2836 sum = DoubleSupport::add(sum, DoubleSupport::toDouble(theString, executionContext.getMemoryManager()));
2837
2838 theString.clear();
2839 }
2840 }
2841
2842 return sum;
2843 }
2844
2845
2846
2847 XPath::eMatchScore
locationPathPattern(XPathExecutionContext & executionContext,XalanNode & context,OpCodeMapPositionType opPos) const2848 XPath::locationPathPattern(
2849 XPathExecutionContext& executionContext,
2850 XalanNode& context,
2851 OpCodeMapPositionType opPos) const
2852 {
2853 eMatchScore score = eMatchScoreNone;
2854
2855 stepPattern(executionContext, &context, opPos + 2, score);
2856
2857 return score;
2858 }
2859
2860
2861
2862 void
step(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,MutableNodeRefList & queryResults) const2863 XPath::step(
2864 XPathExecutionContext& executionContext,
2865 XalanNode* context,
2866 OpCodeMapPositionType opPos,
2867 MutableNodeRefList& queryResults) const
2868 {
2869 const XPathExpression& currentExpression = getExpression();
2870
2871 const OpCodeMapValueType stepType =
2872 currentExpression.getOpCodeMapValue(opPos);
2873
2874 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
2875
2876 BorrowReturnMutableNodeRefList subQueryResults(executionContext);
2877
2878 bool continueStepRecursion = true;
2879
2880 switch(stepType)
2881 {
2882 case XPathExpression::eOP_VARIABLE:
2883 case XPathExpression::eOP_EXTFUNCTION:
2884 case XPathExpression::eOP_FUNCTION:
2885 case XPathExpression::eOP_GROUP:
2886 opPos = findNodeSet(executionContext, context, opPos, stepType, *subQueryResults);
2887 break;
2888
2889 case XPathExpression::eFROM_ROOT:
2890 opPos = findRoot(executionContext, context, opPos, stepType, *subQueryResults);
2891 break;
2892
2893 case XPathExpression::eFROM_PARENT:
2894 opPos = findParent(executionContext, context, opPos, stepType, *subQueryResults);
2895 break;
2896
2897 case XPathExpression::eFROM_SELF:
2898 opPos = findSelf(executionContext, context, opPos, stepType, *subQueryResults);
2899 break;
2900
2901 case XPathExpression::eFROM_ANCESTORS:
2902 opPos = findAncestors(executionContext, context, opPos, stepType, *subQueryResults);
2903 break;
2904
2905 case XPathExpression::eFROM_ANCESTORS_OR_SELF:
2906 opPos = findAncestorsOrSelf(executionContext, context, opPos, stepType, *subQueryResults);
2907 break;
2908
2909 case XPathExpression::eMATCH_ATTRIBUTE:
2910 continueStepRecursion = false;
2911 // fall-through on purpose.
2912
2913 case XPathExpression::eFROM_ATTRIBUTES:
2914 opPos = findAttributes(executionContext, context, opPos, stepType, *subQueryResults);
2915 break;
2916
2917 case XPathExpression::eMATCH_ANY_ANCESTOR:
2918 case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
2919 case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
2920 continueStepRecursion = false;
2921 // fall-through on purpose.
2922
2923 case XPathExpression::eFROM_CHILDREN:
2924 opPos = findChildren(executionContext, context, opPos, stepType, *subQueryResults);
2925 break;
2926
2927 case XPathExpression::eFROM_DESCENDANTS:
2928 case XPathExpression::eFROM_DESCENDANTS_OR_SELF:
2929 opPos = findDescendants(executionContext, context, opPos, stepType, *subQueryResults);
2930 break;
2931
2932 case XPathExpression::eFROM_FOLLOWING:
2933 opPos = findFollowing(executionContext, context, opPos, stepType, *subQueryResults);
2934 break;
2935
2936 case XPathExpression::eFROM_FOLLOWING_SIBLINGS:
2937 opPos = findFollowingSiblings(executionContext, context, opPos, stepType, *subQueryResults);
2938 break;
2939
2940 case XPathExpression::eFROM_PRECEDING:
2941 opPos = findPreceeding(executionContext, context, opPos, stepType, *subQueryResults);
2942 break;
2943
2944 case XPathExpression::eFROM_PRECEDING_SIBLINGS:
2945 opPos = findPreceedingSiblings(executionContext, context, opPos, stepType, *subQueryResults);
2946 break;
2947
2948 case XPathExpression::eFROM_NAMESPACE:
2949 opPos = findNamespace(executionContext, context, opPos, stepType, *subQueryResults);
2950 break;
2951
2952 default:
2953 opPos = findNodesOnUnknownAxis(executionContext, context, opPos, stepType, *subQueryResults);
2954 break;
2955 }
2956
2957 OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos);
2958
2959 // Push and pop the context node list...
2960 XPathExecutionContext::ContextNodeListPushAndPop thePushAndPop(
2961 executionContext,
2962 *subQueryResults);
2963
2964 if(XPathExpression::eOP_PREDICATE == nextStepType ||
2965 XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
2966 {
2967 opPos =
2968 predicates(
2969 executionContext,
2970 opPos,
2971 *subQueryResults);
2972
2973 nextStepType = currentExpression.getOpCodeMapValue(opPos);
2974 }
2975
2976 if(XPathExpression::eENDOP != nextStepType && continueStepRecursion == true)
2977 {
2978 const NodeRefListBase::size_type nContexts = subQueryResults->getLength();
2979
2980 if (nContexts > 0)
2981 {
2982 for(NodeRefListBase::size_type i = 0; i < nContexts; i++)
2983 {
2984 XalanNode* const node = subQueryResults->item(i);
2985 assert(node != 0);
2986
2987 BorrowReturnMutableNodeRefList mnl(executionContext);
2988
2989 step(executionContext, node, opPos, *mnl);
2990
2991 if (mnl->empty() == false)
2992 {
2993 if(queryResults.empty() == false)
2994 {
2995 queryResults.addNodesInDocOrder(*mnl, executionContext);
2996
2997 queryResults.setDocumentOrder();
2998 }
2999 else
3000 {
3001 assert(mnl->getDocumentOrder() == true);
3002
3003 queryResults.swap(*mnl);
3004 }
3005 }
3006 }
3007
3008 if (queryResults.empty() == true)
3009 {
3010 queryResults.setDocumentOrder();
3011 }
3012 }
3013 }
3014 else
3015 {
3016 if (subQueryResults->empty() == true)
3017 {
3018 queryResults.clear();
3019
3020 queryResults.setDocumentOrder();
3021 }
3022 else if (subQueryResults->getReverseDocumentOrder() == true)
3023 {
3024 queryResults.swap(*subQueryResults);
3025
3026 queryResults.reverse();
3027 }
3028 else
3029 {
3030 assert(subQueryResults->getDocumentOrder() == true);
3031
3032 queryResults.swap(*subQueryResults);
3033 }
3034 }
3035 }
3036
3037
3038
3039 XPath::eMatchScore
doStepPredicate(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapPositionType startOpPos,eMatchScore score) const3040 XPath::doStepPredicate(
3041 XPathExecutionContext& executionContext,
3042 XalanNode* context,
3043 OpCodeMapPositionType opPos,
3044 OpCodeMapPositionType startOpPos,
3045 eMatchScore score) const
3046 {
3047 const XPathExpression& currentExpression = getExpression();
3048
3049 OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos);
3050
3051 if (XPathExpression::eOP_PREDICATE == nextStepType ||
3052 XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
3053 {
3054 do
3055 {
3056 // This is a quick hack to look ahead and see if we have
3057 // number literal as the predicate, i.e. match="foo[1]".
3058 if (XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
3059 {
3060 if (m_expression.getOpCodeMapValue(opPos + 2) == XPathExpression::eOP_NUMBERLIT)
3061 {
3062 score = handleFoundIndexPositional(
3063 executionContext,
3064 context,
3065 startOpPos);
3066 }
3067 else
3068 {
3069 score = handleFoundIndex(
3070 executionContext,
3071 context,
3072 startOpPos);
3073 }
3074 }
3075 else
3076 {
3077 const XObjectPtr pred(predicate(context, opPos, executionContext));
3078 assert(pred.get() != 0);
3079
3080 if(XObject::eTypeNumber == pred->getType())
3081 {
3082 score = handleFoundIndex(executionContext, context, startOpPos);
3083 }
3084 else if(pred->boolean(executionContext) == false)
3085 {
3086 score = eMatchScoreNone;
3087
3088 break;
3089 }
3090 }
3091
3092 opPos = currentExpression.getNextOpCodePosition(opPos);
3093 nextStepType = currentExpression.getOpCodeMapValue(opPos);
3094 }
3095 while(XPathExpression::eOP_PREDICATE == nextStepType ||
3096 XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType);
3097 }
3098
3099 return score;
3100 }
3101
3102
3103
3104 XalanNode*
stepPattern(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,eMatchScore & scoreHolder) const3105 XPath::stepPattern(
3106 XPathExecutionContext& executionContext,
3107 XalanNode* context,
3108 OpCodeMapPositionType opPos,
3109 eMatchScore& scoreHolder) const
3110 {
3111 const XPathExpression& currentExpression = getExpression();
3112
3113 const OpCodeMapPositionType endStep = currentExpression.getNextOpCodePosition(opPos);
3114 OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(endStep);
3115
3116 bool fDoPredicates = true;
3117
3118 if(XPathExpression::eENDOP != nextStepType)
3119 {
3120 // Continue step via recursion...
3121 context = stepPattern(
3122 executionContext,
3123 context,
3124 endStep,
3125 scoreHolder);
3126
3127 if(0 == context)
3128 {
3129 scoreHolder = eMatchScoreNone;
3130
3131 }
3132
3133 if (scoreHolder == eMatchScoreNone)
3134 {
3135 // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
3136 return 0;
3137 }
3138
3139 scoreHolder = eMatchScoreOther;
3140
3141 if (nextStepType != XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL)
3142 {
3143 context = DOMServices::getParentOfNode(*context);
3144 }
3145
3146 if(0 == context)
3147 {
3148 // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
3149 return 0;
3150 }
3151 }
3152
3153 assert(context != 0);
3154
3155 OpCodeMapValueType argLen = 0;
3156
3157 eMatchScore score = eMatchScoreNone;
3158
3159 const OpCodeMapPositionType startOpPos = opPos;
3160 const OpCodeMapValueType stepType =
3161 currentExpression.getOpCodeMapValue(opPos);
3162
3163 switch(stepType)
3164 {
3165 case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL:
3166 score = scoreHolder;
3167 break;
3168
3169 case XPathExpression::eOP_FUNCTION:
3170 {
3171 argLen = currentExpression.getOpCodeLengthFromOpMap(opPos,
3172 executionContext.getMemoryManager());
3173
3174 const XObjectPtr obj(executeMore(context, opPos, executionContext));
3175 assert(obj.get() != 0);
3176
3177 const NodeRefListBase& nl = obj->nodeset();
3178
3179 const NodeRefListBase::size_type len = nl.getLength();
3180
3181 if (nextStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL)
3182 {
3183 bool fFound = false;
3184
3185 while(context != 0 && fFound == false)
3186 {
3187 for(NodeRefListBase::size_type i = 0; i < len; i++)
3188 {
3189 XalanNode* const n = nl.item(i);
3190
3191 if(n == context)
3192 {
3193 score = eMatchScoreOther;
3194
3195 context = n;
3196
3197 fFound = true;
3198
3199 break;
3200 }
3201 }
3202
3203 context = DOMServices::getParentOfNode(*context);
3204 }
3205 }
3206 else
3207 {
3208 for(NodeRefListBase::size_type i = 0; i < len; i++)
3209 {
3210 XalanNode* const n = nl.item(i);
3211
3212 if(n == context)
3213 {
3214 score = eMatchScoreOther;
3215
3216 context = n;
3217
3218 break;
3219 }
3220 }
3221 }
3222 }
3223 break;
3224
3225 case XPathExpression::eFROM_ROOT:
3226 {
3227 argLen = currentExpression.getOpCodeArgumentLength(opPos);
3228
3229 opPos += 3;
3230
3231 const XalanNode::NodeType nodeType = context->getNodeType();
3232
3233 if (nodeType == XalanNode::DOCUMENT_NODE ||
3234 nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
3235 {
3236 score = eMatchScoreOther;
3237 }
3238 else
3239 {
3240 const OpCodeMapPositionType prevPos = currentExpression.getNextOpCodePosition(startOpPos);
3241 const OpCodeMapValueType prevStepType = currentExpression.getOpCodeMapValue(prevPos);
3242
3243 if (eMatchScoreNone == score &&
3244 (prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR ||
3245 prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE))
3246 {
3247 const NodeTester theTester(
3248 *this,
3249 executionContext,
3250 opPos,
3251 argLen,
3252 stepType);
3253
3254 while(0 != context)
3255 {
3256 score =
3257 theTester(*context, context->getNodeType());
3258
3259 if(eMatchScoreNone != score)
3260 break;
3261
3262 context = DOMServices::getParentOfNode(*context);
3263 }
3264 }
3265 }
3266 }
3267 break;
3268
3269 case XPathExpression::eMATCH_ATTRIBUTE:
3270 {
3271 argLen = currentExpression.getOpCodeArgumentLength(opPos);
3272
3273 opPos += 3;
3274
3275 score = NodeTester(
3276 *this,
3277 executionContext,
3278 opPos,
3279 argLen,
3280 XPathExpression::eFROM_ATTRIBUTES)(*context, context->getNodeType());
3281 }
3282 break;
3283
3284 case XPathExpression::eMATCH_ANY_ANCESTOR:
3285 case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
3286 {
3287 assert(fDoPredicates == true);
3288 fDoPredicates = false;
3289
3290 argLen = currentExpression.getOpCodeArgumentLength(opPos);
3291
3292 XalanNode::NodeType nodeType = context->getNodeType();
3293
3294 if(nodeType != XalanNode::ATTRIBUTE_NODE)
3295 {
3296 opPos += 3;
3297
3298 const NodeTester theTester(
3299 *this,
3300 executionContext,
3301 opPos,
3302 argLen,
3303 stepType);
3304
3305 for(;;)
3306 {
3307 score = theTester(*context, nodeType);
3308
3309 if (eMatchScoreNone != score)
3310 {
3311 score =
3312 doStepPredicate(
3313 executionContext,
3314 context,
3315 opPos + argLen,
3316 startOpPos,
3317 score);
3318 if (eMatchScoreNone != score)
3319 {
3320 break;
3321 }
3322 }
3323
3324 context = DOMServices::getParentOfNode(*context);
3325
3326 if (context == 0)
3327 break;
3328
3329 nodeType = context->getNodeType();
3330 }
3331 }
3332 }
3333 break;
3334
3335 case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
3336 {
3337 argLen = currentExpression.getOpCodeArgumentLength(opPos);
3338
3339 const XalanNode::NodeType nodeType = context->getNodeType();
3340
3341 if(nodeType != XalanNode::ATTRIBUTE_NODE)
3342 {
3343 opPos += 3;
3344
3345 score = NodeTester(
3346 *this,
3347 executionContext,
3348 opPos,
3349 argLen,
3350 XPathExpression::eMATCH_IMMEDIATE_ANCESTOR)(*context, nodeType);
3351 }
3352 }
3353 break;
3354
3355 default:
3356 {
3357 const GetCachedString theGuard1(executionContext);
3358 const GetCachedString theGuard2(executionContext);
3359
3360 executionContext.problem(
3361 XPathExecutionContext::eXPath,
3362 XPathExecutionContext::eError,
3363 XalanMessageLoader::getMessage(
3364 theGuard1.get(),
3365 XalanMessages::UnknownMatchOpCode_1Param,
3366 NumberToDOMString(
3367 stepType,
3368 theGuard2.get())),
3369 getLocator(),
3370 context);
3371
3372 break;
3373 }
3374 }
3375
3376 if (fDoPredicates == true && score != eMatchScoreNone)
3377 {
3378 score =
3379 doStepPredicate(
3380 executionContext,
3381 context,
3382 opPos + argLen,
3383 startOpPos,
3384 score);
3385 }
3386
3387 if (scoreHolder == eMatchScoreNone ||
3388 score == eMatchScoreNone)
3389 {
3390 scoreHolder = score;
3391 }
3392
3393 return score == eMatchScoreNone ? 0 : context;
3394 }
3395
3396
3397
3398 XPath::eMatchScore
handleFoundIndex(XPathExecutionContext & executionContext,XalanNode * localContext,OpCodeMapPositionType startOpPos) const3399 XPath::handleFoundIndex(
3400 XPathExecutionContext& executionContext,
3401 XalanNode* localContext,
3402 OpCodeMapPositionType startOpPos) const
3403 {
3404 // We have an index somewhere in our pattern. So, we have
3405 // to do a full search for our step, using the parent as
3406 // localContext, then see if the current localContext is found in the
3407 // node set. Seems crazy, but, so far, it seems like the
3408 // easiest way.
3409 XalanNode* const parentContext =
3410 DOMServices::getParentOfNode(*localContext);
3411
3412 if (parentContext == 0)
3413 {
3414 return eMatchScoreNone;
3415 }
3416 else
3417 {
3418 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
3419
3420 BorrowReturnMutableNodeRefList mnl(executionContext);
3421
3422 step(executionContext, parentContext, startOpPos, *mnl);
3423
3424 if (mnl->indexOf(localContext) == MutableNodeRefList::npos)
3425 {
3426 return eMatchScoreNone;
3427 }
3428 else
3429 {
3430 return eMatchScoreOther;
3431 }
3432 }
3433 }
3434
3435
3436
3437 XPath::eMatchScore
handleFoundIndexPositional(XPathExecutionContext & executionContext,XalanNode * localContext,OpCodeMapPositionType startOpPos) const3438 XPath::handleFoundIndexPositional(
3439 XPathExecutionContext& executionContext,
3440 XalanNode* localContext,
3441 OpCodeMapPositionType startOpPos) const
3442 {
3443 XalanNode* const parentContext =
3444 DOMServices::getParentOfNode(*localContext);
3445
3446 if (parentContext == 0)
3447 {
3448 return eMatchScoreNone;
3449 }
3450 else
3451 {
3452 typedef XPathExecutionContext::BorrowReturnMutableNodeRefList BorrowReturnMutableNodeRefList;
3453
3454 BorrowReturnMutableNodeRefList mnl(executionContext);
3455
3456 step(executionContext, parentContext, startOpPos, *mnl);
3457
3458 if (mnl->empty() == true)
3459 {
3460 return eMatchScoreNone;
3461 }
3462 else
3463 {
3464 assert(mnl->getLength() == 1 && mnl->item(0) == localContext);
3465
3466 return eMatchScoreOther;
3467 }
3468 }
3469 }
3470
3471
3472
3473 XPath::OpCodeMapPositionType
findNodeSet(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType,MutableNodeRefList & subQueryResults) const3474 XPath::findNodeSet(
3475 XPathExecutionContext& executionContext,
3476 XalanNode* context,
3477 OpCodeMapPositionType opPos,
3478 OpCodeMapValueType /* stepType */,
3479 MutableNodeRefList& subQueryResults) const
3480 {
3481 assert(subQueryResults.empty() == true);
3482
3483 const XObjectPtr nodesetResult(executeMore(context, opPos, executionContext, subQueryResults));
3484
3485 if (nodesetResult.null() == true)
3486 {
3487 assert(subQueryResults.getDocumentOrder());
3488 }
3489 else
3490 {
3491 subQueryResults.addNodesInDocOrder(nodesetResult->nodeset(), executionContext);
3492
3493 subQueryResults.setDocumentOrder();
3494 }
3495
3496 return opPos + getExpression().getOpCodeLengthFromOpMap(opPos, executionContext.getMemoryManager());
3497 }
3498
3499
3500
3501 XPath::OpCodeMapPositionType
findRoot(XPathExecutionContext &,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType,MutableNodeRefList & subQueryResults) const3502 XPath::findRoot(
3503 XPathExecutionContext& /* executionContext */,
3504 XalanNode* context,
3505 OpCodeMapPositionType opPos,
3506 OpCodeMapValueType /* stepType */,
3507 MutableNodeRefList& subQueryResults) const
3508 {
3509 assert(context != 0);
3510 assert(subQueryResults.empty() == true);
3511
3512 const XPathExpression& currentExpression = getExpression();
3513
3514 const OpCodeMapValueType argLen =
3515 currentExpression.getOpCodeArgumentLength(opPos);
3516
3517 XalanNode::NodeType nodeType =
3518 context->getNodeType();
3519
3520 XalanNode* docContext =
3521 nodeType == XalanNode::DOCUMENT_NODE ?
3522 context :
3523 context->getOwnerDocument();
3524
3525 // This is a special case for RTFs, as the "owner document" is
3526 // just a factory for the RTF. Instead, we have to search for
3527 // the containing XalanDocumentFragment node.
3528 if (static_cast<const XalanDocument*>(docContext)->getDocumentElement() == 0)
3529 {
3530 docContext = context;
3531
3532 for(;;)
3533 {
3534 if (nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
3535 {
3536 break;
3537 }
3538 else
3539 {
3540 docContext =
3541 DOMServices::getParentOfNode(*docContext);
3542 assert(docContext != 0);
3543
3544 nodeType = docContext->getNodeType();
3545
3546 }
3547 }
3548 }
3549
3550 assert(docContext != 0);
3551
3552 subQueryResults.addNode(docContext);
3553
3554 subQueryResults.setDocumentOrder();
3555
3556 return opPos + argLen + 3;
3557 }
3558
3559
3560
3561 XPath::OpCodeMapPositionType
findParent(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3562 XPath::findParent(
3563 XPathExecutionContext& executionContext,
3564 XalanNode* context,
3565 OpCodeMapPositionType opPos,
3566 OpCodeMapValueType stepType,
3567 MutableNodeRefList& subQueryResults) const
3568 {
3569 assert(subQueryResults.empty() == true);
3570 assert(context != 0);
3571
3572 const XPathExpression& currentExpression = getExpression();
3573
3574 const OpCodeMapValueType argLen =
3575 currentExpression.getOpCodeArgumentLength(opPos);
3576
3577 XalanNode* const theParent = DOMServices::getParentOfNode(*context);
3578
3579 opPos += 3;
3580
3581 if(0 != theParent)
3582 {
3583 if(argLen > 0)
3584 {
3585 const NodeTester theTester(
3586 *this,
3587 executionContext,
3588 opPos,
3589 argLen,
3590 stepType);
3591
3592 const eMatchScore score = theTester(*theParent, theParent->getNodeType());
3593
3594 if(eMatchScoreNone != score)
3595 {
3596 subQueryResults.addNode(theParent);
3597 }
3598 }
3599 else
3600 {
3601 subQueryResults.addNode(theParent);
3602 }
3603 }
3604
3605 subQueryResults.setDocumentOrder();
3606
3607 return opPos + argLen;
3608 }
3609
3610
3611
3612 XPath::OpCodeMapPositionType
findSelf(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3613 XPath::findSelf(
3614 XPathExecutionContext& executionContext,
3615 XalanNode* context,
3616 OpCodeMapPositionType opPos,
3617 OpCodeMapValueType stepType,
3618 MutableNodeRefList& subQueryResults) const
3619 {
3620 assert(subQueryResults.empty() == true);
3621 assert(context != 0);
3622
3623 const XPathExpression& currentExpression = getExpression();
3624
3625 const OpCodeMapValueType argLen =
3626 currentExpression.getOpCodeArgumentLength(opPos);
3627
3628 opPos += 3;
3629
3630 if(argLen == 0)
3631 {
3632 subQueryResults.addNode(context);
3633 }
3634 else
3635 {
3636 const NodeTester theTester(
3637 *this,
3638 executionContext,
3639 opPos,
3640 argLen,
3641 stepType);
3642
3643 const eMatchScore score =
3644 theTester(*context, context->getNodeType());
3645
3646 if(eMatchScoreNone != score)
3647 {
3648 subQueryResults.addNode(context);
3649 }
3650 }
3651
3652 subQueryResults.setDocumentOrder();
3653
3654 return opPos + argLen;
3655 }
3656
3657
3658
3659 XPath::OpCodeMapPositionType
findAncestors(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3660 XPath::findAncestors(
3661 XPathExecutionContext& executionContext,
3662 XalanNode* context,
3663 OpCodeMapPositionType opPos,
3664 OpCodeMapValueType stepType,
3665 MutableNodeRefList& subQueryResults) const
3666 {
3667 assert(subQueryResults.empty() == true);
3668 assert(context != 0);
3669
3670 context = DOMServices::getParentOfNode(*context);
3671
3672 const XPathExpression& currentExpression = getExpression();
3673
3674 const OpCodeMapValueType argLen =
3675 currentExpression.getOpCodeArgumentLength(opPos);
3676
3677 opPos += 3;
3678
3679 if (context != 0)
3680 {
3681 const NodeTester theTester(
3682 *this,
3683 executionContext,
3684 opPos,
3685 argLen,
3686 stepType);
3687
3688 do
3689 {
3690 const eMatchScore score =
3691 theTester(*context, context->getNodeType());
3692
3693 if(eMatchScoreNone != score)
3694 {
3695 subQueryResults.addNode(context);
3696 }
3697
3698 context = DOMServices::getParentOfNode(*context);
3699 } while(0 != context);
3700 }
3701
3702 subQueryResults.setReverseDocumentOrder();
3703
3704 return opPos + argLen;
3705 }
3706
3707
3708
3709 XPath::OpCodeMapPositionType
findAncestorsOrSelf(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3710 XPath::findAncestorsOrSelf(
3711 XPathExecutionContext& executionContext,
3712 XalanNode* context,
3713 OpCodeMapPositionType opPos,
3714 OpCodeMapValueType stepType,
3715 MutableNodeRefList& subQueryResults) const
3716 {
3717 assert(subQueryResults.empty() == true);
3718 assert(context != 0);
3719
3720 const XPathExpression& currentExpression = getExpression();
3721
3722 const OpCodeMapValueType argLen =
3723 currentExpression.getOpCodeArgumentLength(opPos);
3724
3725 opPos += 3;
3726
3727 const NodeTester theTester(
3728 *this,
3729 executionContext,
3730 opPos,
3731 argLen,
3732 stepType);
3733
3734 do
3735 {
3736 const eMatchScore score =
3737 theTester(*context, context->getNodeType());
3738
3739 if(eMatchScoreNone != score)
3740 {
3741 subQueryResults.addNode(context);
3742 }
3743
3744 context = DOMServices::getParentOfNode(*context);
3745 } while(0 != context);
3746
3747 subQueryResults.setReverseDocumentOrder();
3748
3749 return opPos + argLen;
3750 }
3751
3752
3753
3754 XPath::OpCodeMapPositionType
findAttributes(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3755 XPath::findAttributes(
3756 XPathExecutionContext& executionContext,
3757 XalanNode* context,
3758 OpCodeMapPositionType opPos,
3759 OpCodeMapValueType stepType,
3760 MutableNodeRefList& subQueryResults) const
3761 {
3762 assert(subQueryResults.empty() == true);
3763 assert(context != 0);
3764
3765 const XPathExpression& currentExpression = getExpression();
3766
3767 const OpCodeMapValueType argLen =
3768 currentExpression.getOpCodeArgumentLength(opPos);
3769
3770 opPos += 3;
3771
3772 if(context->getNodeType() == XalanNode::ELEMENT_NODE)
3773 {
3774 const XalanNamedNodeMap* const attributeList = context->getAttributes();
3775
3776 if(attributeList != 0)
3777 {
3778 const XalanSize_t nAttrs = attributeList->getLength();
3779
3780 if (nAttrs != 0)
3781 {
3782 const NodeTester theTester(
3783 *this,
3784 executionContext,
3785 opPos,
3786 argLen,
3787 stepType);
3788
3789 for (XalanSize_t j = 0; j < nAttrs; j++)
3790 {
3791 XalanNode* const theNode = attributeList->item(j);
3792 assert(theNode != 0 && theNode->getNodeType() == XalanNode::ATTRIBUTE_NODE);
3793
3794 const eMatchScore score =
3795 theTester(*theNode, XalanNode::ATTRIBUTE_NODE);
3796
3797 if(eMatchScoreNone != score)
3798 {
3799 subQueryResults.addNode(theNode);
3800 }
3801 }
3802 }
3803 }
3804 }
3805
3806 subQueryResults.setDocumentOrder();
3807
3808 return opPos + argLen;
3809 }
3810
3811
3812
3813 XPath::OpCodeMapPositionType
findChildren(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3814 XPath::findChildren(
3815 XPathExecutionContext& executionContext,
3816 XalanNode* context,
3817 OpCodeMapPositionType opPos,
3818 OpCodeMapValueType stepType,
3819 MutableNodeRefList& subQueryResults) const
3820 {
3821 assert(subQueryResults.empty() == true);
3822 assert(context != 0);
3823
3824 XalanNode* child = context->getFirstChild();
3825
3826 const XPathExpression& currentExpression = getExpression();
3827
3828 const OpCodeMapValueType argLen =
3829 currentExpression.getOpCodeArgumentLength(opPos);
3830
3831 opPos += 3;
3832
3833 if (child != 0)
3834 {
3835 const NodeTester theTester(
3836 *this,
3837 executionContext,
3838 opPos,
3839 argLen,
3840 stepType);
3841
3842 do
3843 {
3844 const eMatchScore score =
3845 theTester(*child, child->getNodeType());
3846
3847 if(eMatchScoreNone != score)
3848 {
3849 subQueryResults.addNode(child);
3850 }
3851
3852 child = child->getNextSibling();
3853 } while(0 != child);
3854 }
3855
3856 subQueryResults.setDocumentOrder();
3857
3858 return opPos + argLen;
3859 }
3860
3861
3862
3863 XPath::OpCodeMapPositionType
findDescendants(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3864 XPath::findDescendants(
3865 XPathExecutionContext& executionContext,
3866 XalanNode* context,
3867 OpCodeMapPositionType opPos,
3868 OpCodeMapValueType stepType,
3869 MutableNodeRefList& subQueryResults) const
3870 {
3871 assert(subQueryResults.empty() == true);
3872 assert(context != 0);
3873
3874 const XPathExpression& currentExpression = getExpression();
3875
3876 const OpCodeMapValueType argLen =
3877 currentExpression.getOpCodeArgumentLength(opPos);
3878
3879 // Perform a pre-order traversal of descendents...
3880 XalanNode* pos = context;
3881
3882 opPos += 3;
3883
3884 const NodeTester theTester(
3885 *this,
3886 executionContext,
3887 opPos,
3888 argLen,
3889 stepType);
3890
3891 do
3892 {
3893 if(stepType == XPathExpression::eFROM_DESCENDANTS_OR_SELF ||
3894 context != pos)
3895 {
3896 const eMatchScore score =
3897 theTester(*pos, pos->getNodeType());
3898
3899 if(score != eMatchScoreNone)
3900 {
3901 subQueryResults.addNode(pos);
3902 }
3903 }
3904
3905 XalanNode* nextNode = pos->getFirstChild();
3906
3907 while(0 == nextNode)
3908 {
3909 if(context == pos)
3910 break;
3911
3912 nextNode = pos->getNextSibling();
3913
3914 if(0 == nextNode)
3915 {
3916 pos = DOMServices::getParentOfNode(*pos);
3917
3918 if(context == pos || pos == 0)
3919 {
3920 nextNode = 0;
3921 break;
3922 }
3923 }
3924 }
3925
3926 pos = nextNode;
3927 } while(0 != pos);
3928
3929 subQueryResults.setDocumentOrder();
3930
3931 return opPos + argLen;
3932 }
3933
3934
3935
3936 XPath::OpCodeMapPositionType
findFollowing(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const3937 XPath::findFollowing(
3938 XPathExecutionContext& executionContext,
3939 XalanNode* context,
3940 OpCodeMapPositionType opPos,
3941 OpCodeMapValueType stepType,
3942 MutableNodeRefList& subQueryResults) const
3943 {
3944 assert(subQueryResults.empty() == true);
3945 assert(context != 0);
3946
3947 const XPathExpression& currentExpression = getExpression();
3948
3949 const OpCodeMapValueType argLen =
3950 currentExpression.getOpCodeArgumentLength(opPos);
3951
3952 opPos += 3;
3953
3954 // What fun...
3955 XalanDocument* const doc = context->getOwnerDocument();
3956
3957 XalanNode* pos = context;
3958
3959 const NodeTester theTester(
3960 *this,
3961 executionContext,
3962 opPos,
3963 argLen,
3964 stepType);
3965
3966 while(0 != pos)
3967 {
3968 XalanNode* nextNode = 0;
3969
3970 if(pos != context)
3971 {
3972 const eMatchScore score =
3973 theTester(*pos, pos->getNodeType());
3974
3975 if(eMatchScoreNone != score)
3976 {
3977 subQueryResults.addNodeInDocOrder(pos, executionContext);
3978 }
3979
3980 nextNode = pos->getFirstChild();
3981 }
3982 else
3983 {
3984 nextNode = 0;
3985 }
3986
3987 while(0 == nextNode)
3988 {
3989 // This requires some explanation. pos could be an attribute
3990 // node, so getNextSibling() will always return 0. In that
3991 // case, I want to continue the search with the first child of
3992 // the owner element, as if attribute nodes are children which
3993 // are always _before_ the first child element. I don't have to
3994 // consider following attributes, since they _never_ match the
3995 // following axis.
3996 if (pos->getNodeType() == XalanNode::ATTRIBUTE_NODE)
3997 {
3998 assert(DOMServices::getParentOfNode(*pos) != 0);
3999
4000 nextNode = DOMServices::getParentOfNode(*pos)->getFirstChild();
4001 }
4002 else
4003 {
4004 nextNode = pos->getNextSibling();
4005 }
4006
4007 if(0 == nextNode)
4008 {
4009 pos = DOMServices::getParentOfNode(*pos);
4010
4011 if(doc == pos || 0 == pos)
4012 {
4013 nextNode = 0;
4014
4015 break;
4016 }
4017 }
4018 }
4019
4020 pos = nextNode;
4021 }
4022
4023 subQueryResults.setDocumentOrder();
4024
4025 return opPos + argLen;
4026 }
4027
4028
4029
4030 XPath::OpCodeMapPositionType
findFollowingSiblings(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const4031 XPath::findFollowingSiblings(
4032 XPathExecutionContext& executionContext,
4033 XalanNode* context,
4034 OpCodeMapPositionType opPos,
4035 OpCodeMapValueType stepType,
4036 MutableNodeRefList& subQueryResults) const
4037 {
4038 assert(subQueryResults.empty() == true);
4039 assert(context != 0);
4040
4041 const XPathExpression& currentExpression = getExpression();
4042
4043 const OpCodeMapValueType argLen =
4044 currentExpression.getOpCodeArgumentLength(opPos);
4045
4046 XalanNode* pos = context->getNextSibling();
4047
4048 opPos += 3;
4049
4050 if (pos != 0)
4051 {
4052 const NodeTester theTester(
4053 *this,
4054 executionContext,
4055 opPos,
4056 argLen,
4057 stepType);
4058
4059 do
4060 {
4061 const eMatchScore score =
4062 theTester(*pos, pos->getNodeType());
4063
4064 if(eMatchScoreNone != score)
4065 {
4066 subQueryResults.addNode(pos);
4067 }
4068
4069 pos = pos->getNextSibling();
4070 } while(0 != pos);
4071 }
4072
4073 subQueryResults.setDocumentOrder();
4074
4075 return opPos + argLen;
4076 }
4077
4078
4079
4080 /*
4081 * This is bit of a hack to figure out where we should start for
4082 * the preceeding axis. It's mostly to support RTFs which have
4083 * been coerced to nodesets through the nodeset() extension function.
4084 */
4085 static XalanNode*
findTopNode(XalanNode * context,XalanNode::NodeType theType)4086 findTopNode(
4087 XalanNode* context,
4088 XalanNode::NodeType theType)
4089 {
4090 assert(context != 0);
4091
4092 if (theType == XalanNode::DOCUMENT_NODE)
4093 {
4094 return context;
4095 }
4096 else
4097 {
4098 XalanDocument* const theDocument = context->getOwnerDocument();
4099 assert(theDocument != 0);
4100
4101 if (theDocument->getDocumentElement() != 0)
4102 {
4103 return theDocument;
4104 }
4105 else
4106 {
4107 XalanNode* theNode = 0;
4108
4109 while(context != 0 &&
4110 context->getNodeType() != XalanNode::DOCUMENT_NODE)
4111 {
4112 theNode = context;
4113
4114 context = DOMServices::getParentOfNode(*context);
4115 }
4116
4117 assert(theNode != 0);
4118
4119 return theNode;
4120 }
4121 }
4122 }
4123
4124
4125
4126 XPath::OpCodeMapPositionType
findPreceeding(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const4127 XPath::findPreceeding(
4128 XPathExecutionContext& executionContext,
4129 XalanNode* context,
4130 OpCodeMapPositionType opPos,
4131 OpCodeMapValueType stepType,
4132 MutableNodeRefList& subQueryResults) const
4133 {
4134 assert(subQueryResults.empty() == true);
4135 assert(context != 0);
4136
4137 const XPathExpression& currentExpression = getExpression();
4138
4139 const OpCodeMapValueType argLen =
4140 currentExpression.getOpCodeArgumentLength(opPos);
4141
4142 opPos += 3;
4143
4144 // Ugh. Reverse document order, no parents, I guess.
4145 const XalanNode::NodeType theType = context->getNodeType();
4146
4147 XalanNode* const topNode = findTopNode(context, theType);
4148
4149 XalanNode* pos = topNode;
4150
4151 // If the context node is an attribute, we need to perform some
4152 // magic to stop the search at the appropriate point, which is when
4153 // we arrive back at the parent.
4154 const bool contextIsAttribute =
4155 theType == XalanNode::ATTRIBUTE_NODE ? true : false;
4156
4157 const XalanNode* const theAttributeContextParent =
4158 contextIsAttribute == true ? DOMServices::getParentOfNode(*context) : 0;
4159
4160 const NodeTester theTester(
4161 *this,
4162 executionContext,
4163 opPos,
4164 argLen,
4165 stepType);
4166
4167 while(0 != pos)
4168 {
4169 if(context == pos)
4170 {
4171 break;
4172 }
4173
4174 const eMatchScore score =
4175 theTester(*pos, pos->getNodeType());
4176
4177 if(eMatchScoreNone != score)
4178 {
4179 // Ugh. If I could think a little better tonight, I'm
4180 // sure there's a better way to check for the parent.
4181 bool isParent = false;
4182
4183 XalanNode* parent = DOMServices::getParentOfNode(*context);
4184
4185 while(0 != parent)
4186 {
4187 if(parent == pos)
4188 {
4189 isParent = true;
4190 break;
4191 }
4192
4193 parent = DOMServices::getParentOfNode(*parent);
4194 }
4195
4196 if(isParent == false)
4197 {
4198 subQueryResults.addNode(pos);
4199 }
4200 }
4201
4202 XalanNode* nextNode = 0;
4203
4204 // Check to see if we're back at the attribute context node's
4205 // parent, in which case, we should stop.
4206 if (contextIsAttribute == true &&
4207 pos == theAttributeContextParent)
4208 {
4209 nextNode = context;
4210 }
4211 else
4212 {
4213 nextNode = pos->getFirstChild();
4214 }
4215
4216 while(0 == nextNode)
4217 {
4218 nextNode = pos->getNextSibling();
4219
4220 if(0 == nextNode)
4221 {
4222 pos = DOMServices::getParentOfNode(*pos);
4223
4224 if(topNode == pos)
4225 {
4226 nextNode = 0;
4227 break;
4228 }
4229 }
4230 }
4231
4232 pos = nextNode;
4233 }
4234
4235 // Now, reverse the order of the nodes, since
4236 // preceeding is a reverse axis, and we searched
4237 // the document from the root to this node.
4238 subQueryResults.reverse();
4239
4240 subQueryResults.setReverseDocumentOrder();
4241
4242 return opPos + argLen;
4243 }
4244
4245
4246
4247 XPath::OpCodeMapPositionType
findPreceedingSiblings(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const4248 XPath::findPreceedingSiblings(
4249 XPathExecutionContext& executionContext,
4250 XalanNode* context,
4251 OpCodeMapPositionType opPos,
4252 OpCodeMapValueType stepType,
4253 MutableNodeRefList& subQueryResults) const
4254 {
4255 assert(subQueryResults.empty() == true);
4256 assert(context != 0);
4257
4258 const XPathExpression& currentExpression = getExpression();
4259
4260 const OpCodeMapValueType argLen =
4261 currentExpression.getOpCodeArgumentLength(opPos);
4262
4263 opPos += 3;
4264
4265 #if 1
4266 XalanNode* pos = context->getPreviousSibling();
4267
4268 if (pos != 0)
4269 {
4270 const NodeTester theTester(
4271 *this,
4272 executionContext,
4273 opPos,
4274 argLen,
4275 stepType);
4276
4277 do
4278 {
4279 const eMatchScore score =
4280 theTester(*pos, pos->getNodeType());
4281
4282 if(eMatchScoreNone != score)
4283 {
4284 subQueryResults.addNode(pos);
4285 }
4286
4287 pos = pos->getPreviousSibling();
4288 } while(0 != pos);
4289 }
4290 #else
4291 // This is some experimental code which avoids using getPreviousSibling(), with the idea that we
4292 // could reduce our in-memory representation size by not keeping the previous sibling node.
4293 XalanNode* pos = context->getParentNode();
4294
4295 if (pos != 0)
4296 {
4297 pos = pos->getFirstChild();
4298
4299 if (pos != context)
4300 {
4301 const NodeTester theTester(
4302 *this,
4303 executionContext,
4304 opPos,
4305 argLen,
4306 stepType);
4307
4308 do
4309 {
4310 const eMatchScore score =
4311 theTester(*pos, pos->getNodeType());
4312
4313 if(eMatchScoreNone != score)
4314 {
4315 subQueryResults.addNode(pos);
4316 }
4317
4318 pos = pos->getNextSibling();
4319 } while(pos != context);
4320 }
4321
4322 // Now, reverse the order of the nodes, since
4323 // preceeding-sibling is a reverse axis, and we searched
4324 // the document from the root to this node.
4325 subQueryResults.reverse();
4326 }
4327 #endif
4328
4329 subQueryResults.setReverseDocumentOrder();
4330
4331 return opPos + argLen;
4332 }
4333
4334
4335
4336 XPath::OpCodeMapPositionType
findNamespace(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList & subQueryResults) const4337 XPath::findNamespace(
4338 XPathExecutionContext& executionContext,
4339 XalanNode* context,
4340 OpCodeMapPositionType opPos,
4341 OpCodeMapValueType stepType,
4342 MutableNodeRefList& subQueryResults) const
4343 {
4344 assert(subQueryResults.empty() == true);
4345 assert(context != 0);
4346
4347 const XPathExpression& currentExpression = getExpression();
4348
4349 const OpCodeMapValueType argLen =
4350 currentExpression.getOpCodeArgumentLength(opPos);
4351
4352 opPos += 3;
4353
4354 if(context->getNodeType() == XalanNode::ELEMENT_NODE)
4355 {
4356 // Look up the element chain until we hit the document, so that we
4357 // get all of the attribute/namespace nodes.
4358 const XalanNode* const theOwnerDocument = context->getOwnerDocument();
4359 assert(theOwnerDocument != 0);
4360
4361 const XalanNode* theCurrentNode = context;
4362
4363 const NodeTester theTester(
4364 *this,
4365 executionContext,
4366 opPos,
4367 argLen,
4368 stepType);
4369
4370 NodeRefListBase::size_type nNSFound = 0;
4371 bool defaultNSFound = false;
4372
4373 do
4374 {
4375 const XalanNamedNodeMap* const attributeList =
4376 theCurrentNode->getAttributes();
4377
4378 if(attributeList != 0)
4379 {
4380 XalanSize_t nAttrs = attributeList->getLength();
4381
4382 while (nAttrs > 0)
4383 {
4384 --nAttrs;
4385
4386 XalanNode* const attr = attributeList->item(nAttrs);
4387 assert(attr != 0 && attr->getNodeType() == XalanNode::ATTRIBUTE_NODE);
4388
4389 const XalanDOMString& theNodeName = attr->getNodeName();
4390
4391 // This is an optimization to keep non-namespace attributes out of
4392 // the call to the NodeTester.
4393 if (startsWith(theNodeName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
4394 theNodeName == DOMServices::s_XMLNamespace)
4395 {
4396 const eMatchScore score =
4397 theTester(*attr, XalanNode::ATTRIBUTE_NODE);
4398
4399 if(score != eMatchScoreNone)
4400 {
4401 const XalanDOMString& theNodeValue = attr->getNodeValue();
4402
4403 bool foundNSMatch = false;
4404
4405 // Need to check default NS slightly differently
4406 if (theNodeName == DOMServices::s_XMLNamespace)
4407 {
4408 // If namespace is empty, don't add anything
4409 // as under XPath an empty default is indicated
4410 // by no node.
4411
4412 foundNSMatch = defaultNSFound ||
4413 (theNodeValue == DOMServices::s_emptyString);
4414 defaultNSFound = true;
4415 }
4416
4417 for (NodeRefListBase::size_type lstIndex = 0;
4418 foundNSMatch == false && lstIndex < nNSFound;
4419 ++lstIndex)
4420 {
4421 if (subQueryResults.item(lstIndex)->getNodeName() == theNodeName)
4422 {
4423 foundNSMatch = true;
4424 }
4425 }
4426
4427 if (foundNSMatch == false)
4428 {
4429 subQueryResults.addNode(attr);
4430 ++nNSFound;
4431 }
4432 }
4433 }
4434 }
4435 }
4436
4437 theCurrentNode = theCurrentNode->getParentNode();
4438 } while (theCurrentNode != theOwnerDocument && theCurrentNode != 0);
4439 }
4440
4441 subQueryResults.reverse();
4442
4443 subQueryResults.setDocumentOrder();
4444
4445 return opPos + argLen;
4446 }
4447
4448
4449
4450 XPath::OpCodeMapPositionType
findNodesOnUnknownAxis(XPathExecutionContext & executionContext,XalanNode * context,OpCodeMapPositionType opPos,OpCodeMapValueType stepType,MutableNodeRefList &) const4451 XPath::findNodesOnUnknownAxis(
4452 XPathExecutionContext& executionContext,
4453 XalanNode* context,
4454 OpCodeMapPositionType opPos,
4455 OpCodeMapValueType stepType,
4456 MutableNodeRefList& /* subQueryResults */) const
4457 {
4458 const XPathExpression& currentExpression = getExpression();
4459
4460 const OpCodeMapValueType argLen =
4461 currentExpression.getOpCodeArgumentLength(opPos);
4462
4463 const GetCachedString theGuard1(executionContext);
4464 const GetCachedString theGuard2(executionContext);
4465
4466 executionContext.problem(
4467 XPathExecutionContext::eXPath,
4468 XPathExecutionContext::eError,
4469 XalanMessageLoader::getMessage(
4470 theGuard1.get(),
4471 XalanMessages::UnknownAxis_1Param,
4472 NumberToDOMString(
4473 stepType,
4474 theGuard2.get())),
4475 getLocator(),
4476 context);
4477
4478 return opPos + argLen + 3;
4479 }
4480
4481
4482
4483 XPath::OpCodeMapPositionType
predicates(XPathExecutionContext & executionContext,OpCodeMapPositionType opPos,MutableNodeRefList & subQueryResults) const4484 XPath::predicates(
4485 XPathExecutionContext& executionContext,
4486 OpCodeMapPositionType opPos,
4487 MutableNodeRefList& subQueryResults) const
4488 {
4489 assert(&executionContext.getContextNodeList() == &subQueryResults);
4490
4491 const XPathExpression& currentExpression = getExpression();
4492
4493 assert(currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE ||
4494 currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE_WITH_POSITION);
4495
4496 NodeRefListBase::size_type theLength = subQueryResults.getLength();
4497
4498 for(;;)
4499 {
4500 // If we have no nodes left, then there's no point in executing any
4501 // predicates. However, we will continue to loop, since we need to
4502 // update endPredicatePos.
4503 if (theLength > 0)
4504 {
4505 const OpCodeMapPositionType predOpPos = opPos + 2;
4506
4507 // OK, this is a huge hack/optimization. If the predicate is
4508 // simple a number, such as [2], we can just get the
4509 // numeric value from the expression, and not bother executing
4510 // the predicate. Furthermore, we don't need to execute the
4511 // predicate for each node, since the evaluation is no dependent
4512 // on the context node. All we really have to do is remove all
4513 // nodes from subQueryResults, _except_ for the node at that
4514 // position. The only trick is that XPath indexes from 1, while
4515 // our node lists index from 0.
4516 if (m_expression.getOpCodeMapValue(predOpPos) == XPathExpression::eOP_NUMBERLIT)
4517 {
4518 assert(m_expression.tokenQueueSize() > m_expression.getOpCodeMapValue(predOpPos + 3));
4519
4520 // Get the value of the number...
4521 const double theIndex =
4522 m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(predOpPos + 2));
4523
4524 // If the index is out of range, or not an integer, just clear subQueryResults...
4525 if (theIndex <= 0.0 ||
4526 NodeRefListBase::size_type(theIndex) > theLength ||
4527 double(NodeRefListBase::size_type(theIndex)) != theIndex)
4528 {
4529 subQueryResults.clear();
4530 }
4531 else if (theLength > 1)
4532 {
4533 // Save the matching node...
4534 XalanNode* const theNode =
4535 subQueryResults.item(NodeRefListBase::size_type(theIndex) - 1);
4536
4537 // Clear the list...
4538 subQueryResults.clear();
4539
4540 // Add the node back in...
4541 subQueryResults.addNode(theNode);
4542
4543 subQueryResults.setDocumentOrder();
4544 }
4545 else
4546 {
4547 // OK, if there's only 1 node in the list, then
4548 // we don't need to bother modifying the list.
4549 // Just assert that theIndex == 1.0...
4550 assert(theIndex == 1.0);
4551 }
4552 }
4553 else
4554 {
4555 for(NodeRefListBase::size_type i = 0; i < theLength; ++i)
4556 {
4557 XalanNode* const theNode = subQueryResults.item(i);
4558 assert(theNode != 0);
4559
4560 const XObjectPtr pred(predicate(theNode, opPos, executionContext));
4561 assert(pred.get() != 0);
4562
4563 // Remove any node that doesn't satisfy the predicate.
4564 if((XObject::eTypeNumber == pred->getType() && i + 1 != pred->num(executionContext)) ||
4565 pred->boolean(executionContext) == false)
4566 {
4567 // Set the node to 0. After we're done,
4568 // we'll clear it out.
4569 subQueryResults.setNode(i, 0);
4570 }
4571 }
4572
4573 // Clear out any null entries...
4574 subQueryResults.clearNulls();
4575 }
4576 }
4577
4578 opPos = currentExpression.getNextOpCodePosition(opPos);
4579
4580 const OpCodeMapValueType nextStepType = currentExpression.getOpCodeMapValue(opPos);
4581
4582 if (nextStepType != XPathExpression::eOP_PREDICATE &&
4583 nextStepType != XPathExpression::eOP_PREDICATE_WITH_POSITION)
4584 {
4585 break;
4586 }
4587 else
4588 {
4589 theLength = subQueryResults.getLength();
4590 }
4591 }
4592
4593 return opPos;
4594 }
4595
4596
4597
NodeTester(const NodeTester & theSource)4598 XPath::NodeTester::NodeTester(const NodeTester& theSource) :
4599 m_executionContext(theSource.m_executionContext),
4600 m_targetNamespace(theSource.m_targetNamespace),
4601 m_targetLocalName(theSource.m_targetLocalName),
4602 m_testFunction(theSource.m_testFunction),
4603 m_testFunction2(theSource.m_testFunction2)
4604 {
4605 }
4606
4607
4608
NodeTester(const XPath & xpath,XPathExecutionContext & executionContext,OpCodeMapPositionType opPos,OpCodeMapValueType argLen,OpCodeMapValueType stepType)4609 XPath::NodeTester::NodeTester(
4610 const XPath& xpath,
4611 XPathExecutionContext& executionContext,
4612 OpCodeMapPositionType opPos,
4613 OpCodeMapValueType argLen,
4614 OpCodeMapValueType stepType) :
4615 m_executionContext(&executionContext),
4616 m_targetNamespace(0),
4617 m_targetLocalName(0),
4618 m_testFunction(0),
4619 m_testFunction2(&NodeTester::testDefault2)
4620 {
4621 const XPathExpression& theExpression = xpath.getExpression();
4622
4623 switch(theExpression.getOpCodeMapValue(opPos))
4624 {
4625 case XPathExpression::eNODETYPE_COMMENT:
4626 m_testFunction = &NodeTester::testComment;
4627 break;
4628
4629 case XPathExpression::eNODETYPE_TEXT:
4630 m_testFunction = &NodeTester::testText;
4631 break;
4632
4633 case XPathExpression::eNODETYPE_PI:
4634 if (argLen == 1)
4635 {
4636 m_testFunction = &NodeTester::testPI;
4637 }
4638 else if(argLen == 2)
4639 {
4640 m_testFunction = &NodeTester::testPIName;
4641
4642 m_targetLocalName = getStringFromTokenQueue(
4643 theExpression,
4644 opPos + 1);
4645 }
4646 else
4647 {
4648 GetCachedString theGuard(executionContext);
4649
4650 executionContext.problem(
4651 XPathExecutionContext::eXPath,
4652 XPathExecutionContext::eError,
4653 XalanMessageLoader::getMessage(
4654 theGuard.get(),
4655 XalanMessages::ArgLengthNodeTestIsIncorrect_1Param,
4656 "processing-instruction()"),
4657 xpath.getLocator(),
4658 executionContext.getCurrentNode());
4659 }
4660 break;
4661
4662 case XPathExpression::eNODETYPE_NODE:
4663 m_testFunction = &NodeTester::testNode;
4664 break;
4665
4666 case XPathExpression::eNODETYPE_ROOT:
4667 m_testFunction = &NodeTester::testRoot;
4668 break;
4669
4670 case XPathExpression::eNODENAME:
4671 {
4672 bool isTotallyWild = false;
4673
4674 m_targetNamespace = getStringFromTokenQueue(
4675 theExpression,
4676 opPos + 1);
4677
4678 if (m_targetNamespace == 0 &&
4679 theExpression.getOpCodeMapValue(opPos + 2) == XPathExpression::eELEMWILDCARD)
4680 {
4681 isTotallyWild = true;
4682 }
4683 else
4684 {
4685 m_targetLocalName = getStringFromTokenQueue(
4686 theExpression,
4687 opPos + 2);
4688 }
4689
4690 if(stepType == XPathExpression::eFROM_ATTRIBUTES)
4691 {
4692 if (isTotallyWild == true)
4693 {
4694 m_testFunction = &NodeTester::testAttributeTotallyWild;
4695 }
4696 else if (m_targetNamespace == 0)
4697 {
4698 assert(m_targetLocalName != 0);
4699
4700 m_testFunction = &NodeTester::testAttributeNCName;
4701 }
4702 else if (m_targetLocalName == 0)
4703 {
4704 assert(m_targetNamespace != 0);
4705
4706 m_testFunction = &NodeTester::testAttributeNamespaceOnly;
4707 }
4708 else
4709 {
4710 assert(m_targetNamespace != 0 && m_targetLocalName != 0);
4711
4712
4713 m_testFunction = &NodeTester::testAttributeQName;
4714 }
4715 }
4716 else if (stepType == XPathExpression::eFROM_NAMESPACE)
4717 {
4718 if (isTotallyWild == true)
4719 {
4720 m_testFunction = &NodeTester::testNamespaceTotallyWild;
4721 }
4722 else
4723 {
4724 m_testFunction = &NodeTester::testNamespaceNCName;
4725 }
4726 }
4727 else
4728 {
4729 if (isTotallyWild == true)
4730 {
4731 m_testFunction = &NodeTester::testElementTotallyWild;
4732 }
4733 else if (m_targetNamespace == 0)
4734 {
4735 m_testFunction = &NodeTester::testElementNCName;
4736 }
4737 else if (m_targetLocalName == 0)
4738 {
4739 assert(m_targetNamespace != 0);
4740
4741 m_testFunction = &NodeTester::testElementNamespaceOnly;
4742 }
4743 else
4744 {
4745 assert(m_targetNamespace != 0 && m_targetLocalName != 0);
4746
4747 m_testFunction = &NodeTester::testElementQName;
4748 }
4749 }
4750 }
4751 break;
4752
4753 default:
4754 m_testFunction = &NodeTester::testDefault;
4755 break;
4756 }
4757
4758 assert(m_testFunction != 0);
4759 }
4760
4761
4762
NodeTester()4763 XPath::NodeTester::NodeTester() :
4764 m_executionContext(0),
4765 m_targetNamespace(0),
4766 m_targetLocalName(0),
4767 m_testFunction(&NodeTester::testDefault),
4768 m_testFunction2(&NodeTester::testDefault2)
4769 {
4770 }
4771
4772
4773
NodeTester(XPathConstructionContext & theConstructionContext,const XalanDOMString & theNameTest,const PrefixResolver & thePrefixResolver,const Locator * theLocator,eMatchScore * theMatchScore)4774 XPath::NodeTester::NodeTester(
4775 XPathConstructionContext& theConstructionContext,
4776 const XalanDOMString& theNameTest,
4777 const PrefixResolver& thePrefixResolver,
4778 const Locator* theLocator,
4779 eMatchScore* theMatchScore) :
4780 m_executionContext(0),
4781 m_targetNamespace(0),
4782 m_targetLocalName(0),
4783 m_testFunction(&NodeTester::testDefault),
4784 m_testFunction2(&NodeTester::testDefault2)
4785 {
4786 const eMatchScore theScore =
4787 initialize(
4788 theConstructionContext,
4789 theNameTest,
4790 thePrefixResolver,
4791 theLocator);
4792
4793 if (theMatchScore != 0)
4794 {
4795 *theMatchScore = theScore;
4796 }
4797 }
4798
4799
4800
NodeTester(const XalanDOMString & theNamespaceURI,const XalanDOMString & theLocalName,eMatchScore * theMatchScore)4801 XPath::NodeTester::NodeTester(
4802 const XalanDOMString& theNamespaceURI,
4803 const XalanDOMString& theLocalName,
4804 eMatchScore* theMatchScore) :
4805 m_executionContext(0),
4806 m_targetNamespace(0),
4807 m_targetLocalName(0),
4808 m_testFunction(&NodeTester::testDefault),
4809 m_testFunction2(0)
4810 {
4811 const eMatchScore theScore =
4812 initialize(theNamespaceURI, theLocalName);
4813
4814 if (theMatchScore != 0)
4815 {
4816 *theMatchScore = theScore;
4817 }
4818 }
4819
4820
4821
4822 XPath::eMatchScore
initialize(XPathConstructionContext & theConstructionContext,const XalanDOMString & theNameTest,const PrefixResolver & thePrefixResolver,const Locator * theLocator)4823 XPath::NodeTester::initialize(
4824 XPathConstructionContext& theConstructionContext,
4825 const XalanDOMString& theNameTest,
4826 const PrefixResolver& thePrefixResolver,
4827 const Locator* theLocator)
4828 {
4829 const XalanDOMString::size_type theLength =
4830 theNameTest.length();
4831
4832 if (theLength == 1 && theNameTest[0] == XPath::PSEUDONAME_ANY[0])
4833 {
4834 return initialize(s_emptyString, s_emptyString);
4835 }
4836 else
4837 {
4838 eMatchScore theResult = eMatchScoreNone;
4839
4840 const XalanDOMString::size_type theIndex =
4841 indexOf(theNameTest, XalanUnicode::charColon);
4842
4843 // If there's no ':', it's an NCName...
4844 if (theIndex == theLength)
4845 {
4846 if (XalanQName::isValidNCName(theNameTest) == false)
4847 {
4848 const XPathConstructionContext::GetCachedString theGuard(theConstructionContext);
4849
4850 theConstructionContext.problem(
4851 XPathConstructionContext::eXPath,
4852 XPathConstructionContext::eError,
4853 XalanMessageLoader::getMessage(
4854 theGuard.get(),
4855 XalanMessages::IsNotValidQName_1Param,
4856 theNameTest),
4857 theLocator,
4858 0);
4859 }
4860 else
4861 {
4862 theResult = initialize(
4863 s_emptyString,
4864 theConstructionContext.getPooledString(theNameTest));
4865 }
4866 }
4867 else
4868 {
4869 const XPathConstructionContext::GetCachedString scratchGuard(theConstructionContext);
4870
4871 XalanDOMString& theScratchString = scratchGuard.get();
4872
4873 theScratchString.assign(theNameTest, 0, theIndex);
4874
4875 // Get the namespace URI for the prefix...
4876 const XalanDOMString* const theNamespaceURI =
4877 thePrefixResolver.getNamespaceForPrefix(theScratchString);
4878
4879 if (theNamespaceURI == 0)
4880 {
4881 theConstructionContext.problem(
4882 XPathConstructionContext::eXPath,
4883 XPathConstructionContext::eError,
4884 XalanMessageLoader::getMessage(
4885 theScratchString,
4886 XalanMessages::PrefixIsNotDeclared_1Param),
4887 theLocator,
4888 0);
4889 }
4890 else
4891 {
4892 // OK, now we have a namespace URI...
4893 if (XalanQName::isValidNCName(theScratchString) == false)
4894 {
4895 theConstructionContext.problem(
4896 XPathConstructionContext::eXPath,
4897 XPathConstructionContext::eError,
4898 XalanMessageLoader::getMessage(
4899 theScratchString,
4900 XalanMessages::IsNotValidQName_1Param,
4901 theNameTest),
4902 theLocator,
4903 0);
4904 }
4905 else if (theIndex == theLength - 2 &&
4906 theNameTest[theIndex + 1] == XPath::PSEUDONAME_ANY[0])
4907 {
4908 // It's of the form "NCName:*"
4909 theResult = initialize(
4910 theConstructionContext.getPooledString(*theNamespaceURI),
4911 s_emptyString);
4912 }
4913 else
4914 {
4915 theScratchString.assign(theNameTest, theIndex + 1, theLength - theIndex - 1);
4916
4917 if (XalanQName::isValidNCName(theScratchString) == false)
4918 {
4919 theConstructionContext.problem(
4920 XPathConstructionContext::eXPath,
4921 XPathConstructionContext::eError,
4922 XalanMessageLoader::getMessage(
4923 theScratchString,
4924 XalanMessages::IsNotValidQName_1Param,
4925 theNameTest),
4926 theLocator,
4927 0);
4928 }
4929 else
4930 {
4931 // It's of the form "NCName:NCName"
4932 theResult = initialize(
4933 theConstructionContext.getPooledString(*theNamespaceURI),
4934 theConstructionContext.getPooledString(theScratchString));
4935 }
4936 }
4937 }
4938 }
4939
4940 return theResult;
4941 }
4942 }
4943
4944
4945
4946 XPath::eMatchScore
initialize(const XalanDOMString & theNamespaceURI,const XalanDOMString & theLocalName)4947 XPath::NodeTester::initialize(
4948 const XalanDOMString& theNamespaceURI,
4949 const XalanDOMString& theLocalName)
4950 {
4951 if (theNamespaceURI.empty() == false)
4952 {
4953 m_targetNamespace = &theNamespaceURI;
4954
4955 if (theLocalName.empty() == true)
4956 {
4957 m_testFunction2 = &NodeTester::testElementNamespaceOnly2;
4958
4959 return eMatchScoreNSWild;
4960 }
4961 else
4962 {
4963 m_testFunction2 = &NodeTester::testElementQName2;
4964
4965 m_targetLocalName = &theLocalName;
4966
4967 return eMatchScoreQName;
4968 }
4969 }
4970 else if (theLocalName.empty() == false)
4971 {
4972 m_testFunction2 = &NodeTester::testElementNCName2;
4973
4974 m_targetLocalName = &theLocalName;
4975
4976 return eMatchScoreQName;
4977 }
4978 else
4979 {
4980 m_testFunction2 = &NodeTester::testElementTotallyWild2;
4981
4982 return eMatchScoreNodeTest;
4983 }
4984 }
4985
4986
4987
4988 inline bool
isNamespaceDeclaration(const XalanNode & theAttributeNode)4989 isNamespaceDeclaration(const XalanNode& theAttributeNode)
4990 {
4991 assert(theAttributeNode.getNodeType() == XalanNode::ATTRIBUTE_NODE);
4992
4993 return DOMServices::isNamespaceDeclaration(static_cast<const XalanAttr&>(theAttributeNode));
4994 }
4995
4996
4997
4998 // MSVC 6 generates some really horrible code for some of these very simple functions when they're inlined...
4999 #if defined(_MSC_VER) && _MSC_VER <= 1300 && !defined(__INTEL_COMPILER)
5000 #pragma auto_inline(off)
5001 #endif
5002
5003 XPath::eMatchScore
testComment(const XalanNode &,XalanNode::NodeType nodeType) const5004 XPath::NodeTester::testComment(
5005 const XalanNode& /* context */,
5006 XalanNode::NodeType nodeType) const
5007 {
5008 if (XalanNode::COMMENT_NODE == nodeType)
5009 {
5010 return eMatchScoreNodeTest;
5011 }
5012 else
5013 {
5014 return eMatchScoreNone;
5015 }
5016 }
5017
5018
5019
5020 XPath::eMatchScore
testText(const XalanNode & context,XalanNode::NodeType nodeType) const5021 XPath::NodeTester::testText(
5022 const XalanNode& context,
5023 XalanNode::NodeType nodeType) const
5024 {
5025 if (XalanNode::TEXT_NODE == nodeType &&
5026 shouldStripSourceNode(static_cast<const XalanText&>(context)) == false)
5027 {
5028 return eMatchScoreNodeTest;
5029 }
5030 else
5031 {
5032 return eMatchScoreNone;
5033 }
5034 }
5035
5036
5037
5038 XPath::eMatchScore
testPI(const XalanNode &,XalanNode::NodeType nodeType) const5039 XPath::NodeTester::testPI(
5040 const XalanNode& /* context */,
5041 XalanNode::NodeType nodeType) const
5042 {
5043 if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType)
5044 {
5045 return eMatchScoreNodeTest;
5046 }
5047 else
5048 {
5049 return eMatchScoreNone;
5050 }
5051 }
5052
5053
5054
5055 XPath::eMatchScore
testPIName(const XalanNode & context,XalanNode::NodeType nodeType) const5056 XPath::NodeTester::testPIName(
5057 const XalanNode& context,
5058 XalanNode::NodeType nodeType) const
5059 {
5060 assert(m_targetLocalName != 0);
5061
5062 if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType &&
5063 context.getNodeName() == *m_targetLocalName)
5064 {
5065 return eMatchScoreQName;
5066 }
5067 else
5068 {
5069 return eMatchScoreNone;
5070 }
5071 }
5072
5073
5074
5075 XPath::eMatchScore
testNode(const XalanNode & context,XalanNode::NodeType nodeType) const5076 XPath::NodeTester::testNode(
5077 const XalanNode& context,
5078 XalanNode::NodeType nodeType) const
5079 {
5080 if (nodeType != XalanNode::TEXT_NODE ||
5081 shouldStripSourceNode(static_cast<const XalanText&>(context)) == false)
5082 {
5083 return eMatchScoreNodeTest;
5084 }
5085 else
5086 {
5087 return eMatchScoreNone;
5088 }
5089 }
5090
5091
5092
5093 XPath::eMatchScore
testRoot(const XalanNode &,XalanNode::NodeType nodeType) const5094 XPath::NodeTester::testRoot(
5095 const XalanNode& /* context */,
5096 XalanNode::NodeType nodeType) const
5097 {
5098 if (XalanNode::DOCUMENT_NODE == nodeType ||
5099 XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType)
5100 {
5101 return eMatchScoreOther;
5102 }
5103 else
5104 {
5105 return eMatchScoreNone;
5106 }
5107 }
5108
5109
5110
5111 XPath::eMatchScore
testAttributeNCName(const XalanNode & context,XalanNode::NodeType nodeType) const5112 XPath::NodeTester::testAttributeNCName(
5113 const XalanNode& context,
5114 XalanNode::NodeType nodeType) const
5115 {
5116 assert(m_targetNamespace == 0 && m_targetLocalName != 0);
5117
5118 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5119 isNamespaceDeclaration(context) == true ||
5120 matchLocalName(context) == false)
5121 {
5122 return eMatchScoreNone;
5123 }
5124 else
5125 {
5126 return eMatchScoreQName;
5127 }
5128 }
5129
5130 inline bool
matchLocalNameAndNamespaceURI(const XalanNode & context) const5131 XPath::NodeTester::matchLocalNameAndNamespaceURI(const XalanNode& context) const
5132 {
5133 assert(m_targetNamespace != 0 && m_targetLocalName != 0);
5134
5135 return DOMServices::getLocalNameOfNode(context) == *m_targetLocalName &&
5136 context.getNamespaceURI() == *m_targetNamespace;
5137 }
5138
5139
5140 XPath::eMatchScore
testAttributeQName(const XalanNode & context,XalanNode::NodeType nodeType) const5141 XPath::NodeTester::testAttributeQName(
5142 const XalanNode& context,
5143 XalanNode::NodeType nodeType) const
5144 {
5145 assert(m_targetNamespace != 0 && m_targetLocalName != 0);
5146
5147 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5148 isNamespaceDeclaration(context) == true ||
5149 matchLocalNameAndNamespaceURI(context) == false)
5150 {
5151 return eMatchScoreNone;
5152 }
5153 else
5154 {
5155 return eMatchScoreQName;
5156 }
5157 }
5158
5159
5160
5161 XPath::eMatchScore
testAttributeNamespaceOnly(const XalanNode & context,XalanNode::NodeType nodeType) const5162 XPath::NodeTester::testAttributeNamespaceOnly(
5163 const XalanNode& context,
5164 XalanNode::NodeType nodeType) const
5165 {
5166 assert(m_targetNamespace != 0 && m_targetLocalName == 0);
5167
5168 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5169 isNamespaceDeclaration(context) == true ||
5170 matchNamespaceURI(context) == false)
5171 {
5172 return eMatchScoreNone;
5173 }
5174 else
5175 {
5176 return eMatchScoreNSWild;
5177 }
5178 }
5179
5180
5181
5182 XPath::eMatchScore
testAttributeTotallyWild(const XalanNode & context,XalanNode::NodeType nodeType) const5183 XPath::NodeTester::testAttributeTotallyWild(
5184 const XalanNode& context,
5185 XalanNode::NodeType nodeType) const
5186 {
5187 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5188 isNamespaceDeclaration(context) == true)
5189 {
5190 return eMatchScoreNone;
5191 }
5192 else
5193 {
5194 return eMatchScoreNodeTest;
5195 }
5196 }
5197
5198
5199
5200 XPath::eMatchScore
testElementNCName(const XalanNode & context,XalanNode::NodeType nodeType) const5201 XPath::NodeTester::testElementNCName(
5202 const XalanNode& context,
5203 XalanNode::NodeType nodeType) const
5204 {
5205 assert(m_targetNamespace == 0 && m_targetLocalName != 0);
5206
5207 if (XalanNode::ELEMENT_NODE != nodeType ||
5208 matchLocalName(context) == false)
5209 {
5210 return eMatchScoreNone;
5211 }
5212 else
5213 {
5214 return eMatchScoreQName;
5215 }
5216 }
5217
5218
5219
5220 XPath::eMatchScore
testElementQName(const XalanNode & context,XalanNode::NodeType nodeType) const5221 XPath::NodeTester::testElementQName(
5222 const XalanNode& context,
5223 XalanNode::NodeType nodeType) const
5224 {
5225 assert(m_targetNamespace != 0 && m_targetLocalName != 0);
5226
5227 if (XalanNode::ELEMENT_NODE != nodeType ||
5228 matchLocalNameAndNamespaceURI(context) == false)
5229 {
5230 return eMatchScoreNone;
5231 }
5232 else
5233 {
5234 return eMatchScoreQName;
5235 }
5236 }
5237
5238
5239
5240 XPath::eMatchScore
testElementNamespaceOnly(const XalanNode & context,XalanNode::NodeType nodeType) const5241 XPath::NodeTester::testElementNamespaceOnly(
5242 const XalanNode& context,
5243 XalanNode::NodeType nodeType) const
5244 {
5245 assert(m_targetNamespace != 0 && m_targetLocalName == 0);
5246
5247 if (XalanNode::ELEMENT_NODE != nodeType ||
5248 matchNamespaceURI(context) == false)
5249 {
5250 return eMatchScoreNone;
5251 }
5252 else
5253 {
5254 return eMatchScoreNSWild;
5255 }
5256 }
5257
5258
5259
5260 XPath::eMatchScore
testElementTotallyWild(const XalanNode &,XalanNode::NodeType nodeType) const5261 XPath::NodeTester::testElementTotallyWild(
5262 const XalanNode& /* context */,
5263 XalanNode::NodeType nodeType) const
5264 {
5265 assert(m_targetNamespace == 0 && m_targetLocalName == 0);
5266
5267 if (XalanNode::ELEMENT_NODE != nodeType)
5268 {
5269 return eMatchScoreNone;
5270 }
5271 else
5272 {
5273 return eMatchScoreNodeTest;
5274 }
5275 }
5276
5277
5278
5279 XPath::eMatchScore
testElementNCName2(const XalanElement & context) const5280 XPath::NodeTester::testElementNCName2(const XalanElement& context) const
5281 {
5282 assert(
5283 m_targetNamespace == 0 &&
5284 m_targetLocalName != 0);
5285
5286 if (matchLocalName(context) == false)
5287 {
5288 return eMatchScoreNone;
5289 }
5290 else
5291 {
5292 return eMatchScoreQName;
5293 }
5294 }
5295
5296
5297
5298 XPath::eMatchScore
testElementQName2(const XalanElement & context) const5299 XPath::NodeTester::testElementQName2(const XalanElement& context) const
5300 {
5301 assert(
5302 m_targetNamespace != 0 &&
5303 m_targetLocalName != 0);
5304
5305 if (matchLocalNameAndNamespaceURI(context) == false)
5306 {
5307 return eMatchScoreNone;
5308 }
5309 else
5310 {
5311 return eMatchScoreQName;
5312 }
5313 }
5314
5315
5316
5317 XPath::eMatchScore
testElementNamespaceOnly2(const XalanElement & context) const5318 XPath::NodeTester::testElementNamespaceOnly2(const XalanElement& context) const
5319 {
5320 assert(
5321 m_targetNamespace != 0 &&
5322 m_targetLocalName == 0);
5323
5324 if (matchNamespaceURI(context) == false)
5325 {
5326 return eMatchScoreNone;
5327 }
5328 else
5329 {
5330 return eMatchScoreNSWild;
5331 }
5332 }
5333
5334
5335
5336 XPath::eMatchScore
testElementTotallyWild2(const XalanElement &) const5337 XPath::NodeTester::testElementTotallyWild2(const XalanElement& /* context */) const
5338 {
5339 assert(
5340 m_targetNamespace == 0 &&
5341 m_targetLocalName == 0);
5342
5343 return eMatchScoreNodeTest;
5344 }
5345
5346
5347
5348 XPath::eMatchScore
testNamespaceNCName(const XalanNode & context,XalanNode::NodeType nodeType) const5349 XPath::NodeTester::testNamespaceNCName(
5350 const XalanNode& context,
5351 XalanNode::NodeType nodeType) const
5352 {
5353 assert(m_targetNamespace == 0 && m_targetLocalName != 0);
5354
5355 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5356 isNamespaceDeclaration(context) == false ||
5357 matchNamespace(context) == false)
5358 {
5359 return eMatchScoreNone;
5360 }
5361 else
5362 {
5363 return eMatchScoreQName;
5364 }
5365 }
5366
5367
5368
5369 XPath::eMatchScore
testNamespaceTotallyWild(const XalanNode & context,XalanNode::NodeType nodeType) const5370 XPath::NodeTester::testNamespaceTotallyWild(
5371 const XalanNode& context,
5372 XalanNode::NodeType nodeType) const
5373 {
5374 assert(m_targetNamespace == 0 && m_targetLocalName == 0);
5375
5376 if (XalanNode::ATTRIBUTE_NODE != nodeType ||
5377 isNamespaceDeclaration(context) == false)
5378 {
5379 return eMatchScoreNone;
5380 }
5381 else
5382 {
5383 return eMatchScoreNodeTest;
5384 }
5385 }
5386
5387
5388
5389 XPath::eMatchScore
testDefault(const XalanNode &,XalanNode::NodeType) const5390 XPath::NodeTester::testDefault(
5391 const XalanNode& /* context */,
5392 XalanNode::NodeType /* nodeType */) const
5393 {
5394 return eMatchScoreNone;
5395 }
5396
5397
5398
5399 XPath::eMatchScore
testDefault2(const XalanElement &) const5400 XPath::NodeTester::testDefault2(const XalanElement& /* context */) const
5401 {
5402 return eMatchScoreNone;
5403 }
5404
5405
5406
5407 bool
matchLocalName(const XalanNode & context) const5408 XPath::NodeTester::matchLocalName(const XalanNode& context) const
5409 {
5410 assert(m_targetLocalName != 0);
5411
5412 return context.getNamespaceURI().empty() == true &&
5413 DOMServices::getLocalNameOfNode(context) == *m_targetLocalName;
5414 }
5415
5416
5417
5418 bool
matchNamespaceURI(const XalanNode & context) const5419 XPath::NodeTester::matchNamespaceURI(const XalanNode& context) const
5420 {
5421 assert(m_targetNamespace != 0);
5422
5423 return context.getNamespaceURI() == *m_targetNamespace;
5424 }
5425
5426
5427 bool
matchNamespace(const XalanNode & context) const5428 XPath::NodeTester::matchNamespace(const XalanNode& context) const
5429 {
5430 assert(m_targetLocalName != 0);
5431
5432 return context.getLocalName() == *m_targetLocalName;
5433 }
5434
5435
5436
5437 bool
shouldStripSourceNode(const XalanText & context) const5438 XPath::NodeTester::shouldStripSourceNode(const XalanText& context) const
5439 {
5440 assert(m_executionContext != 0);
5441
5442 return m_executionContext->shouldStripSourceNode(context);
5443 }
5444
5445
5446
5447 const XalanDOMChar XPath::PSEUDONAME_ANY[] =
5448 {
5449 XalanUnicode::charAsterisk,
5450 0
5451 };
5452
5453 const XalanDOMChar XPath::PSEUDONAME_ROOT[] =
5454 {
5455 XalanUnicode::charSolidus,
5456 0
5457 };
5458
5459 const XalanDOMChar XPath::PSEUDONAME_TEXT[] =
5460 {
5461 XalanUnicode::charNumberSign,
5462 XalanUnicode::charLetter_t,
5463 XalanUnicode::charLetter_e,
5464 XalanUnicode::charLetter_x,
5465 XalanUnicode::charLetter_t,
5466 0
5467 };
5468
5469 const XalanDOMChar XPath::PSEUDONAME_COMMENT[] =
5470 {
5471 XalanUnicode::charNumberSign,
5472 XalanUnicode::charLetter_c,
5473 XalanUnicode::charLetter_o,
5474 XalanUnicode::charLetter_m,
5475 XalanUnicode::charLetter_m,
5476 XalanUnicode::charLetter_e,
5477 XalanUnicode::charLetter_n,
5478 XalanUnicode::charLetter_t,
5479 0
5480 };
5481
5482 const XalanDOMChar XPath::PSEUDONAME_PI[] =
5483 {
5484 XalanUnicode::charNumberSign,
5485 XalanUnicode::charLetter_p,
5486 XalanUnicode::charLetter_i,
5487 0
5488 };
5489
5490 const XalanDOMChar XPath::PSEUDONAME_OTHER[] =
5491 {
5492 XalanUnicode::charAsterisk,
5493 0
5494 };
5495
5496 const XalanDOMChar XPath::PSEUDONAME_NODE[] =
5497 {
5498 XalanUnicode::charNumberSign,
5499 XalanUnicode::charLetter_n,
5500 XalanUnicode::charLetter_o,
5501 XalanUnicode::charLetter_d,
5502 XalanUnicode::charLetter_e,
5503 0
5504 };
5505
5506
5507
5508 // Don't auto-create the table...
5509
5510 XPath::FunctionTableType XPath::s_functions(false);
5511
5512
5513
5514 void
initialize(MemoryManager & theManager)5515 XPath::initialize(MemoryManager& theManager)
5516 {
5517 s_functions.setMemoryManager(theManager);
5518
5519 s_functions.CreateTable();
5520 }
5521
5522
5523
5524 void
terminate()5525 XPath::terminate()
5526 {
5527 s_functions.DestroyTable();
5528 }
5529
5530
5531
5532 }
5533