Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.11


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

Interpreting class diagrams

Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.

Xalan-C++ XSLT Processor Version 1.11
Copyright © 1999-2012 The Apache Software Foundation.
All Rights Reserved.

Apache Logo