domstring.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,182 行 · 第 1/3 页

CPP
1,182
字号
/* * Copyright 1999-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: DOMString.cpp,v 1.11 2004/09/28 10:56:04 amassari Exp $ */#include <stdio.h>#include <xercesc/util/PlatformUtils.hpp>#include <xercesc/util/RuntimeException.hpp>#include <xercesc/util/TransService.hpp>#include <xercesc/util/XMLString.hpp>#include <xercesc/util/XMLRegisterCleanup.hpp>#include "DOM_DOMException.hpp"#include "DOMString.hpp"#ifndef XML_DEBUG#include "DOMStringImpl.hpp"#endif#include <assert.h>#include <string.h>XERCES_CPP_NAMESPACE_BEGIN//----------------------------------------------////  Forward decls////----------------------------------------------static void reinitDomConverter();static void reinitDomMutex();XMLLCPTranscoder*  getDomConverter();// ---------------------------------------------------------------------------//  Local static functions// ---------------------------------------------------------------------------//  getDOMConverter - get the converter from the system default//          codepage to Unicode that is to be used when//          a DOMString is constructed from a char *.//static XMLLCPTranscoder* gDomConverter = 0;static XMLRegisterCleanup cleanupDomConverter;int DOMString::gLiveStringDataCount    = 0;int DOMString::gTotalStringDataCount   = 0;int DOMString::gLiveStringHandleCount  = 0;int DOMString::gTotalStringHandleCount = 0;XMLLCPTranscoder*  getDomConverter(){    if (!gDomConverter)    {        XMLLCPTranscoder* transcoder = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder();        if (!transcoder)            XMLPlatformUtils::panic(PanicHandler::Panic_NoDefTranscoder            );        if (XMLPlatformUtils::compareAndSwap((void **)&gDomConverter, transcoder, 0) != 0)            delete transcoder;        else            cleanupDomConverter.registerCleanup(reinitDomConverter);    }    return gDomConverter;};////  There is one global mutex that is used to synchronize access to the//     allocator free list for DOMStringHandles.  This function gets that//     mutex, and will create it on the first attempt to get it.//static XMLMutex* DOMStringHandleMutex = 0;   // Mutex will be deleted by ~DOMStringHandle.static XMLRegisterCleanup cleanupDomMutex;XMLMutex& DOMStringHandle::getMutex(){    if (!DOMStringHandleMutex)    {        XMLMutex* tmpMutex = new XMLMutex;        if (XMLPlatformUtils::compareAndSwap((void**)&DOMStringHandleMutex, tmpMutex, 0))        {            // Someone beat us to it, so let's clean up ours            delete tmpMutex;        }        else            cleanupDomMutex.registerCleanup(reinitDomMutex);    }    return *DOMStringHandleMutex;}//----------------------------------------------////      DOMStringData////----------------------------------------------void DOMStringData::removeRef(){    int result = XMLPlatformUtils::atomicDecrement(fRefCount);    if (result==0)    {        fBufferLength = 0xcccc;        fRefCount     = 0xcccc;        XMLPlatformUtils::fgMemoryManager->deallocate(this);//delete [] this;  //  was allocated with new char[size] !        XMLPlatformUtils::atomicDecrement(DOMString::gLiveStringDataCount);    };};void DOMStringData::addRef(){    XMLPlatformUtils::atomicIncrement(fRefCount);};DOMStringData *DOMStringData::allocateBuffer(unsigned int length){    unsigned int sizeToAllocate = sizeof(DOMStringData) //  buffer will contain an        + length*sizeof(XMLCh);                //  extra elem because of stub                                               //  array in DOMStringData struct.    DOMStringData *buf = 0;    buf = (DOMStringData *) XMLPlatformUtils::fgMemoryManager->allocate        (            sizeToAllocate * sizeof(char)        );//new char[sizeToAllocate];    XMLPlatformUtils::atomicIncrement(DOMString::gLiveStringDataCount);    XMLPlatformUtils::atomicIncrement(DOMString::gTotalStringDataCount);    buf->fBufferLength = length;    buf->fRefCount = 1;    buf->fData[0] = 0;    return buf;}//----------------------------------------------------////      DOMStringHandle////-----------------------------------------------------////  Specialized new and delete operators for DOMStringHandles.//      These are used, rather than the standard system operator new,//      for improved performance.////      We allocate largish blocks of memory using the standard system//      new function, and sub-allocate string handles from that block.//      Un-allocated string handles within the allocated blocks are kept//      in a singly linked list, making allocation and deallocation//      very quick in the common case.////      String handle allocation is thread safe.  A multi-threaded//      application may have threads concurrently accessing multiple//      DOM documents; since all string handles come from the same pool,//      this allocator must be safe.  The compare and exchange function,//      which is available as a single instruction in most processor//      architectures, and typically surfaced as an OS function,//      is used to safely update the string handle free list.//void *DOMStringHandle::freeListPtr = 0;   // Point to the head of the                                          //  free list of un-allocated                                          //  string handles, or 0 if there                                          //  are no free string handles.static const int allocGroupSize = 1024;   // Number of string handles to allocate                                          //  as a chunk from the system's                                          //  memory allocator.DOMStringHandle *DOMStringHandle::blockListPtr = 0;  // Point to the head of the list                                          //  of larger blocks in which DOMStringHandles                                          //  are allocated.////  Operator new for DOMStringHandles.  Called implicitly from the//          DOMStringHandle constructor.//void *DOMStringHandle::operator new(size_t sizeToAlloc){    assert(sizeToAlloc == sizeof(DOMStringHandle));    void    *retPtr;    XMLMutexLock lock(&getMutex());    // Lock the DOMStringHandle mutex for                                       //  the duration of this function.    if (freeListPtr == 0)    {        // Uncommon case.  The free list of string handles is empty        // Allocate a new batch of them, using the system's        // operator new to get a chunk of memory.        //        DOMStringHandle *dsg = (DOMStringHandle*)            XMLPlatformUtils::fgMemoryManager->allocate            (                allocGroupSize * sizeof(DOMStringHandle)            );//::new DOMStringHandle[allocGroupSize];        // Link the block itself into the list of blocks.  The purpose of this is to        //   let us locate and delete the blocks when shutting down.        //        *(DOMStringHandle **)dsg = blockListPtr;        blockListPtr = dsg;        // Link all of the new storage for StringHandles into the StringHandle free list        int   i;    //   Start with index 1;  index 0 is reserved for linking the                    //   larger allocation blocks together.        for (i=1; i<allocGroupSize-1; i++) {            *(void **)&dsg[i] = freeListPtr;            freeListPtr = &dsg[i];        }    }    retPtr = freeListPtr;    freeListPtr = *(void **)freeListPtr;    XMLPlatformUtils::atomicIncrement(DOMString::gLiveStringHandleCount);    return retPtr;};////  Operator delete for DOMStringHandles.  Called implicitly from the//              Destructor for DOMStringHandle.//void DOMStringHandle::operator delete(void *pMem){    XMLMutexLock   lock(&getMutex());    // Lock the DOMStringHandle mutex for the    //    duration of this function.    XMLPlatformUtils::atomicDecrement(DOMString::gLiveStringHandleCount);    *(void **)pMem = freeListPtr;    freeListPtr = pMem;    // If ALL of the string handles are gone, delete the storage blocks used for the    //   handles as well.    if (DOMString::gLiveStringHandleCount == 0)    {        DOMStringHandle *pThisBlock, *pNextBlock;        for (pThisBlock = blockListPtr; pThisBlock != 0; pThisBlock = pNextBlock)        {            pNextBlock = *(DOMStringHandle **)pThisBlock;            XMLPlatformUtils::fgMemoryManager->deallocate(pThisBlock);//delete [] pThisBlock;        }        blockListPtr = 0;        freeListPtr  = 0;    }};void DOMStringHandle::addRef(){    XMLPlatformUtils::atomicIncrement(fRefCount);};void DOMStringHandle::removeRef(){    int result = XMLPlatformUtils::atomicDecrement(fRefCount);    if (result==0)    {        fDSData->removeRef();//        delete this;        DOMStringHandle* ptr = this;        delete ptr;    };};DOMStringHandle *DOMStringHandle::createNewStringHandle(unsigned int bufLength){    DOMStringHandle  *h = new DOMStringHandle;    XMLPlatformUtils::atomicIncrement(DOMString::gTotalStringHandleCount);    h -> fLength = 0;    h -> fRefCount = 1;    h -> fDSData = DOMStringData::allocateBuffer(bufLength);    return h;};DOMStringHandle *DOMStringHandle::cloneStringHandle(){    DOMStringHandle *h = new DOMStringHandle;    h->fLength   = fLength;    h->fRefCount = 1;    h->fDSData   = fDSData;    h->fDSData->addRef();    return h;}//------------------------------------------------------------////      DOMString////------------------------------------------------------------DOMString::DOMString(){    fHandle = 0;};DOMString::DOMString(const DOMString &other){    fHandle = other.fHandle;    if (fHandle)        fHandle->addRef();};DOMString::DOMString(const XMLCh *data){    fHandle = 0;    if (data != 0)    {        unsigned int dataLength = 0;        while (data[dataLength] != 0)            ++dataLength;        if (dataLength != 0)        {            fHandle = DOMStringHandle::createNewStringHandle(dataLength+1);            fHandle->fLength = dataLength;            XMLCh *strData = fHandle->fDSData->fData;            unsigned int i;            for (i=0; i<dataLength ; ++i)                strData[i] = data[i];            strData[dataLength] = 0;        }    }}DOMString::DOMString(const XMLCh *data, unsigned int dataLength){    fHandle = 0;    if (data != 0)    {        if (dataLength > 0)        {            fHandle = DOMStringHandle::createNewStringHandle(dataLength+1);            fHandle->fLength = dataLength;            XMLCh *strData = fHandle->fDSData->fData;            unsigned int i;            for (i=0; i<dataLength ; ++i)                strData[i] = data[i];            strData[dataLength] = 0;        }    }}////  Create a DOMString from a char * string in the default code page//                     of the system on which we are executing.////DOMString::DOMString(const char *srcString){    fHandle = 0;    if (srcString != 0)    {        XMLLCPTranscoder*  uniConverter = getDomConverter();        unsigned int srcLen = strlen(srcString);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?