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 + -
显示快捷键?