You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@apache.org on 2001/01/16 03:52:36 UTC

cvs commit: xml-xalan/c/src/XalanSourceTree XalanSourceTreeContentHandler.cpp XalanSourceTreeContentHandler.hpp XalanSourceTreeHelper.cpp XalanSourceTreeHelper.hpp

dbertoni    01/01/15 18:52:36

  Modified:    c/src/XalanSourceTree XalanSourceTreeContentHandler.cpp
                        XalanSourceTreeContentHandler.hpp
                        XalanSourceTreeHelper.cpp XalanSourceTreeHelper.hpp
  Log:
  Cache last node appended to fix major performance degradation with broad documents.
  
  Revision  Changes    Path
  1.4       +111 -32   xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.cpp
  
  Index: XalanSourceTreeContentHandler.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.cpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeContentHandler.cpp	2000/12/29 03:23:26	1.3
  +++ XalanSourceTreeContentHandler.cpp	2001/01/16 02:52:35	1.4
  @@ -68,6 +68,7 @@
   
   #include "XalanSourceTreeDocument.hpp"
   #include "XalanSourceTreeElement.hpp"
  +#include "XalanSourceTreeHelper.hpp"
   
   
   
  @@ -80,6 +81,8 @@
   	m_document(theDocument),
   	m_currentElement(0),
   	m_elementStack(),
  +	m_lastChild(0),
  +	m_lastChildStack(),
   	m_ownsDocument(false),
   	m_accumulateText(fAccumulateText),
   	m_textBuffer()
  @@ -125,7 +128,12 @@
   void
   XalanSourceTreeContentHandler::endDocument()
   {
  +	// Pop off the dummy value that we pushed in 
  +	// startDocument()...
  +	m_elementStack.pop_back();
  +
   	assert(m_elementStack.empty() == true);
  +	assert(m_lastChildStack.empty() == true);
   
   	assert(isEmpty(m_textBuffer) == true);
   }
  @@ -138,6 +146,7 @@
   			const XMLCh* const	/* localname */, 
   			const XMLCh* const	/* qname */)
   {
  +	// Process any text that we may have accumulated...
   	processAccumulatedText();
   
   	assert(m_elementStack.empty() == false);
  @@ -145,20 +154,71 @@
   	// Pop the element of the stack...
   	m_elementStack.pop_back();
   
  +	assert(m_elementStack.empty() == false);
  +
   	// Get the element from the back of the
  -	// stack, if any...
  -	if (m_elementStack.empty() == false)
  +	// stack.
  +	m_currentElement = m_elementStack.back();
  +
  +	assert(m_lastChildStack.empty() == false);
  +
  +	m_lastChild = m_lastChildStack.back();
  +
  +	// Pop the last child stack
  +	m_lastChildStack.pop_back();
  +}
  +
  +
  +
  +// A helper function to manage appending the new child.
  +template <class ParentNodeType, class ChildNodeType>
  +inline void
  +doAppendChildNode(
  +			ParentNodeType*		theParent,
  +			XalanNode*&			theLastChild,
  +			ChildNodeType		theNewChild)
  +{
  +	assert(theParent != 0);
  +	assert(theNewChild != 0);
  +
  +	if (theLastChild == 0)
   	{
  -		m_currentElement = m_elementStack.back();
  +		theParent->appendChildNode(theNewChild);
   	}
   	else
   	{
  -		m_currentElement = 0;
  +		XalanSourceTreeHelper::appendSibling(theLastChild, theNewChild);
   	}
  +
  +	theLastChild = theNewChild;
   }
   
   
   
  +// A helper function to manage appending the new child.
  +template <class ChildNodeType>
  +inline void
  +doAppendChildNode(
  +			XalanSourceTreeDocument*	theDocument,
  +			XalanSourceTreeElement*		theCurrentElement,
  +			XalanNode*&					theLastChild,
  +			ChildNodeType				theNewChild)
  +{
  +	assert(theDocument != 0);
  +	assert(theNewChild != 0);
  +
  +	if (theCurrentElement == 0)
  +	{
  +		doAppendChildNode(theDocument, theLastChild, theNewChild);
  +	}
  +	else
  +	{
  +		doAppendChildNode(theCurrentElement, theLastChild, theNewChild);
  +	}
  +}
  +
  +
  +
   void
   XalanSourceTreeContentHandler::ignorableWhitespace(
   			const XMLCh* const	chars,
  @@ -167,9 +227,14 @@
   	// Ignore any whitespace reported before the document element has been parsed.
   	if (m_elementStack.empty() == false)
   	{
  +		assert(m_currentElement != 0);
  +
   		processAccumulatedText();
  +
  +		XalanSourceTreeText*	theNewTextNode =
  +			m_document->createTextIWSNode(chars, length, m_currentElement);
   
  -		m_currentElement->appendChildNode(m_document->createTextIWSNode(chars, length, m_currentElement));
  +		doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
   	}
   }
   
  @@ -180,18 +245,16 @@
   		const XMLCh* const	target,
   		const XMLCh* const	data)
   {
  -	if (m_currentElement == 0)
  -	{
  -		assert(m_document != 0);
  +	processAccumulatedText();
   
  -		m_document->appendChildNode(m_document->createProcessingInstructionNode(target, data));
  -	}
  -	else
  -	{
  -		processAccumulatedText();
  +	XalanSourceTreeProcessingInstruction* const		theNewPI =
  +		m_document->createProcessingInstructionNode(target, data, m_currentElement);
   
  -		m_currentElement->appendChildNode(m_document->createProcessingInstructionNode(target, data, m_currentElement));
  -	}
  +	doAppendChildNode(
  +			m_document,
  +			m_currentElement,
  +			m_lastChild,
  +			theNewPI);
   }
   
   
  @@ -206,6 +269,7 @@
   void
   XalanSourceTreeContentHandler::startDocument()
   {
  +	// Clean up and reset everything...
   	if (m_document == 0)
   	{
   		m_document = new XalanSourceTreeDocument;
  @@ -217,16 +281,28 @@
   		m_document = new XalanSourceTreeDocument;
   	}
   
  +	m_currentElement = 0;
  +
   	m_elementStack.clear();
   
   	m_elementStack.reserve(eDefaultStackSize);
   
  +	m_lastChild = 0;
  +
  +	m_lastChildStack.clear();
  +
  +	m_lastChildStack.reserve(eDefaultStackSize);
  +
   	if (m_accumulateText == true)
   	{
   		clear(m_textBuffer);
   
   		reserve(m_textBuffer, eDefaultTextBufferSize);
   	}
  +
  +	// Push a dummy value for the current element, so we
  +	// don't have to check for an empty stack in endElement().
  +	m_elementStack.push_back(0);
   }
   
   
  @@ -243,18 +319,19 @@
   	XalanSourceTreeElement* const	theNewElement =
   		createElement(uri, localname, qname, attrs, m_currentElement);
   
  -	if (m_currentElement == 0)
  -	{
  -		m_document->appendChildNode(theNewElement);
  -	}
  -	else
  -	{
  -		m_currentElement->appendChildNode(theNewElement);
  -	}
  +	doAppendChildNode(
  +			m_document,
  +			m_currentElement,
  +			m_lastChild,
  +			theNewElement);
   
   	m_elementStack.push_back(theNewElement);
   
  +	m_lastChildStack.push_back(m_lastChild);
  +
   	m_currentElement = theNewElement;
  +
  +	m_lastChild = 0;
   }
   
   
  @@ -325,14 +402,11 @@
   	XalanSourceTreeComment* const	theNewComment =
   		m_document->createCommentNode(chars, length, m_currentElement);
   
  -	if (m_currentElement != 0)
  -	{
  -		m_currentElement->appendChildNode(theNewComment);
  -	}
  -	else
  -	{
  -		m_document->appendChildNode(theNewComment);
  -	}
  +	doAppendChildNode(
  +			m_document,
  +			m_currentElement,
  +			m_lastChild,
  +			theNewComment);
   }
   
   
  @@ -451,5 +525,10 @@
   			const XMLCh*	chars,
   			unsigned int	length)
   {
  -	m_currentElement->appendChildNode(m_document->createTextNode(chars, length, m_currentElement));
  +	assert(m_currentElement != 0);
  +
  +	XalanSourceTreeText*	theNewTextNode = 
  +				m_document->createTextNode(chars, length, m_currentElement);
  +
  +	doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
   }
  
  
  
  1.4       +23 -0     xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.hpp
  
  Index: XalanSourceTreeContentHandler.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeContentHandler.hpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeContentHandler.hpp	2000/12/29 03:23:26	1.3
  +++ XalanSourceTreeContentHandler.hpp	2001/01/16 02:52:35	1.4
  @@ -78,6 +78,7 @@
   
   
   
  +class XalanNode;
   class XalanSourceTreeDocument;
   class XalanSourceTreeElement;
   
  @@ -90,8 +91,10 @@
   
   #if defined(XALAN_NO_NAMESPACES)
   	typedef vector<XalanSourceTreeElement*> 		ElementStackType;
  +	typedef vector<XalanNode*> 						LastChildStackType;
   #else
   	typedef std::vector<XalanSourceTreeElement*>	ElementStackType;
  +	typedef std::vector<XalanNode*> 				LastChildStackType;
   #endif
   
   	enum { eDefaultStackSize = 50, eDefaultTextBufferSize = 100 };
  @@ -250,16 +253,36 @@
   
   
   	// Data members...
  +
  +	// The current document we're building...
   	XalanSourceTreeDocument*	m_document;
   
  +	// The current element...
   	XalanSourceTreeElement* 	m_currentElement;
   
  +	// Stack of elements...
   	ElementStackType			m_elementStack;
   
  +	// The last child appended to the current element.  This is
  +	// an important optimization, because XalanSourceTreeElement
  +	// does not have a pointer to it's last child.  Without this,
  +	// appending a child becomes a linear search.
  +	XalanNode* 					m_lastChild;
  +
  +	// Stack of last children appended.  There is a ono-to-one
  +	// correspondance to the entries in m_elementStack.
  +	LastChildStackType			m_lastChildStack;
  +
  +	// If true, the instance owns the document and will delete
  +	// it when necessary.
   	bool						m_ownsDocument;
   
  +	// If true, the handler will accumulate text from calls to
  +	// characters() until another event triggers the creation
  +	// of the node.
   	const bool					m_accumulateText;
   
  +	// A buffer to hold accumulated text.
   	XalanDOMString				m_textBuffer;
   };
   
  
  
  
  1.4       +114 -21   xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.cpp
  
  Index: XalanSourceTreeHelper.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.cpp,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XalanSourceTreeHelper.cpp	2000/12/19 02:34:28	1.3
  +++ XalanSourceTreeHelper.cpp	2001/01/16 02:52:35	1.4
  @@ -126,13 +126,13 @@
   template<class NodeType>
   inline void
   doAppendSibling(
  -			XalanNode*	theNode,
  +			XalanNode*	theSibling,
   			NodeType*	theNewSibling)
   {
  -	assert(theNode != 0);
  +	assert(theSibling != 0);
   	assert(theNewSibling != 0);
   
  -	XalanNode* const	theLastSibling = XalanSourceTreeHelper::getLastSibling(theNode);
  +	XalanNode* const	theLastSibling = XalanSourceTreeHelper::getLastSibling(theSibling);
   
   	switch(theLastSibling->getNodeType())
   	{
  @@ -160,6 +160,42 @@
   
   
   
  +template<class NodeType>
  +inline void
  +doAppendToLastSibling(
  +			XalanNode*	theLastSibling,
  +			NodeType*	theNewSibling)
  +{
  +	assert(theLastSibling != 0);
  +	assert(theNewSibling != 0);
  +	assert(theLastSibling->getNextSibling() == 0);
  +
  +	switch(theLastSibling->getNodeType())
  +	{
  +	case XalanNode::COMMENT_NODE:
  +		castToComment(theLastSibling)->appendSiblingNode(theNewSibling);
  +		break;
  +
  +	case XalanNode::ELEMENT_NODE:
  +		castToElement(theLastSibling)->appendSiblingNode(theNewSibling);
  +		break;
  +
  +	case XalanNode::PROCESSING_INSTRUCTION_NODE:
  +		castToProcessingInstruction(theLastSibling)->appendSiblingNode(theNewSibling);
  +		break;
  +
  +	case XalanNode::TEXT_NODE:
  +		castToText(theLastSibling)->appendSiblingNode(theNewSibling);
  +		break;
  +
  +	default:
  +		throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
  +		break;
  +	}
  +}
  +
  +
  +
   template <class NodeType1, class NodeType2>
   inline void
   append(
  @@ -317,6 +353,70 @@
   
   
   
  +void
  +XalanSourceTreeHelper::appendSibling(
  +			XalanNode*					theLastSibling,
  +			XalanSourceTreeComment*		theNewLastSibling)
  +{
  +	doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +			XalanNode*					theLastSibling,
  +			XalanSourceTreeElement*		theNewLastSibling)
  +{
  +	doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +			XalanNode*								theLastSibling,
  +			XalanSourceTreeProcessingInstruction*	theNewLastSibling)
  +{
  +	doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +void
  +XalanSourceTreeHelper::appendSibling(
  +			XalanNode*				theLastSibling,
  +			XalanSourceTreeText*	theNewLastSibling)
  +{
  +	doAppendToLastSibling(theLastSibling, theNewLastSibling);
  +}
  +
  +
  +
  +XalanNode*
  +doGetLastSibling(XalanNode*		theNode)
  +{
  +	if (theNode == 0)
  +	{
  +		return 0;
  +	}
  +	else
  +	{
  +		XalanNode*	theNextSibling = theNode->getNextSibling();
  +
  +		while(theNextSibling != 0)
  +		{
  +			theNode = theNextSibling;
  +
  +			theNextSibling = theNode->getNextSibling();
  +		}
  +
  +		return theNode;
  +	}
  +}
  +
  +
  +
   template <class NodeType>
   void
   doAppendSiblingToChild(
  @@ -332,7 +432,16 @@
   		theNewSibling->setParentElement(theOwnerElement);
   	}
   
  -	append(theFirstChildSlot, theNewSibling);
  +	if (theFirstChildSlot == 0)
  +	{
  +		append(theFirstChildSlot, theNewSibling);
  +	}
  +	else
  +	{
  +		XalanNode* const	theLastSibling = doGetLastSibling(theFirstChildSlot);
  +
  +		doAppendSibling(theLastSibling, theNewSibling);	
  +	}
   }
   
   
  @@ -385,21 +494,5 @@
   XalanNode*
   XalanSourceTreeHelper::getLastSibling(XalanNode*	theNode)
   {
  -	if (theNode == 0)
  -	{
  -		return 0;
  -	}
  -	else
  -	{
  -		XalanNode*	theNextSibling = theNode->getNextSibling();
  -
  -		while(theNextSibling != 0)
  -		{
  -			theNode = theNextSibling;
  -
  -			theNextSibling = theNode->getNextSibling();
  -		}
  -
  -		return theNode;
  -	}
  +	return doGetLastSibling(theNode);
   }
  
  
  
  1.3       +23 -8     xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.hpp
  
  Index: XalanSourceTreeHelper.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XalanSourceTree/XalanSourceTreeHelper.hpp,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XalanSourceTreeHelper.hpp	2000/12/17 22:26:59	1.2
  +++ XalanSourceTreeHelper.hpp	2001/01/16 02:52:35	1.3
  @@ -80,17 +80,9 @@
   {
   public:
   
  -	friend class XalanSourceTreeComment;
  -	friend class XalanSourceTreeDocument;
  -	friend class XalanSourceTreeElement;
  -	friend class XalanSourceTreeProcessingInstruction;
  -	friend class XalanSourceTreeText;
  -
   	static XalanNode*
   	getLastSibling(XalanNode*	theNode);
   
  -private:
  -
   	static void
   	appendSibling(
   			XalanSourceTreeDocument*	theDocument,
  @@ -121,11 +113,34 @@
   			XalanNode*&				theNextSiblingSlot,
   			XalanNode*				theNewSibling);
   
  +	// New appendSibling interfaces...
  +	static void
  +	appendSibling(
  +			XalanNode*					theLastSibling,
  +			XalanSourceTreeComment*		theNewLastSibling);
  +
  +	static void
  +	appendSibling(
  +			XalanNode*					theLastSibling,
  +			XalanSourceTreeElement*		theNewLastSibling);
  +
   	static void
  +	appendSibling(
  +			XalanNode*								theLastSibling,
  +			XalanSourceTreeProcessingInstruction*	theNewLastSibling);
  +
  +	static void
  +	appendSibling(
  +			XalanNode*				theLastSibling,
  +			XalanSourceTreeText*	theNewLastSibling);
  +
  +
  +	static void
   	appendSiblingToChild(
   			XalanSourceTreeElement*		theOwnerElement,
   			XalanNode*&					theChildSlot,
   			XalanSourceTreeComment*		theNewSibling);
  +
   
   	static void
   	appendSiblingToChild(