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