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 
45 #include <xalanc/XPath/XToken.hpp>
47 
48 
49 
50 namespace XALAN_CPP_NAMESPACE {
51 
52 
53 
54 using xercesc::MemoryManager;
55 
56 
57 
59 {
60 public:
61 
62  typedef std::ostream OstreamType;
63 
66 
67  typedef OpCodeMapType::value_type OpCodeMapValueType;
69 
71 
73 
74 #define XALAN_XPATH_EXPRESSION_USE_ITERATORS
75 
76 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS)
77  typedef OpCodeMapType::const_iterator OpCodeMapPositionType;
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  */
104  enum eOpCodes
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  */
607  XPathExpressionException(const XalanDOMString& theMessage,
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  */
627  OpCodeMapValueType theOpCode,
628  XalanDOMString& theBuffer);
629 
630  virtual~
632 
633  private:
634 
635  static XalanDOMString&
636  FormatErrorMessage(
637  OpCodeMapValueType theOpCode,
638  XalanDOMString& theBuffer);
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  */
657  OpCodeMapValueType theOpCode,
658  OpCodeMapValueType theExpectedCount,
659  OpCodeMapValueType theSuppliedCount,
660  XalanDOMString& theBuffer);
661 
662  virtual~
664 
665  private:
666 
667  static XalanDOMString&
668  FormatErrorMessage(
669  OpCodeMapValueType theOpCode,
670  OpCodeMapValueType theExpectedCount,
671  OpCodeMapValueType theSuppliedCount,
672  XalanDOMString& theBuffer);
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  */
689  OpCodeMapValueType theOpCode,
690  OpCodeMapValueType theValue,
691  XalanDOMString& theBuffer);
692 
693  virtual~
695 
696  private:
697 
698  static XalanDOMString&
699  FormatErrorMessage(
700  OpCodeMapValueType theOpCode,
701  OpCodeMapValueType theValue,
702  XalanDOMString& theBuffer);
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  */
712  enum eDummy
713  {
714  s_opCodeMapLengthIndex = 1
715  };
716 
717  explicit
718  XPathExpression(MemoryManager& theManager);
719 
720  ~XPathExpression();
721 
722  MemoryManager&
724  {
725  return m_opMap.getMemoryManager();
726  }
727  /**
728  * Reset the expression.
729  */
730  void
731  reset();
732 
733  /**
734  * Shrink internal tables.
735  */
736  void
737  shrink();
738 
739  /**
740  * Retrieve number of elements in the operations code map.
741  *
742  * @return size of operations code map
743  */
744  OpCodeMapSizeType
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  {
774  assert(theSize == OpCodeMapValueType(theSize));
775 
776  return OpCodeMapValueType(theSize);
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  {
793  const OpCodeMapDifferenceType theDifference =
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
852  OpCodeMapSizeType theOpCodeMapIndex,
853  const OpCodeMapValueType& theValue)
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
874  getOpCodeLengthFromOpMap(OpCodeMapPositionType opPos,
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  */
885  OpCodeMapValueType
886  getOpCodeLengthFromOpMap(OpCodeMapSizeType theIndex,
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  */
898  OpCodeMapPositionType
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
939  setOpCodeArgs(
940  eOpCodes theOpCode,
941  OpCodeMapSizeType theIndex,
942  const OpCodeMapValueVectorType& theArgs);
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  */
950  OpCodeMapSizeType
951  appendOpCode(eOpCodes theOpCode);
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  */
959  OpCodeMapSizeType
961  eOpCodes theOpCode,
962  const OpCodeMapValueVectorType& theArgs)
963  {
964  const OpCodeMapSizeType thePosition = appendOpCode(theOpCode);
965 
966  setOpCodeArgs(theOpCode,
967  thePosition,
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
981  replaceOpCode(
982  OpCodeMapSizeType theIndex,
983  eOpCodes theOldOpCode,
984  eOpCodes theNewOpCode);
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  */
992  OpCodeMapValueType
993  insertOpCode(
994  eOpCodes theOpCode,
995  OpCodeMapSizeType theIndex);
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
1023  updateShiftedOpCodeLength(
1024  OpCodeMapValueType theOpCode,
1025  OpCodeMapSizeType theOriginalIndex,
1026  OpCodeMapSizeType theNewIndex);
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
1039  updateOpCodeLength(
1040  OpCodeMapValueType theOpCode,
1041  OpCodeMapSizeType theIndex);
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
1051  isNodeTestOpCode(OpCodeMapValueType theOpCode);
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
1059  updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType theIndex);
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
1163  };
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*
1175  TokenQueuePositionType theOffset,
1176  eRelativeDirection theDirection) const
1177  {
1178  const TokenQueuePositionType thePosition =
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
1197  pushToken(const XalanDOMString& theToken)
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,
1216  const XalanDOMString& theString)
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
1232  insertToken(const XalanDOMString& theToken)
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,
1252  const XalanDOMString& theString)
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
1270  TokenQueuePositionType theOffset,
1271  eRelativeDirection theDirection,
1272  const XalanDOMString& theString)
1273  {
1274  const TokenQueuePositionType thePosition =
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
1290  dumpOpCodeMap(
1291  PrintWriter& thePrintWriter,
1292  OpCodeMapSizeType theStartPosition = 0) const;
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
1301  dumpOpCodeMap(
1302  OstreamType& theStream,
1303  OpCodeMapSizeType theStartPosition = 0) const;
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
1312  dumpTokenQueue(
1313  PrintWriter& thePrintWriter,
1314  TokenQueueSizeType theStartPosition = 0) const;
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
1323  dumpTokenQueue(
1324  OstreamType& theStream,
1325  TokenQueueSizeType theStartPosition = 0) const;
1326 
1327  /**
1328  * Diagnostic function to output the remaining tokens in the token queue.
1329  *
1330  * @param thePrintWriter output device
1331  */
1332  void
1333  dumpRemainingTokenQueue(PrintWriter& thePrintWriter) const;
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
1342  dumpRemainingTokenQueue(
1343  OstreamType& theStream,
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
1353  pushValueOnOpCodeMap(const OpCodeMapType::value_type& theValue)
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
1369  pushArgumentOnOpCodeMap(const XToken& theXToken);
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
1378  pushArgumentOnOpCodeMap(const XalanDOMString& theString);
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
1388  pushArgumentOnOpCodeMap(
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
1399  pushNumberLiteralOnOpCodeMap(double theNumber);
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
1407  getNumberLiteral(int theIndex) const
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
1420  pushCurrentTokenOnOpCodeMap();
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 
1446 private:
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
xalanc::XPathExpression::pushValueOnOpCodeMap
void pushValueOnOpCodeMap(const OpCodeMapType::value_type &theValue)
Push a value onto the operations code map.
Definition: XPathExpression.hpp:1353
xalanc::XPathExpression
Definition: XPathExpression.hpp:58
xalanc::XPathExpression::isValidTokenQueuePosition
bool isValidTokenQueuePosition(TokenQueueSizeType thePosition) const
Definition: XPathExpression.hpp:1084
xalanc::XPathExpression::pushToken
void pushToken(double theNumber, const XalanDOMString &theString)
Push a token onto the token queue.
Definition: XPathExpression.hpp:1214
XALAN_CPP_NAMESPACE
#define XALAN_CPP_NAMESPACE
Xalan-C++ namespace, including major and minor version.
Definition: XalanVersion.hpp:76
xalanc::XPathExpression::appendOpCode
OpCodeMapSizeType appendOpCode(eOpCodes theOpCode, const OpCodeMapValueVectorType &theArgs)
Add an operation code with supplied arguments to the list.
Definition: XPathExpression.hpp:960
xalanc::XPathExpression::getToken
const XToken * getToken(TokenQueuePositionType thePosition) const
Retrieve a token at the specified position in the token queue.
Definition: XPathExpression.hpp:1116
XalanDOMString.hpp
xalanc::XalanVector< int >
xalanc::XPathExpression::getOpCodeArgumentLength
OpCodeMapValueType getOpCodeArgumentLength(OpCodeMapPositionType opPos) const
Definition: XPathExpression.hpp:861
xalanc::XPathExpression::getOpCodeMapValue
OpCodeMapValueType getOpCodeMapValue(OpCodeMapSizeType theIndex) const
Retrieve the value of an operation code at a specified index in the op code map.
Definition: XPathExpression.hpp:815
xalanc::XPathExpression::getMemoryManager
MemoryManager & getMemoryManager()
Definition: XPathExpression.hpp:723
xalanc::XPathExpression::isValidOpCodePosition
bool isValidOpCodePosition(OpCodeMapSizeType theIndex) const
Definition: XPathExpression.hpp:802
xalanc::size_type
size_t size_type
Definition: XalanMap.hpp:46
xalanc::XPathExpression::eRelativeDirection
eRelativeDirection
Definition: XPathExpression.hpp:1159
xalanc::XPathExpression::insertToken
void insertToken(const XalanDOMString &theToken)
Insert a token onto the token queue at the current position.
Definition: XPathExpression.hpp:1232
xalanc::XPathExpression::XPathExpressionException
Exception class thrown when an invalid XPath expression is encountered.
Definition: XPathExpression.hpp:598
xalanc::XPathExpression::setOpCodeMapValue
void setOpCodeMapValue(OpCodeMapSizeType theOpCodeMapIndex, const OpCodeMapValueType &theValue)
Set the value of an operation code at a specified index in the OpCode map.
Definition: XPathExpression.hpp:851
xalanc::XPathExpression::TokenQueueSizeType
int TokenQueueSizeType
Definition: XPathExpression.hpp:83
XalanVector.hpp
xalanc::XPathExpression::NumberLiteralValueVectorType
XalanVector< double > NumberLiteralValueVectorType
Definition: XPathExpression.hpp:72
xalanc::XPathExpression::OstreamType
std::ostream OstreamType
Definition: XPathExpression.hpp:62
xalanc::XPathExpression::eRelativeBackward
@ eRelativeBackward
Definition: XPathExpression.hpp:1161
XALAN_XPATH_EXPORT
#define XALAN_XPATH_EXPORT
Definition: XPathDefinitions.hpp:35
DOMStringHelper.hpp
xalanc::XPathExpression::getInitialOpCodePosition
OpCodeMapPositionType getInitialOpCodePosition() const
Definition: XPathExpression.hpp:781
xalanc::XPathExpression::OpCodeMapType
XalanVector< int > OpCodeMapType
Definition: XPathExpression.hpp:64
xalanc::XalanXPathException
Definition: XalanXPathException.hpp:46
xalanc::XalanVector< int >::difference_type
ptrdiff_t difference_type
Definition: XalanVector.hpp:69
xalanc::XPathExpression::getNextToken
const XToken * getNextToken()
Retrieve the next token in the token queue.
Definition: XPathExpression.hpp:1129
xalanc::XPathExpression::updateOpCodeLength
void updateOpCodeLength(OpCodeMapSizeType theIndex)
Update the length of an operation code at a specified index in the list.
Definition: XPathExpression.hpp:1007
xalanc::XPathExpression::pushToken
void pushToken(const XalanDOMString &theToken)
Push a token onto the token queue.
Definition: XPathExpression.hpp:1197
xalanc::XPathExpression::eDummy
eDummy
The length is always the opcode position + 1.
Definition: XPathExpression.hpp:712
xalanc::XPathExpression::opCodeMapSize
OpCodeMapSizeType opCodeMapSize() const
Retrieve number of elements in the operations code map.
Definition: XPathExpression.hpp:745
xalanc::XToken
Definition: XToken.hpp:41
xalanc::XPathExpression::getTokenPosition
TokenQueueSizeType getTokenPosition() const
Retrieve the current position in the token queue.
Definition: XPathExpression.hpp:1095
xalanc::XPathExpression::InvalidArgumentException
Exception class thrown when an invalid XPath argument is encountered.
Definition: XPathExpression.hpp:678
xalanc::XPathExpression::getPreviousToken
const XToken * getPreviousToken()
Retrieve the previous token in the token queue.
Definition: XPathExpression.hpp:1147
xalanc::XPathExpression::getNextOpCodePosition
OpCodeMapPositionType getNextOpCodePosition(OpCodeMapPositionType opPos) const
Retrieve the position of the next operation code at a specified position in the list.
Definition: XPathExpression.hpp:899
xalanc::XPathExpression::tokenQueueSize
TokenQueueSizeType tokenQueueSize() const
Retrieve number of elements in the token queue.
Definition: XPathExpression.hpp:1078
xalanc::XPathExpression::TokenQueueType
XalanVector< XToken > TokenQueueType
Definition: XPathExpression.hpp:65
xalanc::XPathExpression::setCurrentPattern
void setCurrentPattern(const XalanDOMString &thePattern)
Change the current pattern in the pattern map.
Definition: XPathExpression.hpp:1428
xalanc::XPathExpression::getOpCodeMapValue
OpCodeMapValueType getOpCodeMapValue(OpCodeMapPositionType opPos) const
Retrieve the value of an operation code at a specified position in the list.
Definition: XPathExpression.hpp:831
xalanc::XPathExpression::replaceRelativeToken
void replaceRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection, const XalanDOMString &theString)
Replace a token in the token queue.
Definition: XPathExpression.hpp:1269
xalanc::XPathExpression::opCodeMapLength
OpCodeMapValueType opCodeMapLength() const
Retrieve length of the operations code map stored in the map.
Definition: XPathExpression.hpp:762
xalanc::XPathExpression::insertToken
void insertToken(double theNumber, const XalanDOMString &theString)
Insert a token onto the token queue at the current position.
Definition: XPathExpression.hpp:1250
xalanc::PrintWriter
Definition: PrintWriter.hpp:37
xalanc::XPathExpression::getRelativeToken
const XToken * getRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection) const
Retrieve a token at the specified offset relative to the current position in the token queue.
Definition: XPathExpression.hpp:1174
xalanc::XPathExpression::OpCodeMapValueVectorType
XalanVector< OpCodeMapValueType > OpCodeMapValueVectorType
Definition: XPathExpression.hpp:70
PrintWriter.hpp
xalanc::XPathExpression::InvalidOpCodeException
Exception class thrown when an invalid XPath operation code is encountered.
Definition: XPathExpression.hpp:617
xalanc::XPathExpression::isValidOpCodePosition
bool isValidOpCodePosition(OpCodeMapPositionType opPos) const
Definition: XPathExpression.hpp:791
xalanc::XPathExpression::OpCodeMapValueType
OpCodeMapType::value_type OpCodeMapValueType
Definition: XPathExpression.hpp:67
XToken.hpp
xalanc::XPathExpression::TokenQueueValueType
TokenQueueType::value_type TokenQueueValueType
Definition: XPathExpression.hpp:82
xalanc::XPathExpression::OpCodeMapDifferenceType
OpCodeMapType::difference_type OpCodeMapDifferenceType
Definition: XPathExpression.hpp:81
xalanc::XPathExpression::TokenQueuePositionType
TokenQueueSizeType TokenQueuePositionType
Definition: XPathExpression.hpp:84
xalanc::XPathExpression::hasMoreTokens
bool hasMoreTokens() const
Whether there are any more tokens in the token queue.
Definition: XPathExpression.hpp:1067
xalanc::XPathExpression::OpCodeMapPositionType
OpCodeMapType::const_iterator OpCodeMapPositionType
Definition: XPathExpression.hpp:77
xalanc::XPathExpression::getCurrentPattern
const XalanDOMString & getCurrentPattern() const
Retrieve the current pattern in the pattern map.
Definition: XPathExpression.hpp:1439
xalanc::XPathExpression::getNumberLiteral
double getNumberLiteral(int theIndex) const
Get a number literal from the vector of number literals.
Definition: XPathExpression.hpp:1407
xalanc::XalanDOMString
Definition: XalanDOMString.hpp:45
xalanc::XPathExpression::InvalidArgumentCountException
Exception class thrown when an invalid number of XPath arguments is encountered.
Definition: XPathExpression.hpp:645
xalanc::XPathExpression::getNextOpCodePosition
OpCodeMapSizeType getNextOpCodePosition(OpCodeMapSizeType theIndex) const
Retrieve the position of the next operation code at a specified index in the list.
Definition: XPathExpression.hpp:916
XalanXPathException.hpp
xalanc::XPathExpression::resetTokenPosition
void resetTokenPosition()
Set the current position in the token queue to zero.
Definition: XPathExpression.hpp:1104
xalanc::XalanVector< double >::size_type
size_t size_type
Definition: XalanVector.hpp:68
xalanc::XPathExpression::eOpCodes
eOpCodes
List of operations codes.
Definition: XPathExpression.hpp:104
xalanc::XPathExpression::OpCodeMapSizeType
OpCodeMapValueType OpCodeMapSizeType
Definition: XPathExpression.hpp:68
XPathDefinitions.hpp