Xalan-C++ API Reference 1.12.0
XPathExpression.hpp
Go to the documentation of this file.
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#if !defined(XPATHEXPRESSION_HEADER_GUARD_1357924680)
19#define XPATHEXPRESSION_HEADER_GUARD_1357924680
20
21
22
23// Base header file. Must be first.
25
26
27
29
30
31
32#include <iosfwd>
33
34
35
37
38
39
42
43
44
47
48
49
50namespace XALAN_CPP_NAMESPACE {
51
52
53
54using xercesc::MemoryManager;
55
56
57
59{
60public:
61
62 typedef std::ostream OstreamType;
63
66
69
71
73
74#define XALAN_XPATH_EXPRESSION_USE_ITERATORS
75
76#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
78#else
80#endif
83 typedef int TokenQueueSizeType;
85
86 /**
87 * List of operations codes.
88 *
89 * Code for the descriptions of the operations codes:
90 * [UPPER CASE] indicates a literal value,
91 * [lower case] is a description of a value,
92 * ([length] always indicates the length of the operation,
93 * including the operations code and the length integer.)
94 * {UPPER CASE} indicates the given production,
95 * {description} is the description of a new production,
96 * (For instance, {boolean expression} means some expression
97 * that should be resolved to a boolean.)
98 * * means that it occurs zero or more times,
99 * + means that it occurs one or more times,
100 * ? means that it is optional.
101 *
102 * returns: indicates what the production should return.
103 */
105 {
106 /**
107 * [ELEMWILDCARD]
108 * Means ELEMWILDCARD ("*"), used instead
109 * of string index in some places.
110 */
111 eELEMWILDCARD = -3,
112
113 /**
114 * [EMPTY]
115 * Empty slot to indicate NULL.
116 */
117 eEMPTY = -2,
118
119 /**
120 * [ENDOP]
121 * Some operators may like to have a terminator.
122 */
123 eENDOP = -1,
124
125 /**
126 * [OP_XPATH]
127 * [length]
128 * {expression}
129 *
130 * returns:
131 * XNodeSet
132 * XNumber
133 * XString
134 * XBoolean
135 * XRTree
136 * XObject
137 */
138 eOP_XPATH = 1,
139
140 /**
141 * [OP_OR]
142 * [length]
143 * {boolean expression}
144 * {boolean expression}
145 *
146 * returns:
147 * XBoolean
148 */
149 eOP_OR = 2,
150
151 /**
152 * [OP_AND]
153 * [length]
154 * {boolean expression}
155 * {boolean expression}
156 *
157 * returns:
158 * XBoolean
159 */
160 eOP_AND = 3,
161
162 /**
163 * [OP_NOTEQUALS]
164 * [length]
165 * {expression}
166 * {expression}
167 *
168 * returns:
169 * XBoolean
170 */
171 eOP_NOTEQUALS = 4,
172
173 /**
174 * [OP_EQUALS]
175 * [length]
176 * {expression}
177 * {expression}
178 *
179 * returns:
180 * XBoolean
181 */
182 eOP_EQUALS = 5,
183
184 /**
185 * [OP_LTE] (less-than-or-equals)
186 * [length]
187 * {number expression}
188 * {number expression}
189 *
190 * returns:
191 * XBoolean
192 */
193 eOP_LTE = 6,
194
195 /**
196 * [OP_LT] (less-than)
197 * [length]
198 * {number expression}
199 * {number expression}
200 *
201 * returns:
202 * XBoolean
203 */
204 eOP_LT = 7,
205
206 /**
207 * [OP_GTE] (greater-than-or-equals)
208 * [length]
209 * {number expression}
210 * {number expression}
211 *
212 * returns:
213 * XBoolean
214 */
215 eOP_GTE = 8,
216
217 /**
218 * [OP_GT] (greater-than)
219 * [length]
220 * {number expression}
221 * {number expression}
222 *
223 * returns:
224 * XBoolean
225 */
226 eOP_GT = 9,
227
228 /**
229 * [OP_PLUS]
230 * [length]
231 * {number expression}
232 * {number expression}
233 *
234 * returns:
235 * XNumber
236 */
237 eOP_PLUS = 10,
238
239 /**
240 * [OP_MINUS]
241 * [length]
242 * {number expression}
243 * {number expression}
244 *
245 * returns:
246 * XNumber
247 */
248 eOP_MINUS = 11,
249
250 /**
251 * [OP_MULT]
252 * [length]
253 * {number expression}
254 * {number expression}
255 *
256 * returns:
257 * XNumber
258 */
259 eOP_MULT = 12,
260
261 /**
262 * [OP_DIV]
263 * [length]
264 * {number expression}
265 * {number expression}
266 *
267 * returns:
268 * XNumber
269 */
270 eOP_DIV = 13,
271
272 /**
273 * [OP_MOD]
274 * [length]
275 * {number expression}
276 * {number expression}
277 *
278 * returns:
279 * XNumber
280 */
281 eOP_MOD = 14,
282
283 /**
284 * [OP_NEG]
285 * [length]
286 * {number expression}
287 *
288 * returns:
289 * XNumber
290 */
291 eOP_NEG = 15,
292
293 /**
294 * [OP_BOOL] (cast operation)
295 * [length]
296 * {expression}
297 *
298 * returns:
299 * XBoolean
300 */
301 eOP_BOOL = 16,
302
303 /**
304 * [OP_UNION]
305 * [length]
306 * {PathExpr}+
307 *
308 * returns:
309 * XNodeSet
310 */
311 eOP_UNION = 17,
312
313 /**
314 * [OP_LITERAL]
315 * [3]
316 * [index to token]
317 *
318 * returns:
319 * XString
320 */
321 eOP_LITERAL = 18,
322
323 /**
324 * [OP_VARIABLE]
325 * [3]
326 * [index to token]
327 *
328 * returns:
329 * XString
330 */
331 eOP_VARIABLE = 19,
332
333 /**
334 * [OP_GROUP]
335 * [length]
336 * {expression}
337 *
338 * returns:
339 * XNodeSet
340 * XNumber
341 * XString
342 * XBoolean
343 * XRTree
344 * XObject
345 */
346 eOP_GROUP = 20,
347
348 /**
349 * [OP_NUMBERLIT] (Number literal.)
350 * [3]
351 * [index to token]
352 *
353 * returns:
354 * XString
355 */
356 eOP_NUMBERLIT = 21,
357
358 /**
359 * [OP_ARGUMENT] (Function argument.)
360 * [length]
361 * {expression}
362 *
363 * returns:
364 * XNodeSet
365 * XNumber
366 * XString
367 * XBoolean
368 * XRTree
369 * XObject
370 */
371 eOP_ARGUMENT = 22,
372
373 /**
374 * [OP_EXTFUNCTION] (Extension function.)
375 * [length]
376 * [index to namespace token]
377 * [index to function name token]
378 * {OP_ARGUMENT}*
379 *
380 * returns:
381 * XNodeSet
382 * XNumber
383 * XString
384 * XBoolean
385 * XRTree
386 * XObject
387 */
388 eOP_EXTFUNCTION = 23,
389
390 /**
391 * [OP_FUNCTION]
392 * [length]
393 * [FUNC_ID]
394 * [arg count]
395 * {OP_ARGUMENT}*
396 * [ENDOP]
397 *
398 * returns:
399 * XNodeSet
400 * XNumber
401 * XString
402 * XBoolean
403 * XRTree
404 * XObject
405 */
406 eOP_FUNCTION = 24,
407
408 /**
409 * [OP_LOCATIONPATH]
410 * [length]
411 * {FROM_stepType}
412 * | {function}{predicate}*
413 * [ENDOP]
414 *
415 * (Note that element and attribute namespaces and
416 * names can be wildcarded '*'.)
417 *
418 * returns:
419 * XNodeSet
420 */
421 eOP_LOCATIONPATH = 25,
422
423 /**
424 * [OP_PREDICATE]
425 * [length]
426 * {expression}
427 * [ENDOP] (For safety)
428 *
429 * returns:
430 * XBoolean or XNumber
431 */
432 eOP_PREDICATE = 26,
433
434 /**
435 * [NODETYPE_COMMENT]
436 * No size or arguments.
437 *
438 * returns:
439 * XBoolean
440 */
441 eNODETYPE_COMMENT = 27,
442
443 /**
444 * [NODETYPE_TEXT]
445 * No size or arguments.
446 *
447 * returns:
448 * XBoolean
449 */
450 eNODETYPE_TEXT = 28,
451
452 /**
453 * [NODETYPE_PI]
454 * [index to token]
455 *
456 * returns:
457 * XBoolean
458 */
459 eNODETYPE_PI = 29,
460
461 /**
462 * [NODETYPE_NODE]
463 * No size or arguments.
464 *
465 * returns:
466 * XBoolean
467 */
468 eNODETYPE_NODE = 30,
469
470 /**
471 * [NODENAME]
472 * [index to ns token or EMPTY]
473 * [index to name token]
474 *
475 * returns:
476 * XBoolean
477 */
478 eNODENAME = 31,
479
480 /**
481 * [NODETYPE_ROOT]
482 * No size or arguments.
483 *
484 * returns:
485 * XBoolean
486 */
487 eNODETYPE_ROOT = 32,
488
489 /**
490 * [NODETYPE_ANY]
491 * No size or arguments.
492 *
493 * returns:
494 * XBoolean
495 */
496 eNODETYPE_ANYELEMENT = 33,
497
498 /**
499 * [FROM_stepType]
500 * [length, including predicates]
501 * [length of just the step, without the predicates]
502 * {node test}
503 * {predicates}?
504 *
505 * returns:
506 * XBoolean
507 */
508 eFROM_ANCESTORS = 34,
509 eFROM_ANCESTORS_OR_SELF = 35,
510 eFROM_ATTRIBUTES = 36,
511 eFROM_CHILDREN = 37,
512 eFROM_DESCENDANTS = 38,
513 eFROM_DESCENDANTS_OR_SELF = 39,
514 eFROM_FOLLOWING = 40,
515 eFROM_FOLLOWING_SIBLINGS = 41,
516 eFROM_PARENT = 42,
517 eFROM_PRECEDING = 43,
518 eFROM_PRECEDING_SIBLINGS = 44,
519 eFROM_SELF = 45,
520 eFROM_NAMESPACE = 46,
521 eFROM_ROOT = 47,
522
523 /**
524 * [OP_UNION]
525 * [length]
526 * {PathExpr}+
527 *
528 * returns:
529 * XNodeSet
530 */
531 eOP_MATCHPATTERN = 48,
532
533 /**
534 * [OP_UNION]
535 * [length]
536 * {PathExpr}+
537 *
538 * returns:
539 * XNodeSet
540 */
541 eOP_LOCATIONPATHPATTERN = 49,
542
543 // For match patterns
544 eMATCH_ATTRIBUTE = 50,
545 eMATCH_ANY_ANCESTOR = 51,
546 eMATCH_IMMEDIATE_ANCESTOR = 52,
547 eMATCH_ANY_ANCESTOR_WITH_PREDICATE = 53,
548 eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL = 54,
549
550 /**
551 * [OP_PREDICATE_WITH_POSITION]
552 * [length]
553 * {expression}
554 * [ENDOP] (For safety)
555 *
556 * returns:
557 * XBoolean or XNumber
558 */
559 eOP_PREDICATE_WITH_POSITION = 55,
560
561 /**
562 * These are values for intrinsic functions which
563 * have been compiled directly into the op map.
564 */
565 eOP_FUNCTION_POSITION = 56,
566 eOP_FUNCTION_LAST = 57,
567 eOP_FUNCTION_COUNT = 58,
568 eOP_FUNCTION_NOT = 59,
569 eOP_FUNCTION_TRUE = 60,
570 eOP_FUNCTION_FALSE = 61,
571 eOP_FUNCTION_BOOLEAN = 62,
572 eOP_FUNCTION_NAME_0 = 63,
573 eOP_FUNCTION_NAME_1 = 64,
574 eOP_FUNCTION_LOCALNAME_0 = 65,
575 eOP_FUNCTION_LOCALNAME_1 = 66,
576 eOP_FUNCTION_FLOOR = 67,
577 eOP_FUNCTION_CEILING = 68,
578 eOP_FUNCTION_ROUND = 69,
579 eOP_FUNCTION_NUMBER_0 = 70,
580 eOP_FUNCTION_NUMBER_1 = 71,
581 eOP_FUNCTION_STRING_0 = 72,
582 eOP_FUNCTION_STRING_1 = 73,
583 eOP_FUNCTION_STRINGLENGTH_0 = 74,
584 eOP_FUNCTION_STRINGLENGTH_1 = 75,
585 eOP_FUNCTION_NAMESPACEURI_0 = 76,
586 eOP_FUNCTION_NAMESPACEURI_1 = 77,
587 eOP_FUNCTION_SUM = 78,
588 eOP_FUNCTION_CONCAT = 79,
589
590 // Always add _before_ this one and update
591 // s_opCodeLengthArray.
592 eOpCodeNextAvailable
593 }; // enum eOpCodes
594
595 /**
596 * Exception class thrown when an invalid XPath expression is encountered
597 */
599 {
600 public:
601
602 /**
603 * Construct an XPathExpressionException object.
604 *
605 * @param theMessage string error message
606 */
608 MemoryManager& theManager);
609
610 virtual~
612 };
613
614 /**
615 * Exception class thrown when an invalid XPath operation code is encountered
616 */
618 {
619 public:
620
621 /**
622 * Construct an InvalidOpCodeException object.
623 *
624 * @param theOpCode operation code that caused the exception
625 */
629
630 virtual~
632
633 private:
634
635 static XalanDOMString&
636 FormatErrorMessage(
639 };
640
641 /**
642 * Exception class thrown when an invalid number of XPath arguments is
643 * encountered
644 */
646 {
647 public:
648
649 /**
650 * Construct an InvalidArgumentCountException object.
651 *
652 * @param theOpCode operation code that caused the exception
653 * @param theExpectedCount the correct number of arguments for "opcode"
654 * @param theSuppliedCount the number of arguments supplied
655 */
661
662 virtual~
664
665 private:
666
667 static XalanDOMString&
668 FormatErrorMessage(
673 };
674
675 /**
676 * Exception class thrown when an invalid XPath argument is encountered
677 */
679 {
680 public:
681
682 /**
683 * Construct an InvalidArgumentException object.
684 *
685 * @param theOpCode operation code that caused the exception
686 * @param theValue invalid argument value
687 */
692
693 virtual~
695
696 private:
697
698 static XalanDOMString&
699 FormatErrorMessage(
703 };
704
705
706 /**
707 * The length is always the opcode position + 1. Length is always expressed
708 * as the opcode+length bytes, so it is always 2 or greater. This is the
709 * offset from the op code where the length is stored. It will always
710 * remain one.
711 */
713 {
714 s_opCodeMapLengthIndex = 1
715 };
716
717 explicit
719
721
722 MemoryManager&
724 {
725 return m_opMap.getMemoryManager();
726 }
727 /**
728 * Reset the expression.
729 */
730 void
732
733 /**
734 * Shrink internal tables.
735 */
736 void
738
739 /**
740 * Retrieve number of elements in the operations code map.
741 *
742 * @return size of operations code map
743 */
746 {
747 return OpCodeMapSizeType(m_opMap.size());
748 }
749
750 /**
751 * Retrieve length of the operations code map stored in the map. The length
752 * of the entire map is stored after the first op code. That offset is
753 * determined by this const static member. Note that as expressions are
754 * defined recursively, this is really just the length of the first
755 * expression in the map, which is the top of the parse tree. Any
756 * subexpression will also have a length entry at the same offset from the
757 * beginning of the subexpression.
758 *
759 * @return length of operations code map
760 */
761 OpCodeMapValueType
763 {
764 const OpCodeMapSizeType theSize = opCodeMapSize();
765
766 if (theSize > s_opCodeMapLengthIndex)
767 {
768 assert(theSize == OpCodeMapSizeType(m_opMap[s_opCodeMapLengthIndex]));
769
770 return m_opMap[s_opCodeMapLengthIndex];
771 }
772 else
773 {
775
777 }
778 }
779
780 OpCodeMapPositionType
782 {
783#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
784 return m_opMap.begin();
785#else
786 return 0;
787#endif
788 }
789
790 bool
792 {
794 OpCodeMapDifferenceType(opPos - getInitialOpCodePosition());
795
796 return theDifference >= 0 &&
797 theDifference < opCodeMapSize();
798 }
799
800#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
801 bool
803 {
804 return theIndex >= 0 && theIndex < opCodeMapSize();
805 }
806
807 /**
808 * Retrieve the value of an operation code at a specified index in the
809 * op code map.
810 *
811 * @param theIndex The index in list
812 * @return value of operation code
813 */
814 OpCodeMapValueType
816 {
817 assert(theIndex < opCodeMapLength());
818
819 return m_opMap[theIndex];
820 }
821#endif
822
823 /**
824 * Retrieve the value of an operation code at a specified position in the
825 * list.
826 *
827 * @param opPos position in list
828 * @return value of operation code
829 */
830 OpCodeMapValueType
832 {
833 assert(opPos < getInitialOpCodePosition() + opCodeMapLength());
834
835#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
836 return *opPos;
837#else
838
839 return m_opMap[opPos];
840#endif
841 }
842
843 /**
844 * Set the value of an operation code at a specified index in the
845 * OpCode map.
846 *
847 * @param theOpCodeMapIndex The index in the OpCode map
848 * @param theValue value of operation code
849 */
850 void
854 {
855 assert(theOpCodeMapIndex < opCodeMapLength());
856
857 m_opMap[theOpCodeMapIndex] = theValue;
858 }
859
860 OpCodeMapValueType
862 {
863 return getOpCodeMapValue(opPos + XPathExpression::s_opCodeMapLengthIndex + 1) - 3;
864 }
865
866 /**
867 * Retrieve the length of an operation code at a specified position in the
868 * op map.
869 *
870 * @param opPos position in the op map
871 * @return length of operation code
872 */
873 OpCodeMapValueType
875 MemoryManager& theManager) const;
876
877#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
878 /**
879 * Retrieve the length of an operation code at a specified index in the
880 * op map.
881 *
882 * @param theIndex The index in the op map
883 * @return length of operation code
884 */
887 MemoryManager& theManager) const;
888#endif
889
890#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
891 /**
892 * Retrieve the position of the next operation code at a specified position
893 * in the list.
894 *
895 * @param opPos position in list
896 * @return position of next operation code
897 */
900 {
901 assert(opPos < getInitialOpCodePosition() + opCodeMapLength());
902
903 return opPos + *(opPos + s_opCodeMapLengthIndex);
904 }
905#endif
906
907 /**
908 * Retrieve the position of the next operation code at a specified index
909 * in the list.
910 *
911 * @param theIndex theIndex in list
912 * @return position of next operation code
913 */
914 OpCodeMapSizeType
915#if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
917#else
918 getNextOpCodePosition(OpCodeMapPositionType theIndex) const
919#endif
920 {
921 assert(theIndex < opCodeMapLength());
922
923 assert(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex] ==
924 OpCodeMapSizeType(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex]));
925
926 return OpCodeMapSizeType(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex]);
927 }
928
929 /**
930 * Set the arguments for an operation code at a specified index in the
931 * list.
932 *
933 * @param opPos position in list
934 * @param theOpCode operation code
935 * @param theIndex index in list
936 * @param theArgs vector or arguments to supply
937 */
938 void
943
944 /**
945 * Add an operation code to the list.
946 *
947 * @param theOpCode operation code
948 * @return the position of the op code
949 */
952
953 /**
954 * Add an operation code with supplied arguments to the list.
955 *
956 * @param theOpCode operation code
957 * @param theArgs vector or arguments to supply
958 */
963 {
964 const OpCodeMapSizeType thePosition = appendOpCode(theOpCode);
965
966 setOpCodeArgs(theOpCode,
968 theArgs);
969
970 return thePosition;
971 }
972
973 /**
974 * Replace an operation code with supplied code.
975 *
976 * @param theIndex The index of the old operation code
977 * @param theOldOpCode The old operation code
978 * @param theNewOpCode The new operation code
979 */
980 void
985
986 /**
987 * Insert an operation code at a specified index in the list.
988 *
989 * @param theOpCode operation code
990 * @param theIndex index in list
991 */
996
997 /**
998 * Update the length of an operation code at a specified index in the list.
999 * This presumes that the other opcodes have been appended to the
1000 * expression, and that the specified op code's length needs to be set.
1001 * The size includes the normal length of the opcode, plus the length of
1002 * its subexpressions.
1003 *
1004 * @param theIndex index in list
1005 */
1006 void
1008 {
1009 assert(theIndex < opCodeMapSize());
1010
1011 updateOpCodeLength(m_opMap[theIndex], theIndex);
1012 }
1013
1014 /**
1015 * Update the length of an operation code that has moved to a new index in
1016 * the list.
1017 *
1018 * @param theOpCode operation code
1019 * @param theOriginalIndex original index in list
1020 * @param theNewIndex new index in list
1021 */
1022 void
1027
1028 /**
1029 * Update the length of an operation code at a specified index in the list.
1030 * This presumes that the other opcodes have been appended to the
1031 * expression, and that the specified op code's length needs to be set.
1032 * The size includes the normal length of the opcode, plus the length of
1033 * its subexpressions.
1034 *
1035 * @param theOpCode operation code at specified index
1036 * @param theIndex index in list
1037 */
1038 void
1042
1043 /**
1044 * Whether the operation code is one of the node test types, for example,
1045 * "ancestor::" or "child::"
1046 *
1047 * @param theOpCode operation code
1048 * @return true if code represents a node test
1049 */
1050 static bool
1052
1053 /**
1054 * Update the length of an operation code after a node test code.
1055 *
1056 * @param theIndex index in list
1057 */
1058 void
1060
1061 /**
1062 * Whether there are any more tokens in the token queue.
1063 *
1064 * @return true if there are more tokens
1065 */
1066 bool
1068 {
1069 return tokenQueueSize() > m_currentPosition ? true : false;
1070 }
1071
1072 /**
1073 * Retrieve number of elements in the token queue.
1074 *
1075 * @return size of token queue
1076 */
1077 TokenQueueSizeType
1079 {
1080 return TokenQueueSizeType(m_tokenQueue.size());
1081 }
1082
1083 bool
1085 {
1086 return thePosition < tokenQueueSize();
1087 }
1088
1089 /**
1090 * Retrieve the current position in the token queue.
1091 *
1092 * @return position in queue
1093 */
1094 TokenQueueSizeType
1096 {
1097 return m_currentPosition;
1098 }
1099
1100 /**
1101 * Set the current position in the token queue to zero.
1102 */
1103 void
1105 {
1106 m_currentPosition = 0;
1107 }
1108
1109 /**
1110 * Retrieve a token at the specified position in the token queue.
1111 *
1112 * @param thePosition position in queue
1113 * @return pointer to XObject token
1114 */
1115 const XToken*
1117 {
1118 assert(thePosition < tokenQueueSize());
1119
1120 return &m_tokenQueue[thePosition];
1121 }
1122
1123 /**
1124 * Retrieve the next token in the token queue.
1125 *
1126 * @return pointer to XObject token
1127 */
1128 const XToken*
1130 {
1131 if (hasMoreTokens() == true)
1132 {
1133 return getToken(m_currentPosition++);
1134 }
1135 else
1136 {
1137 return 0;
1138 }
1139 }
1140
1141 /**
1142 * Retrieve the previous token in the token queue.
1143 *
1144 * @return pointer to XObject token
1145 */
1146 const XToken*
1148 {
1149 if (m_currentPosition > 0)
1150 {
1151 return getToken(--m_currentPosition);
1152 }
1153 else
1154 {
1155 return 0;
1156 }
1157 }
1158
1160 {
1162 eRelativeForward
1164
1165 /**
1166 * Retrieve a token at the specified offset relative to the current
1167 * position in the token queue.
1168 *
1169 * @param theOffset offset from current position
1170 * @param theDirection the direction in which to move
1171 * @return pointer to XObject token
1172 */
1173 const XToken*
1177 {
1179 calculateRelativePosition(theOffset, theDirection);
1180
1181 if (thePosition == tokenQueueSize())
1182 {
1183 return 0;
1184 }
1185 else
1186 {
1187 return getToken(thePosition);
1188 }
1189 }
1190
1191 /**
1192 * Push a token onto the token queue.
1193 *
1194 * @param theToken the string value to push
1195 */
1196 void
1198 {
1199 m_tokenQueue.push_back(
1200 XToken(
1201
1202 DoubleSupport::toDouble(theToken, getMemoryManager()),
1203 theToken,
1204 getMemoryManager()));
1205 }
1206
1207 /**
1208 * Push a token onto the token queue.
1209 *
1210 * @param theNumber the number value to push
1211 * @param theString the string value to push
1212 */
1213 void
1215 double theNumber,
1217 {
1218 m_tokenQueue.push_back(
1219 XToken(
1220 theNumber,
1221 theString,
1222 getMemoryManager()));
1223 }
1224
1225 /**
1226 * Insert a token onto the token queue at the
1227 * current position.
1228 *
1229 * @param theToken the string value to push
1230 */
1231 void
1233 {
1234 m_tokenQueue.insert(
1235 m_tokenQueue.begin() + (m_currentPosition - 1),
1236 XToken(
1237 theToken,
1238 DoubleSupport::toDouble(theToken, getMemoryManager()),
1239 getMemoryManager()));
1240 }
1241
1242 /**
1243 * Insert a token onto the token queue at the
1244 * current position.
1245 *
1246 * @param theNumber the number value to push
1247 * @param theString the string value to push
1248 */
1249 void
1251 double theNumber,
1253 {
1254 m_tokenQueue.insert(
1255 m_tokenQueue.begin() + (m_currentPosition - 1),
1256 XToken(
1257 theNumber,
1258 theString,
1259 getMemoryManager()));
1260 }
1261
1262 /**
1263 * Replace a token in the token queue.
1264 *
1265 * @param theOffset the offset at which to replace the token.
1266 * @param theString The string data for the token. The instance will keep a pointer to this string, so it must be persistent.
1267 */
1268 void
1273 {
1275 calculateRelativePosition(theOffset, theDirection);
1276 assert(thePosition < tokenQueueSize());
1277
1278 m_tokenQueue[thePosition].set(
1279 theString,
1280 DoubleSupport::toDouble(theString, getMemoryManager()));
1281 }
1282
1283 /**
1284 * Diagnostic function to output the operation code map.
1285 *
1286 * @param thePrintWriter output device
1287 * @param theStartPosition starting position in map
1288 */
1289 void
1293
1294 /**
1295 * Diagnostic function to output the operation code map.
1296 *
1297 * @param theStream output stream
1298 * @param theStartPosition starting position in map
1299 */
1300 void
1304
1305 /**
1306 * Diagnostic function to output the token queue.
1307 *
1308 * @param thePrintWriter output device
1309 * @param theStartPosition starting position in token queue
1310 */
1311 void
1315
1316 /**
1317 * Diagnostic function to output the token queue.
1318 *
1319 * @param thePrintWriter output device
1320 * @param theStartPosition starting position in token queue
1321 */
1322 void
1326
1327 /**
1328 * Diagnostic function to output the remaining tokens in the token queue.
1329 *
1330 * @param thePrintWriter output device
1331 */
1332 void
1334
1335 /**
1336 * Diagnostic function to output the remaining tokens in the token queue.
1337 *
1338 * @param theStream The output stream
1339 * @param theMemoryManager The MemoryManager instance.
1340 */
1341 void
1344 MemoryManager& theMemoryManager) const;
1345
1346 /**
1347 * Push a value onto the operations code
1348 * map.
1349 *
1350 * @param theToken string value of the token to push
1351 */
1352 void
1354 {
1355 // Push the index onto the op map.
1356 m_opMap.push_back(theValue);
1357
1358 // Update the op map length.
1359 ++m_opMap[s_opCodeMapLengthIndex];
1360 }
1361
1362 /**
1363 * Push a token onto the token queue and its index onto the operations code
1364 * map.
1365 *
1366 * @param theXToken the XToken to push
1367 */
1368 void
1370
1371 /**
1372 * Push a token onto the token queue and its index onto the operations code
1373 * map.
1374 *
1375 * @param theString The string data for the token. The instance will keep a pointer to this string, so it must be persistent.
1376 */
1377 void
1379
1380 /**
1381 * Push a token onto the token queue and its index onto the operations code
1382 * map.
1383 *
1384 * @param theNumber The numeric data for the token. This must be consistent with the lexical value in theString.
1385 * @param theString The string data for the token. The instance will keep a pointer to this string, so it must be persistent.
1386 */
1387 void
1389 double theNumber,
1390 const XalanDOMString& theString);
1391
1392 /**
1393 * Push a number literal onto the vector of number literals and its index onto
1394 * the operations code map.
1395 *
1396 * @param theToken number value of the token to push
1397 */
1398 void
1400
1401 /**
1402 * Get a number literal from the vector of number literals.
1403 *
1404 * @param theIndex The index of the desired value.
1405 */
1406 double
1408 {
1409 assert(theIndex >= 0 &&
1410 NumberLiteralValueVectorType::size_type(theIndex) < m_numberLiteralValues.size());
1411
1412 return m_numberLiteralValues[NumberLiteralValueVectorType::size_type(theIndex)];
1413 }
1414
1415 /**
1416 * Push the current position in the token queue onto the operations code
1417 * map.
1418 */
1419 void
1421
1422 /**
1423 * Change the current pattern in the pattern map.
1424 *
1425 * @param thePattern match pattern to make current
1426 */
1427 void
1429 {
1430 m_currentPattern = &thePattern;
1431 }
1432
1433 /**
1434 * Retrieve the current pattern in the pattern map.
1435 *
1436 * @return string for current match pattern
1437 */
1438 const XalanDOMString&
1440 {
1441 assert(m_currentPattern != 0);
1442
1443 return *m_currentPattern;
1444 }
1445
1446private:
1447
1448 /**
1449 * Calculate the relative token position given the offset
1450 * and direction. Returns the size of the token queue
1451 * if the offset is not valid.
1452 *
1453 * @param theOffset offset from current position
1454 * @param theDirection the direction in which to move
1455 * @return thePosition
1456 */
1457 TokenQueuePositionType
1458 calculateRelativePosition(
1459 TokenQueuePositionType theOffset,
1460 eRelativeDirection theDirection) const
1461 {
1462 if (theDirection == eRelativeBackward &&
1463 theOffset <= m_currentPosition)
1464 {
1465 return m_currentPosition - theOffset;
1466 }
1467 else if (theDirection == eRelativeForward &&
1468 m_currentPosition + theOffset < tokenQueueSize())
1469 {
1470 return m_currentPosition + theOffset;
1471 }
1472 else
1473 {
1474 return tokenQueueSize();
1475 }
1476 }
1477
1478 /**
1479 * An operations map is used instead of a proper parse tree. It contains
1480 * operations codes and indexes into the m_tokenQueue. We use an array
1481 * instead of a full parse tree in order to cut down on the number of
1482 * objects created.
1483 */
1484 OpCodeMapType m_opMap;
1485
1486 /**
1487 * The index of the last opcode that was appended or inserted.
1488 *
1489 */
1490 OpCodeMapSizeType m_lastOpCodeIndex;
1491
1492 /**
1493 * The queue of used tokens. The current token is the token at the end of
1494 * the m_tokenQueue. The idea is that the queue can be marked and a
1495 * sequence of tokens can be reused.
1496 */
1497 TokenQueueType m_tokenQueue;
1498
1499 /**
1500 * The current position in the token queue.
1501 */
1502 TokenQueueSizeType m_currentPosition;
1503
1504 /**
1505 * The current pattern string, for diagnostics purposes.
1506 */
1507 const XalanDOMString* m_currentPattern;
1508
1509 // Default vector allocation sizes.
1510 enum
1511 {
1512 eDefaultOpMapSize = 100,
1513 eDefaultTokenQueueSize = 30
1514 };
1515
1516 NumberLiteralValueVectorType m_numberLiteralValues;
1517};
1518
1519
1520
1521}
1522
1523
1524
1525#endif // XPATHEXPRESSION_HEADER_GUARD_1357924680
#define XALAN_XPATH_EXPORT
#define XALAN_CPP_NAMESPACE
Xalan-C++ namespace, including major and minor version.
Exception class thrown when an invalid number of XPath arguments is encountered.
InvalidArgumentCountException(OpCodeMapValueType theOpCode, OpCodeMapValueType theExpectedCount, OpCodeMapValueType theSuppliedCount, XalanDOMString &theBuffer)
Construct an InvalidArgumentCountException object.
Exception class thrown when an invalid XPath argument is encountered.
InvalidArgumentException(OpCodeMapValueType theOpCode, OpCodeMapValueType theValue, XalanDOMString &theBuffer)
Construct an InvalidArgumentException object.
Exception class thrown when an invalid XPath operation code is encountered.
InvalidOpCodeException(OpCodeMapValueType theOpCode, XalanDOMString &theBuffer)
Construct an InvalidOpCodeException object.
Exception class thrown when an invalid XPath expression is encountered.
XPathExpressionException(const XalanDOMString &theMessage, MemoryManager &theManager)
Construct an XPathExpressionException object.
void reset()
Reset the expression.
void dumpOpCodeMap(OstreamType &theStream, OpCodeMapSizeType theStartPosition=0) const
Diagnostic function to output the operation code map.
XPathExpression(MemoryManager &theManager)
void dumpRemainingTokenQueue(PrintWriter &thePrintWriter) const
Diagnostic function to output the remaining tokens in the token queue.
void updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType theIndex)
Update the length of an operation code after a node test code.
const XToken * getNextToken()
Retrieve the next token in the token queue.
OpCodeMapValueType insertOpCode(eOpCodes theOpCode, OpCodeMapSizeType theIndex)
Insert an operation code at a specified index in the list.
void insertToken(const XalanDOMString &theToken)
Insert a token onto the token queue at the current position.
XalanVector< XToken > TokenQueueType
const XToken * getRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection) const
Retrieve a token at the specified offset relative to the current position in the token queue.
eDummy
The length is always the opcode position + 1.
OpCodeMapSizeType opCodeMapSize() const
Retrieve number of elements in the operations code map.
XalanVector< OpCodeMapValueType > OpCodeMapValueVectorType
void setOpCodeMapValue(OpCodeMapSizeType theOpCodeMapIndex, const OpCodeMapValueType &theValue)
Set the value of an operation code at a specified index in the OpCode map.
static bool isNodeTestOpCode(OpCodeMapValueType theOpCode)
Whether the operation code is one of the node test types, for example, "ancestor::" or "child::".
MemoryManager & getMemoryManager()
void pushValueOnOpCodeMap(const OpCodeMapType::value_type &theValue)
Push a value onto the operations code map.
void pushToken(double theNumber, const XalanDOMString &theString)
Push a token onto the token queue.
bool isValidTokenQueuePosition(TokenQueueSizeType thePosition) const
const XToken * getToken(TokenQueuePositionType thePosition) const
Retrieve a token at the specified position in the token queue.
XalanVector< double > NumberLiteralValueVectorType
OpCodeMapType::const_iterator OpCodeMapPositionType
void dumpOpCodeMap(PrintWriter &thePrintWriter, OpCodeMapSizeType theStartPosition=0) const
Diagnostic function to output the operation code map.
void pushCurrentTokenOnOpCodeMap()
Push the current position in the token queue onto the operations code map.
double getNumberLiteral(int theIndex) const
Get a number literal from the vector of number literals.
OpCodeMapValueType getOpCodeMapValue(OpCodeMapSizeType theIndex) const
Retrieve the value of an operation code at a specified index in the op code map.
void updateOpCodeLength(OpCodeMapValueType theOpCode, OpCodeMapSizeType theIndex)
Update the length of an operation code at a specified index in the list.
void pushArgumentOnOpCodeMap(double theNumber, const XalanDOMString &theString)
Push a token onto the token queue and its index onto the operations code map.
TokenQueueSizeType getTokenPosition() const
Retrieve the current position in the token queue.
bool isValidOpCodePosition(OpCodeMapPositionType opPos) const
XalanVector< int > OpCodeMapType
void pushNumberLiteralOnOpCodeMap(double theNumber)
Push a number literal onto the vector of number literals and its index onto the operations code map.
void pushArgumentOnOpCodeMap(const XToken &theXToken)
Push a token onto the token queue and its index onto the operations code map.
OpCodeMapValueType getOpCodeArgumentLength(OpCodeMapPositionType opPos) const
OpCodeMapSizeType getNextOpCodePosition(OpCodeMapSizeType theIndex) const
Retrieve the position of the next operation code at a specified index in the list.
OpCodeMapSizeType appendOpCode(eOpCodes theOpCode)
Add an operation code to the list.
void replaceOpCode(OpCodeMapSizeType theIndex, eOpCodes theOldOpCode, eOpCodes theNewOpCode)
Replace an operation code with supplied code.
void pushArgumentOnOpCodeMap(const XalanDOMString &theString)
Push a token onto the token queue and its index onto the operations code map.
bool hasMoreTokens() const
Whether there are any more tokens in the token queue.
OpCodeMapType::value_type OpCodeMapValueType
TokenQueueSizeType tokenQueueSize() const
Retrieve number of elements in the token queue.
void updateOpCodeLength(OpCodeMapSizeType theIndex)
Update the length of an operation code at a specified index in the list.
TokenQueueSizeType TokenQueuePositionType
void dumpTokenQueue(OstreamType &theStream, TokenQueueSizeType theStartPosition=0) const
Diagnostic function to output the token queue.
void setOpCodeArgs(eOpCodes theOpCode, OpCodeMapSizeType theIndex, const OpCodeMapValueVectorType &theArgs)
Set the arguments for an operation code at a specified index in the list.
void replaceRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection, const XalanDOMString &theString)
Replace a token in the token queue.
void pushToken(const XalanDOMString &theToken)
Push a token onto the token queue.
void shrink()
Shrink internal tables.
void updateShiftedOpCodeLength(OpCodeMapValueType theOpCode, OpCodeMapSizeType theOriginalIndex, OpCodeMapSizeType theNewIndex)
Update the length of an operation code that has moved to a new index in the list.
OpCodeMapValueType opCodeMapLength() const
Retrieve length of the operations code map stored in the map.
OpCodeMapPositionType getInitialOpCodePosition() const
const XToken * getPreviousToken()
Retrieve the previous token in the token queue.
void dumpTokenQueue(PrintWriter &thePrintWriter, TokenQueueSizeType theStartPosition=0) const
Diagnostic function to output the token queue.
void setCurrentPattern(const XalanDOMString &thePattern)
Change the current pattern in the pattern map.
OpCodeMapSizeType appendOpCode(eOpCodes theOpCode, const OpCodeMapValueVectorType &theArgs)
Add an operation code with supplied arguments to the list.
void insertToken(double theNumber, const XalanDOMString &theString)
Insert a token onto the token queue at the current position.
TokenQueueType::value_type TokenQueueValueType
bool isValidOpCodePosition(OpCodeMapSizeType theIndex) const
OpCodeMapPositionType getNextOpCodePosition(OpCodeMapPositionType opPos) const
Retrieve the position of the next operation code at a specified position in the list.
OpCodeMapValueType getOpCodeLengthFromOpMap(OpCodeMapSizeType theIndex, MemoryManager &theManager) const
Retrieve the length of an operation code at a specified index in the op map.
eOpCodes
List of operations codes.
void resetTokenPosition()
Set the current position in the token queue to zero.
const XalanDOMString & getCurrentPattern() const
Retrieve the current pattern in the pattern map.
OpCodeMapValueType getOpCodeLengthFromOpMap(OpCodeMapPositionType opPos, MemoryManager &theManager) const
Retrieve the length of an operation code at a specified position in the op map.
OpCodeMapType::difference_type OpCodeMapDifferenceType
OpCodeMapValueType getOpCodeMapValue(OpCodeMapPositionType opPos) const
Retrieve the value of an operation code at a specified position in the list.
void dumpRemainingTokenQueue(OstreamType &theStream, MemoryManager &theMemoryManager) const
Diagnostic function to output the remaining tokens in the token queue.
OpCodeMapValueType OpCodeMapSizeType