00001 /* 00002 * The Apache Software License, Version 1.1 00003 * 00004 * 00005 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights 00006 * reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in 00017 * the documentation and/or other materials provided with the 00018 * distribution. 00019 * 00020 * 3. The end-user documentation included with the redistribution, 00021 * if any, must include the following acknowledgment: 00022 * "This product includes software developed by the 00023 * Apache Software Foundation (http://www.apache.org/)." 00024 * Alternately, this acknowledgment may appear in the software itself, 00025 * if and wherever such third-party acknowledgments normally appear. 00026 * 00027 * 4. The names "Xalan" and "Apache Software Foundation" must 00028 * not be used to endorse or promote products derived from this 00029 * software without prior written permission. For written 00030 * permission, please contact apache@apache.org. 00031 * 00032 * 5. Products derived from this software may not be called "Apache", 00033 * nor may "Apache" appear in their name, without prior written 00034 * permission of the Apache Software Foundation. 00035 * 00036 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 00037 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00038 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00039 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 00040 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00041 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00042 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00043 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00044 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00045 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00046 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00047 * SUCH DAMAGE. 00048 * ==================================================================== 00049 * 00050 * This software consists of voluntary contributions made by many 00051 * individuals on behalf of the Apache Software Foundation and was 00052 * originally based on software copyright (c) 1999, International 00053 * Business Machines, Inc., http://www.ibm.com. For more 00054 * information on the Apache Software Foundation, please see 00055 * <http://www.apache.org/>. 00056 */ 00057 #if !defined(XPATHEXPRESSION_HEADER_GUARD_1357924680) 00058 #define XPATHEXPRESSION_HEADER_GUARD_1357924680 00059 00060 00061 00062 // Base header file. Must be first. 00063 #include <xalanc/XPath/XPathDefinitions.hpp> 00064 00065 00066 00067 #include <vector> 00068 00069 #if defined(XALAN_CLASSIC_IOSTREAMS) 00070 #include <iostream.h> 00071 #else 00072 #include <iosfwd> 00073 #endif 00074 00075 00076 00077 #include <xalanc/XalanDOM/XalanDOMString.hpp> 00078 00079 00080 00081 #include <xalanc/PlatformSupport/DOMStringHelper.hpp> 00082 #include <xalanc/PlatformSupport/PrintWriter.hpp> 00083 00084 00085 00086 #include <xalanc/XPath/XToken.hpp> 00087 #include <xalanc/XPath/XalanXPathException.hpp> 00088 00089 00090 00091 XALAN_CPP_NAMESPACE_BEGIN 00092 00093 00094 00095 class XALAN_XPATH_EXPORT XPathExpression 00096 { 00097 public: 00098 00099 #if defined(XALAN_NO_STD_NAMESPACE) 00100 typedef ostream OstreamType; 00101 #else 00102 typedef std::ostream OstreamType; 00103 #endif 00104 00123 enum eOpCodes 00124 { 00130 eELEMWILDCARD = -3, 00131 00136 eEMPTY = -2, 00137 00142 eENDOP = -1, 00143 00157 eOP_XPATH = 1, 00158 00168 eOP_OR = 2, 00169 00179 eOP_AND = 3, 00180 00190 eOP_NOTEQUALS = 4, 00191 00201 eOP_EQUALS = 5, 00202 00212 eOP_LTE = 6, 00213 00223 eOP_LT = 7, 00224 00234 eOP_GTE = 8, 00235 00245 eOP_GT = 9, 00246 00256 eOP_PLUS = 10, 00257 00267 eOP_MINUS = 11, 00268 00278 eOP_MULT = 12, 00279 00289 eOP_DIV = 13, 00290 00300 eOP_MOD = 14, 00301 00310 eOP_NEG = 15, 00311 00320 eOP_BOOL = 16, 00321 00330 eOP_UNION = 17, 00331 00340 eOP_LITERAL = 18, 00341 00350 eOP_VARIABLE = 19, 00351 00365 eOP_GROUP = 20, 00366 00375 eOP_NUMBERLIT = 21, 00376 00390 eOP_ARGUMENT = 22, 00391 00407 eOP_EXTFUNCTION = 23, 00408 00425 eOP_FUNCTION = 24, 00426 00440 eOP_LOCATIONPATH = 25, 00441 00451 eOP_PREDICATE = 26, 00452 00460 eNODETYPE_COMMENT = 27, 00461 00469 eNODETYPE_TEXT = 28, 00470 00478 eNODETYPE_PI = 29, 00479 00487 eNODETYPE_NODE = 30, 00488 00497 eNODENAME = 31, 00498 00506 eNODETYPE_ROOT = 32, 00507 00515 eNODETYPE_ANYELEMENT = 33, 00516 00527 eFROM_ANCESTORS = 34, 00528 eFROM_ANCESTORS_OR_SELF = 35, 00529 eFROM_ATTRIBUTES = 36, 00530 eFROM_CHILDREN = 37, 00531 eFROM_DESCENDANTS = 38, 00532 eFROM_DESCENDANTS_OR_SELF = 39, 00533 eFROM_FOLLOWING = 40, 00534 eFROM_FOLLOWING_SIBLINGS = 41, 00535 eFROM_PARENT = 42, 00536 eFROM_PRECEDING = 43, 00537 eFROM_PRECEDING_SIBLINGS = 44, 00538 eFROM_SELF = 45, 00539 eFROM_NAMESPACE = 46, 00540 eFROM_ROOT = 47, 00541 00550 eOP_MATCHPATTERN = 48, 00551 00560 eOP_LOCATIONPATHPATTERN = 49, 00561 00562 // For match patterns 00563 eMATCH_ATTRIBUTE = 50, 00564 eMATCH_ANY_ANCESTOR = 51, 00565 eMATCH_IMMEDIATE_ANCESTOR = 52, 00566 eMATCH_ANY_ANCESTOR_WITH_PREDICATE = 53, 00567 eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL = 54, 00568 00578 eOP_PREDICATE_WITH_POSITION = 55, 00579 00584 eOP_FUNCTION_POSITION = 56, 00585 eOP_FUNCTION_LAST = 57, 00586 eOP_FUNCTION_COUNT = 58, 00587 eOP_FUNCTION_NOT = 59, 00588 eOP_FUNCTION_TRUE = 60, 00589 eOP_FUNCTION_FALSE = 61, 00590 eOP_FUNCTION_BOOLEAN = 62, 00591 eOP_FUNCTION_NAME_0 = 63, 00592 eOP_FUNCTION_NAME_1 = 64, 00593 eOP_FUNCTION_LOCALNAME_0 = 65, 00594 eOP_FUNCTION_LOCALNAME_1 = 66, 00595 eOP_FUNCTION_FLOOR = 67, 00596 eOP_FUNCTION_CEILING = 68, 00597 eOP_FUNCTION_ROUND = 69, 00598 eOP_FUNCTION_NUMBER_0 = 70, 00599 eOP_FUNCTION_NUMBER_1 = 71, 00600 eOP_FUNCTION_STRING_0 = 72, 00601 eOP_FUNCTION_STRING_1 = 73, 00602 eOP_FUNCTION_STRINGLENGTH_0 = 74, 00603 eOP_FUNCTION_STRINGLENGTH_1 = 75, 00604 eOP_FUNCTION_NAMESPACEURI_0 = 76, 00605 eOP_FUNCTION_NAMESPACEURI_1 = 77, 00606 eOP_FUNCTION_SUM = 78, 00607 eOP_FUNCTION_CONCAT = 79, 00608 00609 // Always add _before_ this one and update 00610 // s_opCodeLengthArray. 00611 eOpCodeNextAvailable 00612 }; // enum eOpCodes 00613 00617 class XALAN_XPATH_EXPORT XPathExpressionException : public XalanXPathException 00618 { 00619 public: 00620 00626 XPathExpressionException(const XalanDOMString& theMessage); 00627 00628 virtual~ 00629 XPathExpressionException(); 00630 }; 00631 00635 class XALAN_XPATH_EXPORT InvalidOpCodeException : public XPathExpressionException 00636 { 00637 public: 00638 00644 InvalidOpCodeException(int theOpCode); 00645 00646 virtual~ 00647 InvalidOpCodeException(); 00648 00649 private: 00650 00651 static XalanDOMString 00652 FormatErrorMessage(int theOpCode); 00653 }; 00654 00659 class XALAN_XPATH_EXPORT InvalidArgumentCountException : public XPathExpressionException 00660 { 00661 public: 00662 00670 InvalidArgumentCountException( 00671 int theOpCode, 00672 int theExpectedCount, 00673 int theSuppliedCount); 00674 00675 virtual~ 00676 InvalidArgumentCountException(); 00677 00678 private: 00679 00680 static XalanDOMString 00681 FormatErrorMessage( 00682 int theOpCode, 00683 int theExpectedCount, 00684 int theSuppliedCount); 00685 }; 00686 00690 class XALAN_XPATH_EXPORT InvalidArgumentException : public XPathExpressionException 00691 { 00692 public: 00693 00700 InvalidArgumentException( 00701 int theOpCode, 00702 int theValue); 00703 00704 virtual~ 00705 InvalidArgumentException(); 00706 00707 private: 00708 00709 static XalanDOMString 00710 FormatErrorMessage( 00711 int theOpCode, 00712 int theValue); 00713 }; 00714 00718 class XALAN_XPATH_EXPORT InvalidRelativeTokenPosition : public XPathExpressionException 00719 { 00720 public: 00721 00727 InvalidRelativeTokenPosition(int theOffset); 00728 00729 virtual~ 00730 InvalidRelativeTokenPosition(); 00731 00732 private: 00733 00734 static XalanDOMString 00735 FormatErrorMessage(int theOffset); 00736 }; 00737 00738 00739 #if defined(XALAN_NO_STD_NAMESPACE) 00740 00741 typedef vector<int> OpCodeMapType; 00742 typedef vector<XToken> TokenQueueType; 00743 00744 typedef OpCodeMapType::value_type OpCodeMapValueType; 00745 typedef OpCodeMapType::size_type OpCodeMapSizeType; 00746 00747 typedef vector<OpCodeMapValueType> OpCodeMapValueVectorType; 00748 00749 typedef vector<double> NumberLiteralValueVectorType; 00750 #else 00751 00752 typedef std::vector<int> OpCodeMapType; 00753 typedef std::vector<XToken> TokenQueueType; 00754 00755 typedef OpCodeMapType::value_type OpCodeMapValueType; 00756 typedef OpCodeMapType::size_type OpCodeMapSizeType; 00757 00758 typedef std::vector<OpCodeMapValueType> OpCodeMapValueVectorType; 00759 00760 typedef std::vector<double> NumberLiteralValueVectorType; 00761 #endif 00762 00763 typedef TokenQueueType::value_type TokenQueueValueType; 00764 typedef TokenQueueType::size_type TokenQueueSizeType; 00765 00772 #if defined(XALAN_INLINE_INITIALIZATION) 00773 static const TokenQueueSizeType s_opCodeMapLengthIndex = 1; 00774 #else 00775 enum eDummy 00776 { 00777 s_opCodeMapLengthIndex = 1 00778 }; 00779 #endif 00780 00781 explicit 00782 XPathExpression(); 00783 00784 ~XPathExpression(); 00785 00789 void 00790 reset(); 00791 00795 void 00796 shrink(); 00797 00803 OpCodeMapSizeType 00804 opCodeMapSize() const 00805 { 00806 return m_opMap.size(); 00807 } 00808 00820 OpCodeMapValueType 00821 opCodeMapLength() const 00822 { 00823 const OpCodeMapSizeType theSize = opCodeMapSize(); 00824 00825 if (theSize > s_opCodeMapLengthIndex) 00826 { 00827 assert(theSize == OpCodeMapSizeType(m_opMap[s_opCodeMapLengthIndex])); 00828 00829 return m_opMap[s_opCodeMapLengthIndex]; 00830 } 00831 else 00832 { 00833 assert(theSize == OpCodeMapValueType(theSize)); 00834 00835 return OpCodeMapValueType(theSize); 00836 } 00837 } 00838 00844 TokenQueueSizeType 00845 tokenQueueSize() const 00846 { 00847 return m_tokenQueue.size(); 00848 } 00849 00857 OpCodeMapValueType 00858 getOpCodeMapValue(OpCodeMapSizeType opPos) const 00859 { 00860 return m_opMap[opPos]; 00861 } 00862 00863 OpCodeMapValueType 00864 getOpCodeArgumentLength(OpCodeMapSizeType opPos) const 00865 { 00866 return getOpCodeMapValue(opPos + XPathExpression::s_opCodeMapLengthIndex + 1) - 3; 00867 } 00868 00876 OpCodeMapValueType 00877 getOpCodeLengthFromOpMap(OpCodeMapSizeType opPos) const; 00878 00886 OpCodeMapValueType 00887 getNextOpCodePosition(OpCodeMapSizeType opPos) const 00888 { 00889 assert(opPos < opCodeMapSize()); 00890 00891 assert(opPos + m_opMap[opPos + s_opCodeMapLengthIndex] == OpCodeMapValueType(opPos + m_opMap[opPos + s_opCodeMapLengthIndex])); 00892 00893 return OpCodeMapValueType(opPos + m_opMap[opPos + s_opCodeMapLengthIndex]); 00894 } 00895 00905 void 00906 setOpCodeArgs( 00907 eOpCodes theOpCode, 00908 OpCodeMapSizeType theIndex, 00909 const OpCodeMapValueVectorType& theArgs); 00910 00917 OpCodeMapSizeType 00918 appendOpCode(eOpCodes theOpCode); 00919 00926 OpCodeMapSizeType 00927 appendOpCode(eOpCodes theOpCode, 00928 const OpCodeMapValueVectorType& theArgs) 00929 { 00930 const OpCodeMapSizeType thePosition = appendOpCode(theOpCode); 00931 00932 setOpCodeArgs(theOpCode, 00933 thePosition, 00934 theArgs); 00935 00936 return thePosition; 00937 } 00938 00946 void 00947 replaceOpCode( 00948 OpCodeMapSizeType theIndex, 00949 eOpCodes theOldOpCode, 00950 eOpCodes theNewOpCode); 00951 00958 OpCodeMapValueType 00959 insertOpCode( 00960 eOpCodes theOpCode, 00961 OpCodeMapSizeType theIndex); 00962 00972 void 00973 updateOpCodeLength(OpCodeMapSizeType theIndex) 00974 { 00975 assert(theIndex < opCodeMapSize()); 00976 00977 updateOpCodeLength(m_opMap[theIndex], theIndex); 00978 } 00979 00988 void 00989 updateShiftedOpCodeLength( 00990 OpCodeMapValueType theOpCode, 00991 OpCodeMapSizeType theOriginalIndex, 00992 OpCodeMapSizeType theNewIndex); 00993 01004 void 01005 updateOpCodeLength( 01006 OpCodeMapValueType theOpCode, 01007 OpCodeMapSizeType theIndex); 01008 01016 static bool 01017 isNodeTestOpCode(OpCodeMapValueType theOpCode); 01018 01024 void 01025 updateOpCodeLengthAfterNodeTest(OpCodeMapSizeType theIndex); 01026 01032 bool 01033 hasMoreTokens() const 01034 { 01035 return tokenQueueSize() - m_currentPosition > 0 ? true : false; 01036 } 01037 01043 TokenQueueSizeType 01044 getTokenPosition() const 01045 { 01046 return m_currentPosition; 01047 } 01048 01052 void 01053 resetTokenPosition() 01054 { 01055 m_currentPosition = 0; 01056 } 01057 01063 void 01064 setTokenPosition(TokenQueueSizeType thePosition) 01065 { 01066 const TokenQueueSizeType theSize = tokenQueueSize(); 01067 01068 m_currentPosition = thePosition > theSize ? theSize : thePosition; 01069 } 01070 01076 void 01077 setTokenPosition(int thePosition) 01078 { 01079 setTokenPosition(thePosition > 0 ? TokenQueueSizeType(thePosition) : 0); 01080 } 01081 01088 const XObject* 01089 getToken(TokenQueueSizeType thePosition) const 01090 { 01091 assert(thePosition < tokenQueueSize()); 01092 01093 return &m_tokenQueue[thePosition]; 01094 } 01095 01101 const XObject* 01102 getNextToken() 01103 { 01104 if (hasMoreTokens() == true) 01105 { 01106 return getToken(m_currentPosition++); 01107 } 01108 else 01109 { 01110 return 0; 01111 } 01112 } 01113 01119 const XObject* 01120 getPreviousToken() 01121 { 01122 if (m_currentPosition > 0) 01123 { 01124 return getToken(--m_currentPosition); 01125 } 01126 else 01127 { 01128 return 0; 01129 } 01130 } 01131 01139 const XObject* 01140 getRelativeToken(int theOffset) const 01141 { 01142 const int thePosition = int(m_currentPosition) + theOffset; 01143 01144 if (thePosition < 0 || 01145 thePosition >= int(tokenQueueSize())) 01146 { 01147 return 0; 01148 } 01149 else 01150 { 01151 return getToken(thePosition); 01152 } 01153 } 01154 01160 void 01161 pushToken(const XalanDOMString& theToken) 01162 { 01163 m_tokenQueue.push_back(XToken(theToken)); 01164 } 01165 01172 void 01173 pushToken( 01174 double theNumber, 01175 const XalanDOMString& theString) 01176 { 01177 m_tokenQueue.push_back(XToken(theNumber, theString)); 01178 } 01179 01186 void 01187 insertToken(const XalanDOMString& theToken) 01188 { 01189 m_tokenQueue.insert(m_tokenQueue.begin() + (m_currentPosition - 1), XToken(theToken)); 01190 } 01191 01199 void 01200 insertToken( 01201 double theNumber, 01202 const XalanDOMString& theString) 01203 { 01204 m_tokenQueue.insert(m_tokenQueue.begin() + (m_currentPosition - 1), XToken(theNumber, theString)); 01205 } 01206 01213 void 01214 replaceRelativeToken( 01215 int theOffset, 01216 const XToken& theToken) 01217 { 01218 const int thePosition = int(m_currentPosition) + theOffset; 01219 01220 if (thePosition < 0 || 01221 thePosition >= int(tokenQueueSize())) 01222 { 01223 throw InvalidRelativeTokenPosition(theOffset); 01224 } 01225 01226 m_tokenQueue[thePosition] = theToken; 01227 } 01228 01235 void 01236 replaceRelativeToken( 01237 int theOffset, 01238 const XalanDOMString& theString) 01239 { 01240 const int thePosition = int(m_currentPosition) + theOffset; 01241 01242 if (thePosition < 0 || 01243 thePosition >= int(tokenQueueSize())) 01244 { 01245 throw InvalidRelativeTokenPosition(theOffset); 01246 } 01247 01248 m_tokenQueue[thePosition].set(theString); 01249 } 01250 01257 void 01258 dumpOpCodeMap( 01259 PrintWriter& thePrintWriter, 01260 OpCodeMapSizeType theStartPosition = 0) const; 01261 01268 void 01269 dumpOpCodeMap( 01270 OstreamType& theStream, 01271 OpCodeMapSizeType theStartPosition = 0) const; 01272 01279 void 01280 dumpTokenQueue( 01281 PrintWriter& thePrintWriter, 01282 TokenQueueSizeType theStartPosition = 0) const; 01283 01290 void 01291 dumpTokenQueue( 01292 OstreamType& theStream, 01293 TokenQueueSizeType theStartPosition = 0) const; 01294 01300 void 01301 dumpRemainingTokenQueue(PrintWriter& thePrintWriter) const; 01302 01308 void 01309 dumpRemainingTokenQueue(OstreamType& theStream) const; 01310 01317 void 01318 pushValueOnOpCodeMap(const OpCodeMapType::value_type& theValue) 01319 { 01320 // Push the index onto the op map. 01321 m_opMap.push_back(theValue); 01322 01323 // Update the op map length. 01324 m_opMap[s_opCodeMapLengthIndex]++; 01325 } 01326 01333 void 01334 pushArgumentOnOpCodeMap(const XToken& theXToken); 01335 01342 void 01343 pushArgumentOnOpCodeMap(const XalanDOMString& theString); 01344 01352 void 01353 pushArgumentOnOpCodeMap( 01354 double theNumber, 01355 const XalanDOMString& theString); 01356 01363 void 01364 pushNumberLiteralOnOpCodeMap(double theNumber); 01365 01371 double 01372 getNumberLiteral(int theIndex) const 01373 { 01374 assert(theIndex >= 0 && 01375 NumberLiteralValueVectorType::size_type(theIndex) < m_numberLiteralValues.size()); 01376 01377 return m_numberLiteralValues[NumberLiteralValueVectorType::size_type(theIndex)]; 01378 } 01379 01384 void 01385 pushCurrentTokenOnOpCodeMap(); 01386 01392 void 01393 setCurrentPattern(const XalanDOMString& thePattern) 01394 { 01395 m_currentPattern = &thePattern; 01396 } 01397 01403 const XalanDOMString& 01404 getCurrentPattern() const 01405 { 01406 assert(m_currentPattern != 0); 01407 01408 return *m_currentPattern; 01409 } 01410 01417 OpCodeMapType m_opMap; 01418 01423 OpCodeMapSizeType m_lastOpCodeIndex; 01424 01430 TokenQueueType m_tokenQueue; 01431 01435 TokenQueueSizeType m_currentPosition; 01436 01440 const XalanDOMString* m_currentPattern; 01441 01442 private: 01443 01444 // Default vector allocation sizes. 01445 enum 01446 { 01447 eDefaultOpMapSize = 100, 01448 eDefaultTokenQueueSize = 30 01449 }; 01450 01451 NumberLiteralValueVectorType m_numberLiteralValues; 01452 }; 01453 01454 01455 01456 XALAN_CPP_NAMESPACE_END 01457 01458 01459 01460 #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.6 |
|