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)
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
void setOpCodeMapValue(OpCodeMapSizeType theOpCodeMapIndex, const OpCodeMapValueType &theValue)
Set the value of an operation code at a specified index in the OpCode map.
OpCodeMapValueType getOpCodeMapValue(OpCodeMapPositionType opPos) const
Retrieve the value of an operation code at a specified position in the list.
XalanVector< double > NumberLiteralValueVectorType
OpCodeMapPositionType getNextOpCodePosition(OpCodeMapPositionType opPos) const
Retrieve the position of the next operation code at a specified position in the list.
Exception class thrown when an invalid number of XPath arguments is encountered.
void replaceRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection, const XalanDOMString &theString)
Replace a token in the token queue.
OpCodeMapValueType getOpCodeMapValue(OpCodeMapSizeType theIndex) const
Retrieve the value of an operation code at a specified index in the op code map.
bool hasMoreTokens() const
Whether there are any more tokens in the token queue.
OpCodeMapType::const_iterator OpCodeMapPositionType
bool isValidOpCodePosition(OpCodeMapPositionType opPos) const
OpCodeMapType::value_type OpCodeMapValueType
void resetTokenPosition()
Set the current position in the token queue to zero.
TokenQueueSizeType tokenQueueSize() const
Retrieve number of elements in the token queue.
const XToken * getToken(TokenQueuePositionType thePosition) const
Retrieve a token at the specified position in the token queue.
#define XALAN_CPP_NAMESPACE
Xalan-C++ namespace, including major and minor version.
XalanVector< OpCodeMapValueType > OpCodeMapValueVectorType
OpCodeMapSizeType getNextOpCodePosition(OpCodeMapSizeType theIndex) const
Retrieve the position of the next operation code at a specified index in the list.
const XToken * getPreviousToken()
Retrieve the previous token in the token queue.
XalanVector< XToken > TokenQueueType
OpCodeMapSizeType appendOpCode(eOpCodes theOpCode, const OpCodeMapValueVectorType &theArgs)
Add an operation code with supplied arguments to the list.
OpCodeMapValueType OpCodeMapSizeType
TokenQueueType::value_type TokenQueueValueType
Exception class thrown when an invalid XPath operation code is encountered.
MemoryManager & getMemoryManager()
void insertToken(double theNumber, const XalanDOMString &theString)
Insert a token onto the token queue at the current position.
void updateOpCodeLength(OpCodeMapSizeType theIndex)
Update the length of an operation code at a specified index in the list.
bool isValidOpCodePosition(OpCodeMapSizeType theIndex) const
void pushToken(double theNumber, const XalanDOMString &theString)
Push a token onto the token queue.
const XalanDOMString & getCurrentPattern() const
Retrieve the current pattern in the pattern map.
OpCodeMapSizeType opCodeMapSize() const
Retrieve number of elements in the operations code map.
const XToken * getRelativeToken(TokenQueuePositionType theOffset, eRelativeDirection theDirection) const
Retrieve a token at the specified offset relative to the current position in the token queue...
Exception class thrown when an invalid XPath expression is encountered.
void setCurrentPattern(const XalanDOMString &thePattern)
Change the current pattern in the pattern map.
void pushValueOnOpCodeMap(const OpCodeMapType::value_type &theValue)
Push a value onto the operations code map.
bool isValidTokenQueuePosition(TokenQueueSizeType thePosition) const
OpCodeMapValueType opCodeMapLength() const
Retrieve length of the operations code map stored in the map.
OpCodeMapPositionType getInitialOpCodePosition() const
OpCodeMapValueType getOpCodeArgumentLength(OpCodeMapPositionType opPos) const
void insertToken(const XalanDOMString &theToken)
Insert a token onto the token queue at the current position.
const XToken * getNextToken()
Retrieve the next token in the token queue.
void pushToken(const XalanDOMString &theToken)
Push a token onto the token queue.
TokenQueueSizeType TokenQueuePositionType
eDummy
The length is always the opcode position + 1.
TokenQueueSizeType getTokenPosition() const
Retrieve the current position in the token queue.
XalanVector< int > OpCodeMapType
const value_type * const_iterator
Definition: XalanVector.hpp:72
double getNumberLiteral(int theIndex) const
Get a number literal from the vector of number literals.
Exception class thrown when an invalid XPath argument is encountered.
eOpCodes
List of operations codes.
#define XALAN_XPATH_EXPORT
size_t size_type
Definition: XalanMap.hpp:46
OpCodeMapType::difference_type OpCodeMapDifferenceType