From d55df8d0dc7d2228c293b7fce305018d4ab2db7f Mon Sep 17 00:00:00 2001
From: Alberto Massari <amassari@apache.org>
Date: Tue, 25 Jul 2006 08:44:03 +0000
Subject: [PATCH] Reduce the number of allocations needed by text and attribute
 nodes (jira#1585)

git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@425332 13f79535-47bb-0310-9956-ffa450edef68
---
 src/xercesc/dom/impl/DOMCharacterDataImpl.cpp |  4 ++--
 src/xercesc/dom/impl/DOMDocumentImpl.cpp      |  6 +++++-
 src/xercesc/dom/impl/DOMDocumentImpl.hpp      |  2 +-
 src/xercesc/dom/impl/DOMStringPool.hpp        |  5 +++++
 src/xercesc/util/RefStackOf.c                 | 11 ++++++++++-
 src/xercesc/util/RefStackOf.hpp               |  1 +
 6 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp b/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp
index 7c9948c54..c858b16c6 100644
--- a/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp
+++ b/src/xercesc/dom/impl/DOMCharacterDataImpl.cpp
@@ -35,7 +35,7 @@ DOMCharacterDataImpl::DOMCharacterDataImpl(DOMDocument *doc, const XMLCh *dat)
 {
     fDoc = (DOMDocumentImpl*)doc;
 
-    fDataBuf = fDoc->popBuffer();
+    fDataBuf = fDoc->popBuffer(XMLString::stringLen(dat)+1);
     if (!fDataBuf)
         fDataBuf = new (fDoc) DOMBuffer(fDoc, dat);
     else
@@ -50,7 +50,7 @@ DOMCharacterDataImpl::DOMCharacterDataImpl(const DOMCharacterDataImpl &other)
 {
     fDoc = (DOMDocumentImpl*)other.fDoc;
 
-    fDataBuf = fDoc->popBuffer();
+    fDataBuf = fDoc->popBuffer(other.getLength()+1);
     if (!fDataBuf)
         fDataBuf = new (fDoc) DOMBuffer(fDoc, other.fDataBuf->getRawBuffer());
     else
diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
index 48beb41fb..0fa2dd20c 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp
@@ -1414,11 +1414,15 @@ void DOMDocumentImpl::releaseBuffer(DOMBuffer* buffer)
     fRecycleBufferPtr->push(buffer);
 }
 
-DOMBuffer* DOMDocumentImpl::popBuffer()
+DOMBuffer* DOMDocumentImpl::popBuffer(XMLSize_t nMinSize)
 {
     if (!fRecycleBufferPtr || fRecycleBufferPtr->empty())
         return 0;
 
+    for(unsigned int index=fRecycleBufferPtr->size()-1;index>0;index--)
+        if(fRecycleBufferPtr->elementAt(index)->getCapacity()>=nMinSize)
+            return fRecycleBufferPtr->popAt(index);
+    // if we didn't find a buffer big enough, get the last one
     return fRecycleBufferPtr->pop();
 }
 
diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.hpp b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
index c5ef881bc..b4f0ca46d 100644
--- a/src/xercesc/dom/impl/DOMDocumentImpl.hpp
+++ b/src/xercesc/dom/impl/DOMDocumentImpl.hpp
@@ -255,7 +255,7 @@ public:
     void                         deleteHeap();
     void                         releaseDocNotifyUserData(DOMNode* object);
     void                         releaseBuffer(DOMBuffer* buffer);
-    DOMBuffer*                   popBuffer();
+    DOMBuffer*                   popBuffer(XMLSize_t nMinSize);
     MemoryManager*               getMemoryManager() const;
 
     // Factory methods for getting/creating node lists.
diff --git a/src/xercesc/dom/impl/DOMStringPool.hpp b/src/xercesc/dom/impl/DOMStringPool.hpp
index bf92c9f7f..1128ad91b 100644
--- a/src/xercesc/dom/impl/DOMStringPool.hpp
+++ b/src/xercesc/dom/impl/DOMStringPool.hpp
@@ -130,6 +130,11 @@ public :
         return fIndex;
     }
 
+    unsigned int getCapacity() const
+    {
+        return fCapacity;
+    }
+
     // -----------------------------------------------------------------------
     //  Private helpers
     // -----------------------------------------------------------------------
diff --git a/src/xercesc/util/RefStackOf.c b/src/xercesc/util/RefStackOf.c
index ac635f23f..e791d0056 100644
--- a/src/xercesc/util/RefStackOf.c
+++ b/src/xercesc/util/RefStackOf.c
@@ -51,11 +51,20 @@ template <class TElem> RefStackOf<TElem>::~RefStackOf()
 template <class TElem> const TElem* RefStackOf<TElem>::
 elementAt(const unsigned int index) const
 {
-    if (index > fVector.size())
+    if (index >= fVector.size())
         ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Stack_BadIndex, fVector.getMemoryManager());
     return fVector.elementAt(index);
 }
 
+template <class TElem> TElem* RefStackOf<TElem>::popAt(const unsigned int index)
+{
+    if (index >= fVector.size())
+        ThrowXMLwithMemMgr(ArrayIndexOutOfBoundsException, XMLExcepts::Stack_BadIndex, fVector.getMemoryManager());
+
+    // Orphan off the element from the slot in the vector
+    return fVector.orphanElementAt(index);
+}
+
 template <class TElem> void RefStackOf<TElem>::push(TElem* const toPush)
 {
     fVector.addElement(toPush);
diff --git a/src/xercesc/util/RefStackOf.hpp b/src/xercesc/util/RefStackOf.hpp
index b24928ce3..822d8ec53 100644
--- a/src/xercesc/util/RefStackOf.hpp
+++ b/src/xercesc/util/RefStackOf.hpp
@@ -49,6 +49,7 @@ public :
     //  Element management methods
     // -----------------------------------------------------------------------
     const TElem* elementAt(const unsigned int index) const;
+    TElem* popAt(const unsigned int index);
     void push(TElem* const toPush);
     const TElem* peek() const;
     TElem* pop();
-- 
GitLab