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