00001 /* 00002 * Copyright 1999-2004 The Apache Software Foundation. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #if !defined(XPATHEXPRESSION_HEADER_GUARD_1357924680) 00017 #define XPATHEXPRESSION_HEADER_GUARD_1357924680 00018 00019 00020 00021 // Base header file. Must be first. 00022 #include <xalanc/XPath/XPathDefinitions.hpp> 00023 00024 00025 00026 #include <xalanc/Include/XalanVector.hpp> 00027 00028 00029 00030 #if defined(XALAN_CLASSIC_IOSTREAMS) 00031 #include <iostream.h> 00032 #else 00033 #include <iosfwd> 00034 #endif 00035 00036 00037 00038 #include <xalanc/XalanDOM/XalanDOMString.hpp> 00039 00040 00041 00042 #include <xalanc/PlatformSupport/DOMStringHelper.hpp> 00043 #include <xalanc/PlatformSupport/PrintWriter.hpp> 00044 00045 00046 00047 #include <xalanc/XPath/XToken.hpp> 00048 #include <xalanc/XPath/XalanXPathException.hpp> 00049 00050 00051 00052 XALAN_CPP_NAMESPACE_BEGIN 00053 00054 00055 00056 class XALAN_XPATH_EXPORT XPathExpression 00057 { 00058 public: 00059 00060 typedef XALAN_STD_QUALIFIER ostream OstreamType; 00061 00062 typedef XalanVector<int> OpCodeMapType; 00063 typedef XalanVector<XToken> TokenQueueType; 00064 00065 typedef OpCodeMapType::value_type OpCodeMapValueType; 00066 typedef OpCodeMapValueType OpCodeMapSizeType; 00067 00068 typedef XalanVector<OpCodeMapValueType> OpCodeMapValueVectorType; 00069 00070 typedef XalanVector<double> NumberLiteralValueVectorType; 00071 00072 #define XALAN_XPATH_EXPRESSION_USE_ITERATORS 00073 00074 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00075 typedef OpCodeMapType::const_iterator OpCodeMapPositionType; 00076 #else 00077 typedef OpCodeMapSizeType OpCodeMapPositionType; 00078 #endif 00079 typedef OpCodeMapType::difference_type OpCodeMapDifferenceType; 00080 typedef TokenQueueType::value_type TokenQueueValueType; 00081 typedef int TokenQueueSizeType; 00082 typedef TokenQueueSizeType TokenQueuePositionType; 00083 00102 enum eOpCodes 00103 { 00109 eELEMWILDCARD = -3, 00110 00115 eEMPTY = -2, 00116 00121 eENDOP = -1, 00122 00136 eOP_XPATH = 1, 00137 00147 eOP_OR = 2, 00148 00158 eOP_AND = 3, 00159 00169 eOP_NOTEQUALS = 4, 00170 00180 eOP_EQUALS = 5, 00181 00191 eOP_LTE = 6, 00192 00202 eOP_LT = 7, 00203 00213 eOP_GTE = 8, 00214 00224 eOP_GT = 9, 00225 00235 eOP_PLUS = 10, 00236 00246 eOP_MINUS = 11, 00247 00257 eOP_MULT = 12, 00258 00268 eOP_DIV = 13, 00269 00279 eOP_MOD = 14, 00280 00289 eOP_NEG = 15, 00290 00299 eOP_BOOL = 16, 00300 00309 eOP_UNION = 17, 00310 00319 eOP_LITERAL = 18, 00320 00329 eOP_VARIABLE = 19, 00330 00344 eOP_GROUP = 20, 00345 00354 eOP_NUMBERLIT = 21, 00355 00369 eOP_ARGUMENT = 22, 00370 00386 eOP_EXTFUNCTION = 23, 00387 00404 eOP_FUNCTION = 24, 00405 00419 eOP_LOCATIONPATH = 25, 00420 00430 eOP_PREDICATE = 26, 00431 00439 eNODETYPE_COMMENT = 27, 00440 00448 eNODETYPE_TEXT = 28, 00449 00457 eNODETYPE_PI = 29, 00458 00466 eNODETYPE_NODE = 30, 00467 00476 eNODENAME = 31, 00477 00485 eNODETYPE_ROOT = 32, 00486 00494 eNODETYPE_ANYELEMENT = 33, 00495 00506 eFROM_ANCESTORS = 34, 00507 eFROM_ANCESTORS_OR_SELF = 35, 00508 eFROM_ATTRIBUTES = 36, 00509 eFROM_CHILDREN = 37, 00510 eFROM_DESCENDANTS = 38, 00511 eFROM_DESCENDANTS_OR_SELF = 39, 00512 eFROM_FOLLOWING = 40, 00513 eFROM_FOLLOWING_SIBLINGS = 41, 00514 eFROM_PARENT = 42, 00515 eFROM_PRECEDING = 43, 00516 eFROM_PRECEDING_SIBLINGS = 44, 00517 eFROM_SELF = 45, 00518 eFROM_NAMESPACE = 46, 00519 eFROM_ROOT = 47, 00520 00529 eOP_MATCHPATTERN = 48, 00530 00539 eOP_LOCATIONPATHPATTERN = 49, 00540 00541 // For match patterns 00542 eMATCH_ATTRIBUTE = 50, 00543 eMATCH_ANY_ANCESTOR = 51, 00544 eMATCH_IMMEDIATE_ANCESTOR = 52, 00545 eMATCH_ANY_ANCESTOR_WITH_PREDICATE = 53, 00546 eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL = 54, 00547 00557 eOP_PREDICATE_WITH_POSITION = 55, 00558 00563 eOP_FUNCTION_POSITION = 56, 00564 eOP_FUNCTION_LAST = 57, 00565 eOP_FUNCTION_COUNT = 58, 00566 eOP_FUNCTION_NOT = 59, 00567 eOP_FUNCTION_TRUE = 60, 00568 eOP_FUNCTION_FALSE = 61, 00569 eOP_FUNCTION_BOOLEAN = 62, 00570 eOP_FUNCTION_NAME_0 = 63, 00571 eOP_FUNCTION_NAME_1 = 64, 00572 eOP_FUNCTION_LOCALNAME_0 = 65, 00573 eOP_FUNCTION_LOCALNAME_1 = 66, 00574 eOP_FUNCTION_FLOOR = 67, 00575 eOP_FUNCTION_CEILING = 68, 00576 eOP_FUNCTION_ROUND = 69, 00577 eOP_FUNCTION_NUMBER_0 = 70, 00578 eOP_FUNCTION_NUMBER_1 = 71, 00579 eOP_FUNCTION_STRING_0 = 72, 00580 eOP_FUNCTION_STRING_1 = 73, 00581 eOP_FUNCTION_STRINGLENGTH_0 = 74, 00582 eOP_FUNCTION_STRINGLENGTH_1 = 75, 00583 eOP_FUNCTION_NAMESPACEURI_0 = 76, 00584 eOP_FUNCTION_NAMESPACEURI_1 = 77, 00585 eOP_FUNCTION_SUM = 78, 00586 eOP_FUNCTION_CONCAT = 79, 00587 00588 // Always add _before_ this one and update 00589 // s_opCodeLengthArray. 00590 eOpCodeNextAvailable 00591 }; // enum eOpCodes 00592 00596 class XALAN_XPATH_EXPORT XPathExpressionException : public XalanXPathException 00597 { 00598 public: 00599 00605 XPathExpressionException(const XalanDOMString& theMessage, 00606 MemoryManagerType& theManager); 00607 00608 virtual~ 00609 XPathExpressionException(); 00610 }; 00611 00615 class XALAN_XPATH_EXPORT InvalidOpCodeException : public XPathExpressionException 00616 { 00617 public: 00618 00624 InvalidOpCodeException(OpCodeMapValueType theOpCode, 00625 XalanDOMString& theResult); 00626 00627 virtual~ 00628 InvalidOpCodeException(); 00629 00630 private: 00631 00632 static XalanDOMString& 00633 FormatErrorMessage(OpCodeMapValueType theOpCode, 00634 XalanDOMString& theResult); 00635 }; 00636 00641 class XALAN_XPATH_EXPORT InvalidArgumentCountException : public XPathExpressionException 00642 { 00643 public: 00644 00652 InvalidArgumentCountException( 00653 OpCodeMapValueType theOpCode, 00654 OpCodeMapValueType theExpectedCount, 00655 OpCodeMapValueType theSuppliedCount, 00656 XalanDOMString& theResult); 00657 00658 virtual~ 00659 InvalidArgumentCountException(); 00660 00661 private: 00662 00663 static XalanDOMString& 00664 FormatErrorMessage( 00665 OpCodeMapValueType theOpCode, 00666 OpCodeMapValueType theExpectedCount, 00667 OpCodeMapValueType theSuppliedCount, 00668 XalanDOMString& theResult); 00669 }; 00670 00674 class XALAN_XPATH_EXPORT InvalidArgumentException : public XPathExpressionException 00675 { 00676 public: 00677 00684 InvalidArgumentException( 00685 OpCodeMapValueType theOpCode, 00686 OpCodeMapValueType theValue, 00687 XalanDOMString& theResult); 00688 00689 virtual~ 00690 InvalidArgumentException(); 00691 00692 private: 00693 00694 static XalanDOMString& 00695 FormatErrorMessage( 00696 OpCodeMapValueType theOpCode, 00697 OpCodeMapValueType theValue, 00698 XalanDOMString& theResult); 00699 }; 00700 00701 00708 #if defined(XALAN_INLINE_INITIALIZATION) 00709 static const TokenQueueSizeType s_opCodeMapLengthIndex = 1; 00710 #else 00711 enum eDummy 00712 { 00713 s_opCodeMapLengthIndex = 1 00714 }; 00715 #endif 00716 00717 explicit 00718 XPathExpression(MemoryManagerType& theManager); 00719 00720 ~XPathExpression(); 00721 00722 MemoryManagerType& 00723 getMemoryManager() 00724 { 00725 return m_opMap.getMemoryManager(); 00726 } 00730 void 00731 reset(); 00732 00736 void 00737 shrink(); 00738 00744 OpCodeMapSizeType 00745 opCodeMapSize() const 00746 { 00747 return OpCodeMapSizeType(m_opMap.size()); 00748 } 00749 00761 OpCodeMapValueType 00762 opCodeMapLength() const 00763 { 00764 const OpCodeMapSizeType theSize = opCodeMapSize(); 00765 00766 if (theSize > s_opCodeMapLengthIndex) 00767 { 00768 assert(theSize == OpCodeMapSizeType(m_opMap[s_opCodeMapLengthIndex])); 00769 00770 return m_opMap[s_opCodeMapLengthIndex]; 00771 } 00772 else 00773 { 00774 assert(theSize == OpCodeMapValueType(theSize)); 00775 00776 return OpCodeMapValueType(theSize); 00777 } 00778 } 00779 00780 OpCodeMapPositionType 00781 getInitialOpCodePosition() const 00782 { 00783 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00784 return m_opMap.begin(); 00785 #else 00786 return 0; 00787 #endif 00788 } 00789 00790 bool 00791 isValidOpCodePosition(OpCodeMapPositionType opPos) const 00792 { 00793 const OpCodeMapDifferenceType theDifference = 00794 OpCodeMapDifferenceType(opPos - getInitialOpCodePosition()); 00795 00796 return theDifference >= 0 && 00797 theDifference < opCodeMapSize(); 00798 } 00799 00800 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00801 bool 00802 isValidOpCodePosition(OpCodeMapSizeType theIndex) const 00803 { 00804 return theIndex >= 0 && theIndex < opCodeMapSize(); 00805 } 00806 00814 OpCodeMapValueType 00815 getOpCodeMapValue(OpCodeMapSizeType theIndex) const 00816 { 00817 assert(theIndex < opCodeMapLength()); 00818 00819 return m_opMap[theIndex]; 00820 } 00821 #endif 00822 00830 OpCodeMapValueType 00831 getOpCodeMapValue(OpCodeMapPositionType opPos) const 00832 { 00833 assert(opPos < getInitialOpCodePosition() + opCodeMapLength()); 00834 00835 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00836 return *opPos; 00837 #else 00838 00839 return m_opMap[opPos]; 00840 #endif 00841 } 00842 00850 void 00851 setOpCodeMapValue( 00852 OpCodeMapSizeType theOpCodeMapIndex, 00853 const OpCodeMapValueType& theValue) 00854 { 00855 assert(theOpCodeMapIndex < opCodeMapLength()); 00856 00857 m_opMap[theOpCodeMapIndex] = theValue; 00858 } 00859 00860 OpCodeMapValueType 00861 getOpCodeArgumentLength(OpCodeMapPositionType opPos) const 00862 { 00863 return getOpCodeMapValue(opPos + XPathExpression::s_opCodeMapLengthIndex + 1) - 3; 00864 } 00865 00873 OpCodeMapValueType 00874 getOpCodeLengthFromOpMap(OpCodeMapPositionType opPos, 00875 MemoryManagerType& theManager) const; 00876 00877 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00878 00885 OpCodeMapValueType 00886 getOpCodeLengthFromOpMap(OpCodeMapSizeType theIndex, 00887 MemoryManagerType& theManager) const; 00888 #endif 00889 00890 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00891 00898 OpCodeMapPositionType 00899 getNextOpCodePosition(OpCodeMapPositionType opPos) const 00900 { 00901 assert(opPos < getInitialOpCodePosition() + opCodeMapLength()); 00902 00903 return opPos + *(opPos + s_opCodeMapLengthIndex); 00904 } 00905 #endif 00906 00914 OpCodeMapSizeType 00915 #if defined(XALAN_XPATH_EXPRESSION_USE_ITERATORS) 00916 getNextOpCodePosition(OpCodeMapSizeType theIndex) const 00917 #else 00918 getNextOpCodePosition(OpCodeMapPositionType theIndex) const 00919 #endif 00920 { 00921 assert(theIndex < opCodeMapLength()); 00922 00923 assert(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex] == 00924 OpCodeMapSizeType(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex])); 00925 00926 return OpCodeMapSizeType(theIndex + m_opMap[theIndex + s_opCodeMapLengthIndex]); 00927 } 00928 00938 void 00939 setOpCodeArgs( 00940 eOpCodes theOpCode, 00941 OpCodeMapSizeType theIndex, 00942 const OpCodeMapValueVectorType& theArgs); 00943 00950 OpCodeMapSizeType 00951 appendOpCode(eOpCodes theOpCode); 00952 00959 OpCodeMapSizeType 00960 appendOpCode( 00961 eOpCodes theOpCode, 00962 const OpCodeMapValueVectorType& theArgs) 00963 { 00964 const OpCodeMapSizeType thePosition = appendOpCode(theOpCode); 00965 00966 setOpCodeArgs(theOpCode, 00967 thePosition, 00968 theArgs); 00969 00970 return thePosition; 00971 } 00972 00980 void 00981 replaceOpCode( 00982 OpCodeMapSizeType theIndex, 00983 eOpCodes theOldOpCode, 00984 eOpCodes theNewOpCode); 00985 00992 OpCodeMapValueType 00993 insertOpCode( 00994 eOpCodes theOpCode, 00995 OpCodeMapSizeType theIndex); 00996 01006 void 01007 updateOpCodeLength(OpCodeMapSizeType theIndex) 01008 { 01009 assert(theIndex < opCodeMapSize()); 01010 01011 updateOpCodeLength(m_opMap[theIndex], theIndex); 01012 } 01013 01022 void 01023 updateShiftedOpCodeLength( 01024 OpCodeMapValueType theOpCode, 01025 OpCodeMapSizeType theOriginalIndex, 01026 OpCodeMapSizeType theNewIndex); 01027 01038 void 01039 updateOpCodeLength( 01040 OpCodeMapValueType theOpCode, 01041 OpCodeMapSizeType theIndex); 01042 01050 static bool 01051 isNodeTestOpCode(OpCodeMapValueType theOpCode); 01052 01058 void 01059 updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType theIndex); 01060 01066 bool 01067 hasMoreTokens() const 01068 { 01069 return tokenQueueSize() > m_currentPosition ? true : false; 01070 } 01071 01077 TokenQueueSizeType 01078 tokenQueueSize() const 01079 { 01080 return TokenQueueSizeType(m_tokenQueue.size()); 01081 } 01082 01083 bool 01084 isValidTokenQueuePosition(TokenQueueSizeType thePosition) const 01085 { 01086 return thePosition < tokenQueueSize(); 01087 } 01088 01094 TokenQueueSizeType 01095 getTokenPosition() const 01096 { 01097 return m_currentPosition; 01098 } 01099 01103 void 01104 resetTokenPosition() 01105 { 01106 m_currentPosition = 0; 01107 } 01108 01115 const XToken* 01116 getToken(TokenQueuePositionType thePosition) const 01117 { 01118 assert(thePosition < tokenQueueSize()); 01119 01120 return &m_tokenQueue[thePosition]; 01121 } 01122 01128 const XToken* 01129 getNextToken() 01130 { 01131 if (hasMoreTokens() == true) 01132 { 01133 return getToken(m_currentPosition++); 01134 } 01135 else 01136 { 01137 return 0; 01138 } 01139 } 01140 01146 const XToken* 01147 getPreviousToken() 01148 { 01149 if (m_currentPosition > 0) 01150 { 01151 return getToken(--m_currentPosition); 01152 } 01153 else 01154 { 01155 return 0; 01156 } 01157 } 01158 01159 enum eRelativeDirection 01160 { 01161 eRelativeBackward, 01162 eRelativeForward 01163 }; 01164 01173 const XToken* 01174 getRelativeToken( 01175 TokenQueuePositionType theOffset, 01176 eRelativeDirection theDirection) const 01177 { 01178 const TokenQueuePositionType thePosition = 01179 calculateRelativePosition(theOffset, theDirection); 01180 01181 if (thePosition == tokenQueueSize()) 01182 { 01183 return 0; 01184 } 01185 else 01186 { 01187 return getToken(thePosition); 01188 } 01189 } 01190 01196 void 01197 pushToken(const XalanDOMString& theToken) 01198 { 01199 m_tokenQueue.push_back(XToken(theToken, getMemoryManager())); 01200 } 01201 01208 void 01209 pushToken( 01210 double theNumber, 01211 const XalanDOMString& theString) 01212 { 01213 m_tokenQueue.push_back(XToken(theNumber, theString)); 01214 } 01215 01222 void 01223 insertToken(const XalanDOMString& theToken) 01224 { 01225 m_tokenQueue.insert(m_tokenQueue.begin() + (m_currentPosition - 1), XToken(theToken, getMemoryManager())); 01226 } 01227 01235 void 01236 insertToken( 01237 double theNumber, 01238 const XalanDOMString& theString) 01239 { 01240 m_tokenQueue.insert(m_tokenQueue.begin() + (m_currentPosition - 1), XToken(theNumber, theString)); 01241 } 01242 01249 void 01250 replaceRelativeToken( 01251 TokenQueuePositionType theOffset, 01252 eRelativeDirection theDirection, 01253 const XalanDOMString& theString) 01254 { 01255 const TokenQueuePositionType thePosition = 01256 calculateRelativePosition(theOffset, theDirection); 01257 assert(thePosition < tokenQueueSize()); 01258 01259 m_tokenQueue[thePosition].set(theString, getMemoryManager()); 01260 } 01261 01268 void 01269 dumpOpCodeMap( 01270 PrintWriter& thePrintWriter, 01271 OpCodeMapSizeType theStartPosition = 0) const; 01272 01279 void 01280 dumpOpCodeMap( 01281 OstreamType& theStream, 01282 OpCodeMapSizeType theStartPosition = 0) const; 01283 01290 void 01291 dumpTokenQueue( 01292 PrintWriter& thePrintWriter, 01293 TokenQueueSizeType theStartPosition = 0) const; 01294 01301 void 01302 dumpTokenQueue( 01303 OstreamType& theStream, 01304 TokenQueueSizeType theStartPosition = 0) const; 01305 01311 void 01312 dumpRemainingTokenQueue(PrintWriter& thePrintWriter) const; 01313 01319 void 01320 dumpRemainingTokenQueue(OstreamType& theStream) const; 01321 01328 void 01329 pushValueOnOpCodeMap(const OpCodeMapType::value_type& theValue) 01330 { 01331 // Push the index onto the op map. 01332 m_opMap.push_back(theValue); 01333 01334 // Update the op map length. 01335 ++m_opMap[s_opCodeMapLengthIndex]; 01336 } 01337 01344 void 01345 pushArgumentOnOpCodeMap(const XToken& theXToken); 01346 01353 void 01354 pushArgumentOnOpCodeMap(const XalanDOMString& theString); 01355 01363 void 01364 pushArgumentOnOpCodeMap( 01365 double theNumber, 01366 const XalanDOMString& theString); 01367 01374 void 01375 pushNumberLiteralOnOpCodeMap(double theNumber); 01376 01382 double 01383 getNumberLiteral(int theIndex) const 01384 { 01385 assert(theIndex >= 0 && 01386 NumberLiteralValueVectorType::size_type(theIndex) < m_numberLiteralValues.size()); 01387 01388 return m_numberLiteralValues[NumberLiteralValueVectorType::size_type(theIndex)]; 01389 } 01390 01395 void 01396 pushCurrentTokenOnOpCodeMap(); 01397 01403 void 01404 setCurrentPattern(const XalanDOMString& thePattern) 01405 { 01406 m_currentPattern = &thePattern; 01407 } 01408 01414 const XalanDOMString& 01415 getCurrentPattern() const 01416 { 01417 assert(m_currentPattern != 0); 01418 01419 return *m_currentPattern; 01420 } 01421 01422 private: 01423 01433 TokenQueuePositionType 01434 calculateRelativePosition( 01435 TokenQueuePositionType theOffset, 01436 eRelativeDirection theDirection) const 01437 { 01438 if (theDirection == eRelativeBackward && 01439 theOffset <= m_currentPosition) 01440 { 01441 return m_currentPosition - theOffset; 01442 } 01443 else if (theDirection == eRelativeForward && 01444 m_currentPosition + theOffset < tokenQueueSize()) 01445 { 01446 return m_currentPosition + theOffset; 01447 } 01448 else 01449 { 01450 return tokenQueueSize(); 01451 } 01452 } 01453 01460 OpCodeMapType m_opMap; 01461 01466 OpCodeMapSizeType m_lastOpCodeIndex; 01467 01473 TokenQueueType m_tokenQueue; 01474 01478 TokenQueueSizeType m_currentPosition; 01479 01483 const XalanDOMString* m_currentPattern; 01484 01485 // Default vector allocation sizes. 01486 enum 01487 { 01488 eDefaultOpMapSize = 100, 01489 eDefaultTokenQueueSize = 30 01490 }; 01491 01492 NumberLiteralValueVectorType m_numberLiteralValues; 01493 }; 01494 01495 01496 01497 XALAN_CPP_NAMESPACE_END 01498 01499 01500 01501 #endif // XPATHEXPRESSION_HEADER_GUARD_1357924680
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.9 |
|