/* * Copyright 2001-2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: DOMStringPool.cpp 176026 2004-09-08 13:57:07Z peiyongz $ */ #include #include #include "DOMStringPool.hpp" #include "DOMDocumentImpl.hpp" XERCES_CPP_NAMESPACE_BEGIN // // DStringPoolEntry - one of these structs is allocated for each // XMLCh String in the pool. Each slot in the // hash table array itself is a pointer to the head // of a singly-linked list of these structs. // // Although this struct is delcared with a string length of one, // the factory method allocates enough storage to hold the full // string length. // struct DOMStringPoolEntry { DOMStringPoolEntry *fNext; XMLCh fString[1]; }; // // createSPE - factory method for creating sting pool entry structs. // Allocates sufficient storage to hold the entire string // static DOMStringPoolEntry *createSPE(const XMLCh *str, DOMDocumentImpl *doc) { // Compute size to allocate. Note that there's 1 char of string declared in the // struct, so we don't need to add one again to account for the trailing null. // size_t sizeToAllocate = sizeof(DOMStringPoolEntry) + XMLString::stringLen(str)*sizeof(XMLCh); DOMStringPoolEntry *newSPE = (DOMStringPoolEntry *)doc->allocate(sizeToAllocate); newSPE->fNext = 0; XMLCh * nonConstStr = (XMLCh *)newSPE->fString; XMLString::copyString(nonConstStr, str); return newSPE; } DOMStringPool::DOMStringPool(int hashTableSize, DOMDocumentImpl *doc) : fDoc(doc) , fHashTableSize(hashTableSize) { // needed to get access to the doc's storage allocator. //fHashTable = new (fDoc) DOMStringPoolEntry *[hashTableSize]; void* p = doc->allocate(sizeof(DOMStringPoolEntry*) * hashTableSize); fHashTable = (DOMStringPoolEntry**) p; for (int i=0; igetMemoryManager()); pspe = &fHashTable[inHash]; while (*pspe != 0) { if (XMLString::equals((*pspe)->fString, in)) return (*pspe)->fString; pspe = &((*pspe)->fNext); } // This string hasn't been seen before. Add it to the pool. *pspe = spe = createSPE(in, fDoc); return spe->fString; } // ----------------------------------------------------------------------- // DOMBuffer: Constructors // ----------------------------------------------------------------------- DOMBuffer::DOMBuffer(DOMDocumentImpl *doc, int capacity) : fBuffer(0) , fIndex(0) , fCapacity(capacity) , fDoc(doc) { // Buffer is one larger than capacity, to allow for zero term fBuffer = (XMLCh*) doc->allocate((fCapacity+1)*sizeof(XMLCh)); // Keep it null terminated fBuffer[0] = XMLCh(0); } DOMBuffer::DOMBuffer(DOMDocumentImpl *doc, const XMLCh* string) : fBuffer(0) , fIndex(0) , fCapacity(0) , fDoc(doc) { unsigned int actualCount = XMLString::stringLen(string); fCapacity = actualCount + 15; // Buffer is one larger than capacity, to allow for zero term fBuffer = (XMLCh*) doc->allocate((fCapacity+1)*sizeof(XMLCh)); memcpy(fBuffer, string, actualCount * sizeof(XMLCh)); fIndex = actualCount; // Keep it null terminated fBuffer[fIndex] = 0; } // --------------------------------------------------------------------------- // DOMBuffer: Buffer management // --------------------------------------------------------------------------- void DOMBuffer::append(const XMLCh* const chars, const unsigned int count) { unsigned int actualCount = count; if (!count) actualCount = XMLString::stringLen(chars); if (fIndex + actualCount >= fCapacity) expandCapacity(actualCount); memcpy(&fBuffer[fIndex], chars, actualCount * sizeof(XMLCh)); fIndex += actualCount; // Keep it null terminated fBuffer[fIndex] = 0; } void DOMBuffer::set(const XMLCh* const chars, const unsigned int count) { unsigned int actualCount = count; if (!count) actualCount = XMLString::stringLen(chars); fIndex = 0; if (fIndex + actualCount >= fCapacity) expandCapacity(actualCount); memcpy(fBuffer, chars, actualCount * sizeof(XMLCh)); fIndex = actualCount; // Keep it null terminated fBuffer[fIndex] = 0; } // --------------------------------------------------------------------------- // DOMBuffer: Private helper methods // --------------------------------------------------------------------------- void DOMBuffer::expandCapacity(const unsigned int extraNeeded) { //not enough room. Calc new capacity and allocate new buffer const unsigned int newCap = (unsigned int)((fIndex + extraNeeded) * 1.25); XMLCh* newBuf = (XMLCh*) fDoc->allocate((newCap+1)*sizeof(XMLCh)); // Copy over the old stuff memcpy(newBuf, fBuffer, fCapacity * sizeof(XMLCh)); // revisit: Leave the old buffer in document heap, yes, this is a leak, but live with it! // store new stuff fBuffer = newBuf; fCapacity = newCap; } XERCES_CPP_NAMESPACE_END