DOMString.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:36k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: DOMString.cpp,v 1.7 2003/05/22 02:26:50 knoaman Exp $
  58.  */
  59. #include <stdio.h>
  60. #include <xercesc/util/PlatformUtils.hpp>
  61. #include <xercesc/util/RuntimeException.hpp>
  62. #include <xercesc/util/TransService.hpp>
  63. #include <xercesc/util/XMLString.hpp>
  64. #include <xercesc/util/XMLRegisterCleanup.hpp>
  65. #include "DOM_DOMException.hpp"
  66. #include "DOMString.hpp"
  67. #ifndef XML_DEBUG
  68. #include "DOMStringImpl.hpp"
  69. #endif
  70. #include <assert.h>
  71. #include <string.h>
  72. XERCES_CPP_NAMESPACE_BEGIN
  73. //----------------------------------------------
  74. //
  75. //  Forward decls
  76. //
  77. //----------------------------------------------
  78. static void reinitDomConverter();
  79. static void reinitDomMutex();
  80. XMLLCPTranscoder*  getDomConverter();
  81. // ---------------------------------------------------------------------------
  82. //  Local static functions
  83. // ---------------------------------------------------------------------------
  84. //  getDOMConverter - get the converter from the system default
  85. //          codepage to Unicode that is to be used when
  86. //          a DOMString is constructed from a char *.
  87. //
  88. static XMLLCPTranscoder* gDomConverter = 0;
  89. static XMLRegisterCleanup cleanupDomConverter;
  90. XMLLCPTranscoder*  getDomConverter()
  91. {
  92.     if (!gDomConverter)
  93.     {
  94.         XMLLCPTranscoder* transcoder = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder();
  95.         if (!transcoder)
  96.             XMLPlatformUtils::panic(PanicHandler::Panic_NoDefTranscoder
  97.             );
  98.         if (XMLPlatformUtils::compareAndSwap((void **)&gDomConverter, transcoder, 0) != 0)
  99.             delete transcoder;
  100.         else
  101.             cleanupDomConverter.registerCleanup(reinitDomConverter);
  102.     }
  103.     return gDomConverter;
  104. };
  105. //
  106. //  There is one global mutex that is used to synchronize access to the
  107. //     allocator free list for DOMStringHandles.  This function gets that
  108. //     mutex, and will create it on the first attempt to get it.
  109. //
  110. static XMLMutex* DOMStringHandleMutex = 0;   // Mutex will be deleted by ~DOMStringHandle.
  111. static XMLRegisterCleanup cleanupDomMutex;
  112. XMLMutex& DOMStringHandle::getMutex()
  113. {
  114.     if (!DOMStringHandleMutex)
  115.     {
  116.         XMLMutex* tmpMutex = new XMLMutex;
  117.         if (XMLPlatformUtils::compareAndSwap((void**)&DOMStringHandleMutex, tmpMutex, 0))
  118.         {
  119.             // Someone beat us to it, so let's clean up ours
  120.             delete tmpMutex;
  121.         }
  122.         else
  123.             cleanupDomMutex.registerCleanup(reinitDomMutex);
  124.     }
  125.     return *DOMStringHandleMutex;
  126. }
  127. //----------------------------------------------
  128. //
  129. //      DOMStringData
  130. //
  131. //----------------------------------------------
  132. void DOMStringData::removeRef()
  133. {
  134.     int result = XMLPlatformUtils::atomicDecrement(fRefCount);
  135.     if (result==0)
  136.     {
  137.         fBufferLength = 0xcccc;
  138.         fRefCount     = 0xcccc;
  139.         XMLPlatformUtils::fgMemoryManager->deallocate(this);//delete [] this;  //  was allocated with new char[size] !
  140.         XMLPlatformUtils::atomicDecrement(DOMString::gLiveStringDataCount);
  141.     };
  142. };
  143. void DOMStringData::addRef()
  144. {
  145.     XMLPlatformUtils::atomicIncrement(fRefCount);
  146. };
  147. DOMStringData *DOMStringData::allocateBuffer(unsigned int length)
  148. {
  149.     unsigned int sizeToAllocate = sizeof(DOMStringData) //  buffer will contain an
  150.         + length*sizeof(XMLCh);                //  extra elem because of stub
  151.                                                //  array in DOMStringData struct.
  152.     DOMStringData *buf = 0;
  153.     try {
  154.         buf = (DOMStringData *) XMLPlatformUtils::fgMemoryManager->allocate
  155.         (
  156.             sizeToAllocate * sizeof(char)
  157.         );//new char[sizeToAllocate];
  158.     }
  159.     catch (...) {
  160.         ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  161.     }
  162.     if (!buf)
  163.        ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  164.     XMLPlatformUtils::atomicIncrement(DOMString::gLiveStringDataCount);
  165.     XMLPlatformUtils::atomicIncrement(DOMString::gTotalStringDataCount);
  166.     buf->fBufferLength = length;
  167.     buf->fRefCount = 1;
  168.     buf->fData[0] = 0;
  169.     return buf;
  170. }
  171. //----------------------------------------------------
  172. //
  173. //      DOMStringHandle
  174. //
  175. //-----------------------------------------------------
  176. //
  177. //  Specialized new and delete operators for DOMStringHandles.
  178. //      These are used, rather than the standard system operator new,
  179. //      for improved performance.
  180. //
  181. //      We allocate largish blocks of memory using the standard system
  182. //      new function, and sub-allocate string handles from that block.
  183. //      Un-allocated string handles within the allocated blocks are kept
  184. //      in a singly linked list, making allocation and deallocation
  185. //      very quick in the common case.
  186. //
  187. //      String handle allocation is thread safe.  A multi-threaded
  188. //      application may have threads concurrently accessing multiple
  189. //      DOM documents; since all string handles come from the same pool,
  190. //      this allocator must be safe.  The compare and exchange function,
  191. //      which is available as a single instruction in most processor
  192. //      architectures, and typically surfaced as an OS function,
  193. //      is used to safely update the string handle free list.
  194. //
  195. void *DOMStringHandle::freeListPtr = 0;   // Point to the head of the
  196.                                           //  free list of un-allocated
  197.                                           //  string handles, or 0 if there
  198.                                           //  are no free string handles.
  199. static const int allocGroupSize = 1024;   // Number of string handles to allocate
  200.                                           //  as a chunk from the system's
  201.                                           //  memory allocator.
  202. DOMStringHandle *DOMStringHandle::blockListPtr = 0;  // Point to the head of the list
  203.                                           //  of larger blocks in which DOMStringHandles
  204.                                           //  are allocated.
  205. //
  206. //  Operator new for DOMStringHandles.  Called implicitly from the
  207. //          DOMStringHandle constructor.
  208. //
  209. void *DOMStringHandle::operator new(size_t sizeToAlloc)
  210. {
  211.     assert(sizeToAlloc == sizeof(DOMStringHandle));
  212.     void    *retPtr;
  213.     XMLMutexLock lock(&getMutex());    // Lock the DOMStringHandle mutex for
  214.                                        //  the duration of this function.
  215.     if (freeListPtr == 0)
  216.     {
  217.         // Uncommon case.  The free list of string handles is empty
  218.         // Allocate a new batch of them, using the system's
  219.         // operator new to get a chunk of memory.
  220.         //
  221.         DOMStringHandle *dsg = (DOMStringHandle*)
  222.             XMLPlatformUtils::fgMemoryManager->allocate
  223.             (
  224.                 allocGroupSize * sizeof(DOMStringHandle)
  225.             );//::new DOMStringHandle[allocGroupSize];
  226.         // Link the block itself into the list of blocks.  The purpose of this is to
  227.         //   let us locate and delete the blocks when shutting down.
  228.         //
  229.         *(DOMStringHandle **)dsg = blockListPtr;
  230.         blockListPtr = dsg;
  231.         // Link all of the new storage for StringHandles into the StringHandle free list
  232.         int   i;    //   Start with index 1;  index 0 is reserved for linking the
  233.                     //   larger allocation blocks together.
  234.         for (i=1; i<allocGroupSize-1; i++) {
  235.             *(void **)&dsg[i] = freeListPtr;
  236.             freeListPtr = &dsg[i];
  237.         }
  238.     }
  239.     retPtr = freeListPtr;
  240.     freeListPtr = *(void **)freeListPtr;
  241.     XMLPlatformUtils::atomicIncrement(DOMString::gLiveStringHandleCount);
  242.     return retPtr;
  243. };
  244. //
  245. //  Operator delete for DOMStringHandles.  Called implicitly from the
  246. //              Destructor for DOMStringHandle.
  247. //
  248. void DOMStringHandle::operator delete(void *pMem)
  249. {
  250.     XMLMutexLock   lock(&getMutex());    // Lock the DOMStringHandle mutex for the
  251.     //    duration of this function.
  252.     XMLPlatformUtils::atomicDecrement(DOMString::gLiveStringHandleCount);
  253.     *(void **)pMem = freeListPtr;
  254.     freeListPtr = pMem;
  255.     // If ALL of the string handles are gone, delete the storage blocks used for the
  256.     //   handles as well.
  257.     if (DOMString::gLiveStringHandleCount == 0)
  258.     {
  259.         DOMStringHandle *pThisBlock, *pNextBlock;
  260.         for (pThisBlock = blockListPtr; pThisBlock != 0; pThisBlock = pNextBlock)
  261.         {
  262.             pNextBlock = *(DOMStringHandle **)pThisBlock;
  263.             XMLPlatformUtils::fgMemoryManager->deallocate(pThisBlock);//delete [] pThisBlock;
  264.         }
  265.         blockListPtr = 0;
  266.         freeListPtr  = 0;
  267.     }
  268. };
  269. void DOMStringHandle::addRef()
  270. {
  271.     XMLPlatformUtils::atomicIncrement(fRefCount);
  272. };
  273. void DOMStringHandle::removeRef()
  274. {
  275.     int result = XMLPlatformUtils::atomicDecrement(fRefCount);
  276.     if (result==0)
  277.     {
  278.         fDSData->removeRef();
  279. //        delete this;
  280.         DOMStringHandle* ptr = this;
  281.         delete ptr;
  282.     };
  283. };
  284. DOMStringHandle *DOMStringHandle::createNewStringHandle(unsigned int bufLength)
  285. {
  286.     DOMStringHandle  *h = new DOMStringHandle;
  287.     XMLPlatformUtils::atomicIncrement(DOMString::gTotalStringHandleCount);
  288.     h -> fLength = 0;
  289.     h -> fRefCount = 1;
  290.     h -> fDSData = DOMStringData::allocateBuffer(bufLength);
  291.     return h;
  292. };
  293. DOMStringHandle *DOMStringHandle::cloneStringHandle()
  294. {
  295.     DOMStringHandle *h = new DOMStringHandle;
  296.     h->fLength   = fLength;
  297.     h->fRefCount = 1;
  298.     h->fDSData   = fDSData;
  299.     h->fDSData->addRef();
  300.     return h;
  301. }
  302. //------------------------------------------------------------
  303. //
  304. //      DOMString
  305. //
  306. //------------------------------------------------------------
  307. int DOMString::gLiveStringDataCount    = 0;
  308. int DOMString::gTotalStringDataCount   = 0;
  309. int DOMString::gLiveStringHandleCount  = 0;
  310. int DOMString::gTotalStringHandleCount = 0;
  311. DOMString::DOMString()
  312. {
  313.     fHandle = 0;
  314. };
  315. DOMString::DOMString(const DOMString &other)
  316. {
  317.     fHandle = other.fHandle;
  318.     if (fHandle)
  319.         fHandle->addRef();
  320. };
  321. DOMString::DOMString(const XMLCh *data)
  322. {
  323.     fHandle = 0;
  324.     if (data != 0)
  325.     {
  326.         unsigned int dataLength = 0;
  327.         while (data[dataLength] != 0)
  328.             ++dataLength;
  329.         if (dataLength != 0)
  330.         {
  331.             fHandle = DOMStringHandle::createNewStringHandle(dataLength+1);
  332.             fHandle->fLength = dataLength;
  333.             XMLCh *strData = fHandle->fDSData->fData;
  334.             unsigned int i;
  335.             for (i=0; i<dataLength ; ++i)
  336.                 strData[i] = data[i];
  337.             strData[dataLength] = 0;
  338.         }
  339.     }
  340. }
  341. DOMString::DOMString(const XMLCh *data, unsigned int dataLength)
  342. {
  343.     fHandle = 0;
  344.     if (data != 0)
  345.     {
  346.         if (dataLength > 0)
  347.         {
  348.             fHandle = DOMStringHandle::createNewStringHandle(dataLength+1);
  349.             fHandle->fLength = dataLength;
  350.             XMLCh *strData = fHandle->fDSData->fData;
  351.             unsigned int i;
  352.             for (i=0; i<dataLength ; ++i)
  353.                 strData[i] = data[i];
  354.             strData[dataLength] = 0;
  355.         }
  356.     }
  357. }
  358. //
  359. //  Create a DOMString from a char * string in the default code page
  360. //                     of the system on which we are executing.
  361. //
  362. //
  363. DOMString::DOMString(const char *srcString)
  364. {
  365.     fHandle = 0;
  366.     if (srcString != 0)
  367.     {
  368.         XMLLCPTranscoder*  uniConverter = getDomConverter();
  369.         unsigned int srcLen = strlen(srcString);
  370.         if (srcLen == 0)
  371.             return;
  372.         // The charsNeeded normally is same as srcLen.  To enhance performance,
  373.         // we start with this estimate, and if overflow, then call calcRequiredSize for actual size
  374.         fHandle = DOMStringHandle::createNewStringHandle(srcLen + 1);
  375.         XMLCh *strData = fHandle->fDSData->fData;
  376.         if (!uniConverter->transcode(srcString, strData, srcLen) || (XMLString::stringLen(strData) != srcLen))
  377.         {
  378.             // conversion failed, so try again
  379.             if (fHandle)
  380.                 fHandle->removeRef();
  381.             fHandle = 0;
  382.             srcLen = uniConverter->calcRequiredSize(srcString);
  383.             fHandle = DOMStringHandle::createNewStringHandle(srcLen + 1);
  384.             XMLCh *strData2 = fHandle->fDSData->fData;
  385.             if (!uniConverter->transcode(srcString, strData2, srcLen))
  386.             {
  387.                 // <TBD> We should throw something here?
  388.             }
  389.         }
  390.         fHandle->fLength = srcLen;
  391.     }
  392. };
  393. DOMString::DOMString(int nullValue)
  394. {
  395.    assert(nullValue == 0);
  396.    fHandle = 0;
  397. };
  398. DOMString::~DOMString()
  399. {
  400.     if (fHandle)
  401.         fHandle->removeRef();
  402.     fHandle = 0;
  403. };
  404. DOMString & DOMString::operator =(const DOMString &other)
  405. {
  406.     if (this == &other)
  407.         return *this;
  408.     if (fHandle)
  409.         fHandle->removeRef();
  410.     fHandle = other.fHandle;
  411.     if (fHandle)
  412.         fHandle->addRef();
  413.     return *this;
  414. };
  415. DOMString & DOMString::operator = (DOM_NullPtr *arg)
  416. {
  417.     assert(arg == 0);
  418.     if (fHandle)
  419.         fHandle->removeRef();
  420.     fHandle = 0;
  421.     return *this;
  422. };
  423. bool DOMString::operator ==(const DOMString &other) const
  424. {
  425.     return this->fHandle == other.fHandle;
  426. };
  427. bool DOMString::operator !=(const DOMString &other) const
  428. {
  429.     return this->fHandle != other.fHandle;
  430. };
  431. bool DOMString::operator == (const DOM_NullPtr *p) const
  432. {
  433.     return (fHandle == 0);
  434. };
  435. bool DOMString::operator != (const DOM_NullPtr *p) const
  436. {
  437.     return (fHandle != 0);
  438. };
  439. void DOMString::reserve(unsigned int size)
  440. {
  441. if (fHandle == 0)
  442. {
  443.     if (size > 0)
  444.         fHandle = DOMStringHandle::createNewStringHandle(size);
  445. }
  446. }
  447. void DOMString::appendData(const DOMString &other)
  448. {
  449.     if (other.fHandle == 0 || other.fHandle->fLength == 0)
  450.         return;
  451.     // If this string is empty and this string does not have an
  452.     //   already allocated buffer sufficient to hold the string being
  453.     //   appended, return a clone of the other string.
  454.     //
  455.     if (fHandle == 0 || (fHandle->fLength == 0 &&
  456.         fHandle->fDSData->fBufferLength < other.fHandle->fLength))
  457.     {
  458.         if (fHandle) fHandle->removeRef();
  459.         this->fHandle = other.fHandle->cloneStringHandle();
  460.         return;
  461.     }
  462.     unsigned int newLength = fHandle->fLength + other.fHandle->fLength;
  463.     if (newLength >= fHandle->fDSData->fBufferLength ||
  464.         fHandle->fDSData->fRefCount > 1)
  465.     {
  466.         // We can't stick the data to be added onto the end of the
  467.         //  existing string, either because there is not space in
  468.         //  the buffer, or because the buffer is being shared with
  469.         //  some other string.  So, make a new buffer.
  470.         DOMStringData *newBuf = DOMStringData::allocateBuffer(newLength);
  471.         XMLCh *newP = newBuf->fData;
  472.         XMLCh *oldP = fHandle->fDSData->fData;
  473.         unsigned int i;
  474.         for (i=0; i<fHandle->fLength; ++i)
  475.             newP[i] = oldP[i];
  476.         fHandle->fDSData->removeRef();
  477.         fHandle->fDSData = newBuf;
  478.     }
  479.     //
  480.     // This string now had enough buffer room to hold the data to
  481.     //  be appended.  Go ahead and copy it in.
  482.     XMLCh *srcP = other.fHandle->fDSData->fData;
  483.     XMLCh *destP = &fHandle->fDSData->fData[fHandle->fLength];
  484.     unsigned int i;
  485.     for (i=0; i<other.fHandle->fLength; i++)
  486.         destP[i] = srcP[i];
  487.     fHandle->fLength += other.fHandle->fLength;
  488. }
  489. void DOMString::appendData(XMLCh ch)
  490. {
  491. unsigned int newLength = 0;
  492. if (fHandle == 0)
  493. {
  494. fHandle = DOMStringHandle::createNewStringHandle(1);
  495. newLength = 1;
  496. }
  497. else
  498. newLength = fHandle->fLength + 1;
  499.     if (newLength >= fHandle->fDSData->fBufferLength ||
  500.         fHandle->fDSData->fRefCount > 1)
  501.     {
  502.         // We can't stick the data to be added onto the end of the
  503.         //  existing string, either because there is not space in
  504.         //  the buffer, or because the buffer is being shared with
  505.         //  some other string.  So, make a new buffer.
  506.         DOMStringData *newBuf = DOMStringData::allocateBuffer(newLength);
  507.         XMLCh *newP = newBuf->fData;
  508.         XMLCh *oldP = fHandle->fDSData->fData;
  509.         unsigned int i;
  510.         for (i=0; i<fHandle->fLength; ++i)
  511.             newP[i] = oldP[i];
  512.         fHandle->fDSData->removeRef();
  513.         fHandle->fDSData = newBuf;
  514.     }
  515.     XMLCh *destP = &fHandle->fDSData->fData[fHandle->fLength];
  516. destP[0] = ch;
  517.     fHandle->fLength ++;
  518. }
  519. // TODO: A custom version could be written more efficiently, avoiding
  520. // the creation of the temporary DOMString
  521. void DOMString::appendData(const XMLCh* other)
  522. {
  523. appendData(DOMString(other));
  524. }
  525. DOMString& DOMString::operator +=(const DOMString &other)
  526. {
  527. appendData(other);
  528. return *this;
  529. }
  530. DOMString& DOMString::operator +=(const XMLCh *str)
  531. {
  532. appendData(str);
  533. return *this;
  534. }
  535. DOMString& DOMString::operator +=(XMLCh ch)
  536. {
  537. appendData(ch);
  538. return *this;
  539. }
  540. XMLCh     DOMString::charAt(unsigned int index) const
  541. {
  542.     XMLCh retCh = 0;
  543.     if ((fHandle != 0) && (index < fHandle->fLength))
  544.         retCh = fHandle->fDSData->fData[index];
  545.     return retCh;
  546. };
  547. DOMString DOMString::clone() const
  548. {
  549.     DOMString retString;
  550.     if (fHandle != 0)
  551.         retString.fHandle = this->fHandle->cloneStringHandle();
  552.     return retString;
  553. };
  554. void DOMString::deleteData(unsigned int offset, unsigned int delLength)
  555. {
  556.     unsigned int stringLen = this->length();
  557.     if (offset > stringLen || offset < 0 || delLength < 0)
  558.         throw DOM_DOMException(DOM_DOMException::INDEX_SIZE_ERR, 0);
  559.     // Cap the value of delLength to avoid trouble with overflows
  560.     //  in the following length computations.
  561.     if (delLength > stringLen)
  562.         delLength = stringLen;
  563.     // If the length of data to be deleted would extend off the end
  564.     //   of the string, cut it back to stop at the end of string.
  565.     if (offset + delLength >= stringLen)
  566.         delLength = stringLen - offset;
  567.     if (delLength == 0)
  568.         return;
  569.     unsigned int newStringLength = stringLen - delLength;
  570.     if (fHandle->fDSData->fRefCount > 1 && offset+delLength < stringLen)
  571.     {
  572.         // The deletion is of a range in the middle of the string
  573.         //  and there's another string handle using the buffer so
  574.         //  we need to make a new buffer before moving characters
  575.         //  around.
  576.         DOMStringData *newBuf = DOMStringData::allocateBuffer(newStringLength);
  577.         XMLCh *newP = newBuf->fData;
  578.         XMLCh *oldP = fHandle->fDSData->fData;
  579.         unsigned int i;
  580.         for (i=0; i<offset; i++)
  581.             newP[i] = oldP[i];
  582.         for (i=offset; i<newStringLength; i++)
  583.             newP[i] = oldP[i+delLength];
  584.         fHandle->fLength = newStringLength;
  585.         fHandle->fDSData->removeRef();
  586.         fHandle->fDSData = newBuf;
  587.     }
  588.     else if (offset+delLength < stringLen)
  589.     {
  590.         // The deletion is of a range in the middle of the string,
  591.         // but no other string is sharing the buffer, so we can
  592.         // just delete in place.
  593.         unsigned int i;
  594.         XMLCh *bufP =  fHandle->fDSData->fData;
  595.         for (i=offset; i<newStringLength; i++)
  596.             bufP[i] = bufP[i+delLength];
  597.         fHandle->fLength = newStringLength;
  598.     }
  599.     else
  600.     {
  601.         // The deletion continues to the end of the string.
  602.         // Simply reset the length.  We don't need to worry
  603.         // about other strings sharing the buffer because
  604.         // no characters are moved.
  605.         fHandle->fLength = newStringLength;
  606.     }
  607. };
  608. bool DOMString::equals(const DOMString &other) const
  609. {
  610.     bool retVal = true;
  611.     if (this->fHandle != 0  && other.fHandle != 0)
  612.     {
  613.         if (this->fHandle->fLength != other.fHandle->fLength)
  614.         {
  615.             retVal =  false;
  616.         }
  617.         else
  618.         {
  619.             XMLCh *thisP  = this->fHandle->fDSData->fData;
  620.             XMLCh *otherP = other.fHandle->fDSData->fData;
  621.             unsigned int i;
  622.             for (i=0; i<this->fHandle->fLength; i++)
  623.             {
  624.                 if (thisP[i] != otherP[i])
  625.                 {
  626.                     retVal = false;
  627.                     break;
  628.                 }
  629.             }
  630.         }
  631.     }
  632.     else
  633.     {
  634.         // At this point, one or more of the fHandle
  635.         //  pointers is known to be zero.
  636.         if (fHandle       && fHandle->fLength != 0  ||
  637.             other.fHandle && other.fHandle->fLength != 0)
  638.             retVal = false;
  639.     }
  640.     return retVal;
  641. };
  642. bool DOMString::equals(const XMLCh *other) const
  643. {
  644.     if (this->fHandle != 0  && other != 0)
  645.     {
  646.         // Both strings have non-null data pointers, so
  647.         //  we can go ahead and actually compare them.
  648.         XMLCh *thisP  = this->fHandle->fDSData->fData;
  649.         unsigned int len    = this->fHandle->fLength;
  650.         unsigned int i;
  651.         for (i=0; i<len; i++)
  652.         {
  653.             if (other[i] == 0)   // "other" is null terminated.
  654.                 return false;    //   (If there were no chance of a DOM
  655.                                  //   string having a 0 char in the middle of
  656.                                  //   it, this test could be omitted.)
  657.             if (thisP[i] != other[i])
  658.                 return false;
  659.         }
  660.         if (other[len] != 0)     // This test for the end of the other
  661.             return false;        //  string can't be done without first
  662.                                  //  checking that we haven't walked off the
  663.                                  //  end.  (It has actually happened - off end
  664.                                  //  of string, page, and valid memory.)
  665.         return true;
  666.     }
  667.     // At this point, we know that at least one of the strings had a null
  668.     //  data pointer.
  669.     if (fHandle  && fHandle->fLength != 0)
  670.         return false;
  671.     if (other && *other != 0)
  672.         return false;
  673.     return true;  // Both strings are empty.  DOMString treats zero-length
  674.                   //   and a null data pointer as equivalent.
  675. };
  676. void DOMString::insertData(unsigned int offset, const DOMString &src)
  677. {
  678.     unsigned int origStrLength = this->length();
  679.     if (offset > origStrLength)
  680.         throw DOM_DOMException(DOM_DOMException::INDEX_SIZE_ERR, 0);
  681.     if (fHandle == 0)
  682.     {
  683.         *this = src.clone();
  684.         return;
  685.     }
  686.     if (src.fHandle == 0 || src.fHandle->fLength == 0)
  687.         return;
  688.     XMLCh *srcP = src.fHandle->fDSData->fData;
  689.     unsigned int srcLength = src.fHandle->fLength;
  690.     unsigned int newLength = fHandle->fLength + srcLength;
  691.     if (newLength >= fHandle->fDSData->fBufferLength ||
  692.         fHandle->fDSData->fRefCount > 1  || fHandle == src.fHandle )
  693.     {
  694.         // We can't stick the data to be added into the
  695.         //  existing string, either because there is not space in
  696.         //  the buffer, or because the buffer is being shared with
  697.         //  some other string.
  698.         //  So, make a new buffer.
  699.         DOMStringData *newBuf = DOMStringData::allocateBuffer(newLength);
  700.         XMLCh *newP  = newBuf->fData;
  701.         XMLCh *oldP   = fHandle->fDSData->fData;
  702.         unsigned int i;
  703.         for (i=0; i<offset; ++i)
  704.             newP[i] = oldP[i];
  705.         for (i=0; i<srcLength; i++)
  706.             newP[i+offset] = srcP[i];
  707.         for (i=offset; i<origStrLength; i++)
  708.             newP[i+srcLength] = oldP[i];
  709.         fHandle->fDSData->removeRef();
  710.         fHandle->fDSData = newBuf;
  711.     }
  712.     else
  713.     {
  714.         // There is room in the already-existing buffer to hold
  715.         //  the data to be inserted.  Insert it.
  716.         //
  717.         XMLCh *destP = fHandle->fDSData->fData;
  718.         int i;
  719.         for (i=(int)origStrLength-1; i>=(int)offset; i--)
  720.             destP[i+srcLength] = destP[i];
  721.         unsigned int j;
  722.         for (j=0; j<srcLength; j++)
  723.             destP[j+offset] = srcP[j];
  724.     };
  725.     fHandle->fLength += srcLength;
  726. }
  727. unsigned int DOMString::length() const
  728. {
  729.     unsigned int len = 0;
  730.     if (fHandle != 0)
  731.         len = fHandle->fLength;
  732.     return len;
  733. };
  734. void DOMString::print() const
  735. {
  736.     unsigned int len = this->length();
  737.     if (len > 0)
  738.     {
  739.         // Transcode from Unicode to char * in whatever the system local code page is.
  740.         char *pc = transcode(XMLPlatformUtils::fgMemoryManager);
  741.         fputs(pc, stdout);
  742.         XMLPlatformUtils::fgMemoryManager->deallocate(pc);//delete [] pc;
  743.     }
  744. };
  745. void DOMString::println() const
  746. {
  747. print();
  748.     putchar('n');
  749. };
  750. const XMLCh *DOMString::rawBuffer() const
  751. {
  752.     XMLCh  *retP = 0;
  753.     if (fHandle)
  754.     {
  755.         retP = fHandle->fDSData->fData;
  756.     }
  757.     return retP;
  758. };
  759. char *DOMString::transcode() const
  760. {
  761.     if (!fHandle || fHandle->fLength == 0)
  762.     {
  763.         char* retP = new char[1];
  764.         *retP = 0;
  765.         return retP;
  766.     }
  767.     // We've got some data
  768.     // DOMStrings are not always null terminated, so we may need to
  769.     // copy to another buffer first in order to null terminate it for
  770.     // use as input to the transcoding routines..
  771.     //
  772.     XMLCh* DOMStrData = fHandle->fDSData->fData;
  773.     const unsigned int localBufLen = 1000;
  774.     XMLCh localBuf[localBufLen];
  775.     XMLCh *allocatedBuf = 0;
  776.     XMLCh *srcP;
  777.     if (DOMStrData[fHandle->fLength] == 0)
  778.     {
  779.         // The data in the DOMString itself happens to be null terminated.
  780.         //  Just use it in place.
  781.         srcP = DOMStrData;
  782.     }
  783.     else if (fHandle->fLength < localBufLen-1)
  784.     {
  785.         // The data is not null terminated, but does fit in the
  786.         //  local buffer (fast allocation).  Copy it over, and add
  787.         //  the null termination,
  788.         memcpy(localBuf, DOMStrData, fHandle->fLength * sizeof(XMLCh));
  789.         srcP = localBuf;
  790.         srcP[fHandle->fLength] = 0;
  791.     }
  792.     else
  793.     {
  794.         // The data is too big for the local buffer.  Heap allocate one.
  795.         allocatedBuf = srcP = new XMLCh[fHandle->fLength + 1];
  796.         memcpy(allocatedBuf, DOMStrData, fHandle->fLength * sizeof(XMLCh));
  797.         srcP[fHandle->fLength] = 0;
  798.     }
  799.     //
  800.     //  Find out how many output chars we need and allocate a buffer big enough
  801.     //  for that plus a null.
  802.     //
  803.     //  The charsNeeded normally is same as fHandle->fLength.  To enhance performance,
  804.     //  we start with this estimate, and if overflow, then call calcRequiredSize for actual size
  805.     unsigned int charsNeeded = fHandle->fLength;
  806.     char* retP = new char[charsNeeded + 1];
  807.     if (!getDomConverter()->transcode(srcP, retP, charsNeeded) || (XMLString::stringLen(retP) != charsNeeded))
  808.     {
  809.         delete [] retP;
  810.         charsNeeded = getDomConverter()->calcRequiredSize(srcP);
  811.         retP = new char[charsNeeded + 1];
  812.         if (!getDomConverter()->transcode(srcP, retP, charsNeeded))
  813.         {
  814.             // <TBD> We should throw something here?
  815.         }
  816.     }
  817.     delete [] allocatedBuf;   // which will be null if we didn't allocate one.
  818.     // Cap it off and return it
  819.     retP[charsNeeded] = 0;
  820.     return retP;
  821. }
  822. char *DOMString::transcode(MemoryManager* const manager) const
  823. {
  824.     if (!fHandle || fHandle->fLength == 0)
  825.     {
  826.         char* retP = (char*) manager->allocate(sizeof(char));//new char[1];
  827.         *retP = 0;
  828.         return retP;
  829.     }
  830.     // We've got some data
  831.     // DOMStrings are not always null terminated, so we may need to
  832.     // copy to another buffer first in order to null terminate it for
  833.     // use as input to the transcoding routines..
  834.     //
  835.     XMLCh* DOMStrData = fHandle->fDSData->fData;
  836.     const unsigned int localBufLen = 1000;
  837.     XMLCh localBuf[localBufLen];
  838.     XMLCh *allocatedBuf = 0;
  839.     XMLCh *srcP;
  840.     if (DOMStrData[fHandle->fLength] == 0)
  841.     {
  842.         // The data in the DOMString itself happens to be null terminated.
  843.         //  Just use it in place.
  844.         srcP = DOMStrData;
  845.     }
  846.     else if (fHandle->fLength < localBufLen-1)
  847.     {
  848.         // The data is not null terminated, but does fit in the
  849.         //  local buffer (fast allocation).  Copy it over, and add
  850.         //  the null termination,
  851.         memcpy(localBuf, DOMStrData, fHandle->fLength * sizeof(XMLCh));
  852.         srcP = localBuf;
  853.         srcP[fHandle->fLength] = 0;
  854.     }
  855.     else
  856.     {
  857.         // The data is too big for the local buffer.  Heap allocate one.
  858.         allocatedBuf = srcP = (XMLCh*) manager->allocate
  859.         (
  860.             (fHandle->fLength + 1) * sizeof(XMLCh)
  861.         );//new XMLCh[fHandle->fLength + 1];
  862.         memcpy(allocatedBuf, DOMStrData, fHandle->fLength * sizeof(XMLCh));
  863.         srcP[fHandle->fLength] = 0;
  864.     }
  865.     //
  866.     //  Find out how many output chars we need and allocate a buffer big enough
  867.     //  for that plus a null.
  868.     //
  869.     //  The charsNeeded normally is same as fHandle->fLength.  To enhance performance,
  870.     //  we start with this estimate, and if overflow, then call calcRequiredSize for actual size
  871.     unsigned int charsNeeded = fHandle->fLength;
  872.     char* retP = (char*) manager->allocate((charsNeeded + 1) * sizeof(char));//new char[charsNeeded + 1];
  873.     if (!getDomConverter()->transcode(srcP, retP, charsNeeded) || (XMLString::stringLen(retP) != charsNeeded))
  874.     {
  875.         manager->deallocate(retP);//delete [] retP;
  876.         charsNeeded = getDomConverter()->calcRequiredSize(srcP);
  877.         retP = (char*) manager->allocate((charsNeeded + 1) * sizeof(char));//new char[charsNeeded + 1];
  878.         if (!getDomConverter()->transcode(srcP, retP, charsNeeded))
  879.         {
  880.             // <TBD> We should throw something here?
  881.         }
  882.     }
  883.     if (allocatedBuf)
  884.     manager->deallocate(allocatedBuf);//delete [] allocatedBuf;   // which will be null if we didn't allocate one.
  885.     // Cap it off and return it
  886.     retP[charsNeeded] = 0;
  887.     return retP;
  888. }
  889. DOMString DOMString::transcode(const char* str)
  890. {
  891.     return DOMString(str);
  892. }
  893. int DOMString::compareString(const DOMString &other) const
  894. {
  895.     // Note: this strcmp does not match the semantics
  896.     //       of the standard C strcmp.  All it needs to do is
  897.     //       define some less than - equals - greater than ordering
  898.     //       of strings.  How doesn't matter.
  899.     //
  900.     unsigned int thisLen = length();
  901.     unsigned int otherLen = other.length();
  902.     if (thisLen < otherLen)
  903.         return -1;
  904.     if (thisLen > otherLen)
  905.         return 1;
  906.     if (thisLen == 0)
  907.         return 0;
  908.     XMLCh *thisP =  this->fHandle->fDSData->fData;
  909.     XMLCh *otherP = other.fHandle->fDSData->fData;
  910.     unsigned int i;
  911.     for (i=0; i<thisLen; i++)
  912.     {
  913.         if (thisP[i] < otherP[i])
  914.             return -1;
  915.         else if (thisP[i] > otherP[i])
  916.             return 1;
  917.     };
  918.     return 0;
  919. };
  920. DOMString DOMString::substringData(unsigned int offset, unsigned int count) const
  921. {
  922.     unsigned int thisLen = length();
  923.     if (offset > thisLen || offset < 0 || count < 0)
  924.         throw DOM_DOMException(DOM_DOMException::INDEX_SIZE_ERR, 0);
  925.     // Cap count to the string length to eliminate overflow
  926.     //  problems when we get passed bogus values, like -1.
  927.     if (count > thisLen)
  928.         count = thisLen;
  929.     // If the count extends past the end of the string, cut it
  930.     //   back so that the returned string will stop at the end
  931.     //   of the source string.
  932.     if (offset + count >= thisLen)
  933.         count = thisLen - offset;
  934.     if (count == 0)
  935.         return DOMString();
  936.     // If the substring starts at the beginning of the original string
  937.     //   we do not need to copy the data, but can set up a new
  938.     //   string handle with the shorter length.
  939.     if (offset == 0)
  940.     {
  941.         DOMString retString = this->clone();
  942.         retString.fHandle->fLength = count;
  943.         return retString;
  944.     };
  945.     // The substring starts somewhere in the interior of the orignal string.
  946.     // Create a completely new DOMString.  No buffer sharing is possible.
  947.     XMLCh *data = fHandle->fDSData->fData;
  948.     return DOMString(data+offset, count);
  949. };
  950. DOMString operator + (const DOMString &lhs, const DOMString &rhs)
  951. {
  952.     DOMString retString = lhs.clone();
  953.     retString.appendData(rhs);
  954.     return retString;
  955. }
  956. DOMString operator + (const DOMString &lhs, const XMLCh* rhs)
  957. {
  958.     DOMString retString = lhs.clone();
  959.     retString.appendData(rhs);
  960.     return retString;
  961. }
  962. DOMString operator + (const XMLCh* lhs, const DOMString& rhs)
  963. {
  964.     DOMString retString = DOMString(lhs);
  965.     retString.appendData(rhs);
  966.     return retString;
  967. }
  968. DOMString operator + (const DOMString &lhs, XMLCh rhs)
  969. {
  970.     DOMString retString = lhs.clone();
  971.     retString.appendData(rhs);
  972.     return retString;
  973. }
  974. DOMString operator + (XMLCh lhs, const DOMString& rhs)
  975. {
  976.     DOMString retString;
  977. retString.appendData(lhs);
  978.     retString.appendData(rhs);
  979.     return retString;
  980. }
  981. // -----------------------------------------------------------------------
  982. //  Notification that lazy data has been deleted
  983. // -----------------------------------------------------------------------
  984. static void reinitDomConverter()
  985. {
  986.         delete gDomConverter;           //  Delete the local code page converter.
  987.         gDomConverter = 0;
  988. };
  989. static void reinitDomMutex()
  990. {
  991.         delete DOMStringHandleMutex;    //  Delete the synchronization mutex,
  992.         DOMStringHandleMutex = 0;
  993. };
  994. XERCES_CPP_NAMESPACE_END