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 // Class header file.
19 #include "XPathExpression.hpp"
20 
21 
22 
23 #include <algorithm>
24 #include <cstdio>
25 
26 
27 
28 #include <ostream>
29 
30 
31 
32 #include <xalanc/PlatformSupport/DoubleSupport.hpp>
33 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
34 
35 
36 
37 #include "XObjectTypeCallback.hpp"
38 
39 
40 
41 namespace XALAN_CPP_NAMESPACE {
42 
43 
44 
45 
46 
47 // This is an array which indicates which of the value defined by
48 // XPathExpression::eOpCodes are node tests.
49 static const bool   theNodeTestOpCodesArray[] =
50 {
51     false, false, true,  false, false, false, false, false, false, false,
52     false, false, false, false, false, false, false, false, false, false,
53     false, false, false, false, false, false, false, false, false, false,
54     false, false, false, false, true,  true,  true,  true,  true,  true,
55     true,  true,  true,  true,  true,  true,  true,  false, false, false,
56     true,  true,  true
57 };
58 
59 static const XalanSize_t    theNodeTestOpCodesArraySize =
60         sizeof(theNodeTestOpCodesArray) / sizeof(theNodeTestOpCodesArray[0]);
61 
62 
63 // This is an array for all of the opcode defined by XPathExpression::eOpCodes.
64 // It is offset by 3, because there opcode values are -3, -2, and -1.  So,
65 // when getting the length of an opcode, we add three to get the correct index.
66 static const int    theOpCodeLengthArray[] =
67 {
68     1,
69     1,
70     1,
71 
72     0,
73     XPathExpression::s_opCodeMapLengthIndex + 1,
74     XPathExpression::s_opCodeMapLengthIndex + 1,
75     XPathExpression::s_opCodeMapLengthIndex + 1,
76     XPathExpression::s_opCodeMapLengthIndex + 1,
77     XPathExpression::s_opCodeMapLengthIndex + 1,
78     XPathExpression::s_opCodeMapLengthIndex + 1,
79     XPathExpression::s_opCodeMapLengthIndex + 1,
80     XPathExpression::s_opCodeMapLengthIndex + 1,
81     XPathExpression::s_opCodeMapLengthIndex + 1,
82 
83     XPathExpression::s_opCodeMapLengthIndex + 1,
84     XPathExpression::s_opCodeMapLengthIndex + 1,
85     XPathExpression::s_opCodeMapLengthIndex + 1,
86     XPathExpression::s_opCodeMapLengthIndex + 1,
87     XPathExpression::s_opCodeMapLengthIndex + 1,
88     XPathExpression::s_opCodeMapLengthIndex + 1,
89     XPathExpression::s_opCodeMapLengthIndex + 1,
90     XPathExpression::s_opCodeMapLengthIndex + 1,
91     XPathExpression::s_opCodeMapLengthIndex + 1,
92     XPathExpression::s_opCodeMapLengthIndex + 1,
93 
94     XPathExpression::s_opCodeMapLengthIndex + 1,
95     XPathExpression::s_opCodeMapLengthIndex + 1,
96     XPathExpression::s_opCodeMapLengthIndex + 1,
97     XPathExpression::s_opCodeMapLengthIndex + 3,
98     XPathExpression::s_opCodeMapLengthIndex + 3,
99     XPathExpression::s_opCodeMapLengthIndex + 1,
100     XPathExpression::s_opCodeMapLengthIndex + 1,
101     1,
102     1,
103 
104     1,
105     1,
106     1,
107     1,
108     1,
109     XPathExpression::s_opCodeMapLengthIndex + 2,
110     XPathExpression::s_opCodeMapLengthIndex + 2,
111     XPathExpression::s_opCodeMapLengthIndex + 2,
112     XPathExpression::s_opCodeMapLengthIndex + 2,
113     XPathExpression::s_opCodeMapLengthIndex + 2,
114 
115     XPathExpression::s_opCodeMapLengthIndex + 2,
116     XPathExpression::s_opCodeMapLengthIndex + 2,
117     XPathExpression::s_opCodeMapLengthIndex + 2,
118     XPathExpression::s_opCodeMapLengthIndex + 2,
119     XPathExpression::s_opCodeMapLengthIndex + 2,
120     XPathExpression::s_opCodeMapLengthIndex + 2,
121     XPathExpression::s_opCodeMapLengthIndex + 2,
122     XPathExpression::s_opCodeMapLengthIndex + 2,
123     XPathExpression::s_opCodeMapLengthIndex + 2,
124     XPathExpression::s_opCodeMapLengthIndex + 1,
125 
126     XPathExpression::s_opCodeMapLengthIndex + 1,
127     XPathExpression::s_opCodeMapLengthIndex + 1,
128     XPathExpression::s_opCodeMapLengthIndex + 1,
129     XPathExpression::s_opCodeMapLengthIndex + 1,
130     XPathExpression::s_opCodeMapLengthIndex + 2,
131     XPathExpression::s_opCodeMapLengthIndex + 2,
132     XPathExpression::s_opCodeMapLengthIndex + 1,
133     XPathExpression::s_opCodeMapLengthIndex + 1,
134     XPathExpression::s_opCodeMapLengthIndex + 1,
135     XPathExpression::s_opCodeMapLengthIndex + 1,
136     XPathExpression::s_opCodeMapLengthIndex + 1,
137     XPathExpression::s_opCodeMapLengthIndex + 1,
138     XPathExpression::s_opCodeMapLengthIndex + 1,
139     XPathExpression::s_opCodeMapLengthIndex + 1,
140     XPathExpression::s_opCodeMapLengthIndex + 1,
141     XPathExpression::s_opCodeMapLengthIndex + 1,
142     XPathExpression::s_opCodeMapLengthIndex + 1,
143     XPathExpression::s_opCodeMapLengthIndex + 1,
144     XPathExpression::s_opCodeMapLengthIndex + 1,
145     XPathExpression::s_opCodeMapLengthIndex + 1,
146     XPathExpression::s_opCodeMapLengthIndex + 1,
147     XPathExpression::s_opCodeMapLengthIndex + 1,
148     XPathExpression::s_opCodeMapLengthIndex + 1,
149     XPathExpression::s_opCodeMapLengthIndex + 1,
150     XPathExpression::s_opCodeMapLengthIndex + 1,
151     XPathExpression::s_opCodeMapLengthIndex + 1,
152     XPathExpression::s_opCodeMapLengthIndex + 1,
153     XPathExpression::s_opCodeMapLengthIndex + 1,
154     XPathExpression::s_opCodeMapLengthIndex + 1,
155     XPathExpression::s_opCodeMapLengthIndex + 1,
156     XPathExpression::s_opCodeMapLengthIndex + 1
157 };
158 
159 static const int    theOpCodeLengthArraySize =
160         sizeof(theOpCodeLengthArray) / sizeof(theOpCodeLengthArray[0]);
161 
162 
163 
164 inline int
getOpCodeLength(int theOpCode)165 getOpCodeLength(int     theOpCode)
166 {
167     assert(theOpCodeLengthArraySize == XPathExpression::eOpCodeNextAvailable + 3);
168 
169     // Add 3 to get the correct index into the array...
170     theOpCode += 3;
171 
172     if (theOpCode < 0 || theOpCode >= theOpCodeLengthArraySize)
173     {
174         return 0;
175     }
176     else
177     {
178         return theOpCodeLengthArray[theOpCode];
179     }
180 }
181 
182 
183 
XPathExpressionException(const XalanDOMString & theMessage,MemoryManager & theManager)184 XPathExpression::XPathExpressionException::XPathExpressionException(
185             const XalanDOMString&   theMessage,
186             MemoryManager&          theManager) :
187     XalanXPathException(theMessage, theManager)
188 {
189 }
190 
191 
192 
~XPathExpressionException()193 XPathExpression::XPathExpressionException::~XPathExpressionException()
194 {
195 }
196 
197 
198 
InvalidOpCodeException(OpCodeMapValueType theOpCode,XalanDOMString & theBuffer)199 XPathExpression::InvalidOpCodeException::InvalidOpCodeException(
200             OpCodeMapValueType  theOpCode,
201             XalanDOMString&     theBuffer) :
202     XPathExpressionException(
203         FormatErrorMessage(
204             theOpCode,
205             theBuffer),
206         theBuffer.getMemoryManager())
207 {
208 }
209 
210 
211 
~InvalidOpCodeException()212 XPathExpression::InvalidOpCodeException::~InvalidOpCodeException()
213 {
214 }
215 
216 
217 
218 XalanDOMString&
FormatErrorMessage(OpCodeMapValueType theOpCode,XalanDOMString & theBuffer)219 XPathExpression::InvalidOpCodeException::FormatErrorMessage(
220             OpCodeMapValueType  theOpCode,
221             XalanDOMString&     theBuffer)
222 {
223     XalanDOMString  theOpcode(theBuffer.getMemoryManager());
224 
225     NumberToDOMString(theOpCode, theOpcode);
226 
227     return XalanMessageLoader::getMessage(
228                 theBuffer,
229                 XalanMessages::InvalidOpcodeWasDetected_1Param,
230                 theOpcode);
231 }
232 
233 
234 
InvalidArgumentCountException(OpCodeMapValueType theOpCode,OpCodeMapValueType theExpectedCount,OpCodeMapValueType theSuppliedCount,XalanDOMString & theBuffer)235 XPathExpression::InvalidArgumentCountException::InvalidArgumentCountException(
236             OpCodeMapValueType  theOpCode,
237             OpCodeMapValueType  theExpectedCount,
238             OpCodeMapValueType  theSuppliedCount,
239             XalanDOMString&     theBuffer) :
240     XPathExpressionException(
241         FormatErrorMessage(
242             theOpCode,
243             theExpectedCount,
244             theSuppliedCount,
245             theBuffer),
246         theBuffer.getMemoryManager())
247 {
248 }
249 
250 
251 
~InvalidArgumentCountException()252 XPathExpression::InvalidArgumentCountException::~InvalidArgumentCountException()
253 {
254 }
255 
256 
257 
258 XalanDOMString&
FormatErrorMessage(OpCodeMapValueType theOpCode,OpCodeMapValueType theExpectedCount,OpCodeMapValueType theSuppliedCount,XalanDOMString & theBuffer)259 XPathExpression::InvalidArgumentCountException::FormatErrorMessage(
260             OpCodeMapValueType  theOpCode,
261             OpCodeMapValueType  theExpectedCount,
262             OpCodeMapValueType  theSuppliedCount,
263             XalanDOMString&     theBuffer)
264 {
265     XalanDOMString  theResult(theBuffer.getMemoryManager());
266 
267     NumberToDOMString(theOpCode, theResult);
268 
269     XalanDOMString  theResult1(theBuffer.getMemoryManager());
270     NumberToDOMString(theExpectedCount, theResult1);
271 
272     XalanDOMString  theResult2(theBuffer.getMemoryManager());
273     NumberToDOMString(theSuppliedCount, theResult2);
274 
275 
276     return XalanMessageLoader::getMessage(
277                 theBuffer,
278                 XalanMessages::InvalidNumberOfArgsWasDetected_3Param,
279                 theResult1,
280                 theResult2);
281 }
282 
283 
284 
InvalidArgumentException(OpCodeMapValueType theOpCode,OpCodeMapValueType theValue,XalanDOMString & theBuffer)285 XPathExpression::InvalidArgumentException::InvalidArgumentException(
286             OpCodeMapValueType  theOpCode,
287             OpCodeMapValueType  theValue,
288             XalanDOMString&     theBuffer) :
289     XPathExpressionException(
290         FormatErrorMessage(
291             theOpCode,
292             theValue,
293             theBuffer),
294         theBuffer.getMemoryManager())
295 {
296 }
297 
298 
299 
~InvalidArgumentException()300 XPathExpression::InvalidArgumentException::~InvalidArgumentException()
301 {
302 }
303 
304 
305 
306 XalanDOMString&
FormatErrorMessage(OpCodeMapValueType theOpCode,OpCodeMapValueType theValue,XalanDOMString & theBuffer)307 XPathExpression::InvalidArgumentException::FormatErrorMessage(
308                 OpCodeMapValueType  theOpCode,
309                 OpCodeMapValueType  theValue,
310                 XalanDOMString&     theBuffer)
311 {
312     XalanDOMString  theResult(theBuffer.getMemoryManager());
313     NumberToDOMString(theValue, theResult);
314 
315 
316     XalanDOMString  theResult1(theBuffer.getMemoryManager());
317     NumberToDOMString(theOpCode, theResult1);
318 
319     return XalanMessageLoader::getMessage(
320                 theBuffer,
321                 XalanMessages::InvalidNumberOfArgsWasSupplied_2Param,
322                 theResult1) ;
323 }
324 
325 
326 
327 static const XalanDOMString     s_emptyString(XalanMemMgrs::getDummyMemMgr());
328 
329 
330 
XPathExpression(MemoryManager & theManager)331 XPathExpression::XPathExpression(MemoryManager& theManager) :
332     m_opMap(theManager),
333     m_lastOpCodeIndex(0),
334     m_tokenQueue(theManager),
335     m_currentPosition(0),
336     m_currentPattern(&s_emptyString),
337     m_numberLiteralValues(theManager)
338 {
339     m_opMap.reserve(eDefaultOpMapSize);
340     m_tokenQueue.reserve(eDefaultTokenQueueSize);
341 }
342 
343 
344 
~XPathExpression()345 XPathExpression::~XPathExpression()
346 {
347     reset();
348 }
349 
350 
351 
352 void
reset()353 XPathExpression::reset()
354 {
355     m_opMap.clear();
356     m_tokenQueue.clear();
357 }
358 
359 
360 
361 void
shrink()362 XPathExpression::shrink()
363 {
364     if (m_opMap.capacity() > m_opMap.size())
365     {
366         OpCodeMapType tmp(m_opMap, m_opMap.getMemoryManager());
367 
368         tmp.swap(m_opMap);
369     }
370 }
371 
372 
373 
374 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
375 
376 XPathExpression::OpCodeMapValueType
getOpCodeLengthFromOpMap(OpCodeMapPositionType opPos,MemoryManager & theManager) const377 XPathExpression::getOpCodeLengthFromOpMap(
378             OpCodeMapPositionType   opPos,
379             MemoryManager&          theManager) const
380 {
381     assert(opPos - getInitialOpCodePosition() >= 0 &&
382            opPos - getInitialOpCodePosition() < opCodeMapSize());
383 
384     OpCodeMapValueType  theResult = 0;
385 
386     // Is there a valid opcode?
387     const int   theOpCodeLength = getOpCodeLength(*opPos);
388 
389     if (theOpCodeLength == 0)
390     {
391         XalanDOMString   theBuffer(theManager);
392 
393         throw InvalidOpCodeException(-1, theBuffer);
394     }
395     else
396     {
397         // Does the Op code have a length > 1?
398         if (theOpCodeLength > 1)
399         {
400             // Yes, so get the length.
401             theResult = *(opPos + s_opCodeMapLengthIndex);
402         }
403     }
404 
405     return theResult;
406 }
407 
408 #endif
409 
410 XPathExpression::OpCodeMapValueType
getOpCodeLengthFromOpMap(OpCodeMapSizeType theIndex,MemoryManager & theManager) const411 XPathExpression::getOpCodeLengthFromOpMap(
412 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
413             OpCodeMapSizeType       theIndex,
414 #else
415             OpCodeMapPositionType   theIndex,
416 #endif
417             MemoryManager&          theManager) const
418 {
419     OpCodeMapValueType  theResult = 0;
420 
421     if (theIndex >= opCodeMapSize())
422     {
423         XalanDOMString   theBuffer(theManager);
424 
425         throw InvalidOpCodeException(-1, theBuffer);
426     }
427     else
428     {
429         // Is there a valid opcode?
430         const int   theOpCodeLength = getOpCodeLength(m_opMap[theIndex]);
431 
432         if (theOpCodeLength == 0)
433         {
434             XalanDOMString   theBuffer(theManager);
435 
436             throw InvalidOpCodeException(-1, theBuffer);
437         }
438         else
439         {
440             // Does the Op code have a length > 1?
441             if (theOpCodeLength > 1)
442             {
443                 // Yes, so get the length.
444                 theResult = m_opMap[theIndex + s_opCodeMapLengthIndex];
445             }
446         }
447     }
448 
449     return theResult;
450 }
451 
452 
453 
454 void
setOpCodeArgs(eOpCodes theOpCode,OpCodeMapSizeType theIndex,const OpCodeMapValueVectorType & theArgs)455 XPathExpression::setOpCodeArgs(
456             eOpCodes                            theOpCode,
457             OpCodeMapSizeType                   theIndex,
458             const OpCodeMapValueVectorType&     theArgs)
459 {
460     // There must be at least enough space to hold the OpCode
461     // and the length indicator.
462     assert(opCodeMapSize() > theIndex + 1);
463 
464     const int   theOpCodeLength = getOpCodeLength(theOpCode);
465 
466     // Make sure it's a valid op code and that it
467     // matches the op code at supplied index.
468     if (theOpCodeLength == 0 ||
469         m_opMap[theIndex] != theOpCode)
470     {
471         XalanDOMString   theBuffer(getMemoryManager());
472 
473         throw InvalidOpCodeException(
474                 theOpCode,
475                 theBuffer);
476     }
477     else
478     {
479         const OpCodeMapValueType    theArgCount =
480                 theOpCodeLength - 1 - s_opCodeMapLengthIndex;
481 
482         if (OpCodeMapValueVectorType::size_type(theArgCount) != theArgs.size())
483         {
484             XalanDOMString   theBuffer(getMemoryManager());
485 
486             throw InvalidArgumentCountException(
487                     theOpCode,
488                     theOpCodeLength,
489                     theArgCount,
490                     theBuffer);
491         }
492         else
493         {
494             assert(opCodeMapSize() > theIndex + theArgCount);
495 
496             for (OpCodeMapValueType i = 0; i < theArgCount; ++i)
497             {
498                 if (theArgs[i] < 0)
499                 {
500                     XalanDOMString   theBuffer(getMemoryManager());
501 
502                     throw InvalidArgumentException(
503                             theOpCode,
504                             theArgs[i],
505                             theBuffer);
506                 }
507                 else
508                 {
509                     m_opMap[i + theIndex + s_opCodeMapLengthIndex + 1] =
510                         theArgs[i];
511                 }
512             }
513         }
514     }
515 }
516 
517 
518 
519 XPathExpression::OpCodeMapSizeType
appendOpCode(eOpCodes theOpCode)520 XPathExpression::appendOpCode(eOpCodes  theOpCode)
521 {
522     const int   theOpCodeLength = getOpCodeLength(theOpCode);
523 
524     if (theOpCodeLength == 0)
525     {
526         XalanDOMString   theBuffer(getMemoryManager());
527 
528         throw InvalidOpCodeException(
529                 theOpCode,
530                 theBuffer);
531     }
532     else
533     {
534         // Set the current index before pushing, by
535         // getting the length, which will be correct
536         // after the push.
537         m_lastOpCodeIndex = opCodeMapSize();
538 
539         m_opMap.push_back(theOpCode);
540 
541         assert(s_opCodeMapLengthIndex == 1);
542 
543         if (theOpCodeLength > 1)
544         {
545             m_opMap.push_back(theOpCodeLength);
546 
547             for (int i = 2; i < theOpCodeLength; ++i)
548             {
549                 m_opMap.push_back(eENDOP);
550             }
551         }
552 
553         if (m_lastOpCodeIndex != 0)
554         {
555             m_opMap[s_opCodeMapLengthIndex] += theOpCodeLength;
556         }
557     }
558 
559     assert(opCodeMapSize() == OpCodeMapSizeType(opCodeMapLength()));
560 
561     return m_lastOpCodeIndex;
562 }
563 
564 
565 
566 void
replaceOpCode(OpCodeMapSizeType theIndex,eOpCodes theOldOpCode,eOpCodes theNewOpCode)567 XPathExpression::replaceOpCode(
568             OpCodeMapSizeType   theIndex,
569             eOpCodes            theOldOpCode,
570             eOpCodes            theNewOpCode)
571 {
572     if (theIndex >= opCodeMapSize() ||
573         m_opMap[theIndex] != theOldOpCode ||
574         getOpCodeLength(theOldOpCode) != getOpCodeLength(theNewOpCode))
575     {
576         XalanDOMString   theBuffer(getMemoryManager());
577 
578         throw InvalidOpCodeException(
579                 theNewOpCode,
580                 theBuffer);
581     }
582     else
583     {
584         m_opMap[theIndex] = theNewOpCode;
585     }
586 }
587 
588 
589 
590 XPathExpression::OpCodeMapValueType
insertOpCode(eOpCodes theOpCode,OpCodeMapSizeType theIndex)591 XPathExpression::insertOpCode(
592             eOpCodes            theOpCode,
593             OpCodeMapSizeType   theIndex)
594 {
595     const int   theOpCodeLength = getOpCodeLength(theOpCode);
596 
597     if (theOpCodeLength == 0)
598     {
599         XalanDOMString   theBuffer(getMemoryManager());
600 
601         throw InvalidOpCodeException(
602                 theOpCode,
603                 theBuffer);
604     }
605     else
606     {
607         // Insert -1 for each element of the opcode.
608         m_opMap.insert(
609             m_opMap.begin() + theIndex,
610             OpCodeMapSizeType(theOpCodeLength),
611             -1);
612 
613         // Set the member that contains the last insert/appended
614         // index.
615         m_lastOpCodeIndex = theIndex;
616 
617         // Assign the opcode.
618         m_opMap[theIndex] = theOpCode;
619 
620         // Update the entire expression length.
621         m_opMap[s_opCodeMapLengthIndex] += theOpCodeLength;
622     }
623 
624     return theOpCodeLength;
625 }
626 
627 
628 
629 void
updateShiftedOpCodeLength(OpCodeMapValueType theOpCode,OpCodeMapSizeType,OpCodeMapSizeType theNewIndex)630 XPathExpression::updateShiftedOpCodeLength(
631             OpCodeMapValueType  theOpCode,
632 #if defined(NDEBUG)
633             OpCodeMapSizeType   /* theOriginalIndex */,
634 #else
635             OpCodeMapSizeType   theOriginalIndex,
636 #endif
637             OpCodeMapSizeType   theNewIndex)
638 {
639     // There must be some other expressions in
640     // the buffer...
641     assert(opCodeMapSize() > theNewIndex + 1);
642 
643     assert(theNewIndex > theOriginalIndex);
644 
645     const OpCodeMapValueType    theOpCodeLength = getOpCodeLength(theOpCode);
646 
647     // Make sure it's a valid op code and that it
648     // matches the op code at supplied index.
649     if (theOpCodeLength == 0 ||
650         m_opMap[theNewIndex] != theOpCode)
651     {
652         XalanDOMString   theBuffer(getMemoryManager());
653 
654         throw InvalidOpCodeException(
655                 theOpCode,
656                 theBuffer);
657     }
658     else
659     {
660         // Determine where the length position of the op code
661         // is.
662         const   OpCodeMapSizeType   theLengthIndex =
663                         theNewIndex + s_opCodeMapLengthIndex;
664 
665         // Too long, then throw an exception.
666         if (theLengthIndex >= opCodeMapSize())
667         {
668             XalanDOMString   theBuffer(getMemoryManager());
669 
670             throw InvalidOpCodeException(
671                     theOpCode,
672                     theBuffer);
673         }
674         else
675         {
676             // Look ahead to where the new operand is.
677             const OpCodeMapSizeType     theNextOpCodePosition =
678                         getNextOpCodePosition(theNewIndex);
679 
680             // If it's there, then update our size by
681             // adding that size in.
682             if (theNextOpCodePosition < opCodeMapSize())
683             {
684                 m_opMap[theLengthIndex] += getOpCodeLengthFromOpMap(theNextOpCodePosition, getMemoryManager());
685             }
686         }
687     }
688 }
689 
690 
691 
692 void
updateOpCodeLength(OpCodeMapValueType theOpCode,OpCodeMapValueType theIndex)693 XPathExpression::updateOpCodeLength(
694             OpCodeMapValueType  theOpCode,
695             OpCodeMapValueType  theIndex)
696 {
697     // There must be some other expressions in
698     // the buffer...
699     assert(opCodeMapSize() > theIndex + 1);
700 
701     const int   theOpCodeLength = getOpCodeLength(theOpCode);
702 
703     // Make sure it's a valid op code and that it
704     // matches the op code at supplied index.
705     if (theOpCodeLength == 0 ||
706         m_opMap[theIndex] != theOpCode)
707     {
708         XalanDOMString   theBuffer(getMemoryManager());
709 
710         throw InvalidOpCodeException(
711                 theOpCode,
712                 theBuffer);
713     }
714     else
715     {
716         // This presumes that the other opcodes
717         // have been appended to the expression,
718         // and that the specified op code's length
719         // needs to be set.  The size includes the
720         // normal length of the opcode, plus the
721         // length of its subexpressions.
722         m_opMap[theIndex + s_opCodeMapLengthIndex] =
723                             opCodeMapLength() - theIndex;
724     }
725 }
726 
727 
728 
729 bool
isNodeTestOpCode(OpCodeMapValueType theOpCode)730 XPathExpression::isNodeTestOpCode(OpCodeMapValueType    theOpCode)
731 {
732     if (theOpCode < theNodeTestOpCodesArraySize)
733     {
734         return theNodeTestOpCodesArray[theOpCode];
735     }
736     else
737     {
738         return false;
739     }
740 }
741 
742 
743 
744 void
updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType theIndex)745 XPathExpression::updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType  theIndex)
746 {
747     // There must be some other expressions in
748     // the buffer...
749     assert(opCodeMapSize() > theIndex + 1);
750 
751     const OpCodeMapValueType    theOpCode =
752                         m_opMap[theIndex];
753 
754     const int   theOpCodeLength = getOpCodeLength(theOpCode);
755 
756     // Make sure it's a valid op code and that it
757     // is a node test op code.
758     if (theOpCodeLength == 0 ||
759         isNodeTestOpCode(theOpCode) == false)
760     {
761         XalanDOMString   theBuffer(getMemoryManager());
762 
763         throw InvalidOpCodeException(
764                 theOpCode,
765                 theBuffer);
766     }
767     else
768     {
769         m_opMap[theIndex + s_opCodeMapLengthIndex + 1] =
770                             opCodeMapLength() - theIndex;
771     }
772 }
773 
774 
775 
776 void
dumpOpCodeMap(PrintWriter & thePrintWriter,OpCodeMapSizeType theStartPosition) const777 XPathExpression::dumpOpCodeMap(
778             PrintWriter&        thePrintWriter,
779             OpCodeMapSizeType   theStartPosition) const
780 {
781     for (OpCodeMapSizeType  i = theStartPosition;
782                 i < opCodeMapSize(); i++)
783     {
784         thePrintWriter.print(" '");
785         thePrintWriter.print(m_opMap[i]);
786         thePrintWriter.print("'");
787     }
788 }
789 
790 
791 
792 void
dumpOpCodeMap(OstreamType & theStream,OpCodeMapSizeType theStartPosition) const793 XPathExpression::dumpOpCodeMap(
794             OstreamType&        theStream,
795             OpCodeMapSizeType   theStartPosition) const
796 {
797     for (OpCodeMapSizeType  i = theStartPosition;
798                 i < opCodeMapSize(); i++)
799     {
800         theStream << " '" << m_opMap[i] << "'";
801     }
802 }
803 
804 
805 
806 void
dumpTokenQueue(OstreamType & theStream,TokenQueueSizeType theStartPosition) const807 XPathExpression::dumpTokenQueue(
808             OstreamType&        theStream,
809             TokenQueueSizeType  theStartPosition) const
810 {
811     for (TokenQueueSizeType i = theStartPosition;
812                 i < tokenQueueSize(); i++)
813     {
814         assert(getToken(i) != 0);
815 
816         theStream << " '" << getToken(i)->str() << "'";
817     }
818 }
819 
820 
821 
822 void
dumpTokenQueue(PrintWriter & thePrintWriter,TokenQueueSizeType theStartPosition) const823 XPathExpression::dumpTokenQueue(
824             PrintWriter&        thePrintWriter,
825             TokenQueueSizeType  theStartPosition) const
826 {
827     for (TokenQueueSizeType i = theStartPosition;
828                 i < tokenQueueSize(); i++)
829     {
830         assert(getToken(i) != 0);
831 
832         if (i > 0)
833         {
834             thePrintWriter.print(" '");
835         }
836         else
837         {
838             thePrintWriter.print("'");
839         }
840 
841         thePrintWriter.print(getToken(i)->str());
842         thePrintWriter.print("'");
843     }
844 }
845 
846 
847 
848 void
dumpRemainingTokenQueue(PrintWriter & thePrintWriter) const849 XPathExpression::dumpRemainingTokenQueue(PrintWriter&   thePrintWriter) const
850 {
851     XalanDOMString  tmpString(thePrintWriter.getMemoryManager());
852 
853     thePrintWriter.print(
854         XalanMessageLoader::getMessage(
855             tmpString,
856             XalanMessages::RemainingTokens));
857 
858     thePrintWriter.print("(");
859 
860     dumpTokenQueue(
861         thePrintWriter,
862         m_currentPosition);
863 
864     thePrintWriter.print(")");
865 }
866 
867 
868 
869 void
dumpRemainingTokenQueue(OstreamType & theStream,MemoryManager & theMemoryManager) const870 XPathExpression::dumpRemainingTokenQueue(
871             OstreamType&    theStream,
872             MemoryManager&  theMemoryManager) const
873 {
874     XalanDOMString  tmpString(theMemoryManager);
875 
876     theStream << XalanMessageLoader::getMessage(tmpString, XalanMessages::RemainingTokens)
877               << "(";
878 
879     dumpTokenQueue(theStream,
880                    m_currentPosition);
881 
882     theStream << ")";
883 }
884 
885 
886 
887 void
pushArgumentOnOpCodeMap(const XToken & theXToken)888 XPathExpression::pushArgumentOnOpCodeMap(const XToken&  theXToken)
889 {
890     assert(m_currentPosition != 0);
891 
892     const int   thePosition = m_currentPosition - 1;
893 
894     assert(thePosition < tokenQueueSize());
895 
896     // Set the entry in the token queue to the XObject.
897     m_tokenQueue[thePosition] = theXToken;
898 
899     // Push the index onto the op map.
900     m_opMap.push_back(thePosition);
901 
902     // Update the op map length.
903     ++m_opMap[s_opCodeMapLengthIndex];
904 }
905 
906 
907 
908 void
pushArgumentOnOpCodeMap(const XalanDOMString & theToken)909 XPathExpression::pushArgumentOnOpCodeMap(const XalanDOMString&  theToken)
910 {
911     assert(m_currentPosition != 0);
912 
913     const TokenQueueSizeType    thePosition = m_currentPosition - 1;
914 
915     assert(thePosition < tokenQueueSize());
916 
917     // Set the entry in the token queue to the XObject.
918     m_tokenQueue[thePosition].set(
919         theToken,
920         DoubleSupport::toDouble(theToken, getMemoryManager()));
921 
922     // Push the index onto the op map.
923     m_opMap.push_back(thePosition);
924 
925     // Update the op map length.
926     ++m_opMap[s_opCodeMapLengthIndex];
927 }
928 
929 
930 
931 void
pushArgumentOnOpCodeMap(double theNumber,const XalanDOMString & theString)932 XPathExpression::pushArgumentOnOpCodeMap(
933             double                  theNumber,
934             const XalanDOMString&   theString)
935 {
936     assert(m_currentPosition != 0);
937 
938     const TokenQueueSizeType    thePosition = m_currentPosition - 1;
939 
940     assert(thePosition < tokenQueueSize());
941 
942     // Set the entry in the token queue to the XObject.
943     m_tokenQueue[thePosition].set(theNumber, theString);
944 
945     // Push the index onto the op map.
946     m_opMap.push_back(thePosition);
947 
948     // Update the op map length.
949     ++m_opMap[s_opCodeMapLengthIndex];
950 }
951 
952 
953 
954 void
pushNumberLiteralOnOpCodeMap(double theNumber)955 XPathExpression::pushNumberLiteralOnOpCodeMap(double    theNumber)
956 {
957     // Get the new index for the literal...
958     const OpCodeMapValueType    theIndex = OpCodeMapValueType(m_numberLiteralValues.size());
959 
960     assert(NumberLiteralValueVectorType::size_type(theIndex) == m_numberLiteralValues.size());
961 
962     // Push the index onto the op map.
963     m_opMap.push_back(theIndex);
964 
965     // Update the op map length.
966     ++m_opMap[s_opCodeMapLengthIndex];
967 
968     m_numberLiteralValues.push_back(theNumber);
969 }
970 
971 
972 
973 void
pushCurrentTokenOnOpCodeMap()974 XPathExpression::pushCurrentTokenOnOpCodeMap()
975 {
976     assert(m_currentPosition != 0);
977 
978     const TokenQueueSizeType    thePosition = m_currentPosition - 1;
979 
980     assert(thePosition < tokenQueueSize());
981 
982     // Push the index onto the op map.
983     m_opMap.push_back(thePosition);
984 
985     // Update the op map length.
986     ++m_opMap[s_opCodeMapLengthIndex];
987 }
988 
989 
990 
991 }
992