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: ElemStack.hpp 568078 2007-08-21 11:43:25Z amassari $ |
|
20 */ |
|
21 |
|
22 #if !defined(ELEMSTACK_HPP) |
|
23 #define ELEMSTACK_HPP |
|
24 |
|
25 #include <xercesc/util/StringPool.hpp> |
|
26 #include <xercesc/util/QName.hpp> |
|
27 #include <xercesc/util/ValueVectorOf.hpp> |
|
28 |
|
29 XERCES_CPP_NAMESPACE_BEGIN |
|
30 |
|
31 class XMLElementDecl; |
|
32 class Grammar; |
|
33 |
|
34 struct PrefMapElem : public XMemory |
|
35 { |
|
36 unsigned int fPrefId; |
|
37 unsigned int fURIId; |
|
38 }; |
|
39 |
|
40 // |
|
41 // During the scan of content, we have to keep up with the nesting of |
|
42 // elements (for validation and wellformedness purposes) and we have to |
|
43 // have places to remember namespace (prefix to URI) mappings. |
|
44 // |
|
45 // We only have to keep a stack of the current path down through the tree |
|
46 // that we are currently scanning, and keep track of any children of any |
|
47 // elements along that path. |
|
48 // |
|
49 // So, this data structure is a stack, which represents the current path |
|
50 // through the tree that we've worked our way down to. For each node in |
|
51 // the stack, there is an array of element ids that represent the ids of |
|
52 // the child elements scanned so far. Upon exit from that element, its |
|
53 // array of child elements is validated. |
|
54 // |
|
55 // Since we have the actual XMLElementDecl in the stack nodes, when its time |
|
56 // to validate, we just extract the content model from that element decl |
|
57 // and validate. All the required data falls easily to hand. Note that we |
|
58 // actually have some derivative of XMLElementDecl, which is specific to |
|
59 // the validator used, but the abstract API is sufficient for the needs of |
|
60 // the scanner. |
|
61 // |
|
62 // Since the namespace support also requires the storage of information on |
|
63 // a nested element basis, this structure also holds the namespace info. For |
|
64 // each level, the prefixes defined at that level (and the namespaces that |
|
65 // they map to) are stored. |
|
66 // |
|
67 class XMLPARSER_EXPORT ElemStack : public XMemory |
|
68 { |
|
69 public : |
|
70 // ----------------------------------------------------------------------- |
|
71 // Class specific data types |
|
72 // |
|
73 // These really should be private, but some of the compilers we have to |
|
74 // support are too dumb to deal with that. |
|
75 // |
|
76 // PrefMapElem |
|
77 // fURIId is the id of the URI from the validator's URI map. The |
|
78 // fPrefId is the id of the prefix from our own prefix pool. The |
|
79 // namespace stack consists of these elements. |
|
80 // |
|
81 // StackElem |
|
82 // fThisElement is the basic element decl for the current element. |
|
83 // The fRowCapacity is how large fChildIds has grown so far. |
|
84 // fChildCount is how many of them are valid right now. |
|
85 // |
|
86 // The fMapCapacity is how large fMap has grown so far. fMapCount |
|
87 // is how many of them are valid right now. |
|
88 // |
|
89 // Note that we store the reader number we were in when we found the |
|
90 // start tag. We'll use this at the end tag to test for unbalanced |
|
91 // markup in entities. |
|
92 // |
|
93 // MapModes |
|
94 // When a prefix is mapped to a namespace id, it matters whether the |
|
95 // QName being mapped is an attribute or name. Attributes are not |
|
96 // affected by an sibling xmlns attributes, whereas elements are |
|
97 // affected by its own xmlns attributes. |
|
98 // ----------------------------------------------------------------------- |
|
99 struct StackElem : public XMemory |
|
100 { |
|
101 XMLElementDecl* fThisElement; |
|
102 unsigned int fReaderNum; |
|
103 |
|
104 unsigned int fChildCapacity; |
|
105 unsigned int fChildCount; |
|
106 QName** fChildren; |
|
107 |
|
108 PrefMapElem* fMap; |
|
109 unsigned int fMapCapacity; |
|
110 unsigned int fMapCount; |
|
111 |
|
112 bool fValidationFlag; |
|
113 bool fCommentOrPISeen; |
|
114 bool fReferenceEscaped; |
|
115 int fCurrentScope; |
|
116 Grammar* fCurrentGrammar; |
|
117 unsigned int fCurrentURI; |
|
118 XMLCh * fSchemaElemName; |
|
119 unsigned int fSchemaElemNameMaxLen; |
|
120 |
|
121 int fPrefixColonPos; |
|
122 }; |
|
123 |
|
124 enum MapModes |
|
125 { |
|
126 Mode_Attribute |
|
127 , Mode_Element |
|
128 }; |
|
129 |
|
130 |
|
131 // ----------------------------------------------------------------------- |
|
132 // Constructors and Destructor |
|
133 // ----------------------------------------------------------------------- |
|
134 ElemStack(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
|
135 ~ElemStack(); |
|
136 |
|
137 |
|
138 // ----------------------------------------------------------------------- |
|
139 // Stack access |
|
140 // ----------------------------------------------------------------------- |
|
141 unsigned int addLevel(); |
|
142 unsigned int addLevel(XMLElementDecl* const toSet, const unsigned int readerNum); |
|
143 const StackElem* popTop(); |
|
144 |
|
145 |
|
146 // ----------------------------------------------------------------------- |
|
147 // Stack top access |
|
148 // ----------------------------------------------------------------------- |
|
149 unsigned int addChild(QName* const child, const bool toParent); |
|
150 const StackElem* topElement() const; |
|
151 void setElement(XMLElementDecl* const toSet, const unsigned int readerNum); |
|
152 |
|
153 void setValidationFlag(bool validationFlag); |
|
154 bool getValidationFlag(); |
|
155 |
|
156 inline void setCommentOrPISeen(); |
|
157 inline bool getCommentOrPISeen() const; |
|
158 |
|
159 inline void setReferenceEscaped(); |
|
160 inline bool getReferenceEscaped() const; |
|
161 |
|
162 void setCurrentScope(int currentScope); |
|
163 int getCurrentScope(); |
|
164 |
|
165 void setCurrentGrammar(Grammar* currentGrammar); |
|
166 Grammar* getCurrentGrammar(); |
|
167 |
|
168 void setCurrentURI(unsigned int uri); |
|
169 unsigned int getCurrentURI(); |
|
170 |
|
171 inline void setCurrentSchemaElemName(const XMLCh * const schemaElemName); |
|
172 inline XMLCh *getCurrentSchemaElemName(); |
|
173 |
|
174 void setPrefixColonPos(int colonPos); |
|
175 int getPrefixColonPos() const; |
|
176 |
|
177 // ----------------------------------------------------------------------- |
|
178 // Prefix map methods |
|
179 // ----------------------------------------------------------------------- |
|
180 void addPrefix |
|
181 ( |
|
182 const XMLCh* const prefixToAdd |
|
183 , const unsigned int uriId |
|
184 ); |
|
185 unsigned int mapPrefixToURI |
|
186 ( |
|
187 const XMLCh* const prefixToMap |
|
188 , const MapModes mode |
|
189 , bool& unknown |
|
190 ) const; |
|
191 ValueVectorOf<PrefMapElem*>* getNamespaceMap() const; |
|
192 unsigned int getPrefixId(const XMLCh* const prefix) const; |
|
193 const XMLCh* getPrefixForId(unsigned int prefId) const; |
|
194 |
|
195 // ----------------------------------------------------------------------- |
|
196 // Miscellaneous methods |
|
197 // ----------------------------------------------------------------------- |
|
198 bool isEmpty() const; |
|
199 void reset |
|
200 ( |
|
201 const unsigned int emptyId |
|
202 , const unsigned int unknownId |
|
203 , const unsigned int xmlId |
|
204 , const unsigned int xmlNSId |
|
205 ); |
|
206 |
|
207 |
|
208 private : |
|
209 // ----------------------------------------------------------------------- |
|
210 // Unimplemented constructors and operators |
|
211 // ----------------------------------------------------------------------- |
|
212 ElemStack(const ElemStack&); |
|
213 ElemStack& operator=(const ElemStack&); |
|
214 |
|
215 |
|
216 // ----------------------------------------------------------------------- |
|
217 // Private helper methods |
|
218 // ----------------------------------------------------------------------- |
|
219 void expandMap(StackElem* const toExpand); |
|
220 void expandStack(); |
|
221 |
|
222 |
|
223 // ----------------------------------------------------------------------- |
|
224 // Data members |
|
225 // |
|
226 // fEmptyNamespaceId |
|
227 // This is the special URI id for the "" namespace, which is magic |
|
228 // because of the xmlns="" operation. |
|
229 // |
|
230 // fGlobalPoolId |
|
231 // This is a special URI id that is returned when the namespace |
|
232 // prefix is "" and no one has explicitly mapped that prefix to an |
|
233 // explicit URI (or when they explicitly clear any such mapping, |
|
234 // which they can also do.) And also its prefix pool id, which is |
|
235 // stored here for fast access. |
|
236 // |
|
237 // fPrefixPool |
|
238 // This is the prefix pool where prefixes are hashed and given unique |
|
239 // ids. These ids are used to track prefixes in the element stack. |
|
240 // |
|
241 // fStack |
|
242 // fStackCapacity |
|
243 // fStackTop |
|
244 // This the stack array. Its an array of pointers to StackElem |
|
245 // structures. The capacity is the current high water mark of the |
|
246 // stack. The top is the current top of stack (i.e. the part of it |
|
247 // being used.) |
|
248 // |
|
249 // fUnknownNamespaceId |
|
250 // This is the URI id for the special URI that is assigned to any |
|
251 // prefix which has not been mapped. This lets us keep going after |
|
252 // issuing the error. |
|
253 // |
|
254 // fXMLNamespaceId |
|
255 // fXMLPoolId |
|
256 // fXMLNSNamespaceId |
|
257 // fXMLNSPoolId |
|
258 // These are the URI ids for the special URIs that are assigned to |
|
259 // the 'xml' and 'xmlns' namespaces. And also its prefix pool id, |
|
260 // which is stored here for fast access. |
|
261 // ----------------------------------------------------------------------- |
|
262 unsigned int fEmptyNamespaceId; |
|
263 unsigned int fGlobalPoolId; |
|
264 XMLStringPool fPrefixPool; |
|
265 StackElem** fStack; |
|
266 unsigned int fStackCapacity; |
|
267 unsigned int fStackTop; |
|
268 unsigned int fUnknownNamespaceId; |
|
269 unsigned int fXMLNamespaceId; |
|
270 unsigned int fXMLPoolId; |
|
271 unsigned int fXMLNSNamespaceId; |
|
272 unsigned int fXMLNSPoolId; |
|
273 ValueVectorOf<PrefMapElem*>* fNamespaceMap; |
|
274 MemoryManager* fMemoryManager; |
|
275 }; |
|
276 |
|
277 |
|
278 class XMLPARSER_EXPORT WFElemStack : public XMemory |
|
279 { |
|
280 public : |
|
281 // ----------------------------------------------------------------------- |
|
282 // Class specific data types |
|
283 // |
|
284 // These really should be private, but some of the compilers we have to |
|
285 // support are too dumb to deal with that. |
|
286 // |
|
287 // PrefMapElem |
|
288 // fURIId is the id of the URI from the validator's URI map. The |
|
289 // fPrefId is the id of the prefix from our own prefix pool. The |
|
290 // namespace stack consists of these elements. |
|
291 // |
|
292 // StackElem |
|
293 // fThisElement is the basic element decl for the current element. |
|
294 // The fRowCapacity is how large fChildIds has grown so far. |
|
295 // fChildCount is how many of them are valid right now. |
|
296 // |
|
297 // The fMapCapacity is how large fMap has grown so far. fMapCount |
|
298 // is how many of them are valid right now. |
|
299 // |
|
300 // Note that we store the reader number we were in when we found the |
|
301 // start tag. We'll use this at the end tag to test for unbalanced |
|
302 // markup in entities. |
|
303 // |
|
304 // MapModes |
|
305 // When a prefix is mapped to a namespace id, it matters whether the |
|
306 // QName being mapped is an attribute or name. Attributes are not |
|
307 // affected by an sibling xmlns attributes, whereas elements are |
|
308 // affected by its own xmlns attributes. |
|
309 // ----------------------------------------------------------------------- |
|
310 struct StackElem : public XMemory |
|
311 { |
|
312 int fTopPrefix; |
|
313 unsigned int fCurrentURI; |
|
314 unsigned int fReaderNum; |
|
315 unsigned int fElemMaxLength; |
|
316 XMLCh* fThisElement; |
|
317 }; |
|
318 |
|
319 enum MapModes |
|
320 { |
|
321 Mode_Attribute |
|
322 , Mode_Element |
|
323 }; |
|
324 |
|
325 |
|
326 // ----------------------------------------------------------------------- |
|
327 // Constructors and Destructor |
|
328 // ----------------------------------------------------------------------- |
|
329 WFElemStack(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
|
330 ~WFElemStack(); |
|
331 |
|
332 |
|
333 // ----------------------------------------------------------------------- |
|
334 // Stack access |
|
335 // ----------------------------------------------------------------------- |
|
336 unsigned int addLevel(); |
|
337 unsigned int addLevel(const XMLCh* const toSet, const unsigned int toSetLen, |
|
338 const unsigned int readerNum); |
|
339 const StackElem* popTop(); |
|
340 |
|
341 |
|
342 // ----------------------------------------------------------------------- |
|
343 // Stack top access |
|
344 // ----------------------------------------------------------------------- |
|
345 const StackElem* topElement() const; |
|
346 void setElement(const XMLCh* const toSet, const unsigned int toSetLen, |
|
347 const unsigned int readerNum); |
|
348 |
|
349 void setCurrentURI(unsigned int uri); |
|
350 unsigned int getCurrentURI(); |
|
351 |
|
352 // ----------------------------------------------------------------------- |
|
353 // Prefix map methods |
|
354 // ----------------------------------------------------------------------- |
|
355 void addPrefix |
|
356 ( |
|
357 const XMLCh* const prefixToAdd |
|
358 , const unsigned int uriId |
|
359 ); |
|
360 unsigned int mapPrefixToURI |
|
361 ( |
|
362 const XMLCh* const prefixToMap |
|
363 , const MapModes mode |
|
364 , bool& unknown |
|
365 ) const; |
|
366 |
|
367 |
|
368 // ----------------------------------------------------------------------- |
|
369 // Miscellaneous methods |
|
370 // ----------------------------------------------------------------------- |
|
371 bool isEmpty() const; |
|
372 void reset |
|
373 ( |
|
374 const unsigned int emptyId |
|
375 , const unsigned int unknownId |
|
376 , const unsigned int xmlId |
|
377 , const unsigned int xmlNSId |
|
378 ); |
|
379 |
|
380 |
|
381 private : |
|
382 // ----------------------------------------------------------------------- |
|
383 // Unimplemented constructors and operators |
|
384 // ----------------------------------------------------------------------- |
|
385 WFElemStack(const WFElemStack&); |
|
386 WFElemStack& operator=(const WFElemStack&); |
|
387 |
|
388 |
|
389 // ----------------------------------------------------------------------- |
|
390 // Private helper methods |
|
391 // ----------------------------------------------------------------------- |
|
392 void expandMap(); |
|
393 void expandStack(); |
|
394 |
|
395 |
|
396 // ----------------------------------------------------------------------- |
|
397 // Data members |
|
398 // |
|
399 // fEmptyNamespaceId |
|
400 // This is the special URI id for the "" namespace, which is magic |
|
401 // because of the xmlns="" operation. |
|
402 // |
|
403 // fGlobalPoolId |
|
404 // This is a special URI id that is returned when the namespace |
|
405 // prefix is "" and no one has explicitly mapped that prefix to an |
|
406 // explicit URI (or when they explicitly clear any such mapping, |
|
407 // which they can also do.) And also its prefix pool id, which is |
|
408 // stored here for fast access. |
|
409 // |
|
410 // fPrefixPool |
|
411 // This is the prefix pool where prefixes are hashed and given unique |
|
412 // ids. These ids are used to track prefixes in the element stack. |
|
413 // |
|
414 // fStack |
|
415 // fStackCapacity |
|
416 // fStackTop |
|
417 // This the stack array. Its an array of pointers to StackElem |
|
418 // structures. The capacity is the current high water mark of the |
|
419 // stack. The top is the current top of stack (i.e. the part of it |
|
420 // being used.) |
|
421 // |
|
422 // fUnknownNamespaceId |
|
423 // This is the URI id for the special URI that is assigned to any |
|
424 // prefix which has not been mapped. This lets us keep going after |
|
425 // issuing the error. |
|
426 // |
|
427 // fXMLNamespaceId |
|
428 // fXMLPoolId |
|
429 // fXMLNSNamespaceId |
|
430 // fXMLNSPoolId |
|
431 // These are the URI ids for the special URIs that are assigned to |
|
432 // the 'xml' and 'xmlns' namespaces. And also its prefix pool id, |
|
433 // which is stored here for fast access. |
|
434 // ----------------------------------------------------------------------- |
|
435 unsigned int fEmptyNamespaceId; |
|
436 unsigned int fGlobalPoolId; |
|
437 unsigned int fStackCapacity; |
|
438 unsigned int fStackTop; |
|
439 unsigned int fUnknownNamespaceId; |
|
440 unsigned int fXMLNamespaceId; |
|
441 unsigned int fXMLPoolId; |
|
442 unsigned int fXMLNSNamespaceId; |
|
443 unsigned int fXMLNSPoolId; |
|
444 unsigned int fMapCapacity; |
|
445 PrefMapElem* fMap; |
|
446 StackElem** fStack; |
|
447 XMLStringPool fPrefixPool; |
|
448 MemoryManager* fMemoryManager; |
|
449 }; |
|
450 |
|
451 |
|
452 // --------------------------------------------------------------------------- |
|
453 // ElemStack: Miscellaneous methods |
|
454 // --------------------------------------------------------------------------- |
|
455 inline bool ElemStack::isEmpty() const |
|
456 { |
|
457 return (fStackTop == 0); |
|
458 } |
|
459 |
|
460 inline bool ElemStack::getValidationFlag() |
|
461 { |
|
462 return fStack[fStackTop-1]->fValidationFlag; |
|
463 } |
|
464 |
|
465 inline void ElemStack::setValidationFlag(bool validationFlag) |
|
466 { |
|
467 fStack[fStackTop-1]->fValidationFlag = validationFlag; |
|
468 return; |
|
469 } |
|
470 |
|
471 inline bool ElemStack::getCommentOrPISeen() const |
|
472 { |
|
473 return fStack[fStackTop-1]->fCommentOrPISeen; |
|
474 } |
|
475 |
|
476 inline void ElemStack::setCommentOrPISeen() |
|
477 { |
|
478 fStack[fStackTop-1]->fCommentOrPISeen = true; |
|
479 return; |
|
480 } |
|
481 |
|
482 inline bool ElemStack::getReferenceEscaped() const |
|
483 { |
|
484 return fStack[fStackTop-1]->fReferenceEscaped; |
|
485 } |
|
486 |
|
487 inline void ElemStack::setReferenceEscaped() |
|
488 { |
|
489 fStack[fStackTop-1]->fReferenceEscaped = true; |
|
490 return; |
|
491 } |
|
492 |
|
493 inline void ElemStack::setCurrentSchemaElemName(const XMLCh * const schemaElemName) |
|
494 { |
|
495 unsigned int schemaElemNameLen = XMLString::stringLen(schemaElemName); |
|
496 unsigned int stackPos = fStackTop-1; |
|
497 |
|
498 if(fStack[stackPos]->fSchemaElemNameMaxLen <= schemaElemNameLen) |
|
499 { |
|
500 XMLCh *tempStr = fStack[stackPos]->fSchemaElemName; |
|
501 fStack[stackPos]->fSchemaElemNameMaxLen = schemaElemNameLen << 1; |
|
502 fStack[stackPos]->fSchemaElemName = (XMLCh *)fMemoryManager->allocate((fStack[stackPos]->fSchemaElemNameMaxLen)*sizeof(XMLCh)); |
|
503 fMemoryManager->deallocate(tempStr); |
|
504 } |
|
505 XMLString::copyString(fStack[stackPos]->fSchemaElemName, schemaElemName); |
|
506 } |
|
507 |
|
508 inline XMLCh *ElemStack::getCurrentSchemaElemName() |
|
509 { |
|
510 return fStack[fStackTop-1]->fSchemaElemName; |
|
511 } |
|
512 |
|
513 inline int ElemStack::getCurrentScope() |
|
514 { |
|
515 return fStack[fStackTop-1]->fCurrentScope; |
|
516 } |
|
517 |
|
518 inline void ElemStack::setCurrentScope(int currentScope) |
|
519 { |
|
520 fStack[fStackTop-1]->fCurrentScope = currentScope; |
|
521 return; |
|
522 } |
|
523 |
|
524 inline Grammar* ElemStack::getCurrentGrammar() |
|
525 { |
|
526 return fStack[fStackTop-1]->fCurrentGrammar; |
|
527 } |
|
528 |
|
529 inline void ElemStack::setCurrentGrammar(Grammar* currentGrammar) |
|
530 { |
|
531 fStack[fStackTop-1]->fCurrentGrammar = currentGrammar; |
|
532 return; |
|
533 } |
|
534 |
|
535 inline unsigned int ElemStack::getCurrentURI() |
|
536 { |
|
537 return fStack[fStackTop-1]->fCurrentURI; |
|
538 } |
|
539 |
|
540 inline void ElemStack::setCurrentURI(unsigned int uri) |
|
541 { |
|
542 fStack[fStackTop-1]->fCurrentURI = uri; |
|
543 return; |
|
544 } |
|
545 |
|
546 inline unsigned int ElemStack::getPrefixId(const XMLCh* const prefix) const |
|
547 { |
|
548 return fPrefixPool.getId(prefix); |
|
549 } |
|
550 |
|
551 inline const XMLCh* ElemStack::getPrefixForId(unsigned int prefId) const |
|
552 { |
|
553 return fPrefixPool.getValueForId(prefId); |
|
554 } |
|
555 |
|
556 inline void ElemStack::setPrefixColonPos(int colonPos) |
|
557 { |
|
558 fStack[fStackTop-1]->fPrefixColonPos = colonPos; |
|
559 } |
|
560 |
|
561 inline int ElemStack::getPrefixColonPos() const { |
|
562 return fStack[fStackTop-1]->fPrefixColonPos; |
|
563 } |
|
564 |
|
565 // --------------------------------------------------------------------------- |
|
566 // WFElemStack: Miscellaneous methods |
|
567 // --------------------------------------------------------------------------- |
|
568 inline bool WFElemStack::isEmpty() const |
|
569 { |
|
570 return (fStackTop == 0); |
|
571 } |
|
572 |
|
573 inline unsigned int WFElemStack::getCurrentURI() |
|
574 { |
|
575 return fStack[fStackTop-1]->fCurrentURI; |
|
576 } |
|
577 |
|
578 inline void WFElemStack::setCurrentURI(unsigned int uri) |
|
579 { |
|
580 fStack[fStackTop-1]->fCurrentURI = uri; |
|
581 return; |
|
582 } |
|
583 |
|
584 |
|
585 XERCES_CPP_NAMESPACE_END |
|
586 |
|
587 #endif |
|