00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 #if !defined(XALAN_VARIABLESSTACK_HEADER_GUARD) 00019 #define XALAN_VARIABLESSTACK_HEADER_GUARD 00020 00021 00022 00023 // Base include file. Must be first. 00024 #include <xalanc/XSLT/XSLTDefinitions.hpp> 00025 00026 00027 00028 #include <cassert> 00029 00030 00031 00032 #include <xalanc/Include/XalanVector.hpp> 00033 00034 00035 00036 #include <xalanc/XPath/XalanQName.hpp> 00037 #include <xalanc/XPath/XObject.hpp> 00038 00039 00040 00041 #include <xalanc/XSLT/XSLTProcessorException.hpp> 00042 00043 00044 00045 XALAN_CPP_NAMESPACE_BEGIN 00046 00047 00048 00049 class Arg; 00050 class ElemTemplateElement; 00051 class ElemVariable; 00052 class StylesheetExecutionContext; 00053 class XalanNode; 00054 00055 00056 00057 /** 00058 * Defines a class to keep track of a stack for macro arguments. 00059 */ 00060 class XALAN_XSLT_EXPORT VariablesStack 00061 { 00062 public: 00063 00064 typedef unsigned long size_type; 00065 00066 /** 00067 * Constructor for a variable stack. 00068 */ 00069 explicit 00070 VariablesStack(MemoryManager& theManager); 00071 00072 ~VariablesStack(); 00073 00074 /** 00075 * Reset the stack. 00076 */ 00077 void 00078 reset(); 00079 00080 /** 00081 * Push a frame marker for an element. 00082 * 00083 * @param elem the element 00084 */ 00085 void 00086 pushElementFrame(const ElemTemplateElement* elem); 00087 00088 /** 00089 * Pop a frame marker for an element. 00090 * 00091 * @param elem the element 00092 */ 00093 void 00094 popElementFrame(); 00095 00096 /** 00097 * Push a context marker onto the stack to let us know when to stop 00098 * searching for a var. 00099 * 00100 * @param caller caller node 00101 * @param sourceNode source node 00102 */ 00103 void 00104 pushContextMarker(); 00105 00106 /** 00107 * Pop the current context from the current context stack. 00108 */ 00109 void 00110 popContextMarker(); 00111 00112 struct ParamsVectorEntry 00113 { 00114 ParamsVectorEntry() : 00115 m_qname(0), 00116 m_value(), 00117 m_variable(0) 00118 { 00119 } 00120 00121 ParamsVectorEntry( 00122 const XalanQName* qname, 00123 const XObjectPtr value) : 00124 m_qname(qname), 00125 m_value(value), 00126 m_variable(0) 00127 { 00128 } 00129 00130 ParamsVectorEntry( 00131 const XalanQName* qname, 00132 const ElemVariable* variable) : 00133 m_qname(qname), 00134 m_value(), 00135 m_variable(variable) 00136 { 00137 } 00138 00139 const XalanQName* m_qname; 00140 00141 XObjectPtr m_value; 00142 00143 const ElemVariable* m_variable; 00144 }; 00145 00146 typedef XalanVector<ParamsVectorEntry> ParamsVectorType; 00147 typedef XalanVector<const ElemVariable*> RecursionGuardStackType; 00148 typedef XalanVector<const ElemTemplateElement*> ElemTemplateElementStackType; 00149 00150 /** 00151 * Push the provided objects as parameters. You must call 00152 * popContextMarker() when you are done with the arguments. 00153 * 00154 * @param theParam The vector containing the parameters. 00155 */ 00156 void 00157 pushParams(const ParamsVectorType& theParams); 00158 00159 /** 00160 * Given a name, return a string representing the value, but don't look 00161 * in the global space. Since the variable may not yet have been 00162 * evaluated, this may return a null XObjectPtr. 00163 * 00164 * @param theName name of variable 00165 * @param exeuctionContext the current execution context 00166 * @param fNameFound set to true if the name was found, false if not. 00167 * @return pointer to XObject for variable 00168 */ 00169 const XObjectPtr 00170 getParamVariable( 00171 const XalanQName& qname, 00172 StylesheetExecutionContext& executionContext, 00173 bool& fNameFound) 00174 { 00175 return findXObject(qname, executionContext, true, false, fNameFound); 00176 } 00177 00178 /** 00179 * Given a name, find the corresponding XObject. If the variable 00180 * exists, but has not yet been evaluated, the variable will be 00181 * evaluated and the result returned. This may return a null XObjectPtr, 00182 * if the variable was not found. 00183 * 00184 * @param qname name of variable 00185 * @param exeuctionContext the current execution context 00186 * @param fNameFound set to true if the name was found, false if not. 00187 * @return pointer to the corresponding XObject 00188 */ 00189 const XObjectPtr 00190 getVariable( 00191 const XalanQName& qname, 00192 StylesheetExecutionContext& executionContext, 00193 bool& fNameFound) 00194 { 00195 return findXObject(qname, executionContext, false, true, fNameFound); 00196 } 00197 00198 /** 00199 * Push a named variable onto the processor variable stack. Don't forget 00200 * to call startContext before pushing a series of arguments for a given 00201 * template. 00202 * 00203 * @param name name of variable 00204 * @param val pointer to ElemVariable 00205 * @param e element marker for variable 00206 */ 00207 void 00208 pushVariable( 00209 const XalanQName& name, 00210 const ElemVariable* var, 00211 const ElemTemplateElement* e); 00212 00213 /** 00214 * Push a named variable onto the processor variable stack. Don't forget 00215 * to call startContext before pushing a series of arguments for a given 00216 * template. 00217 * 00218 * @param name name of variable 00219 * @param val pointer to XObject value 00220 * @param e element marker for variable 00221 */ 00222 void 00223 pushVariable( 00224 const XalanQName& name, 00225 const XObjectPtr& val, 00226 const ElemTemplateElement* e); 00227 00228 /** 00229 * Mark the top of the stack. 00230 */ 00231 void 00232 start(); 00233 00234 /** 00235 * Reset all params in the current stack frame. 00236 */ 00237 void 00238 resetParams(); 00239 00240 /** 00241 * Mark the top of the global stack frame. 00242 */ 00243 void 00244 markGlobalStackFrame(); 00245 00246 /** 00247 * Clear the marking of the global stack frame. 00248 */ 00249 void 00250 unmarkGlobalStackFrame(); 00251 00252 /** 00253 * Set the top of the stack frame from where a search for a variable or 00254 * param should take place. Calling with no parameter will cause the 00255 * index to be set to the size of the stack. 00256 * 00257 * @param currentStackFrameIndex new value of index 00258 */ 00259 void 00260 setCurrentStackFrameIndex(size_type currentStackFrameIndex = ~0u) 00261 { 00262 if (currentStackFrameIndex == ~0u) 00263 { 00264 assert(size_type(m_stack.size()) == m_stack.size()); 00265 00266 m_currentStackFrameIndex = size_type(m_stack.size()); 00267 } 00268 else 00269 { 00270 m_currentStackFrameIndex = currentStackFrameIndex; 00271 } 00272 } 00273 00274 /** 00275 * Get the top of the stack frame from where a search 00276 * for a variable or param should take place. 00277 * 00278 * @return current value of index 00279 */ 00280 size_type 00281 getCurrentStackFrameIndex() const 00282 { 00283 return m_currentStackFrameIndex; 00284 } 00285 00286 /** 00287 * Get the top of the global stack frame. 00288 * 00289 * @return current value of index 00290 */ 00291 size_type 00292 getGlobalStackFrameIndex() const 00293 { 00294 return m_globalStackFrameIndex; 00295 } 00296 00297 class InvalidStackContextException : public XSLTProcessorException 00298 { 00299 public: 00300 00301 InvalidStackContextException(XalanDOMString& theResult); 00302 00303 virtual 00304 ~InvalidStackContextException(); 00305 00306 00307 virtual const XalanDOMChar* 00308 getType() const 00309 { 00310 return m_type; 00311 } 00312 00313 private: 00314 00315 static const XalanDOMChar m_type[]; 00316 00317 }; 00318 00319 class PushParamFunctor 00320 { 00321 public: 00322 00323 PushParamFunctor(VariablesStack& theVariablesStack) : 00324 m_variablesStack(theVariablesStack) 00325 { 00326 } 00327 00328 void 00329 operator()(const ParamsVectorType::value_type& theEntry) const; 00330 00331 private: 00332 00333 VariablesStack& m_variablesStack; 00334 }; 00335 00336 class XALAN_XSLT_EXPORT StackEntry 00337 { 00338 public: 00339 00340 /** 00341 * Enumeration for types of stack entries, one of context state, context 00342 * marker, element marker, or argument. 00343 */ 00344 enum eType { eContextMarker, 00345 eVariable, 00346 eParam, 00347 eActiveParam, 00348 eElementFrameMarker, 00349 eNextValue }; 00350 00351 /** 00352 * Construct a context marker. 00353 */ 00354 explicit 00355 StackEntry(); 00356 00357 /** 00358 * Construct a variable that is already evaluated. 00359 */ 00360 StackEntry( 00361 const XalanQName* name, 00362 const XObjectPtr& val, 00363 bool isParam = false); 00364 00365 /** 00366 * Construct a variable that has not been evaluated yet. 00367 */ 00368 StackEntry( 00369 const XalanQName* name, 00370 const ElemVariable* var, 00371 bool isParam = false); 00372 00373 /** 00374 * Construct an element frame marker. 00375 */ 00376 StackEntry(const ElemTemplateElement* elem); 00377 00378 00379 /** 00380 * Copy constructor... 00381 */ 00382 StackEntry(const StackEntry& theSource); 00383 00384 /** 00385 * Destructor... 00386 */ 00387 ~StackEntry(); 00388 00389 /** 00390 * Determine type of stack entry 00391 * 00392 * @return enumeration value for type 00393 */ 00394 eType 00395 getType() const 00396 { 00397 return m_type; 00398 } 00399 00400 /** 00401 * Retrieve object name. Valid only for variables 00402 * 00403 * @return qualified name of object 00404 */ 00405 const XalanQName* 00406 getName() const 00407 { 00408 return m_qname; 00409 } 00410 00411 /** 00412 * Retrieve object's XObject pointer. Valid only for variables 00413 * 00414 * @return pointer to XObject 00415 */ 00416 const XObjectPtr& 00417 getValue() const 00418 { 00419 return m_value; 00420 } 00421 00422 /** 00423 * Retrieve object's XObject pointer. Valid only for variables 00424 * 00425 * @return pointer to XObject 00426 */ 00427 void 00428 setValue(const XObjectPtr& theValue) 00429 { 00430 m_value = theValue; 00431 } 00432 00433 /** 00434 * Retrieve object's XObject pointer. Valid only for variables 00435 * 00436 * @return pointer to XObject 00437 */ 00438 const ElemVariable* 00439 getVariable() const 00440 { 00441 return m_variable; 00442 } 00443 00444 void 00445 activate(); 00446 00447 void 00448 deactivate(); 00449 00450 /** 00451 * Retrieve the ElemTemplateElem where frame begins. Valid only for element frame markers 00452 * 00453 * @return ElemTemplateElement corresponding to marker 00454 */ 00455 const ElemTemplateElement* 00456 getElement() const 00457 { 00458 return m_element; 00459 } 00460 00461 StackEntry& 00462 operator=(const StackEntry& theRHS); 00463 00464 bool 00465 operator==(const StackEntry& theRHS) const; 00466 00467 private: 00468 00469 // Data members... 00470 eType m_type; 00471 00472 const XalanQName* m_qname; 00473 00474 XObjectPtr m_value; 00475 00476 const ElemVariable* m_variable; 00477 00478 const ElemTemplateElement* m_element; 00479 }; 00480 00481 typedef XalanVector<StackEntry> VariableStackStackType; 00482 00483 size_type 00484 getStackSize() const 00485 { 00486 return size_type(m_stack.size()); 00487 } 00488 00489 enum { eDefaultStackSize = 100 }; 00490 00491 private: 00492 00493 class CommitPushParams 00494 { 00495 public: 00496 00497 CommitPushParams(VariablesStack& theVariablesStack); 00498 00499 ~CommitPushParams(); 00500 00501 void 00502 commit() 00503 { 00504 m_variablesStack = 0; 00505 } 00506 00507 private: 00508 00509 VariablesStack* m_variablesStack; 00510 00511 size_type m_stackSize; 00512 }; 00513 00514 friend class CommitPushParams; 00515 00516 /** 00517 * Check to see if an element frame for the particular element has already 00518 * been pushed. 00519 * 00520 * @param elem element in question 00521 * @return true if it has been pushed already 00522 */ 00523 bool 00524 elementFrameAlreadyPushed(const ElemTemplateElement* elem) const; 00525 00526 /** 00527 * Push an entry onto the stack. 00528 * 00529 * @param stack entry to push 00530 */ 00531 void 00532 push(const StackEntry& theEntry); 00533 00534 /** 00535 * Pop an entry from the top of the stack. 00536 */ 00537 void 00538 pop(); 00539 00540 /** 00541 * Get a reference to the entry at the back (top) of the stack. 00542 * 00543 * @return a reference to the back of the stack. 00544 */ 00545 const StackEntry& 00546 back() const 00547 { 00548 assert(m_stack.empty() == false); 00549 00550 return m_stack.back(); 00551 } 00552 00553 friend class CommitPushElementFrame; 00554 friend class EnsurePop; 00555 friend class PushParamFunctor; 00556 friend class SetAndRestoreForceGlobalSearch; 00557 00558 const XObjectPtr 00559 findXObject( 00560 const XalanQName& name, 00561 StylesheetExecutionContext& executionContext, 00562 bool fIsParam, 00563 bool fSearchGlobalSpace, 00564 bool& fNameFound); 00565 00566 size_type 00567 findEntry( 00568 const XalanQName& name, 00569 bool fIsParam, 00570 bool fSearchGlobalSpace); 00571 00572 00573 VariableStackStackType m_stack; 00574 00575 size_type m_globalStackFrameIndex; 00576 00577 bool m_globalStackFrameMarked; 00578 00579 /** 00580 * This is the top of the stack frame from where a search 00581 * for a variable or param should take place. It may not 00582 * be the real stack top. 00583 */ 00584 size_type m_currentStackFrameIndex; 00585 00586 /** 00587 * This will be a stack for any variable definitions 00588 * that are being evaluated dynamically, to protect 00589 * against circular definitions. 00590 */ 00591 RecursionGuardStackType m_guardStack; 00592 00593 /** 00594 * This will be a stack for tracking element frames. 00595 * This is only used in debug builds. 00596 */ 00597 ElemTemplateElementStackType m_elementFrameStack; 00598 }; 00599 00600 00601 00602 XALAN_CPP_NAMESPACE_END 00603 00604 00605 00606 #endif // #if !defined(XALAN_VARIABLESSTACK_HEADER_GUARD)
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.11 |
|