source: icXML/icXML-devel/src/xercesc/dom/impl/DOMTextImpl.cpp @ 2777

Last change on this file since 2777 was 2777, checked in by cameron, 7 years ago

Set up to use xercesc/icxercesc root-relative paths for all includes

File size: 14.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMTextImpl.cpp 678709 2008-07-22 10:56:56Z borisk $
20 */
21
22
23#include <xercesc/util/XMLUniDefs.hpp>
24
25#include <xercesc/dom/DOMException.hpp>
26#include <xercesc/dom/DOMNode.hpp>
27#include <xercesc/dom/DOMElement.hpp>
28#include <xercesc/dom/DOMCDATASection.hpp>
29#include <xercesc/dom/DOMNodeFilter.hpp>
30#include <xercesc/dom/DOMTreeWalker.hpp>
31
32#include <xercesc/dom/impl/DOMDocumentImpl.hpp>
33#include <xercesc/dom/impl/DOMStringPool.hpp>
34#include <xercesc/dom/impl/DOMTextImpl.hpp>
35#include <xercesc/dom/impl/DOMCharacterDataImpl.hpp>
36#include <xercesc/dom/impl/DOMChildNode.hpp>
37#include <xercesc/dom/impl/DOMRangeImpl.hpp>
38#include <xercesc/dom/impl/DOMCasts.hpp>
39
40#include <assert.h>
41
42XERCES_CPP_NAMESPACE_BEGIN
43
44class DOMDocument;
45
46DOMTextImpl::DOMTextImpl(DOMDocument *ownerDoc, const XMLCh *dat)
47    : fNode(ownerDoc), fCharacterData(ownerDoc, dat)
48{
49    fNode.setIsLeafNode(true);
50}
51
52DOMTextImpl::
53DOMTextImpl(DOMDocument *ownerDoc, const XMLCh* dat, XMLSize_t n)
54    : fNode(ownerDoc), fCharacterData(ownerDoc, dat, n)
55{
56    fNode.setIsLeafNode(true);
57}
58
59DOMTextImpl::DOMTextImpl(const DOMTextImpl &other, bool)
60    : DOMText(other)
61    , fNode(other.fNode)
62    , fCharacterData(other.fCharacterData)
63{
64    fNode.setIsLeafNode(true);
65}
66
67DOMTextImpl::~DOMTextImpl()
68{
69}
70
71
72DOMNode *DOMTextImpl::cloneNode(bool deep) const
73{
74    DOMNode* newNode = new (getOwnerDocument(), DOMMemoryManager::TEXT_OBJECT) DOMTextImpl(*this, deep);
75    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
76    return newNode;
77}
78
79
80const XMLCh * DOMTextImpl::getNodeName() const {
81    static const XMLCh gtext[] = {chPound, chLatin_t, chLatin_e, chLatin_x, chLatin_t, chNull};
82    return gtext;
83}
84
85DOMNode::NodeType DOMTextImpl::getNodeType() const {
86    return DOMNode::TEXT_NODE;
87}
88
89
90DOMText *DOMTextImpl::splitText(XMLSize_t offset)
91{
92    if (fNode.isReadOnly())
93    {
94        throw DOMException(
95            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
96    }
97    XMLSize_t len = fCharacterData.fDataBuf->getLen();
98    if (offset > len)
99        throw DOMException(DOMException::INDEX_SIZE_ERR, 0, GetDOMNodeMemoryManager);
100
101    DOMDocumentImpl *doc = (DOMDocumentImpl *)getOwnerDocument();
102    DOMText *newText = doc->createTextNode(
103      this->substringData(offset, len - offset));
104
105    DOMNode *parent = getParentNode();
106    if (parent != 0)
107        parent->insertBefore(newText, getNextSibling());
108
109    fCharacterData.fDataBuf->chop(offset);
110
111    if (doc != 0) {
112        Ranges* ranges = doc->getRanges();
113        if (ranges != 0) {
114            XMLSize_t sz = ranges->size();
115            if (sz != 0) {
116                for (XMLSize_t i =0; i<sz; i++) {
117                    ranges->elementAt(i)->updateSplitInfo( this, newText, offset);
118                }
119            }
120        }
121    }
122
123    return newText;
124}
125
126
127bool DOMTextImpl::isIgnorableWhitespace() const
128{
129    return fNode.ignorableWhitespace();
130}
131
132
133
134void DOMTextImpl::setIgnorableWhitespace(bool ignorable)
135{
136    fNode.ignorableWhitespace(ignorable);
137}
138
139
140bool DOMTextImpl::getIsElementContentWhitespace() const
141{
142    return isIgnorableWhitespace();
143}
144
145const XMLCh* DOMTextImpl::getWholeText() const
146{
147    DOMDocument *doc = getOwnerDocument();
148    DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
149    pWalker->setCurrentNode((DOMNode*)this);
150    // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
151    // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
152        DOMNode* prevNode;
153    while((prevNode=pWalker->previousNode())!=NULL)
154    {
155        if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
156            break;
157    }
158        XMLBuffer buff(1023, GetDOMNodeMemoryManager);
159        DOMNode* nextNode;
160    while((nextNode=pWalker->nextNode())!=NULL)
161    {
162        if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
163            break;
164        if(nextNode->getNodeType()==TEXT_NODE || nextNode->getNodeType()==CDATA_SECTION_NODE)
165                buff.append(nextNode->getNodeValue());
166    }
167    pWalker->release();
168
169    XMLCh* wholeString = (XMLCh*) (GetDOMNodeMemoryManager->allocate((buff.getLen()+1)*sizeof(XMLCh)));
170        XMLString::copyString(wholeString, buff.getRawBuffer());
171        return wholeString;
172}
173
174DOMText* DOMTextImpl::replaceWholeText(const XMLCh* newText)
175{
176    DOMDocument *doc = getOwnerDocument();
177    DOMTreeWalker* pWalker=doc->createTreeWalker(doc->getDocumentElement(), DOMNodeFilter::SHOW_ALL, NULL, true);
178    pWalker->setCurrentNode((DOMNode*)this);
179    // Logically-adjacent text nodes are Text or CDATASection nodes that can be visited sequentially in document order or in
180    // reversed document order without entering, exiting, or passing over Element, Comment, or ProcessingInstruction nodes.
181    DOMNode* pFirstTextNode=this;
182        DOMNode* prevNode;
183    while((prevNode=pWalker->previousNode())!=NULL)
184    {
185        if(prevNode->getNodeType()==ELEMENT_NODE || prevNode->getNodeType()==COMMENT_NODE || prevNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
186            break;
187        pFirstTextNode=prevNode;
188    }
189    // before doing any change we need to check if we are going to remove an entity reference that doesn't contain just text
190    DOMNode* pCurrentNode=pWalker->getCurrentNode();
191        DOMNode* nextNode;
192    while((nextNode=pWalker->nextNode())!=NULL)
193    {
194        if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
195            break;
196        if(nextNode->getNodeType()==ENTITY_REFERENCE_NODE)
197        {
198            DOMTreeWalker* pInnerWalker=doc->createTreeWalker(nextNode, DOMNodeFilter::SHOW_ALL, NULL, true);
199            while(pInnerWalker->nextNode())
200            {
201                short nodeType=pInnerWalker->getCurrentNode()->getNodeType();
202                if(nodeType!=ENTITY_REFERENCE_NODE && nodeType!=TEXT_NODE && nodeType!=CDATA_SECTION_NODE)
203                    throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
204            }
205            pInnerWalker->release();
206        }
207    }
208    DOMText* retVal=NULL;
209    // if the first node in the chain is a text node, replace its content, otherwise create a new node
210    if(newText && *newText)
211    {
212        if(!castToNodeImpl(pFirstTextNode)->isReadOnly() && (pFirstTextNode->getNodeType()==TEXT_NODE || pFirstTextNode->getNodeType()==CDATA_SECTION_NODE))
213        {
214            pFirstTextNode->setNodeValue(newText);
215            retVal=(DOMText*)pFirstTextNode;
216        }
217        else
218        {
219            if(getNodeType()==TEXT_NODE)
220                retVal=doc->createTextNode(newText);
221            else
222                retVal=doc->createCDATASection(newText);
223            pFirstTextNode->getParentNode()->insertBefore(retVal, pFirstTextNode);
224        }
225    }
226    // now delete all the following text nodes
227    pWalker->setCurrentNode(pCurrentNode);
228    while((nextNode=pWalker->nextNode())!=NULL)
229    {
230        if(nextNode->getNodeType()==ELEMENT_NODE || nextNode->getNodeType()==COMMENT_NODE || nextNode->getNodeType()==PROCESSING_INSTRUCTION_NODE)
231            break;
232        if(nextNode!=retVal)
233        {
234            // keep the tree walker valid
235            pWalker->previousNode();
236            nextNode->getParentNode()->removeChild(nextNode);
237            nextNode->release();
238        }
239    }
240    pWalker->release();
241    return retVal;
242}
243
244
245void DOMTextImpl::release()
246{
247    if (fNode.isOwned() && !fNode.isToBeReleased())
248        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
249
250    DOMDocumentImpl* doc = (DOMDocumentImpl*) getOwnerDocument();
251    if (doc) {
252        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
253        fCharacterData.releaseBuffer();
254        doc->release(this, DOMMemoryManager::TEXT_OBJECT);
255    }
256    else {
257        // shouldn't reach here
258        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
259    }
260}
261
262//
263//  Delegation functions
264//
265           DOMNode*         DOMTextImpl::appendChild(DOMNode *newChild)          {return fNode.appendChild (newChild); }
266           DOMNamedNodeMap* DOMTextImpl::getAttributes() const                   {return fNode.getAttributes (); }
267           DOMNodeList*     DOMTextImpl::getChildNodes() const                   {return fNode.getChildNodes (); }
268           DOMNode*         DOMTextImpl::getFirstChild() const                   {return fNode.getFirstChild (); }
269           DOMNode*         DOMTextImpl::getLastChild() const                    {return fNode.getLastChild (); }
270     const XMLCh*           DOMTextImpl::getLocalName() const                    {return fNode.getLocalName (); }
271     const XMLCh*           DOMTextImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
272           DOMNode*         DOMTextImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
273     const XMLCh*           DOMTextImpl::getNodeValue() const                    {return fCharacterData.getNodeValue (); }
274           DOMDocument*     DOMTextImpl::getOwnerDocument() const                {return fNode.getOwnerDocument (); }
275     const XMLCh*           DOMTextImpl::getPrefix() const                       {return fNode.getPrefix (); }
276           DOMNode*         DOMTextImpl::getParentNode() const                   {return fChild.getParentNode (this); }
277           DOMNode*         DOMTextImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
278           bool             DOMTextImpl::hasChildNodes() const                   {return fNode.hasChildNodes (); }
279           DOMNode*         DOMTextImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
280                                                                                 {return fNode.insertBefore (newChild, refChild); }
281           void             DOMTextImpl::normalize()                             {fNode.normalize (); }
282           DOMNode*         DOMTextImpl::removeChild(DOMNode *oldChild)          {return fNode.removeChild (oldChild); }
283           DOMNode*         DOMTextImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
284                                                                                 {return fNode.replaceChild (newChild, oldChild); }
285           bool             DOMTextImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
286                                                                                 {return fNode.isSupported (feature, version); }
287           void             DOMTextImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
288           bool             DOMTextImpl::hasAttributes() const                   {return fNode.hasAttributes(); }
289           bool             DOMTextImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
290           bool             DOMTextImpl::isEqualNode(const DOMNode* arg) const   {return fNode.isEqualNode(arg); }
291           void*            DOMTextImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
292                                                                                 {return fNode.setUserData(key, data, handler); }
293           void*            DOMTextImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
294           const XMLCh*     DOMTextImpl::getBaseURI() const                      {return fNode.getBaseURI(); }
295           short            DOMTextImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
296           const XMLCh*     DOMTextImpl::getTextContent() const                  {return fNode.getTextContent(); }
297           void             DOMTextImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
298           const XMLCh*     DOMTextImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
299           bool             DOMTextImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
300           const XMLCh*     DOMTextImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
301           void*            DOMTextImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
302
303
304
305//
306//   Delegation of CharacerData functions.
307//
308
309
310          const XMLCh*      DOMTextImpl::getData() const                         {return fCharacterData.getData();}
311          XMLSize_t         DOMTextImpl::getLength() const                       {return fCharacterData.getLength();}
312          const XMLCh*      DOMTextImpl::substringData(XMLSize_t offset, XMLSize_t count) const
313                                                                                 {return fCharacterData.substringData(this, offset, count);}
314          void              DOMTextImpl::appendData(const XMLCh *arg)            {fCharacterData.appendData(this, arg);}
315          void              DOMTextImpl::insertData(XMLSize_t offset, const  XMLCh *arg)
316                                                                                 {fCharacterData.insertData(this, offset, arg);}
317          void              DOMTextImpl::deleteData(XMLSize_t offset, XMLSize_t count)
318                                                                                 {fCharacterData.deleteData(this, offset, count);}
319          void              DOMTextImpl::replaceData(XMLSize_t offset, XMLSize_t count, const XMLCh *arg)
320                                                                                 {fCharacterData.replaceData(this, offset, count, arg);}
321          void              DOMTextImpl::setData(const XMLCh *data)              {fCharacterData.setData(this, data);}
322          void              DOMTextImpl::setNodeValue(const XMLCh  *nodeValue)   {fCharacterData.setNodeValue (this, nodeValue); }
323
324          void              DOMTextImpl::appendData(const XMLCh *arg, XMLSize_t n) {fCharacterData.appendData(this, arg, n);}
325
326XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.