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: DOMDocumentImpl.hpp 679340 2008-07-24 10:28:29Z borisk $
20 */
21
22 #if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP)
23 #define XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP
24
25 //
26 // This file is part of the internal implementation of the C++ XML DOM.
27 // It should NOT be included or used directly by application programs.
28 //
29 // Applications should include the file <xercesc/dom/DOM.hpp> for the entire
30 // DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class
31 // name is substituded for the *.
32 //
33
34 #include <xercesc/util/RefArrayOf.hpp>
35 #include <xercesc/util/RefStackOf.hpp>
36 #include <xercesc/util/RefHash2KeysTableOf.hpp>
37 #include <xercesc/util/StringPool.hpp>
38 #include <xercesc/util/KeyRefPair.hpp>
39 #include <xercesc/util/XMLChar.hpp>
40 #include <xercesc/dom/DOMDocument.hpp>
41 #include <xercesc/dom/DOMUserDataHandler.hpp>
42 #include <xercesc/dom/DOMMemoryManager.hpp>
43 #include "DOMNodeImpl.hpp"
44 #include "DOMStringPool.hpp"
45 #include "DOMParentNode.hpp"
46 #include "DOMDeepNodeListPool.hpp"
47
48 XERCES_CPP_NAMESPACE_BEGIN
49
50
51 class DOMAttrImpl;
52 class DOMCDATASectionImpl;
53 class DOMCommentImpl;
54 class DOMConfiguration;
55 class DOMDeepNodeListImpl;
56 class DOMDocumentFragmentImpl;
57 class DOMDocumentTypeImpl;
58 class DOMElementImpl;
59 class DOMEntityImpl;
60 class DOMEntityReferenceImpl;
61 class DOMNotationImpl;
62 class DOMProcessingInstructionImpl;
63 class DOMTextImpl;
64 class DOMNodeIteratorImpl;
65 class DOMNormalizer;
66 class DOMTreeWalkerImpl;
67 class DOMNodeFilter;
68 class DOMNodeFilterImpl;
69 class DOMImplementation;
70 class DOMNodeIDMap;
71 class DOMRangeImpl;
72 class DOMBuffer;
73 class MemoryManager;
74 class XPathNSResolver;
75 class XPathExpression;
76
77 typedef RefVectorOf<DOMRangeImpl> Ranges;
78 typedef RefVectorOf<DOMNodeIteratorImpl> NodeIterators;
79 typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord;
80 typedef RefStackOf<DOMNode> DOMNodePtr;
81
82 class CDOM_EXPORT DOMDocumentImpl: public XMemory, public DOMMemoryManager, public DOMDocument {
83 public:
84 // -----------------------------------------------------------------------
85 // data
86 // -----------------------------------------------------------------------
87 DOMNodeImpl fNode; // Implements common node functionality.
88 DOMParentNode fParent; // Implements common parent node functionality
89 DOMNodeIDMap* fNodeIDMap; // for use by GetElementsById().
90
91 public:
92 DOMDocumentImpl(DOMImplementation* domImpl, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
93 DOMDocumentImpl(const XMLCh* namespaceURI, //DOM Level 2
94 const XMLCh* qualifiedName,
95 DOMDocumentType* doctype,
96 DOMImplementation* domImpl,
97 MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
98 virtual ~DOMDocumentImpl();
99
100 void setDocumentType(DOMDocumentType *doctype);
101
102 public:
103 // Add all functions that are pure virtual in DOMNODE
104 DOMNODE_FUNCTIONS;
105
106 public:
107 // Add all functions that are pure virtual in DOMDocument
108 virtual DOMAttr* createAttribute(const XMLCh *name);
109 virtual DOMCDATASection* createCDATASection(const XMLCh *data);
110 virtual DOMComment* createComment(const XMLCh *data);
111 virtual DOMDocumentFragment* createDocumentFragment();
112 virtual DOMDocumentType* createDocumentType(const XMLCh *name);
113 virtual DOMDocumentType* createDocumentType(const XMLCh *qName,
114 const XMLCh *publicId,
115 const XMLCh *systemId);
116 virtual DOMElement* createElement(const XMLCh * tagName);
117 virtual DOMElement* createElementNoCheck(const XMLCh *tagName);
118 virtual DOMEntity* createEntity(const XMLCh * name);
119 virtual DOMEntityReference* createEntityReference(const XMLCh * name);
120 virtual DOMNotation* createNotation(const XMLCh * name);
121 virtual DOMProcessingInstruction* createProcessingInstruction(const XMLCh * target, const XMLCh * data);
122 virtual DOMText* createTextNode(const XMLCh * data);
123 virtual DOMDocumentType* getDoctype() const;
124 virtual DOMElement* getDocumentElement() const;
125 virtual DOMNodeList* getElementsByTagName(const XMLCh * tagname) const;
126 virtual DOMImplementation* getImplementation() const;
127 bool isXMLName(const XMLCh * s);
128 virtual DOMNodeIterator* createNodeIterator(DOMNode *root,
129 DOMNodeFilter::ShowType whatToShow,
130 DOMNodeFilter* filter,
131 bool entityReferenceExpansion);
132 virtual DOMTreeWalker* createTreeWalker(DOMNode *root,
133 DOMNodeFilter::ShowType whatToShow,
134 DOMNodeFilter* filter,
135 bool entityReferenceExpansion);
136
137
138 virtual DOMRange* createRange();
139 virtual Ranges* getRanges() const; //non-standard api
140 virtual NodeIterators* getNodeIterators() const; //non-standard api
141 virtual void removeRange(DOMRangeImpl* range); //non-standard api
142 virtual void removeNodeIterator(DOMNodeIteratorImpl* nodeIterator); //non-standard api
143
144 virtual DOMXPathExpression* createExpression(const XMLCh *expression,
145 const DOMXPathNSResolver *resolver);
146 virtual DOMXPathNSResolver* createNSResolver(const DOMNode *nodeResolver);
147 virtual DOMXPathResult* evaluate(const XMLCh *expression,
148 const DOMNode *contextNode,
149 const DOMXPathNSResolver *resolver,
150 DOMXPathResult::ResultType type,
151 DOMXPathResult* result);
152
153
154 // Extension to be called by the Parser
155 DOMEntityReference* createEntityReferenceByParser(const XMLCh * name);
156
157 // Add all functions that are pure virtual in DOMMemoryManager
158 virtual XMLSize_t getMemoryAllocationBlockSize() const;
159 virtual void setMemoryAllocationBlockSize(XMLSize_t size);
160 virtual void* allocate(XMLSize_t amount);
161 virtual void* allocate(XMLSize_t amount, DOMMemoryManager::NodeObjectType type);
162 virtual void release(DOMNode* object, DOMMemoryManager::NodeObjectType type);
163 virtual XMLCh* cloneString(const XMLCh *src);
164
165 //
166 // Functions to keep track of document mutations, so that node list chached
167 // information can be invalidated. One global changes counter per document.
168 //
169 virtual void changed();
170 virtual int changes() const;
171
172 /**
173 * Sets whether the DOM implementation performs error checking
174 * upon operations. Turning off error checking only affects
175 * the following DOM checks:
176 * <ul>
177 * <li>Checking strings to make sure that all characters are
178 * legal XML characters
179 * <li>Hierarchy checking such as allowed children, checks for
180 * cycles, etc.
181 * </ul>
182 * <p>
183 * Turning off error checking does <em>not</em> turn off the
184 * following checks:
185 * <ul>
186 * <li>Read only checks
187 * <li>Checks related to DOM events
188 * </ul>
189 */
setErrorChecking(bool check)190 inline void setErrorChecking(bool check) {
191 errorChecking = check;
192 }
193
194 /**
195 * Returns true if the DOM implementation performs error checking.
196 */
getErrorChecking() const197 inline bool getErrorChecking() const {
198 return errorChecking;
199 }
200
201 //Introduced in DOM Level 2
202 virtual DOMNode* importNode(const DOMNode *source, bool deep);
203 virtual DOMElement* createElementNS(const XMLCh *namespaceURI,
204 const XMLCh *qualifiedName);
205 virtual DOMElement* createElementNS(const XMLCh *namespaceURI,
206 const XMLCh *qualifiedName,
207 const XMLFileLoc lineNo,
208 const XMLFileLoc columnNo);
209 virtual DOMAttr* createAttributeNS(const XMLCh *namespaceURI,
210 const XMLCh *qualifiedName);
211 virtual DOMNodeList* getElementsByTagNameNS(const XMLCh *namespaceURI,
212 const XMLCh *localName) const;
213 virtual DOMElement* getElementById(const XMLCh *elementId) const;
214
215 //Introduced in DOM Level 3
216 virtual const XMLCh* getInputEncoding() const;
217 virtual const XMLCh* getXmlEncoding() const;
218 virtual bool getXmlStandalone() const;
219 virtual void setXmlStandalone(bool standalone);
220 virtual const XMLCh* getXmlVersion() const;
221 virtual void setXmlVersion(const XMLCh* version);
222 virtual const XMLCh* getDocumentURI() const;
223 virtual void setDocumentURI(const XMLCh* documentURI);
224 virtual bool getStrictErrorChecking() const;
225 virtual void setStrictErrorChecking(bool strictErrorChecking);
226 virtual DOMNode* adoptNode(DOMNode* source);
227 virtual void normalizeDocument();
228 virtual DOMConfiguration* getDOMConfig() const;
229
230 void setInputEncoding(const XMLCh* actualEncoding);
231 void setXmlEncoding(const XMLCh* encoding);
232 // helper functions to prevent storing userdata pointers on every node.
233 void* setUserData(DOMNodeImpl* n,
234 const XMLCh* key,
235 void* data,
236 DOMUserDataHandler* handler);
237 void* getUserData(const DOMNodeImpl* n,
238 const XMLCh* key) const;
239 void callUserDataHandlers(const DOMNodeImpl* n,
240 DOMUserDataHandler::DOMOperationType operation,
241 const DOMNode* src,
242 DOMNode* dst) const;
243 void transferUserData(DOMNodeImpl* n1, DOMNodeImpl* n2);
244
245 DOMNode* renameNode(DOMNode* n,
246 const XMLCh* namespaceURI,
247 const XMLCh* name);
248
249 //Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
250 //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd".
251 static int indexofQualifiedName(const XMLCh * qName);
252 static bool isKidOK(DOMNode *parent, DOMNode *child);
253
getNodeIDMap()254 inline DOMNodeIDMap* getNodeIDMap() {return fNodeIDMap;};
255
256
257 //
258 // Memory Management Functions. All memory is allocated by and owned by
259 // a document, and is not recovered until the
260 // document itself is deleted.
261 //
262 const XMLCh* getPooledString(const XMLCh*);
263 const XMLCh* getPooledNString(const XMLCh*, XMLSize_t);
264 void deleteHeap();
265 void releaseDocNotifyUserData(DOMNode* object);
266 void releaseBuffer(DOMBuffer* buffer);
267 DOMBuffer* popBuffer(XMLSize_t nMinSize);
268 MemoryManager* getMemoryManager() const;
269
270 // Factory methods for getting/creating node lists.
271 // Because nothing is ever deleted, the implementation caches and recycles
272 // previously used instances of DOMDeepNodeList
273 //
274 DOMNodeList* getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName);
275 DOMNodeList* getDeepNodeList(const DOMNode *rootNode, //DOM Level 2
276 const XMLCh *namespaceURI,
277 const XMLCh *localName);
278
279 protected:
280 //Internal helper functions
281 virtual DOMNode* importNode(const DOMNode *source, bool deep, bool cloningNode);
282
283 private:
284 // -----------------------------------------------------------------------
285 // Unimplemented constructors and operators
286 // -----------------------------------------------------------------------
287 DOMDocumentImpl(const DOMDocumentImpl &);
288 DOMDocumentImpl & operator = (const DOMDocumentImpl &);
289
290 protected:
291 // -----------------------------------------------------------------------
292 // data
293 // -----------------------------------------------------------------------
294 // New data introduced in DOM Level 3
295 const XMLCh* fInputEncoding;
296 const XMLCh* fXmlEncoding;
297 bool fXmlStandalone;
298 const XMLCh* fXmlVersion;
299 const XMLCh* fDocumentURI;
300 DOMConfiguration* fDOMConfiguration;
301
302 XMLStringPool fUserDataTableKeys;
303 RefHash2KeysTableOf<DOMUserDataRecord, PtrHasher>* fUserDataTable;
304
305
306 // Per-Document heap Variables.
307 // The heap consists of one or more biggish blocks which are
308 // sub-allocated for individual allocations of nodes, strings, etc.
309 // The big blocks form a linked list, allowing them to be located for deletion.
310 //
311 // There is no provision for deleting suballocated blocks, other than
312 // deleting the entire heap when the document is deleted.
313 //
314 // There is no header on individual sub-allocated blocks.
315 // The header on big blocks consists only of a single back pointer to
316 // the previously allocated big block (our linked list of big blocks)
317 //
318 //
319 // revisit - this heap should be encapsulated into its own
320 // class, rather than hanging naked on Document.
321 //
322 void* fCurrentBlock;
323 char* fFreePtr;
324 XMLSize_t fFreeBytesRemaining,
325 fHeapAllocSize;
326
327 // To recycle the DOMNode pointer
328 RefArrayOf<DOMNodePtr>* fRecycleNodePtr;
329
330 // To recycle DOMBuffer pointer
331 RefStackOf<DOMBuffer>* fRecycleBufferPtr;
332
333 // Pool of DOMNodeList for getElementsByTagName
334 DOMDeepNodeListPool<DOMDeepNodeListImpl>* fNodeListPool;
335
336 // Other data
337 DOMDocumentType* fDocType;
338 DOMElement* fDocElement;
339
340 DOMStringPoolEntry** fNameTable;
341 XMLSize_t fNameTableSize;
342
343 DOMNormalizer* fNormalizer;
344 Ranges* fRanges;
345 NodeIterators* fNodeIterators;
346 MemoryManager* fMemoryManager; // configurable memory manager
347 DOMImplementation* fDOMImplementation;
348
349 int fChanges;
350 bool errorChecking; // Bypass error checking.
351
352 };
353
getMemoryManager() const354 inline MemoryManager* DOMDocumentImpl::getMemoryManager() const
355 {
356 return fMemoryManager;
357 }
358
getPooledString(const XMLCh * in)359 inline const XMLCh* DOMDocumentImpl::getPooledString(const XMLCh *in)
360 {
361 if (in == 0)
362 return 0;
363
364 DOMStringPoolEntry **pspe;
365 DOMStringPoolEntry *spe;
366
367 XMLSize_t inHash = XMLString::hash(in, fNameTableSize);
368 pspe = &fNameTable[inHash];
369 while (*pspe != 0)
370 {
371 if (XMLString::equals((*pspe)->fString, in))
372 return (*pspe)->fString;
373 pspe = &((*pspe)->fNext);
374 }
375
376 // This string hasn't been seen before. Add it to the pool.
377 //
378
379 // Compute size to allocate. Note that there's 1 char of string
380 // declared in the struct, so we don't need to add one again to
381 // account for the trailing null.
382 //
383 XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + XMLString::stringLen(in)*sizeof(XMLCh);
384 *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate);
385 spe->fNext = 0;
386 XMLString::copyString((XMLCh*)spe->fString, in);
387
388 return spe->fString;
389 }
390
391 inline const XMLCh* DOMDocumentImpl::
getPooledNString(const XMLCh * in,XMLSize_t n)392 getPooledNString(const XMLCh *in, XMLSize_t n)
393 {
394 if (in == 0)
395 return 0;
396
397 DOMStringPoolEntry **pspe;
398 DOMStringPoolEntry *spe;
399
400 XMLSize_t inHash = XMLString::hashN(in, n, fNameTableSize);
401 pspe = &fNameTable[inHash];
402 while (*pspe != 0)
403 {
404 if (XMLString::equalsN((*pspe)->fString, in, n))
405 return (*pspe)->fString;
406 pspe = &((*pspe)->fNext);
407 }
408
409 // This string hasn't been seen before. Add it to the pool.
410 //
411
412 // Compute size to allocate. Note that there's 1 char of string
413 // declared in the struct, so we don't need to add one again to
414 // account for the trailing null.
415 //
416 XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + n*sizeof(XMLCh);
417 *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate);
418 spe->fNext = 0;
419 XMLString::copyNString((XMLCh*)spe->fString, in, n);
420
421 return spe->fString;
422 }
423
indexofQualifiedName(const XMLCh * name)424 inline int DOMDocumentImpl::indexofQualifiedName(const XMLCh* name)
425 {
426 int i = 0;
427 int colon = -1;
428 int colon_count = 0;
429 for (; *name != 0; ++i, ++name)
430 {
431 if (*name == chColon)
432 {
433 ++colon_count;
434 colon = i;
435 }
436 }
437
438 if (i == 0 || colon == 0 || colon == (i - 1) || colon_count > 1)
439 return -1;
440
441 return colon != -1 ? colon : 0;
442 }
443
444 XERCES_CPP_NAMESPACE_END
445
446 // ---------------------------------------------------------------------------
447 //
448 // Operator new. Global overloaded version, lets any object be allocated on
449 // the heap owned by a document.
450 //
451 // ---------------------------------------------------------------------------
operator new(size_t amt,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * doc,XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type)452 inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type)
453 {
454 void *p = doc->allocate(amt, type);
455 return p;
456 }
457
operator new(size_t amt,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc,XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type)458 inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type)
459 {
460 XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0);
461 void* p=0;
462 if(mgr)
463 p = mgr->allocate(amt, type);
464 return p;
465 }
466
operator new(size_t amt,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * doc)467 inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc)
468 {
469 void* p = doc->allocate(amt);
470 return p;
471 }
472
operator new(size_t amt,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc)473 inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc)
474 {
475 XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0);
476 void* p=0;
477 if(mgr)
478 p = mgr->allocate(amt);
479 return p;
480 }
481
482 // ---------------------------------------------------------------------------
483 // For DOM:
484 // Bypass compiler warning:
485 // no matching operator delete found; memory will not be freed if initialization throws an exception
486 // ---------------------------------------------------------------------------
487 #if !defined(XERCES_NO_MATCHING_DELETE_OPERATOR)
operator delete(void *,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *,XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType)488 inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/)
489 {
490 return;
491 }
operator delete(void *,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *,XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType)492 inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/)
493 {
494 return;
495 }
496
operator delete(void *,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *)497 inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/)
498 {
499 return;
500 }
operator delete(void *,XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *)501 inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/)
502 {
503 return;
504 }
505 #endif
506
507 #endif
508