1 // Copyright (c) 1996, 1997 James Clark
2 // See the file COPYING for copying permission.
3
4 // FIXME location for SgmlDocument node.
5
6 #include "config.h"
7 #include "Boolean.h"
8 #include "Node.h"
9 #include "Resource.h"
10 #include "Ptr.h"
11 #include "xnew.h"
12 #include "Event.h"
13 #include "GroveBuilder.h"
14 #include "ErrorCountEventHandler.h"
15 #include "OutputCharStream.h"
16 #include "MessageFormatter.h"
17 #include "Dtd.h"
18 #include "Syntax.h"
19 #include "Attribute.h"
20 #include "Vector.h"
21 #include "LocNode.h"
22 #include "SdNode.h"
23 #include "threads.h"
24 #include "macros.h"
25
26 #ifdef _MSC_VER
27 #pragma warning ( disable : 4250 ) // inherits via dominance
28 #endif
29
30 #include <stddef.h>
31 #include <string.h>
32
33 #ifdef SP_NAMESPACE
34 namespace SP_NAMESPACE {
35 #endif
36
37 #ifdef GROVE_NAMESPACE
38 using namespace GROVE_NAMESPACE;
39 #endif
40
41 static bool blockingAccess = 1;
42
43 size_t initialBlockSize = 8192;
44 unsigned maxBlocksPerSize = 20;
45
46 struct Chunk;
47 struct ParentChunk;
48 class ElementChunk;
49 struct SgmlDocumentChunk;
50 class DataChunk;
51 class GroveImpl;
52 class BaseNode;
53 class ChunkNode;
54 class ElementNode;
55 class DataNode;
56 class CdataAttributeValueNode;
57 class AttributeValueTokenNode;
58 class AttributeAsgnNode;
59 class EntityNode;
60 class NotationNode;
61 class ExternalIdNode;
62 class DocumentTypeNode;
63 class SgmlConstantsNode;
64 class MessageNode;
65
66 struct Chunk {
67 // second arg never null
68 // Set ptr to a node pointing to first Node in this.
69 virtual AccessResult setNodePtrFirst(NodePtr &ptr,
70 const BaseNode *) const = 0;
71 virtual AccessResult setNodePtrFirst(NodePtr &ptr,
72 const ElementNode *node) const;
73 virtual AccessResult setNodePtrFirst(NodePtr &ptr,
74 const DataNode *node) const;
75 virtual const Chunk *after() const = 0;
76 virtual AccessResult getFollowing(const GroveImpl *,
77 const Chunk *&, unsigned long &nNodes)
78 const;
79 virtual AccessResult getFirstSibling(const GroveImpl *, const Chunk *&) const;
80 virtual const StringC *id() const;
81 virtual Boolean getLocOrigin(const Origin *&) const;
82 ParentChunk *origin;
83 };
84
85 struct LocChunk : public Chunk {
86 Index locIndex;
87 };
88
89 struct ParentChunk : public LocChunk {
ParentChunkSP_NAMESPACE::ParentChunk90 ParentChunk() : nextSibling(0) { }
91 Chunk *nextSibling;
92 };
93
94 class ElementChunk : public ParentChunk {
95 public:
96 virtual const AttributeValue *
97 attributeValue(size_t attIndex, const GroveImpl &grove) const;
98 virtual Boolean mustOmitEndTag() const;
99 virtual Boolean included() const;
100 const AttributeDefinitionList *attDefList() const;
101 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
102 AccessResult setNodePtrFirst(NodePtr &ptr, const DataNode *node) const;
103 AccessResult setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const;
key(const ElementChunk & chunk)104 static const StringC &key(const ElementChunk &chunk) { return *chunk.id(); }
105 const Chunk *after() const;
106 AccessResult getFollowing(const GroveImpl *, const Chunk *&, unsigned long &nNodes)
107 const;
108 private:
109 friend class ElementNode;
110 const ElementType *type;
111 public:
112 unsigned long elementIndex;
113 };
114
115 inline
attDefList() const116 const AttributeDefinitionList *ElementChunk::attDefList() const
117 {
118 return type->attributeDefTemp();
119 }
120
121 class LocOriginChunk : public Chunk {
122 public:
LocOriginChunk(const Origin * lo)123 LocOriginChunk(const Origin *lo) : locOrigin(lo) { }
124 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *) const;
125 AccessResult setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const;
126 AccessResult setNodePtrFirst(NodePtr &ptr, const DataNode *node) const;
127 const Chunk *after() const;
128 AccessResult getFollowing(const GroveImpl *,
129 const Chunk *&, unsigned long &nNodes)
130 const;
131 Boolean getLocOrigin(const Origin *&) const;
132 private:
133 const Origin *locOrigin;
134 };
135
136 class MessageItem {
137 public:
MessageItem(Node::Severity severity,const StringC & text,const Location & loc)138 MessageItem(Node::Severity severity, const StringC &text, const Location &loc)
139 : severity_(severity), text_(text), loc_(loc), next_(0) { }
severity() const140 Node::Severity severity() const { return severity_; }
loc() const141 const Location &loc() const { return loc_; }
text() const142 const StringC &text() const { return text_; }
next() const143 const MessageItem *next() const { return next_; }
nextP()144 MessageItem **nextP() { return &next_; }
145 private:
146 Node::Severity severity_;
147 StringC text_;
148 Location loc_;
149 MessageItem *next_;
150 };
151
152 // multiple threads using const interface.
153
154 class GroveImpl {
155 public:
156 GroveImpl(unsigned groveIndex);
157
158 // Const interface
addRef() const159 void addRef() const { ++(((GroveImpl *)this)->refCount_); }
release() const160 void release() const {
161 if (!--(((GroveImpl *)this)->refCount_))
162 delete (GroveImpl *)this;
163 }
groveIndex() const164 unsigned groveIndex() const { return groveIndex_; }
root() const165 const SgmlDocumentChunk *root() const { return root_; }
impliedAttributeValue() const166 const AttributeValue *impliedAttributeValue() const {
167 return impliedAttributeValue_.pointer();
168 }
169 // Return 0 if not yet available.
170 Boolean getAppinfo(const StringC *&) const;
generalSubstTable() const171 const SubstTable<Char> *generalSubstTable() const {
172 return instanceSyntax_.isNull() ? 0 : instanceSyntax_->generalSubstTable();
173 }
entitySubstTable() const174 const SubstTable<Char> *entitySubstTable() const {
175 return instanceSyntax_.isNull() ? 0 : instanceSyntax_->entitySubstTable();
176 }
177 // Be careful not to change ref counts while accessing DTD.
governingDtd() const178 const Dtd *governingDtd() const { return dtd_.pointer(); }
179 // must not be called till grove is complete
180 Dtd::ConstEntityIter defaultedEntityIter() const;
181 const Entity *lookupDefaultedEntity(const StringC &) const;
182 const ElementChunk *lookupElement(const StringC &) const;
183 typedef PointerTableIter<ElementChunk *,StringC,Hash,ElementChunk> ElementIter;
184 // must not be called till grove is complete
185 ElementIter elementIter() const;
complete() const186 Boolean complete() const { return complete_; }
completeLimit() const187 const void *completeLimit() const { return completeLimit_; }
completeLimitWithLocChunkAfter() const188 const void *completeLimitWithLocChunkAfter() const {
189 return completeLimitWithLocChunkAfter_;
190 }
currentLocOrigin() const191 const Origin *currentLocOrigin() const { return currentLocOrigin_; }
hasDefaultEntity() const192 Boolean hasDefaultEntity() const { return hasDefaultEntity_; }
193 Boolean maybeMoreSiblings(const ParentChunk *chunk) const;
194 // return zero for timeout
195 Boolean waitForMoreNodes() const;
196 AccessResult proxifyLocation(const Location &, Location &) const;
messageList() const197 const MessageItem *messageList() const { return messageList_; }
198 // must not be called till grove is complete
199 void getSd(ConstPtr<Sd> &, ConstPtr<Syntax> &, ConstPtr<Syntax> &) const;
200 // non-const interface
201 void *allocChunk(size_t);
202 void appendSibling(Chunk *);
203 void appendSibling(DataChunk *);
tryExtend(size_t n)204 Boolean tryExtend(size_t n) {
205 if (n <= nFree_) {
206 nFree_ -= n;
207 freePtr_ += n;
208 return 1;
209 }
210 else
211 return 0;
212 }
pendingData()213 DataChunk *pendingData() { return pendingData_; }
214 void push(ElementChunk *, Boolean hasId);
215 void pop();
216 void setAppinfo(const StringC &);
217 void setDtd(const ConstPtr<Dtd> &dtd);
218 void setSd(const ConstPtr<Sd> &, const ConstPtr<Syntax> &, const ConstPtr<Syntax> &);
storeAttributeValue(const ConstPtr<AttributeValue> & value)219 void storeAttributeValue(const ConstPtr<AttributeValue> &value) {
220 values_.push_back(value);
221 }
222 void addDefaultedEntity(const ConstPtr<Entity> &);
223 void setComplete();
224 Boolean haveRootOrigin();
225 void setLocOrigin(const ConstPtr<Origin> &);
226 void appendMessage(MessageItem *);
227 private:
228 GroveImpl(const GroveImpl &);
229 void operator=(const GroveImpl &);
230 ~GroveImpl();
231
232 Boolean maybeMoreSiblings1(const ParentChunk *) const;
233 void *allocFinish(size_t);
234 void pulse();
235 void maybePulse();
236 void finishDocumentElement();
237 void finishProlog();
238 void addBarrier();
239 void storeLocOrigin(const ConstPtr<Origin> &);
240
241 struct BlockHeader {
BlockHeaderSP_NAMESPACE::GroveImpl::BlockHeader242 BlockHeader() : next(0) { }
243 BlockHeader *next;
244 };
245 unsigned groveIndex_;
246 SgmlDocumentChunk *root_;
247 ParentChunk *origin_;
248 DataChunk *pendingData_;
249 Chunk **tailPtr_;
250 ConstPtr<Dtd> dtd_;
251 ConstPtr<Sd> sd_;
252 ConstPtr<Syntax> prologSyntax_;
253 ConstPtr<Syntax> instanceSyntax_;
254 ConstPtr<AttributeValue> impliedAttributeValue_;
255 Vector<ConstPtr<AttributeValue> > values_;
256 Vector<ConstPtr<Origin> > origins_;
257 NamedResourceTable<Entity> defaultedEntityTable_;
258 PointerTable<ElementChunk *,StringC,Hash,ElementChunk> idTable_;
259 Boolean hasDefaultEntity_;
260 Boolean haveAppinfo_;
261 StringC appinfo_;
262 const Origin *currentLocOrigin_;
263
264 Boolean complete_;
265 const void *completeLimit_;
266 const void *completeLimitWithLocChunkAfter_;
267 // pointer to first free byte in current block
268 char *freePtr_;
269 // free bytes in current block
270 // there's space for a forwarding chunk after this if freePtr_ != 0
271 size_t nFree_;
272 // the head of the list of blocks
273 BlockHeader *blocks_;
274 // where to store pointer to next block
275 BlockHeader **blockTailPtr_;
276 // current normal size for a block
277 size_t blockAllocSize_;
278 // number of blocks allocated at this size
279 size_t nBlocksThisSizeAlloced_;
280 RefCount refCount_;
281 Condition moreNodesCondition_;
282 Mutex mutex_;
283 Mutex *mutexPtr_;
284 unsigned pulseStep_;
285 unsigned long nEvents_;
286 unsigned long nElements_;
287 enum { maxChunksWithoutLocOrigin = 100 };
288 unsigned nChunksSinceLocOrigin_;
289 MessageItem *messageList_;
290 MessageItem **messageListTailP_;
291 };
292
293 class GroveImplPtr {
294 public:
GroveImplPtr(const GroveImpl * grove)295 GroveImplPtr(const GroveImpl *grove) : grove_(grove) { grove_->addRef(); }
~GroveImplPtr()296 ~GroveImplPtr() { grove_->release(); }
operator ->() const297 const GroveImpl *operator->() const { return grove_; }
operator const GroveImpl*() const298 operator const GroveImpl *() const { return grove_; }
299 private:
300 GroveImplPtr(const GroveImplPtr &); // undefined
301 void operator=(const GroveImplPtr &); // undefined
302 const GroveImpl *grove_;
303 };
304
305 class GroveImplProxyOrigin : public ProxyOrigin {
306 public:
GroveImplProxyOrigin(const GroveImpl * grove,const Origin * origin)307 GroveImplProxyOrigin(const GroveImpl *grove, const Origin *origin)
308 : grove_(grove), ProxyOrigin(origin) { }
309 private:
310 GroveImplPtr grove_;
311 };
312
313 class GroveBuilderMessageEventHandler : public ErrorCountEventHandler {
314 public:
315 GroveBuilderMessageEventHandler(unsigned groveIndex, Messenger *mgr, MessageFormatter *msgFmt_);
316 ~GroveBuilderMessageEventHandler();
317 void message(MessageEvent *);
318 void sgmlDecl(SgmlDeclEvent *);
319 void makeInitialRoot(NodePtr &);
320 void setSd(const ConstPtr<Sd> &, const ConstPtr<Syntax> &, const ConstPtr<Syntax> &);
321 protected:
322 GroveImpl *grove_;
323 private:
324 Messenger *mgr_;
325 MessageFormatter *msgFmt_;
326 };
327
328 class GroveBuilderEventHandler : public GroveBuilderMessageEventHandler {
329 public:
330 GroveBuilderEventHandler(unsigned groveIndex, Messenger *mgr, MessageFormatter *msgFmt_);
331 void appinfo(AppinfoEvent *);
332 void startElement(StartElementEvent *);
333 void endElement(EndElementEvent *);
334 void data(DataEvent *);
335 void sdataEntity(SdataEntityEvent *);
336 void nonSgmlChar(NonSgmlCharEvent *);
337 void externalDataEntity(ExternalDataEntityEvent *);
338 void subdocEntity(SubdocEntityEvent *);
339 void pi(PiEvent *);
340 void endProlog(EndPrologEvent *);
341 void entityDefaulted(EntityDefaultedEvent *);
342 };
343
344 inline
setString(GroveString & to,const StringC & from)345 void setString(GroveString &to, const StringC &from)
346 {
347 to.assign(from.data(), from.size());
348 }
349
350 inline
operator ==(const StringC & str1,const GroveString & str2)351 bool operator==(const StringC &str1, const GroveString &str2)
352 {
353 return (str1.size() == str2.size()
354 && memcmp(str1.data(), str2.data(), str1.size()*sizeof(Char)) == 0);
355 }
356
357 inline
operator !=(const StringC & str1,const GroveString & str2)358 bool operator!=(const StringC &str1, const GroveString &str2)
359 {
360 return !(str1 == str2);
361 }
362
363 inline
roundUp(size_t n)364 size_t roundUp(size_t n)
365 {
366 return (n + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1);
367 }
368
369 // All nodes in this grove must be derived from BaseNode.
370
371 class BaseNode : public Node, public LocNode {
372 public:
373 BaseNode(const GroveImpl *grove);
374 virtual ~BaseNode();
375 void addRef();
376 void release();
377 bool canReuse(NodePtr &ptr) const;
378 unsigned groveIndex() const;
379 bool operator==(const Node &node) const;
380 // Implemented with double dispatching.
381 virtual bool same(const BaseNode &) const = 0;
382 // The second half of the dispatch.
383 virtual bool same2(const ChunkNode *) const;
384 virtual bool same2(const DataNode *) const;
385 virtual bool same2(const AttributeAsgnNode *) const;
386 virtual bool same2(const AttributeValueTokenNode *) const;
387 virtual bool same2(const CdataAttributeValueNode *) const;
388 virtual bool same2(const EntityNode *) const;
389 virtual bool same2(const NotationNode *) const;
390 virtual bool same2(const ExternalIdNode *) const;
391 virtual bool same2(const DocumentTypeNode *) const;
392 virtual bool same2(const SgmlConstantsNode *) const;
393 virtual bool same2(const MessageNode *) const;
grove() const394 const GroveImpl *grove() const { return grove_; }
395 AccessResult nextSibling(NodePtr &ptr) const;
396 AccessResult follow(NodeListPtr &ptr) const;
397 AccessResult children(NodeListPtr &) const;
398 AccessResult getOrigin(NodePtr &ptr) const;
399 AccessResult getGroveRoot(NodePtr &ptr) const;
400 AccessResult getLocation(Location &) const;
401 bool queryInterface(IID, const void *&) const;
402 bool chunkContains(const Node &) const;
403 bool inChunk(const DataNode *node) const;
404 bool inChunk(const CdataAttributeValueNode *) const;
405 protected:
secondHash(unsigned long n)406 static unsigned long secondHash(unsigned long n) {
407 return n * 1001;
408 }
409 private:
410 unsigned refCount_;
411 GroveImplPtr grove_;
412 };
413
414 inline
BaseNode(const GroveImpl * grove)415 BaseNode::BaseNode(const GroveImpl *grove)
416 : grove_(grove), refCount_(0)
417 {
418 }
419
420 inline
canReuse(NodePtr & ptr) const421 bool BaseNode::canReuse(NodePtr &ptr) const
422 {
423 const Node *tem = &*ptr;
424 return tem == this && refCount_ == 1;
425 }
426
427 struct ForwardingChunk : Chunk {
ForwardingChunkSP_NAMESPACE::ForwardingChunk428 ForwardingChunk(const Chunk *to, ParentChunk *p)
429 : forwardTo(to) { origin = p; }
430 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
431 AccessResult getFollowing(const GroveImpl *,
432 const Chunk *&, unsigned long &nNodes)
433 const;
afterSP_NAMESPACE::ForwardingChunk434 const Chunk *after() const { return forwardTo; }
435 const Chunk *forwardTo;
436 };
437
438 class ChunkNode : public BaseNode {
439 public:
440 ChunkNode(const GroveImpl *grove, const LocChunk *chunk);
chunk() const441 const LocChunk *chunk() const { return chunk_; }
442 bool same(const BaseNode &node) const;
443 bool same2(const ChunkNode *node) const;
444 unsigned long hash() const;
445 AccessResult getParent(NodePtr &ptr) const;
446 AccessResult getTreeRoot(NodePtr &ptr) const;
447 AccessResult getOrigin(NodePtr &) const;
448 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &) const;
449 AccessResult nextChunkSibling(NodePtr &) const;
450 AccessResult nextChunkAfter(NodePtr &) const;
451 AccessResult firstSibling(NodePtr &) const;
452 AccessResult siblingsIndex(unsigned long &) const;
453 AccessResult followSiblingRef(unsigned long, NodePtr &) const;
454 AccessResult getLocation(Location &) const;
455 protected:
456 const LocChunk *chunk_; // never null
457 };
458
459 inline
ChunkNode(const GroveImpl * grove,const LocChunk * chunk)460 ChunkNode::ChunkNode(const GroveImpl *grove, const LocChunk *chunk)
461 : BaseNode(grove), chunk_(chunk)
462 {
463 }
464
465 class SgmlDocumentNode;
466
467 struct SgmlDocumentChunk : public ParentChunk {
SgmlDocumentChunkSP_NAMESPACE::SgmlDocumentChunk468 SgmlDocumentChunk() : prolog(0), documentElement(0), epilog(0) { }
469 Chunk *prolog;
470 Chunk *documentElement;
471 Chunk *epilog;
472 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
afterSP_NAMESPACE::SgmlDocumentChunk473 const Chunk *after() const { return this + 1; }
474 };
475
476 class SgmlDocumentNode : public ChunkNode, public SdNode {
477 public:
478 SgmlDocumentNode(const GroveImpl *grove,
479 const SgmlDocumentChunk *chunk);
480 void accept(NodeVisitor &visitor);
classDef() const481 const ClassDef &classDef() const { return ClassDef::sgmlDocument; }
482 AccessResult getDocumentElement(NodePtr &ptr) const;
483 AccessResult getElements(NamedNodeListPtr &ptr) const;
484 AccessResult getEntities(NamedNodeListPtr &ptr) const;
485 AccessResult getDefaultedEntities(NamedNodeListPtr &ptr) const;
486 AccessResult getGoverningDoctype(NodePtr &ptr) const;
487 AccessResult getDoctypesAndLinktypes(NamedNodeListPtr &ptr) const;
488 AccessResult getProlog(NodeListPtr &ptr) const;
489 AccessResult getEpilog(NodeListPtr &ptr) const;
490 AccessResult getSgmlConstants(NodePtr &) const;
491 AccessResult getApplicationInfo(GroveString &str) const;
492 AccessResult getMessages(NodeListPtr &ptr) const;
nextChunkSibling(NodePtr &) const493 AccessResult nextChunkSibling(NodePtr &) const { return accessNotInClass; }
firstSibling(NodePtr &) const494 AccessResult firstSibling(NodePtr &) const { return accessNotInClass; }
siblingsIndex(unsigned long &) const495 AccessResult siblingsIndex(unsigned long &) const { return accessNotInClass; }
getOriginToSubnodeRelPropertyName(ComponentName::Id &) const496 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &) const { return accessNull; }
497 AccessResult getSd(ConstPtr<Sd> &sd,
498 ConstPtr<Syntax> &prologSyntax,
499 ConstPtr<Syntax> &instanceSyntax) const;
500 private:
chunk() const501 const SgmlDocumentChunk *chunk() const {
502 return (const SgmlDocumentChunk *)ChunkNode::chunk();
503 }
504 };
505
506 inline
SgmlDocumentNode(const GroveImpl * grove,const SgmlDocumentChunk * chunk)507 SgmlDocumentNode::SgmlDocumentNode(const GroveImpl *grove,
508 const SgmlDocumentChunk *chunk)
509 : ChunkNode(grove, chunk)
510 {
511 }
512
513 // array of pointers to attribute values stored after chunk
514
515 class AttElementChunk : private ElementChunk {
516 protected:
AttElementChunk(size_t n)517 AttElementChunk(size_t n) : nAtts(n) { }
518 friend class ElementNode;
519 private:
520 const AttributeValue *
521 attributeValue(size_t attIndex, const GroveImpl &) const;
522 Boolean mustOmitEndTag() const;
523 const Chunk *after() const;
524 const StringC *id() const;
525 size_t nAtts;
526 };
527
528 class IncludedElementChunk : public ElementChunk {
529 friend class ElementNode;
530 Boolean included() const;
531 };
532
533 class IncludedAttElementChunk : public AttElementChunk {
IncludedAttElementChunk(size_t n)534 IncludedAttElementChunk(size_t n) : AttElementChunk(n) { }
535 friend class ElementNode;
536 Boolean included() const;
537 };
538
539 class ElementNode : public ChunkNode {
540 public:
541 friend class ElementChunk;
ElementNode(const GroveImpl * grove,const ElementChunk * chunk)542 ElementNode(const GroveImpl *grove, const ElementChunk *chunk)
543 : ChunkNode(grove, chunk) { }
544 AccessResult attributeRef(unsigned long i, NodePtr &ptr) const;
545 AccessResult nextChunkSibling(NodePtr &ptr) const;
546 AccessResult nextChunkAfter(NodePtr &) const;
547 AccessResult firstChild(NodePtr &ptr) const;
548 AccessResult getAttributes(NamedNodeListPtr &ptr) const;
549 AccessResult getGi(GroveString &str) const;
550 bool hasGi(GroveString) const;
551 AccessResult getId(GroveString &str) const;
552 AccessResult getContent(NodeListPtr &ptr) const;
553 AccessResult getMustOmitEndTag(bool &) const;
554 AccessResult getIncluded(bool &) const;
555 AccessResult elementIndex(unsigned long &) const;
556 void accept(NodeVisitor &visitor);
classDef() const557 const ClassDef &classDef() const { return ClassDef::element; }
558 static void add(GroveImpl &grove, const StartElementEvent &event);
559 private:
560 static
561 ElementChunk *makeAttElementChunk(GroveImpl &grove,
562 const StartElementEvent &,
563 Boolean &hasId);
chunk() const564 const ElementChunk *chunk() const {
565 return (const ElementChunk *)ChunkNode::chunk();
566 }
reuseFor(const ElementChunk * chunk)567 void reuseFor(const ElementChunk *chunk) { chunk_ = chunk; }
568 };
569
570 class CharsChunk : public LocChunk {
571 public:
after() const572 const Chunk *after() const {
573 return (const Chunk *)((char *)this + allocSize(size));
574 }
data() const575 const Char *data() const { return (const Char *)(this + 1); }
576 size_t size;
allocSize(size_t nChars)577 static size_t allocSize(size_t nChars) {
578 return roundUp(sizeof(CharsChunk) + nChars*sizeof(Char));
579 }
580 };
581 // The characters immediately follow the chunk
582
583 class DataChunk : public CharsChunk {
584 private:
585 friend class DataNode;
586 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
587 AccessResult setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const;
588 AccessResult setNodePtrFirst(NodePtr &ptr, const DataNode *node) const;
589 AccessResult getFollowing(const GroveImpl *, const Chunk *&, unsigned long &) const;
590 };
591
592 class DataNode : public ChunkNode {
593 public:
594 friend class DataChunk;
595 DataNode(const GroveImpl *, const DataChunk *chunk, size_t index);
596 bool same(const BaseNode &node) const;
597 bool same2(const DataNode *node) const;
598 AccessResult nextSibling(NodePtr &ptr) const;
599 AccessResult nextChunkSibling(NodePtr &ptr) const;
600 AccessResult nextChunkAfter(NodePtr &) const;
601 AccessResult siblingsIndex(unsigned long &) const;
602 AccessResult followSiblingRef(unsigned long, NodePtr &) const;
603 AccessResult charChunk(const SdataMapper &, GroveString &) const;
604 bool chunkContains(const Node &) const;
605 bool inChunk(const DataNode *node) const;
606 AccessResult getNonSgml(unsigned long &) const;
607 AccessResult getLocation(Location &) const;
608 void accept(NodeVisitor &visitor);
classDef() const609 const ClassDef &classDef() const { return ClassDef::dataChar; }
610 unsigned long hash() const;
611 static void add(GroveImpl &grove, const DataEvent &event);
612 private:
chunk() const613 const DataChunk *chunk() const {
614 return (const DataChunk *)ChunkNode::chunk();
615 }
616 void reuseFor(const DataChunk *chunk, size_t index);
617 size_t index_;
618 };
619
620 inline
DataNode(const GroveImpl * grove,const DataChunk * chunk,size_t index)621 DataNode::DataNode(const GroveImpl *grove,
622 const DataChunk *chunk, size_t index)
623 : ChunkNode(grove, chunk), index_(index)
624 {
625 }
626
627 class PiChunk : private CharsChunk {
628 friend class PiNode;
629 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
630 };
631
632 class PrologPiChunk : public PiChunk {
633 AccessResult getFirstSibling(const GroveImpl *, const ::Chunk *&) const;
634 };
635
636 class EpilogPiChunk : public PiChunk {
637 AccessResult getFirstSibling(const GroveImpl *, const ::Chunk *&) const;
638 };
639
640 class PiNode : public ChunkNode {
641 public:
PiNode(const GroveImpl * grove,const PiChunk * chunk)642 PiNode(const GroveImpl *grove, const PiChunk *chunk)
643 : ChunkNode(grove, chunk) {}
644 AccessResult getSystemData(GroveString &) const;
getEntityName(GroveString &) const645 AccessResult getEntityName(GroveString &) const{ return accessNull; }
getEntity(NodePtr &) const646 AccessResult getEntity(NodePtr &) const { return accessNull; }
accept(NodeVisitor & visitor)647 void accept(NodeVisitor &visitor) { visitor.pi(*this); }
classDef() const648 const ClassDef &classDef() const { return ClassDef::pi; }
649 static void add(GroveImpl &grove, const PiEvent &);
650 private:
chunk() const651 const PiChunk *chunk() const {
652 return (const PiChunk *)ChunkNode::chunk();
653 }
654 };
655
656 class EntityRefChunk : public LocChunk {
657 public:
658 const Entity *entity;
after() const659 const Chunk *after() const { return this + 1; }
660 };
661
662 class EntityRefNode : public ChunkNode {
663 public:
EntityRefNode(const GroveImpl * grove,const EntityRefChunk * chunk)664 EntityRefNode(const GroveImpl *grove, const EntityRefChunk *chunk)
665 : ChunkNode(grove, chunk) { }
666 AccessResult getEntity(NodePtr &) const;
667 AccessResult getEntityName(GroveString &) const;
668 protected:
chunk() const669 const EntityRefChunk *chunk() const {
670 return (const EntityRefChunk *)ChunkNode::chunk();
671 }
672 };
673
674 class SdataNode;
675
676 class SdataChunk : private EntityRefChunk {
677 friend class SdataNode;
678 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
679 };
680
681 class SdataNode : public EntityRefNode {
682 public:
SdataNode(const GroveImpl * grove,const SdataChunk * chunk)683 SdataNode(const GroveImpl *grove, const SdataChunk *chunk)
684 : EntityRefNode(grove, chunk) { }
685 AccessResult charChunk(const SdataMapper &, GroveString &) const;
686 AccessResult getSystemData(GroveString &str) const;
accept(NodeVisitor & visitor)687 void accept(NodeVisitor &visitor) { visitor.sdata(*this); }
classDef() const688 const ClassDef &classDef() const { return ClassDef::sdata; }
689 static void add(GroveImpl &grove, const SdataEntityEvent &event);
690 private:
691 Char c_;
692 };
693
694 class NonSgmlNode;
695
696 class NonSgmlChunk : public LocChunk {
697 public:
698 Char c;
699 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
after() const700 const Chunk *after() const { return this + 1; }
701 };
702
703 class NonSgmlNode : public ChunkNode {
704 public:
NonSgmlNode(const GroveImpl * grove,const NonSgmlChunk * chunk)705 NonSgmlNode(const GroveImpl *grove, const NonSgmlChunk *chunk)
706 : ChunkNode(grove, chunk) { }
707 AccessResult charChunk(const SdataMapper &, GroveString &) const;
708 AccessResult getNonSgml(unsigned long &) const;
accept(NodeVisitor & visitor)709 void accept(NodeVisitor &visitor) { visitor.nonSgml(*this); }
classDef() const710 const ClassDef &classDef() const { return ClassDef::nonSgml; }
711 static void add(GroveImpl &grove, const NonSgmlCharEvent &event);
712 protected:
chunk() const713 const NonSgmlChunk *chunk() const {
714 return (const NonSgmlChunk *)ChunkNode::chunk();
715 }
716 };
717
718 class ExternalDataNode;
719
720 class ExternalDataChunk : private EntityRefChunk {
721 friend class ExternalDataNode;
722 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
723 };
724
725 class ExternalDataNode : public EntityRefNode {
726 public:
ExternalDataNode(const GroveImpl * grove,const ExternalDataChunk * chunk)727 ExternalDataNode(const GroveImpl *grove, const ExternalDataChunk *chunk)
728 : EntityRefNode(grove, chunk) { }
accept(NodeVisitor & visitor)729 void accept(NodeVisitor &visitor) { visitor.externalData(*this); }
classDef() const730 const ClassDef &classDef() const { return ClassDef::externalData; }
731 static void add(GroveImpl &grove, const ExternalDataEntityEvent &event);
732 };
733
734 class SubdocChunk : private EntityRefChunk {
735 friend class SubdocNode;
736 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
737 };
738
739 class SubdocNode : public EntityRefNode {
740 public:
SubdocNode(const GroveImpl * grove,const SubdocChunk * chunk)741 SubdocNode(const GroveImpl *grove, const SubdocChunk *chunk)
742 : EntityRefNode(grove, chunk) { }
accept(NodeVisitor & visitor)743 void accept(NodeVisitor &visitor) { visitor.subdocument(*this); }
classDef() const744 const ClassDef &classDef() const { return ClassDef::subdocument; }
745 static void add(GroveImpl &grove, const SubdocEntityEvent &event);
746 };
747
748 class PiEntityChunk : private EntityRefChunk {
749 friend class PiEntityNode;
750 AccessResult setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const;
751 };
752
753 class PiEntityNode : public EntityRefNode {
754 public:
PiEntityNode(const GroveImpl * grove,const PiEntityChunk * chunk)755 PiEntityNode(const GroveImpl *grove, const PiEntityChunk *chunk)
756 : EntityRefNode(grove, chunk) { }
757 AccessResult getSystemData(GroveString &) const;
accept(NodeVisitor & visitor)758 void accept(NodeVisitor &visitor) { visitor.pi(*this); }
classDef() const759 const ClassDef &classDef() const { return ClassDef::pi; }
760 static void add(GroveImpl &grove, const Entity *, const Location &);
761 };
762
763 struct AttributeOrigin {
764 virtual const AttributeDefinitionList *attDefList() const = 0;
765 virtual const AttributeValue *
766 attributeValue(size_t attIndex, const GroveImpl &grove) const = 0;
767 virtual AccessResult
768 setNodePtrAttributeOrigin(NodePtr &, const BaseNode *) const = 0;
769 virtual Node *makeCdataAttributeValueNode(const GroveImpl *grove,
770 const AttributeValue *value,
771 size_t attIndex,
772 const TextIter &iter,
773 size_t charIndex = 0) const = 0;
774 virtual Node *makeAttributeValueTokenNode(const GroveImpl *grove,
775 const TokenizedAttributeValue *value,
776 size_t attIndex,
777 size_t tokenIndex) const = 0;
778 virtual Node *makeAttributeAsgnNode(const GroveImpl *grove,
779 size_t attIndex) const = 0;
780 virtual const void *attributeOriginId() const = 0;
781 };
782
783 class ElementAttributeOrigin : public virtual AttributeOrigin {
784 public:
785 ElementAttributeOrigin(const ElementChunk *);
786 const AttributeDefinitionList *attDefList() const;
787 const AttributeValue *
788 attributeValue(size_t attIndex, const GroveImpl &grove) const;
789 AccessResult setNodePtrAttributeOrigin(NodePtr &, const BaseNode *) const;
790 Node *makeCdataAttributeValueNode(const GroveImpl *grove,
791 const AttributeValue *value,
792 size_t attIndex,
793 const TextIter &iter,
794 size_t charIndex) const;
795 Node *makeAttributeValueTokenNode(const GroveImpl *grove,
796 const TokenizedAttributeValue *value,
797 size_t attIndex,
798 size_t tokenIndex) const;
799 Node *makeAttributeAsgnNode(const GroveImpl *grove,
800 size_t attIndex) const;
801 const void *attributeOriginId() const;
802 private:
803 const ElementChunk *chunk_;
804 };
805
806 class EntityAttributeOrigin : public virtual AttributeOrigin {
807 public:
808 EntityAttributeOrigin(const ExternalDataEntity *);
809 const AttributeDefinitionList *attDefList() const;
810 const AttributeValue *
811 attributeValue(size_t attIndex, const GroveImpl &grove) const;
812 AccessResult setNodePtrAttributeOrigin(NodePtr &, const BaseNode *) const;
813 Node *makeCdataAttributeValueNode(const GroveImpl *grove,
814 const AttributeValue *value,
815 size_t attIndex,
816 const TextIter &iter,
817 size_t charIndex) const;
818 Node *makeAttributeValueTokenNode(const GroveImpl *grove,
819 const TokenizedAttributeValue *value,
820 size_t attIndex,
821 size_t tokenIndex) const;
822 Node *makeAttributeAsgnNode(const GroveImpl *grove,
823 size_t attIndex) const;
824 const void *attributeOriginId() const;
825 private:
826 const ExternalDataEntity *entity_;
827 };
828
829
830 class AttributeAsgnNode : public BaseNode, public virtual AttributeOrigin {
831 public:
832 AttributeAsgnNode(const GroveImpl *grove, size_t attIndex);
833 AccessResult getOrigin(NodePtr &ptr) const;
834 AccessResult getName(GroveString &str) const;
835 AccessResult getImplied(bool &implied) const;
836 AccessResult getValue(NodeListPtr &ptr) const;
837 AccessResult children(NodeListPtr &ptr) const;
838 AccessResult firstChild(NodePtr &ptr) const;
839 AccessResult nextChunkSibling(NodePtr &ptr) const;
840 AccessResult followSiblingRef(unsigned long, NodePtr &) const;
841 AccessResult firstSibling(NodePtr &) const;
842 AccessResult siblingsIndex(unsigned long &) const;
843 AccessResult getTokenSep(Char &) const;
844 AccessResult tokens(GroveString &) const;
845 void accept(NodeVisitor &visitor);
classDef() const846 const ClassDef &classDef() const { return ClassDef::attributeAssignment; }
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const847 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
848 name = ComponentName::idAttributes;
849 return accessOK;
850 }
851 bool same(const BaseNode &node) const;
852 bool same2(const AttributeAsgnNode *node) const;
853 unsigned long hash() const;
854 private:
855 size_t attIndex_;
856 };
857
858 class ElementAttributeAsgnNode
859 : public AttributeAsgnNode, public ElementAttributeOrigin {
860 public:
861 ElementAttributeAsgnNode(const GroveImpl *grove, size_t attIndex,
862 const ElementChunk *);
863 };
864
865 class EntityAttributeAsgnNode
866 : public AttributeAsgnNode, public EntityAttributeOrigin {
867 public:
868 EntityAttributeAsgnNode(const GroveImpl *grove, size_t attIndex,
869 const ExternalDataEntity *);
870 };
871
872 class AttributeValueTokenNode
873 : public BaseNode, public virtual AttributeOrigin {
874 public:
875 AttributeValueTokenNode(const GroveImpl *grove,
876 const TokenizedAttributeValue *value,
877 size_t attIndex, size_t tokenIndex);
878 AccessResult getParent(NodePtr &ptr) const;
879 AccessResult nextChunkSibling(NodePtr &ptr) const;
880 AccessResult followSiblingRef(unsigned long, NodePtr &ptr) const;
881 AccessResult firstSibling(NodePtr &) const;
882 AccessResult siblingsIndex(unsigned long &) const;
883 AccessResult getToken(GroveString &str) const;
884 AccessResult getEntity(NodePtr &ptr) const;
885 AccessResult getNotation(NodePtr &ptr) const;
886 AccessResult getReferent(NodePtr &ptr) const;
887 AccessResult getLocation(Location &) const;
888 void accept(NodeVisitor &visitor);
classDef() const889 const ClassDef &classDef() const { return ClassDef::attributeValueToken; }
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const890 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
891 name = ComponentName::idValue;
892 return accessOK;
893 }
894 bool same(const BaseNode &node) const;
895 bool same2(const AttributeValueTokenNode *node) const;
896 unsigned long hash() const;
897 private:
898 const TokenizedAttributeValue *value_;
899 size_t attIndex_;
900 size_t tokenIndex_;
901 };
902
903 class ElementAttributeValueTokenNode
904 : public AttributeValueTokenNode, public ElementAttributeOrigin {
905 public:
906 ElementAttributeValueTokenNode(const GroveImpl *grove,
907 const TokenizedAttributeValue *value,
908 size_t attIndex,
909 size_t tokenIndex,
910 const ElementChunk *);
911 };
912
913 class EntityAttributeValueTokenNode
914 : public AttributeValueTokenNode, public EntityAttributeOrigin {
915 public:
916 EntityAttributeValueTokenNode(const GroveImpl *grove,
917 const TokenizedAttributeValue *value,
918 size_t attIndex,
919 size_t tokenIndex,
920 const ExternalDataEntity *);
921 };
922
923 class CdataAttributeValueNode
924 : public BaseNode, public virtual AttributeOrigin {
925 public:
926 static bool skipBoring(TextIter &iter);
927 CdataAttributeValueNode(const GroveImpl *grove,
928 const AttributeValue *value,
929 size_t attIndex,
930 const TextIter &iter,
931 size_t charIndex);
932 AccessResult getParent(NodePtr &ptr) const;
933 AccessResult charChunk(const SdataMapper &, GroveString &) const;
934 bool chunkContains(const Node &) const;
935 bool inChunk(const CdataAttributeValueNode *) const;
936 AccessResult getEntity(NodePtr &) const;
937 AccessResult getEntityName(GroveString &) const;
938 AccessResult getSystemData(GroveString &str) const;
939 AccessResult nextSibling(NodePtr &ptr) const;
940 AccessResult nextChunkSibling(NodePtr &ptr) const;
941 AccessResult firstSibling(NodePtr &) const;
942 AccessResult siblingsIndex(unsigned long &) const;
943 AccessResult getLocation(Location &) const;
944 void accept(NodeVisitor &visitor);
945 const ClassDef &classDef() const;
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const946 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
947 name = ComponentName::idValue;
948 return accessOK;
949 }
950 bool same(const BaseNode &node) const;
951 bool same2(const CdataAttributeValueNode *node) const;
952 unsigned long hash() const;
953 private:
954 const AttributeValue *value_;
955 size_t attIndex_;
956 TextIter iter_; // must be valid
957 size_t charIndex_;
958 Char c_;
959 };
960
961 class ElementCdataAttributeValueNode
962 : public CdataAttributeValueNode, public ElementAttributeOrigin {
963 public:
964 ElementCdataAttributeValueNode(const GroveImpl *grove,
965 const AttributeValue *value,
966 size_t attIndex,
967 const TextIter &iter,
968 size_t charIndex,
969 const ElementChunk *);
970 };
971
972 class EntityCdataAttributeValueNode
973 : public CdataAttributeValueNode, public EntityAttributeOrigin {
974 public:
975 EntityCdataAttributeValueNode(const GroveImpl *grove,
976 const AttributeValue *value,
977 size_t attIndex,
978 const TextIter &iter,
979 size_t charIndex,
980 const ExternalDataEntity *);
981 };
982
983 class EntityNode : public BaseNode {
984 public:
985 EntityNode(const GroveImpl *grove, const Entity *entity);
986 AccessResult getOrigin(NodePtr &ptr) const;
987 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &) const;
988 AccessResult getName(GroveString &str) const;
989 AccessResult getExternalId(NodePtr &ptr) const;
990 AccessResult getNotation(NodePtr &) const;
991 AccessResult getNotationName(GroveString &) const;
992 AccessResult getText(GroveString &) const;
993 AccessResult getEntityType(EntityType &) const;
994 AccessResult getDefaulted(bool &) const;
995 AccessResult getAttributes(NamedNodeListPtr &) const;
996 AccessResult attributeRef(unsigned long i, NodePtr &ptr) const;
997 AccessResult getLocation(Location &) const;
998 bool same(const BaseNode &) const;
999 bool same2(const EntityNode *) const;
1000 void accept(NodeVisitor &);
classDef() const1001 const ClassDef &classDef() const { return ClassDef::entity; }
1002 unsigned long hash() const;
1003 private:
1004 const Entity *entity_;
1005 };
1006
1007 class NotationNode : public BaseNode {
1008 public:
1009 NotationNode(const GroveImpl *grove, const Notation *notation);
1010 AccessResult getOrigin(NodePtr &ptr) const;
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const1011 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
1012 name = ComponentName::idNotations;
1013 return accessOK;
1014 }
1015 AccessResult getName(GroveString &str) const;
1016 AccessResult getExternalId(NodePtr &ptr) const;
1017 bool same(const BaseNode &) const;
1018 bool same2(const NotationNode *) const;
1019 AccessResult getLocation(Location &) const;
1020 void accept(NodeVisitor &);
classDef() const1021 const ClassDef &classDef() const { return ClassDef::notation; }
1022 unsigned long hash() const;
1023 private:
1024 const Notation *notation_;
1025 };
1026
1027 class ExternalIdNode : public BaseNode {
1028 public:
1029 ExternalIdNode(const GroveImpl *grove);
1030 virtual const ExternalId &externalId() const = 0;
1031 AccessResult getPublicId(GroveString &) const;
1032 AccessResult getSystemId(GroveString &) const;
1033 AccessResult getGeneratedSystemId(GroveString &) const;
1034 void accept(NodeVisitor &);
classDef() const1035 const ClassDef &classDef() const { return ClassDef::externalId; }
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const1036 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
1037 name = ComponentName::idExternalId;
1038 return accessOK;
1039 }
1040 bool same(const BaseNode &) const;
1041 bool same2(const ExternalIdNode *) const;
1042 };
1043
1044 class EntityExternalIdNode : public ExternalIdNode {
1045 public:
1046 EntityExternalIdNode(const GroveImpl *grove,
1047 const ExternalEntity *entity);
1048 const ExternalId &externalId() const;
1049 AccessResult getOrigin(NodePtr &ptr) const;
1050 unsigned long hash() const;
1051 private:
1052 const ExternalEntity *entity_;
1053 };
1054
1055 class NotationExternalIdNode : public ExternalIdNode {
1056 public:
1057 NotationExternalIdNode(const GroveImpl *grove,
1058 const Notation *notation);
1059 const ExternalId &externalId() const;
1060 AccessResult getOrigin(NodePtr &ptr) const;
1061 unsigned long hash() const;
1062 private:
1063 const Notation *notation_;
1064 };
1065
1066 class DocumentTypeNode : public BaseNode {
1067 public:
1068 DocumentTypeNode(const GroveImpl *grove, const Dtd *);
1069 AccessResult getName(GroveString &) const;
1070 AccessResult getGoverning(bool &) const;
1071 AccessResult getGeneralEntities(NamedNodeListPtr &) const;
1072 AccessResult getNotations(NamedNodeListPtr &) const;
1073 AccessResult getOrigin(NodePtr &) const;
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const1074 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
1075 name = ComponentName::idDoctypesAndLinktypes;
1076 return accessOK;
1077 }
1078 AccessResult nextChunkSibling(NodePtr &) const;
1079 void accept(NodeVisitor &);
classDef() const1080 const ClassDef &classDef() const { return ClassDef::documentType; }
1081 bool same(const BaseNode &) const;
1082 bool same2(const DocumentTypeNode *) const;
1083 private:
1084 const Dtd *dtd_;
1085 };
1086
1087 class SgmlConstantsNode : public BaseNode {
1088 public:
1089 SgmlConstantsNode(const GroveImpl *);
1090 AccessResult getOrigin(NodePtr &) const;
1091 void accept(NodeVisitor &);
classDef() const1092 const ClassDef &classDef() const { return ClassDef::sgmlConstants; }
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const1093 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
1094 name = ComponentName::idSgmlConstants;
1095 return accessOK;
1096 }
1097 bool same(const BaseNode &) const;
1098 bool same2(const SgmlConstantsNode *) const;
1099 };
1100
1101 class MessageNode : public BaseNode {
1102 public:
1103 MessageNode(const GroveImpl *, const MessageItem *);
1104 AccessResult getOrigin(NodePtr &) const;
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const1105 AccessResult getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const {
1106 name = ComponentName::noId;
1107 return accessOK;
1108 }
1109 AccessResult nextChunkSibling(NodePtr &) const;
1110 AccessResult firstSibling(NodePtr &) const;
1111 AccessResult siblingsIndex(unsigned long &) const;
1112 void accept(NodeVisitor &);
classDef() const1113 const ClassDef &classDef() const { return ClassDef::message; }
1114 bool same(const BaseNode &) const;
1115 bool same2(const MessageNode *) const;
1116 AccessResult getLocation(Location &) const;
1117 AccessResult getText(GroveString &) const;
1118 AccessResult getSeverity(Severity &) const;
1119 private:
1120 const MessageItem *item_;
1121 };
1122
1123 class BaseNodeList : public NodeList {
1124 public:
BaseNodeList()1125 BaseNodeList() : refCount_(0) { }
~BaseNodeList()1126 virtual ~BaseNodeList() { }
addRef()1127 void addRef() { ++refCount_; }
canReuse(NodeListPtr & ptr) const1128 bool canReuse(NodeListPtr &ptr) const {
1129 const NodeList *tem = &*ptr;
1130 return tem == this && refCount_ == 1;
1131 }
release()1132 void release() {
1133 ASSERT(refCount_ != 0);
1134 if (--refCount_ == 0) delete this;
1135 }
first(NodePtr &) const1136 AccessResult first(NodePtr &) const { return accessNull; }
rest(NodeListPtr & ptr) const1137 AccessResult rest(NodeListPtr &ptr) const { return chunkRest(ptr); }
chunkRest(NodeListPtr &) const1138 AccessResult chunkRest(NodeListPtr &) const { return accessNull; }
1139 private:
1140 unsigned refCount_;
1141 };
1142
1143 class SiblingNodeList : public BaseNodeList {
1144 public:
SiblingNodeList(const NodePtr & first)1145 SiblingNodeList(const NodePtr &first) : first_(first) { }
first(NodePtr & ptr) const1146 AccessResult first(NodePtr &ptr) const {
1147 ptr = first_;
1148 return accessOK;
1149 }
rest(NodeListPtr & ptr) const1150 AccessResult rest(NodeListPtr &ptr) const {
1151 AccessResult ret;
1152 if (canReuse(ptr)) {
1153 ret = ((SiblingNodeList *)this)->first_.assignNextSibling();
1154 if (ret == accessOK)
1155 return ret;
1156 }
1157 else {
1158 NodePtr next;
1159 ret = first_->nextSibling(next);
1160 if (ret == accessOK) {
1161 ptr.assign(new SiblingNodeList(next));
1162 return ret;
1163 }
1164 }
1165 if (ret == accessNull) {
1166 ptr.assign(new BaseNodeList);
1167 return accessOK;
1168 }
1169 return ret;
1170 }
chunkRest(NodeListPtr & ptr) const1171 AccessResult chunkRest(NodeListPtr &ptr) const {
1172 AccessResult ret;
1173 if (canReuse(ptr)) {
1174 ret = ((SiblingNodeList *)this)->first_.assignNextChunkSibling();
1175 if (ret == accessOK)
1176 return ret;
1177 }
1178 else {
1179 NodePtr next;
1180 ret = first_->nextChunkSibling(next);
1181 if (ret == accessOK) {
1182 ptr.assign(new SiblingNodeList(next));
1183 return ret;
1184 }
1185 }
1186 if (ret == accessNull) {
1187 ptr.assign(new BaseNodeList);
1188 return accessOK;
1189 }
1190 return ret;
1191 }
ref(unsigned long i,NodePtr & ptr) const1192 AccessResult ref(unsigned long i, NodePtr &ptr) const {
1193 if (i == 0) {
1194 ptr = first_;
1195 return accessOK;
1196 }
1197 return first_->followSiblingRef(i - 1, ptr);
1198 }
1199 private:
1200 NodePtr first_; // never null
1201 };
1202
1203 class BaseNamedNodeList : public NamedNodeList {
1204 public:
BaseNamedNodeList(const GroveImpl * grove,const SubstTable<Char> * substTable)1205 BaseNamedNodeList(const GroveImpl *grove,
1206 const SubstTable<Char> *substTable)
1207 : grove_(grove), substTable_(substTable), refCount_(0) { }
~BaseNamedNodeList()1208 virtual ~BaseNamedNodeList() { }
addRef()1209 void addRef() { ++refCount_; }
canReuse(NamedNodeListPtr & ptr) const1210 bool canReuse(NamedNodeListPtr &ptr) const {
1211 const NamedNodeList *tem = &*ptr;
1212 return tem == this && refCount_ == 1;
1213 }
release()1214 void release() {
1215 ASSERT(refCount_ != 0);
1216 if (--refCount_ == 0) delete this;
1217 }
normalize(Char * s,size_t n) const1218 size_t normalize(Char *s, size_t n) const {
1219 if (substTable_) {
1220 for (size_t i = 0; i < n; i++)
1221 substTable_->subst(s[i]);
1222 }
1223 return n;
1224 }
grove() const1225 const GroveImpl *grove() const { return grove_; }
namedNode(GroveString str,NodePtr & node) const1226 AccessResult namedNode(GroveString str, NodePtr &node) const {
1227 StringC tem(str.data(), str.size());
1228 normalize(&tem[0], tem.size());
1229 return namedNodeU(tem, node);
1230 }
1231 virtual AccessResult namedNodeU(const StringC &, NodePtr &) const = 0;
1232 private:
1233 GroveImplPtr grove_;
1234 const SubstTable<Char> *substTable_;
1235 unsigned refCount_;
1236 };
1237
1238 class AttributesNamedNodeList
1239 : public BaseNamedNodeList, public virtual AttributeOrigin {
1240 public:
AttributesNamedNodeList(const GroveImpl * grove)1241 AttributesNamedNodeList(const GroveImpl *grove)
1242 : BaseNamedNodeList(grove, grove->generalSubstTable()) { }
1243 NodeListPtr nodeList() const;
1244 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1245 Type type() const { return attributes; }
1246 };
1247
1248 class ElementAttributesNamedNodeList
1249 : public AttributesNamedNodeList, public ElementAttributeOrigin {
1250 public:
ElementAttributesNamedNodeList(const GroveImpl * grove,const ElementChunk * chunk)1251 ElementAttributesNamedNodeList(const GroveImpl *grove,
1252 const ElementChunk *chunk)
1253 : AttributesNamedNodeList(grove), ElementAttributeOrigin(chunk) { }
1254 };
1255
1256 class EntityAttributesNamedNodeList
1257 : public AttributesNamedNodeList, public EntityAttributeOrigin {
1258 public:
EntityAttributesNamedNodeList(const GroveImpl * grove,const ExternalDataEntity * entity)1259 EntityAttributesNamedNodeList(const GroveImpl *grove,
1260 const ExternalDataEntity *entity)
1261 : AttributesNamedNodeList(grove), EntityAttributeOrigin(entity) { }
1262 };
1263
1264 class ElementsNamedNodeList : public BaseNamedNodeList {
1265 public:
ElementsNamedNodeList(const GroveImpl * grove)1266 ElementsNamedNodeList(const GroveImpl *grove)
1267 : BaseNamedNodeList(grove, grove->generalSubstTable()) { }
1268 NodeListPtr nodeList() const;
1269 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1270 Type type() const { return elements; }
1271 };
1272
1273 class DocEntitiesNamedNodeList : public BaseNamedNodeList {
1274 public:
DocEntitiesNamedNodeList(const GroveImpl * grove)1275 DocEntitiesNamedNodeList(const GroveImpl *grove)
1276 : BaseNamedNodeList(grove, grove->entitySubstTable()) { }
1277 NodeListPtr nodeList() const;
1278 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1279 Type type() const { return entities; }
1280 };
1281
1282 class DefaultedEntitiesNamedNodeList : public BaseNamedNodeList {
1283 public:
DefaultedEntitiesNamedNodeList(const GroveImpl * grove)1284 DefaultedEntitiesNamedNodeList(const GroveImpl *grove)
1285 : BaseNamedNodeList(grove, grove->entitySubstTable()) { }
1286 NodeListPtr nodeList() const;
1287 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1288 Type type() const { return entities; }
1289 };
1290
1291 class GeneralEntitiesNamedNodeList : public BaseNamedNodeList {
1292 public:
1293 GeneralEntitiesNamedNodeList(const GroveImpl *, const Dtd *);
1294 NodeListPtr nodeList() const;
1295 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1296 Type type() const { return entities; }
1297 private:
1298 const Dtd *dtd_;
1299 };
1300
1301 class NotationsNamedNodeList : public BaseNamedNodeList {
1302 public:
1303 NotationsNamedNodeList(const GroveImpl *, const Dtd *);
1304 NodeListPtr nodeList() const;
1305 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1306 Type type() const { return notations; }
1307 private:
1308 const Dtd *dtd_;
1309 };
1310
1311 class DoctypesAndLinktypesNamedNodeList : public BaseNamedNodeList {
1312 public:
1313 DoctypesAndLinktypesNamedNodeList(const GroveImpl *);
1314 NodeListPtr nodeList() const;
1315 AccessResult namedNodeU(const StringC &, NodePtr &) const;
type() const1316 Type type() const { return doctypesAndLinktypes; }
1317 };
1318
1319 class ElementsNodeList : public BaseNodeList {
1320 public:
1321 ElementsNodeList(const GroveImpl *grove,
1322 const Chunk *head);
1323 AccessResult first(NodePtr &) const;
1324 AccessResult chunkRest(NodeListPtr &) const;
1325 public:
1326 GroveImplPtr grove_;
1327 const Chunk *first_;
1328 };
1329
1330 class EntitiesNodeList : public BaseNodeList {
1331 public:
1332 EntitiesNodeList(const GroveImpl *grove,
1333 const Dtd::ConstEntityIter &iter);
1334 AccessResult first(NodePtr &) const;
1335 AccessResult chunkRest(NodeListPtr &) const;
1336 protected:
grove() const1337 const GroveImpl *grove() const { return grove_; }
1338 public:
1339 GroveImplPtr grove_;
1340 Dtd::ConstEntityIter iter_;
1341 };
1342
1343 class DocEntitiesNodeList : public EntitiesNodeList {
1344 public:
1345 DocEntitiesNodeList(const GroveImpl *grove);
1346 AccessResult first(NodePtr &) const;
1347 AccessResult chunkRest(NodeListPtr &) const;
1348 };
1349
1350 class NotationsNodeList : public BaseNodeList {
1351 public:
1352 NotationsNodeList(const GroveImpl *grove,
1353 const Dtd::ConstNotationIter &iter);
1354 AccessResult first(NodePtr &) const;
1355 AccessResult chunkRest(NodeListPtr &) const;
1356 public:
1357 GroveImplPtr grove_;
1358 Dtd::ConstNotationIter iter_;
1359 };
1360
1361 inline
waitForMoreNodes() const1362 Boolean GroveImpl::waitForMoreNodes() const
1363 {
1364 if (blockingAccess)
1365 return moreNodesCondition_.wait();
1366 else
1367 return 0;
1368 }
1369
1370 inline
pulse()1371 void GroveImpl::pulse()
1372 {
1373 moreNodesCondition_.pulse();
1374 }
1375
1376 inline
maybePulse()1377 void GroveImpl::maybePulse()
1378 {
1379 // Once we've had (2^n)*(2^10) events, only pulse every (2^n)th event.
1380 // Up to a limit of n == 8.
1381 // This reduces the overhead of pulsing to negligible levels on WinNT.
1382 if ((++nEvents_ & ~(~unsigned(0) << pulseStep_)) == 0) {
1383 pulse();
1384 if (pulseStep_ < 8 && nEvents_ > (1 << (pulseStep_ + 10)))
1385 pulseStep_++;
1386 }
1387 }
1388
1389 inline
appendSibling(Chunk * chunk)1390 void GroveImpl::appendSibling(Chunk *chunk)
1391 {
1392 if (pendingData_) {
1393 if (tailPtr_) {
1394 // Must set completeLimit_ before setting tailPtr_.
1395 completeLimit_ = pendingData_->after();
1396 *tailPtr_ = pendingData_;
1397 tailPtr_ = 0;
1398 }
1399 pendingData_ = 0;
1400 }
1401 // Must set origin before advancing completeLimit_.
1402 chunk->origin = origin_;
1403 // Must advance completeLimit_ before setting tailPtr_.
1404 completeLimit_ = freePtr_;
1405 if (tailPtr_) {
1406 *tailPtr_ = chunk;
1407 tailPtr_ = 0;
1408 }
1409 pendingData_ = 0;
1410 maybePulse();
1411 }
1412
1413 inline
appendSibling(DataChunk * chunk)1414 void GroveImpl::appendSibling(DataChunk *chunk)
1415 {
1416 // Since we might extend this DataChunk, it's
1417 // not safe to set completeLimit_ to after this chunk yet.
1418 // This means we can't yet set tailPtr_.
1419 if (pendingData_) {
1420 // Must set completeLimit_ before setting tailPtr_.
1421 completeLimit_ = pendingData_->after();
1422 if (tailPtr_) {
1423 *tailPtr_ = pendingData_;
1424 tailPtr_ = 0;
1425 }
1426 }
1427 chunk->origin = origin_;
1428 pendingData_ = chunk;
1429 maybePulse();
1430 }
1431
1432 inline
push(ElementChunk * chunk,Boolean hasId)1433 void GroveImpl::push(ElementChunk *chunk, Boolean hasId)
1434 {
1435 if (pendingData_) {
1436 if (tailPtr_) {
1437 // Must set completeLimit_ before setting tailPtr_.
1438 completeLimit_ = pendingData_->after();
1439 *tailPtr_ = pendingData_;
1440 tailPtr_ = 0;
1441 }
1442 pendingData_ = 0;
1443 }
1444 chunk->elementIndex = nElements_++;
1445 chunk->origin = origin_;
1446 // Must set origin_ to chunk before advancing completeLimit_
1447 // otherwise thread would look at element and
1448 // maybeMoreSiblings() would return false.
1449 // Must advance completeLimit_ before setting tailPtr_,
1450 // otherwise tailPtr_ would be beyond completeLimit_.
1451 origin_ = chunk;
1452 completeLimit_ = freePtr_;
1453 // Allow for the possibility of invalid documents with elements
1454 // after the document element.
1455 if ((const Chunk *)chunk->origin == root_ && root_->documentElement == 0)
1456 root_->documentElement = chunk;
1457 else if (tailPtr_) {
1458 *tailPtr_ = chunk;
1459 tailPtr_ = 0;
1460 }
1461 if (hasId) {
1462 Mutex::Lock lock(mutexPtr_);
1463 idTable_.insert(chunk);
1464 }
1465 maybePulse();
1466 }
1467
1468 inline
pop()1469 void GroveImpl::pop()
1470 {
1471 if (pendingData_) {
1472 // Must set completeLimit_ before setting tailPtr_.
1473 completeLimit_ = pendingData_->after();
1474 if (tailPtr_) {
1475 *tailPtr_ = pendingData_;
1476 tailPtr_ = 0;
1477 }
1478 pendingData_ = 0;
1479 }
1480 tailPtr_ = &origin_->nextSibling;
1481 origin_ = origin_->origin;
1482 if ((const Chunk *)origin_ == root_)
1483 finishDocumentElement();
1484 maybePulse();
1485 }
1486
1487 inline
haveRootOrigin()1488 Boolean GroveImpl::haveRootOrigin()
1489 {
1490 return (const Chunk *)origin_ == root_;
1491 }
1492
1493 inline
setDtd(const ConstPtr<Dtd> & dtd)1494 void GroveImpl::setDtd(const ConstPtr<Dtd> &dtd)
1495 {
1496 dtd_ = dtd;
1497 hasDefaultEntity_ = !dtd_->defaultEntity().isNull();
1498 finishProlog();
1499 pulse();
1500 }
1501
1502 inline
lookupElement(const StringC & id) const1503 const ElementChunk *GroveImpl::lookupElement(const StringC &id) const
1504 {
1505 Mutex::Lock lock(mutexPtr_);
1506 return idTable_.lookup(id);
1507 }
1508
1509 inline
elementIter() const1510 GroveImpl::ElementIter GroveImpl::elementIter() const
1511 {
1512 ASSERT(complete());
1513 return ElementIter(idTable_);
1514 }
1515
1516 inline
maybeMoreSiblings(const ParentChunk * chunk) const1517 Boolean GroveImpl::maybeMoreSiblings(const ParentChunk *chunk) const
1518 {
1519 return (complete_
1520 ? chunk->nextSibling != 0
1521 : (origin_ == chunk
1522 || &chunk->nextSibling == tailPtr_
1523 || maybeMoreSiblings1(chunk)));
1524 }
1525
1526 inline
allocChunk(size_t n)1527 void *GroveImpl::allocChunk(size_t n)
1528 {
1529 nChunksSinceLocOrigin_++;
1530 if (n <= nFree_) {
1531 void *p = freePtr_;
1532 freePtr_ += n;
1533 nFree_ -= n;
1534 return p;
1535 }
1536 else
1537 return allocFinish(n);
1538 }
1539
1540 inline
setLocOrigin(const ConstPtr<Origin> & locOrigin)1541 void GroveImpl::setLocOrigin(const ConstPtr<Origin> &locOrigin)
1542 {
1543 if (locOrigin.pointer() != currentLocOrigin_
1544 || nChunksSinceLocOrigin_ >= maxChunksWithoutLocOrigin)
1545 storeLocOrigin(locOrigin);
1546 }
1547
1548 inline
appendMessage(MessageItem * item)1549 void GroveImpl::appendMessage(MessageItem *item)
1550 {
1551 *messageListTailP_ = item;
1552 messageListTailP_ = item->nextP();
1553 pulse();
1554 }
1555
1556 inline
add(GroveImpl & grove,const StartElementEvent & event)1557 void ElementNode::add(GroveImpl &grove, const StartElementEvent &event)
1558 {
1559 grove.setLocOrigin(event.location().origin());
1560 ElementChunk *chunk;
1561 const AttributeList &atts = event.attributes();
1562 Boolean hasId;
1563 if (atts.nSpec() == 0 && !atts.anyCurrent()) {
1564 void *mem = grove.allocChunk(sizeof(ElementChunk));
1565 if (event.included())
1566 chunk = new (mem) IncludedElementChunk;
1567 else
1568 chunk = new (mem) ElementChunk;
1569 hasId = 0;
1570 }
1571 else
1572 chunk = makeAttElementChunk(grove, event, hasId);
1573 chunk->type = event.elementType();
1574 chunk->locIndex = event.location().index();
1575 grove.push(chunk, hasId);
1576 }
1577
1578 // We duplicate ChunkNode::nextChunkSibling to take advantage
1579 // of Node reuse (via setNodePtrFirst(NodePtr &, const DataNode *).
1580 inline
nextChunkSibling(NodePtr & ptr) const1581 AccessResult DataNode::nextChunkSibling(NodePtr &ptr) const
1582 {
1583 // The forwarding chunk has origin = 0, so it will stop
1584 // the iteration before after() can return 0.
1585 const Chunk *p = chunk_->after();
1586 while (p == grove()->completeLimit())
1587 if (!grove()->waitForMoreNodes())
1588 return accessTimeout;
1589 if (p->origin != chunk_->origin)
1590 return accessNull;
1591 return p->setNodePtrFirst(ptr, this);
1592 }
1593
1594 inline
reuseFor(const DataChunk * chunk,size_t index)1595 void DataNode::reuseFor(const DataChunk *chunk, size_t index)
1596 {
1597 chunk_ = chunk;
1598 index_ = index;
1599 }
1600
1601 inline
add(GroveImpl & grove,const DataEvent & event)1602 void DataNode::add(GroveImpl &grove, const DataEvent &event)
1603 {
1604 size_t dataLen = event.dataLength();
1605 if (dataLen) {
1606 DataChunk *chunk = grove.pendingData();
1607 if (chunk
1608 && event.location().origin().pointer() == grove.currentLocOrigin()
1609 && event.location().index() == chunk->locIndex + chunk->size
1610 && grove.tryExtend(CharsChunk::allocSize(chunk->size + dataLen)
1611 - CharsChunk::allocSize(chunk->size))) {
1612 memcpy((Char *)(chunk + 1) + chunk->size,
1613 event.data(),
1614 dataLen * sizeof(Char));
1615 chunk->size += dataLen;
1616 }
1617 else {
1618 grove.setLocOrigin(event.location().origin());
1619 chunk = new (grove.allocChunk(CharsChunk::allocSize(dataLen))) DataChunk;
1620 chunk->size = dataLen;
1621 chunk->locIndex = event.location().index();
1622 memcpy(chunk + 1, event.data(), dataLen * sizeof(Char));
1623 grove.appendSibling(chunk);
1624 }
1625 }
1626 }
1627
GroveBuilderMessageEventHandler(unsigned groveIndex,Messenger * mgr,MessageFormatter * msgFmt)1628 GroveBuilderMessageEventHandler::GroveBuilderMessageEventHandler(unsigned groveIndex,
1629 Messenger *mgr,
1630 MessageFormatter *msgFmt)
1631 : mgr_(mgr), grove_(new GroveImpl(groveIndex)), msgFmt_(msgFmt)
1632 {
1633 grove_->addRef();
1634 }
1635
~GroveBuilderMessageEventHandler()1636 GroveBuilderMessageEventHandler::~GroveBuilderMessageEventHandler()
1637 {
1638 grove_->setComplete();
1639 grove_->release();
1640 }
1641
makeInitialRoot(NodePtr & root)1642 void GroveBuilderMessageEventHandler::makeInitialRoot(NodePtr &root)
1643 {
1644 root.assign(new SgmlDocumentNode(grove_, grove_->root()));
1645 }
1646
message(MessageEvent * event)1647 void GroveBuilderMessageEventHandler::message(MessageEvent *event)
1648 {
1649 mgr_->dispatchMessage(event->message());
1650 const Message &msg = event->message();
1651 StrOutputCharStream os;
1652 msgFmt_->formatMessage(*msg.type, msg.args, os);
1653 StringC tem;
1654 os.extractString(tem);
1655 Node::Severity severity;
1656 switch (msg.type->severity()) {
1657 case MessageType::info:
1658 severity = Node::info;
1659 break;
1660 case MessageType::warning:
1661 severity = Node::warning;
1662 break;
1663 default:
1664 severity = Node::error;
1665 break;
1666 }
1667 grove_->appendMessage(new MessageItem(severity, tem, msg.loc));
1668 if (!msg.auxLoc.origin().isNull()) {
1669 msgFmt_->formatMessage(msg.type->auxFragment(), msg.args, os);
1670 os.extractString(tem);
1671 grove_->appendMessage(new MessageItem(Node::info, tem, msg.auxLoc));
1672 }
1673 ErrorCountEventHandler::message(event);
1674 }
1675
sgmlDecl(SgmlDeclEvent * event)1676 void GroveBuilderMessageEventHandler::sgmlDecl(SgmlDeclEvent *event)
1677 {
1678 grove_->setSd(event->sdPointer(), event->prologSyntaxPointer(), event->instanceSyntaxPointer());
1679 delete event;
1680 }
1681
setSd(const ConstPtr<Sd> & sd,const ConstPtr<Syntax> & prologSyntax,const ConstPtr<Syntax> & instanceSyntax)1682 void GroveBuilderMessageEventHandler::setSd(const ConstPtr<Sd> &sd, const ConstPtr<Syntax> &prologSyntax, const ConstPtr<Syntax> &instanceSyntax)
1683 {
1684 grove_->setSd(sd, prologSyntax, instanceSyntax);
1685 }
1686
GroveBuilderEventHandler(unsigned groveIndex,Messenger * mgr,MessageFormatter * msgFmt)1687 GroveBuilderEventHandler::GroveBuilderEventHandler(unsigned groveIndex,
1688 Messenger *mgr,
1689 MessageFormatter *msgFmt)
1690 : GroveBuilderMessageEventHandler(groveIndex, mgr, msgFmt)
1691 {
1692 }
1693
appinfo(AppinfoEvent * event)1694 void GroveBuilderEventHandler::appinfo(AppinfoEvent *event)
1695 {
1696 const StringC *appinfo;
1697 if (event->literal(appinfo))
1698 grove_->setAppinfo(*appinfo);
1699 delete event;
1700 }
1701
endProlog(EndPrologEvent * event)1702 void GroveBuilderEventHandler::endProlog(EndPrologEvent *event)
1703 {
1704 grove_->setDtd(event->dtdPointer());
1705 delete event;
1706 }
1707
startElement(StartElementEvent * event)1708 void GroveBuilderEventHandler::startElement(StartElementEvent *event)
1709 {
1710 ElementNode::add(*grove_, *event);
1711 delete event;
1712 }
1713
endElement(EndElementEvent * event)1714 void GroveBuilderEventHandler::endElement(EndElementEvent *event)
1715 {
1716 grove_->pop();
1717 delete event;
1718 }
1719
data(DataEvent * event)1720 void GroveBuilderEventHandler::data(DataEvent *event)
1721 {
1722 DataNode::add(*grove_, *event);
1723 delete event;
1724 }
1725
sdataEntity(SdataEntityEvent * event)1726 void GroveBuilderEventHandler::sdataEntity(SdataEntityEvent *event)
1727 {
1728 SdataNode::add(*grove_, *event);
1729 delete event;
1730 }
1731
nonSgmlChar(NonSgmlCharEvent * event)1732 void GroveBuilderEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
1733 {
1734 NonSgmlNode::add(*grove_, *event);
1735 delete event;
1736 }
1737
externalDataEntity(ExternalDataEntityEvent * event)1738 void GroveBuilderEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
1739 {
1740 ExternalDataNode::add(*grove_, *event);
1741 delete event;
1742 }
1743
subdocEntity(SubdocEntityEvent * event)1744 void GroveBuilderEventHandler::subdocEntity(SubdocEntityEvent *event)
1745 {
1746 SubdocNode::add(*grove_, *event);
1747 delete event;
1748 }
1749
pi(PiEvent * event)1750 void GroveBuilderEventHandler::pi(PiEvent *event)
1751 {
1752 PiNode::add(*grove_, *event);
1753 delete event;
1754 }
1755
entityDefaulted(EntityDefaultedEvent * event)1756 void GroveBuilderEventHandler::entityDefaulted(EntityDefaultedEvent *event)
1757 {
1758 grove_->addDefaultedEntity(event->entityPointer());
1759 delete event;
1760 }
1761
make(unsigned index,Messenger * mgr,MessageFormatter * msgFmt,bool validateOnly,NodePtr & root)1762 ErrorCountEventHandler *GroveBuilder::make(unsigned index,
1763 Messenger *mgr,
1764 MessageFormatter *msgFmt,
1765 bool validateOnly,
1766 NodePtr &root)
1767 {
1768 GroveBuilderMessageEventHandler *eh;
1769 if (validateOnly)
1770 eh = new GroveBuilderMessageEventHandler(index, mgr, msgFmt);
1771 else
1772 eh = new GroveBuilderEventHandler(index, mgr, msgFmt);
1773 eh->makeInitialRoot(root);
1774 return eh;
1775 }
1776
make(unsigned index,Messenger * mgr,MessageFormatter * msgFmt,bool validateOnly,const ConstPtr<Sd> & sd,const ConstPtr<Syntax> & prologSyntax,const ConstPtr<Syntax> & instanceSyntax,NodePtr & root)1777 ErrorCountEventHandler *GroveBuilder::make(unsigned index,
1778 Messenger *mgr,
1779 MessageFormatter *msgFmt,
1780 bool validateOnly,
1781 const ConstPtr<Sd> &sd,
1782 const ConstPtr<Syntax> &prologSyntax,
1783 const ConstPtr<Syntax> &instanceSyntax,
1784 NodePtr &root)
1785 {
1786 GroveBuilderMessageEventHandler *eh;
1787 if (validateOnly)
1788 eh = new GroveBuilderMessageEventHandler(index, mgr, msgFmt);
1789 else
1790 eh = new GroveBuilderEventHandler(index, mgr, msgFmt);
1791 eh->makeInitialRoot(root);
1792 eh->setSd(sd, prologSyntax, instanceSyntax);
1793 return eh;
1794 }
1795
setBlocking(bool b)1796 bool GroveBuilder::setBlocking(bool b)
1797 {
1798 bool prev = blockingAccess;
1799 blockingAccess = b;
1800 return prev;
1801 }
1802
GroveImpl(unsigned groveIndex)1803 GroveImpl::GroveImpl(unsigned groveIndex)
1804 : groveIndex_(groveIndex),
1805 root_(0),
1806 impliedAttributeValue_(new ImpliedAttributeValue),
1807 tailPtr_(0),
1808 freePtr_(0),
1809 nFree_(0),
1810 blocks_(0),
1811 blockTailPtr_(&blocks_),
1812 blockAllocSize_(initialBlockSize),
1813 nBlocksThisSizeAlloced_(0),
1814 complete_(0),
1815 mutexPtr_(&mutex_),
1816 pulseStep_(0),
1817 nEvents_(0),
1818 haveAppinfo_(0),
1819 pendingData_(0),
1820 nElements_(0),
1821 currentLocOrigin_(0),
1822 completeLimitWithLocChunkAfter_(0),
1823 nChunksSinceLocOrigin_(0),
1824 messageList_(0),
1825 messageListTailP_(&messageList_)
1826 {
1827 root_ = new (allocChunk(sizeof(SgmlDocumentChunk))) SgmlDocumentChunk;
1828 root_->origin = 0;
1829 root_->locIndex = 0;
1830 completeLimit_ = freePtr_;
1831 origin_ = root_;
1832 tailPtr_ = &root_->prolog;
1833 }
1834
~GroveImpl()1835 GroveImpl::~GroveImpl()
1836 {
1837 while (blocks_) {
1838 BlockHeader *tem = blocks_;
1839 blocks_ = blocks_->next;
1840 ::operator delete(tem);
1841 }
1842 while (messageList_) {
1843 MessageItem *tem = messageList_;
1844 messageList_ = *messageList_->nextP();
1845 delete tem;
1846 }
1847 }
1848
setAppinfo(const StringC & appinfo)1849 void GroveImpl::setAppinfo(const StringC &appinfo)
1850 {
1851 appinfo_ = appinfo;
1852 haveAppinfo_ = 1;
1853 }
1854
getAppinfo(const StringC * & appinfo) const1855 Boolean GroveImpl::getAppinfo(const StringC *&appinfo) const
1856 {
1857 if (!haveAppinfo_) {
1858 if (!complete_ && sd_.isNull())
1859 return 0; // not available yet
1860 appinfo = 0;
1861 }
1862 else
1863 appinfo = &appinfo_;
1864 return 1;
1865 }
1866
setSd(const ConstPtr<Sd> & sd,const ConstPtr<Syntax> & prologSyntax,const ConstPtr<Syntax> & instanceSyntax)1867 void GroveImpl::setSd(const ConstPtr<Sd> &sd, const ConstPtr<Syntax> &prologSyntax, const ConstPtr<Syntax> &instanceSyntax)
1868 {
1869 instanceSyntax_ = instanceSyntax;
1870 prologSyntax_ = prologSyntax;
1871 sd_ = sd;
1872 }
1873
getSd(ConstPtr<Sd> & sd,ConstPtr<Syntax> & prologSyntax,ConstPtr<Syntax> & instanceSyntax) const1874 void GroveImpl::getSd(ConstPtr<Sd> &sd, ConstPtr<Syntax> &prologSyntax, ConstPtr<Syntax> &instanceSyntax) const
1875 {
1876 instanceSyntax = instanceSyntax_;
1877 prologSyntax = prologSyntax_;
1878 sd = sd_;
1879 }
1880
finishProlog()1881 void GroveImpl::finishProlog()
1882 {
1883 if (root_->prolog)
1884 addBarrier();
1885 tailPtr_ = 0;
1886 }
1887
finishDocumentElement()1888 void GroveImpl::finishDocumentElement()
1889 {
1890 // Be robust in the case of erroneous documents.
1891 if (root_->epilog == 0) {
1892 addBarrier();
1893 tailPtr_ = &root_->epilog;
1894 }
1895 }
1896
addBarrier()1897 void GroveImpl::addBarrier()
1898 {
1899 if (freePtr_) {
1900 (void) new (freePtr_) ForwardingChunk(0, 0);
1901 if (nFree_ <= sizeof(ForwardingChunk)) {
1902 nFree_ = 0;
1903 freePtr_ = 0;
1904 }
1905 else {
1906 nFree_ -= sizeof(ForwardingChunk);
1907 freePtr_ += sizeof(ForwardingChunk);
1908 }
1909 }
1910 }
1911
setComplete()1912 void GroveImpl::setComplete()
1913 {
1914 addBarrier();
1915 mutexPtr_ = 0;
1916 completeLimit_ = 0;
1917 completeLimitWithLocChunkAfter_ = 0;
1918 if (pendingData_ && tailPtr_)
1919 *tailPtr_ = pendingData_;
1920 tailPtr_ = 0;
1921 pendingData_ = 0;
1922 complete_ = 1;
1923 moreNodesCondition_.set();
1924 }
1925
addDefaultedEntity(const ConstPtr<Entity> & entity)1926 void GroveImpl::addDefaultedEntity(const ConstPtr<Entity> &entity)
1927 {
1928 Mutex::Lock lock(mutexPtr_);
1929 // We need a table of ConstPtr<Entity> but we don't have one.
1930 defaultedEntityTable_.insert((Entity *)entity.pointer());
1931 }
1932
lookupDefaultedEntity(const StringC & name) const1933 const Entity *GroveImpl::lookupDefaultedEntity(const StringC &name) const
1934 {
1935 Mutex::Lock lock(mutexPtr_);
1936 return defaultedEntityTable_.lookupTemp(name);
1937 }
1938
defaultedEntityIter() const1939 Dtd::ConstEntityIter GroveImpl::defaultedEntityIter() const
1940 {
1941 ASSERT(complete());
1942 return Dtd::ConstEntityIter(defaultedEntityTable_);
1943 }
1944
maybeMoreSiblings1(const ParentChunk * chunk) const1945 Boolean GroveImpl::maybeMoreSiblings1(const ParentChunk *chunk) const
1946 {
1947 for (const ParentChunk *open = origin_; open; open = open->origin)
1948 if (open == chunk)
1949 return 1;
1950 // for multi-thread case
1951 return tailPtr_ == &chunk->nextSibling || chunk->nextSibling != 0;
1952 }
1953
allocFinish(size_t n)1954 void *GroveImpl::allocFinish(size_t n)
1955 {
1956 if (++nBlocksThisSizeAlloced_ >= maxBlocksPerSize) {
1957 blockAllocSize_ *= 2;
1958 nBlocksThisSizeAlloced_ = 0;
1959 }
1960 size_t allocSize = n + (sizeof(ForwardingChunk) + sizeof(BlockHeader));
1961 if (allocSize < blockAllocSize_) {
1962 nFree_ = blockAllocSize_ - allocSize;
1963 allocSize = blockAllocSize_;
1964 }
1965 else
1966 nFree_ = 0;
1967 *blockTailPtr_ = new (::operator new(allocSize)) BlockHeader;
1968 char *chunkStart = (char *)(*blockTailPtr_ + 1);
1969 blockTailPtr_ = &(*blockTailPtr_)->next;
1970 if (freePtr_)
1971 (void)new (freePtr_) ForwardingChunk((const Chunk *)chunkStart, origin_);
1972 freePtr_ = chunkStart + n;
1973 return chunkStart;
1974 }
1975
getLocation(Location & loc) const1976 AccessResult ChunkNode::getLocation(Location &loc) const
1977 {
1978 const Origin *origin = grove()->currentLocOrigin();
1979 for (const Chunk *p = chunk_->after(); p; p = p->after()) {
1980 if (p == grove()->completeLimitWithLocChunkAfter()) {
1981 while (!p->getLocOrigin(origin)) {
1982 p = p->after();
1983 ASSERT(p != 0);
1984 }
1985 break;
1986 }
1987 if (p == grove()->completeLimit() || p->getLocOrigin(origin))
1988 break;
1989 }
1990 if (!origin)
1991 return accessNull;
1992 loc = Location(new GroveImplProxyOrigin(grove(), origin), chunk_->locIndex);
1993 return accessOK;
1994 }
1995
storeLocOrigin(const ConstPtr<Origin> & locOrigin)1996 void GroveImpl::storeLocOrigin(const ConstPtr<Origin> &locOrigin)
1997 {
1998 LocOriginChunk *chunk
1999 = new (allocChunk(sizeof(LocOriginChunk)))
2000 LocOriginChunk(currentLocOrigin_);
2001 chunk->origin = origin_;
2002 completeLimitWithLocChunkAfter_ = completeLimit_;
2003 nChunksSinceLocOrigin_ = 0;
2004 if (locOrigin.pointer() == currentLocOrigin_)
2005 return;
2006 if (currentLocOrigin_
2007 && locOrigin == currentLocOrigin_->parent().origin()) {
2008 // Don't need to store it.
2009 currentLocOrigin_ = locOrigin.pointer();
2010 return;
2011 }
2012 currentLocOrigin_ = locOrigin.pointer();
2013 if (locOrigin.isNull())
2014 return;
2015 origins_.push_back(locOrigin);
2016 }
2017
proxifyLocation(const Location & loc,Location & ret) const2018 AccessResult GroveImpl::proxifyLocation(const Location &loc, Location &ret) const
2019 {
2020 if (loc.origin().isNull())
2021 return accessNull;
2022 ret = Location(new GroveImplProxyOrigin(this, loc.origin().pointer()),
2023 loc.index());
2024 return accessOK;
2025 }
2026
nodeList() const2027 NodeListPtr AttributesNamedNodeList::nodeList() const
2028 {
2029 const AttributeDefinitionList *defList = attDefList();
2030 if (!defList || defList->size() == 0)
2031 return new BaseNodeList;
2032 else
2033 return new SiblingNodeList(makeAttributeAsgnNode(grove(), 0));
2034 }
2035
2036 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const2037 AttributesNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
2038 {
2039 const AttributeDefinitionList *defList = attDefList();
2040 if (defList) {
2041 for (size_t i = 0; i < defList->size(); i++)
2042 if (defList->def(i)->name() == str) {
2043 ptr.assign(makeAttributeAsgnNode(grove(), i));
2044 return accessOK;
2045 }
2046 }
2047 return accessNull;
2048 }
2049
accept(NodeVisitor & visitor)2050 void SgmlDocumentNode::accept(NodeVisitor &visitor)
2051 {
2052 visitor.sgmlDocument(*this);
2053 }
2054
getSgmlConstants(NodePtr & ptr) const2055 AccessResult SgmlDocumentNode::getSgmlConstants(NodePtr &ptr) const
2056 {
2057 ptr.assign(new SgmlConstantsNode(grove()));
2058 return accessOK;
2059 }
2060
getApplicationInfo(GroveString & str) const2061 AccessResult SgmlDocumentNode::getApplicationInfo(GroveString &str) const
2062 {
2063 const StringC *appinfo;
2064 while (!grove()->getAppinfo(appinfo))
2065 if (!grove()->waitForMoreNodes())
2066 return accessTimeout;
2067 if (!appinfo)
2068 return accessNull;
2069 setString(str, *appinfo);
2070 return accessOK;
2071 }
2072
getDocumentElement(NodePtr & ptr) const2073 AccessResult SgmlDocumentNode::getDocumentElement(NodePtr &ptr) const
2074 {
2075 while (chunk()->documentElement == 0) {
2076 if (grove()->complete()) {
2077 // Just in case another thread crept
2078 if (chunk()->documentElement)
2079 break;
2080 return accessNull;
2081 }
2082 if (!grove()->waitForMoreNodes())
2083 return accessTimeout;
2084 }
2085 return chunk()->documentElement->setNodePtrFirst(ptr, this);
2086 }
2087
getProlog(NodeListPtr & ptr) const2088 AccessResult SgmlDocumentNode::getProlog(NodeListPtr &ptr) const
2089 {
2090 while (chunk()->prolog == 0) {
2091 if (chunk()->documentElement || grove()->complete())
2092 break;
2093 if (!grove()->waitForMoreNodes())
2094 return accessTimeout;
2095 }
2096 if (chunk()->prolog == 0)
2097 ptr.assign(new BaseNodeList);
2098 else {
2099 NodePtr tem;
2100 chunk()->prolog->setNodePtrFirst(tem, this);
2101 ptr.assign(new SiblingNodeList(tem));
2102 }
2103 return accessOK;
2104 }
2105
getEpilog(NodeListPtr & ptr) const2106 AccessResult SgmlDocumentNode::getEpilog(NodeListPtr &ptr) const
2107 {
2108 while (chunk()->epilog == 0) {
2109 if (grove()->complete())
2110 break;
2111 if (!grove()->waitForMoreNodes())
2112 return accessTimeout;
2113 }
2114 if (chunk()->epilog == 0)
2115 ptr.assign(new BaseNodeList);
2116 else {
2117 NodePtr tem;
2118 chunk()->epilog->setNodePtrFirst(tem, this);
2119 ptr.assign(new SiblingNodeList(tem));
2120 }
2121 return accessOK;
2122 }
2123
getElements(NamedNodeListPtr & ptr) const2124 AccessResult SgmlDocumentNode::getElements(NamedNodeListPtr &ptr) const
2125 {
2126 while (!grove()->root()->documentElement) {
2127 if (grove()->complete()) {
2128 if (grove()->root()->documentElement)
2129 break;
2130 return accessNull;
2131 }
2132 if (!grove()->waitForMoreNodes())
2133 return accessTimeout;
2134 }
2135 if (!grove()->generalSubstTable())
2136 return accessNull;
2137 ptr.assign(new ElementsNamedNodeList(grove()));
2138 return accessOK;
2139 }
2140
getEntities(NamedNodeListPtr & ptr) const2141 AccessResult SgmlDocumentNode::getEntities(NamedNodeListPtr &ptr) const
2142 {
2143 while (!grove()->governingDtd()) {
2144 if (grove()->complete()) {
2145 if (grove()->governingDtd())
2146 break;
2147 return accessNull;
2148 }
2149 if (!grove()->waitForMoreNodes())
2150 return accessTimeout;
2151 }
2152 ptr.assign(new DocEntitiesNamedNodeList(grove()));
2153 return accessOK;
2154 }
2155
getDefaultedEntities(NamedNodeListPtr & ptr) const2156 AccessResult SgmlDocumentNode::getDefaultedEntities(NamedNodeListPtr &ptr) const
2157 {
2158 while (!grove()->complete())
2159 if (!grove()->waitForMoreNodes())
2160 return accessTimeout;
2161 ptr.assign(new DefaultedEntitiesNamedNodeList(grove()));
2162 return accessOK;
2163 }
2164
getGoverningDoctype(NodePtr & ptr) const2165 AccessResult SgmlDocumentNode::getGoverningDoctype(NodePtr &ptr) const
2166 {
2167 while (!grove()->governingDtd()) {
2168 if (grove()->complete()) {
2169 if (grove()->governingDtd())
2170 break;
2171 return accessNull;
2172 }
2173 if (!grove()->waitForMoreNodes())
2174 return accessTimeout;
2175 }
2176 ptr.assign(new DocumentTypeNode(grove(), grove()->governingDtd()));
2177 return accessOK;
2178 }
2179
getDoctypesAndLinktypes(NamedNodeListPtr & ptr) const2180 AccessResult SgmlDocumentNode::getDoctypesAndLinktypes(NamedNodeListPtr &ptr) const
2181 {
2182 while (!grove()->governingDtd()) {
2183 if (grove()->complete()) {
2184 if (grove()->governingDtd())
2185 break;
2186 return accessNull;
2187 }
2188 if (!grove()->waitForMoreNodes())
2189 return accessTimeout;
2190 }
2191 ptr.assign(new DoctypesAndLinktypesNamedNodeList(grove()));
2192 return accessOK;
2193 }
2194
getMessages(NodeListPtr & ptr) const2195 AccessResult SgmlDocumentNode::getMessages(NodeListPtr &ptr) const
2196 {
2197 while (grove()->messageList() == 0) {
2198 if (grove()->complete())
2199 break;
2200 if (!grove()->waitForMoreNodes())
2201 return accessTimeout;
2202 }
2203 if (grove()->messageList()) {
2204 NodePtr tem(new MessageNode(grove(), grove()->messageList()));
2205 ptr.assign(new SiblingNodeList(tem));
2206 }
2207 else
2208 ptr.assign(new BaseNodeList);
2209 return accessOK;
2210 }
2211
getSd(ConstPtr<Sd> & sd,ConstPtr<Syntax> & prologSyntax,ConstPtr<Syntax> & instanceSyntax) const2212 AccessResult SgmlDocumentNode::getSd(ConstPtr<Sd> &sd,
2213 ConstPtr<Syntax> &prologSyntax,
2214 ConstPtr<Syntax> &instanceSyntax) const
2215 {
2216 while (!grove()->complete()) {
2217 if (!grove()->waitForMoreNodes())
2218 return accessTimeout;
2219 }
2220 grove()->getSd(sd, prologSyntax, instanceSyntax);
2221 if (!sd.isNull() && !prologSyntax.isNull() && !instanceSyntax.isNull())
2222 return accessOK;
2223 return accessNull;
2224 }
2225
2226 AccessResult
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2227 SgmlDocumentChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const
2228 {
2229 ptr.assign(new SgmlDocumentNode(node->grove(), this));
2230 return accessOK;
2231 }
2232
DocumentTypeNode(const GroveImpl * grove,const Dtd * dtd)2233 DocumentTypeNode::DocumentTypeNode(const GroveImpl *grove, const Dtd *dtd)
2234 : BaseNode(grove), dtd_(dtd)
2235 {
2236 }
2237
nextChunkSibling(NodePtr &) const2238 AccessResult DocumentTypeNode::nextChunkSibling(NodePtr &) const
2239 {
2240 return accessNull;
2241 }
2242
getName(GroveString & str) const2243 AccessResult DocumentTypeNode::getName(GroveString &str) const
2244 {
2245 setString(str, dtd_->name());
2246 return accessOK;
2247 }
2248
getGoverning(bool & governing) const2249 AccessResult DocumentTypeNode::getGoverning(bool &governing) const
2250 {
2251 governing = dtd_->isBase();
2252 return accessOK;
2253 }
2254
getGeneralEntities(NamedNodeListPtr & ptr) const2255 AccessResult DocumentTypeNode::getGeneralEntities(NamedNodeListPtr &ptr) const
2256 {
2257 ptr.assign(new GeneralEntitiesNamedNodeList(grove(), dtd_));
2258 return accessOK;
2259 }
2260
getNotations(NamedNodeListPtr & ptr) const2261 AccessResult DocumentTypeNode::getNotations(NamedNodeListPtr &ptr) const
2262 {
2263 ptr.assign(new NotationsNamedNodeList(grove(), dtd_));
2264 return accessOK;
2265 }
2266
getOrigin(NodePtr & ptr) const2267 AccessResult DocumentTypeNode::getOrigin(NodePtr &ptr) const
2268 {
2269 ptr.assign(new SgmlDocumentNode(grove(), grove()->root()));
2270 return accessOK;
2271 }
2272
accept(NodeVisitor & visitor)2273 void DocumentTypeNode::accept(NodeVisitor &visitor)
2274 {
2275 visitor.documentType(*this);
2276 }
2277
same(const BaseNode & node) const2278 bool DocumentTypeNode::same(const BaseNode &node) const
2279 {
2280 return node.same2(this);
2281 }
2282
same2(const DocumentTypeNode * node) const2283 bool DocumentTypeNode::same2(const DocumentTypeNode *node) const
2284 {
2285 return dtd_ == node->dtd_;
2286 }
2287
SgmlConstantsNode(const GroveImpl * grove)2288 SgmlConstantsNode::SgmlConstantsNode(const GroveImpl *grove)
2289 : BaseNode(grove)
2290 {
2291 }
2292
getOrigin(NodePtr & ptr) const2293 AccessResult SgmlConstantsNode::getOrigin(NodePtr &ptr) const
2294 {
2295 ptr.assign(new SgmlDocumentNode(grove(), grove()->root()));
2296 return accessOK;
2297 }
2298
accept(NodeVisitor & visitor)2299 void SgmlConstantsNode::accept(NodeVisitor &visitor)
2300 {
2301 visitor.sgmlConstants(*this);
2302 }
2303
same(const BaseNode & node) const2304 bool SgmlConstantsNode::same(const BaseNode &node) const
2305 {
2306 return node.same2(this);
2307 }
2308
same2(const SgmlConstantsNode *) const2309 bool SgmlConstantsNode::same2(const SgmlConstantsNode *) const
2310 {
2311 return 1;
2312 }
2313
MessageNode(const GroveImpl * grove,const MessageItem * item)2314 MessageNode::MessageNode(const GroveImpl *grove, const MessageItem *item)
2315 : BaseNode(grove), item_(item)
2316 {
2317 }
2318
getOrigin(NodePtr & ptr) const2319 AccessResult MessageNode::getOrigin(NodePtr &ptr) const
2320 {
2321 ptr.assign(new SgmlDocumentNode(grove(), grove()->root()));
2322 return accessOK;
2323 }
2324
nextChunkSibling(NodePtr & ptr) const2325 AccessResult MessageNode::nextChunkSibling(NodePtr &ptr) const
2326 {
2327 while (!item_->next()) {
2328 if (grove()->complete()) {
2329 if (item_->next())
2330 break;
2331 return accessNull;
2332 }
2333 if (!grove()->waitForMoreNodes())
2334 return accessTimeout;
2335 }
2336 const MessageItem *p = item_->next();
2337 if (!p)
2338 return accessNull;
2339 ptr.assign(new MessageNode(grove(), p));
2340 return accessOK;
2341 }
2342
firstSibling(NodePtr & ptr) const2343 AccessResult MessageNode::firstSibling(NodePtr &ptr) const
2344 {
2345 ptr.assign(new MessageNode(grove(), grove()->messageList()));
2346 return accessOK;
2347 }
2348
siblingsIndex(unsigned long & n) const2349 AccessResult MessageNode::siblingsIndex(unsigned long &n) const
2350 {
2351 n = 0;
2352 for (const MessageItem *p = grove()->messageList(); p != item_; p = p->next())
2353 n++;
2354 return accessOK;
2355 }
2356
accept(NodeVisitor & visitor)2357 void MessageNode::accept(NodeVisitor &visitor)
2358 {
2359 visitor.message(*this);
2360 }
2361
same(const BaseNode & node) const2362 bool MessageNode::same(const BaseNode &node) const
2363 {
2364 return node.same2(this);
2365 }
2366
same2(const MessageNode * node) const2367 bool MessageNode::same2(const MessageNode *node) const
2368 {
2369 return item_ == node->item_;
2370 }
2371
getLocation(Location & loc) const2372 AccessResult MessageNode::getLocation(Location &loc) const
2373 {
2374 return grove()->proxifyLocation(item_->loc(), loc);
2375 }
2376
getText(GroveString & str) const2377 AccessResult MessageNode::getText(GroveString &str) const
2378 {
2379 setString(str, item_->text());
2380 return accessOK;
2381 }
2382
getSeverity(Severity & severity) const2383 AccessResult MessageNode::getSeverity(Severity &severity) const
2384 {
2385 severity = item_->severity();
2386 return accessOK;
2387 }
2388
nextChunkSibling(NodePtr & ptr) const2389 AccessResult ElementNode::nextChunkSibling(NodePtr &ptr) const
2390 {
2391 while (!chunk()->nextSibling) {
2392 if (!grove()->maybeMoreSiblings(chunk())) {
2393 // Allow for the possibility of invalid documents with elements in the epilog.
2394 if ((const Chunk *)chunk() == grove()->root()->documentElement)
2395 return accessNotInClass;
2396 else
2397 return accessNull;
2398 }
2399 if (!grove()->waitForMoreNodes())
2400 return accessTimeout;
2401 }
2402 return chunk()->nextSibling->setNodePtrFirst(ptr, this);
2403 }
2404
2405 // This is a duplicate of ChunkNode::nextChunkAfter
2406 // to take advantage of overloaded setNodePtrFirst.
2407
nextChunkAfter(NodePtr & nd) const2408 AccessResult ElementNode::nextChunkAfter(NodePtr &nd) const
2409 {
2410 const Chunk *p = chunk_->after();
2411 while (p == grove()->completeLimit())
2412 if (!grove()->waitForMoreNodes())
2413 return accessTimeout;
2414 return p->setNodePtrFirst(nd, this);
2415 }
2416
getFollowing(const GroveImpl * grove,const Chunk * & f,unsigned long & n) const2417 AccessResult ElementChunk::getFollowing(const GroveImpl *grove,
2418 const Chunk *&f,
2419 unsigned long &n) const
2420 {
2421 while (!nextSibling) {
2422 if (!grove->maybeMoreSiblings(this)) {
2423 if ((const Chunk *)origin == grove->root())
2424 return accessNotInClass;
2425 else
2426 return accessNull;
2427 }
2428 if (!grove->waitForMoreNodes())
2429 return accessTimeout;
2430 }
2431 f = nextSibling;
2432 n = 1;
2433 return accessOK;
2434 }
2435
firstChild(NodePtr & ptr) const2436 AccessResult ElementNode::firstChild(NodePtr &ptr) const
2437 {
2438 const Chunk *p = chunk()->after();
2439 while (p == grove()->completeLimit()) {
2440 if (!grove()->waitForMoreNodes())
2441 return accessTimeout;
2442 }
2443 if ((const Chunk *)(p->origin) == chunk())
2444 return p->setNodePtrFirst(ptr, this);
2445 return accessNull;
2446 }
2447
attributeRef(unsigned long n,NodePtr & ptr) const2448 AccessResult ElementNode::attributeRef(unsigned long n, NodePtr &ptr) const
2449 {
2450 const AttributeDefinitionList *defList = chunk()->attDefList();
2451 if (!defList || n >= defList->size())
2452 return accessNull;
2453 ptr.assign(new ElementAttributeAsgnNode(grove(), size_t(n), chunk()));
2454 return accessOK;
2455 }
2456
getAttributes(NamedNodeListPtr & ptr) const2457 AccessResult ElementNode::getAttributes(NamedNodeListPtr &ptr) const
2458 {
2459 ptr.assign(new ElementAttributesNamedNodeList(grove(), chunk()));
2460 return accessOK;
2461 }
2462
getGi(GroveString & str) const2463 AccessResult ElementNode::getGi(GroveString &str) const
2464 {
2465 setString(str, chunk()->type->name());
2466 return accessOK;
2467 }
2468
hasGi(GroveString str) const2469 bool ElementNode::hasGi(GroveString str) const
2470 {
2471 const StringC &gi = chunk()->type->name();
2472 size_t len = gi.size();
2473 if (len != str.size())
2474 return 0;
2475 const SubstTable<Char> *subst = grove()->generalSubstTable();
2476 if (!subst)
2477 return 0;
2478 for (size_t i = 0; i < len; i++)
2479 if ((*subst)[str[i]] != gi[i])
2480 return 0;
2481 return 1;
2482 }
2483
getId(GroveString & str) const2484 AccessResult ElementNode::getId(GroveString &str) const
2485 {
2486 const StringC *id = chunk()->id();
2487 if (!id)
2488 return accessNull;
2489 setString(str, *id);
2490 return accessOK;
2491 }
2492
elementIndex(unsigned long & i) const2493 AccessResult ElementNode::elementIndex(unsigned long &i) const
2494 {
2495 i = chunk()->elementIndex;
2496 return accessOK;
2497 }
2498
getContent(NodeListPtr & ptr) const2499 AccessResult ElementNode::getContent(NodeListPtr &ptr) const
2500 {
2501 return children(ptr);
2502 }
2503
getMustOmitEndTag(bool & b) const2504 AccessResult ElementNode::getMustOmitEndTag(bool &b) const
2505 {
2506 b = chunk()->mustOmitEndTag();
2507 return accessOK;
2508 }
2509
getIncluded(bool & b) const2510 AccessResult ElementNode::getIncluded(bool &b) const
2511 {
2512 b = chunk()->included();
2513 return accessOK;
2514 }
2515
accept(NodeVisitor & visitor)2516 void ElementNode::accept(NodeVisitor &visitor)
2517 {
2518 visitor.element(*this);
2519 }
2520
2521 ElementChunk *
makeAttElementChunk(GroveImpl & grove,const StartElementEvent & event,Boolean & hasId)2522 ElementNode::makeAttElementChunk(GroveImpl &grove,
2523 const StartElementEvent &event,
2524 Boolean &hasId)
2525 {
2526 const AttributeList &atts = event.attributes();
2527 size_t nAtts = atts.size();
2528 while (nAtts > 0 && !atts.specified(nAtts - 1) && !atts.current(nAtts - 1))
2529 nAtts--;
2530 ElementChunk *chunk;
2531 void *mem
2532 = grove.allocChunk(sizeof(AttElementChunk) + nAtts * sizeof(AttributeValue *));
2533 if (event.included()) {
2534 // Workaround VC++ 4.1 bug.
2535 AttElementChunk *tem = new (mem) IncludedAttElementChunk(nAtts);
2536 chunk = tem;
2537 }
2538 else
2539 chunk = new (mem) AttElementChunk(nAtts);
2540 const AttributeValue **values
2541 = (const AttributeValue **)(((AttElementChunk *)chunk) + 1);
2542 const AttributeDefinitionList *defList
2543 = event.elementType()->attributeDef().pointer();
2544 unsigned idIndex;
2545 if (atts.idIndex(idIndex) && atts.specified(idIndex) && atts.value(idIndex))
2546 hasId = 1;
2547 else
2548 hasId = 0;
2549 for (size_t i = 0; i < nAtts; i++) {
2550 if (atts.specified(i) || atts.current(i)) {
2551 grove.storeAttributeValue(atts.valuePointer(i));
2552 values[i] = atts.value(i);
2553 }
2554 else {
2555 // If we stored a reference to the implied attribute value in the
2556 // Dtd then it would be safe just to use atts.value(i) here.
2557 // But that would mean we couldn't conveniently tell whether it
2558 // was specified or implied.
2559 values[i] = defList->def(i)->defaultValue(grove.impliedAttributeValue());
2560 }
2561 }
2562 return chunk;
2563 }
2564
after() const2565 const Chunk *AttElementChunk::after() const
2566 {
2567 return (const Chunk *)((char *)(this + 1)
2568 + (sizeof(const AttributeValue *) * nAtts));
2569 }
2570
2571 const AttributeValue *
attributeValue(size_t attIndex,const GroveImpl & grove) const2572 AttElementChunk::attributeValue(size_t attIndex, const GroveImpl &grove)
2573 const
2574 {
2575 if (attIndex < nAtts)
2576 return ((const AttributeValue **)(this + 1))[attIndex];
2577 else
2578 return ElementChunk::attributeValue(attIndex, grove);
2579 }
2580
id() const2581 const StringC *AttElementChunk::id() const
2582 {
2583 size_t i = ElementChunk::attDefList()->idIndex();
2584 if (i == size_t(-1) || i >= nAtts)
2585 return 0;
2586 const AttributeValue *av = ((const AttributeValue **)(this + 1))[i];
2587 if (!av)
2588 return 0;
2589 const Text *t = av->text();
2590 if (!t)
2591 return 0;
2592 return &t->string();
2593 }
2594
mustOmitEndTag() const2595 Boolean AttElementChunk::mustOmitEndTag() const
2596 {
2597 if (ElementChunk::mustOmitEndTag())
2598 return 1;
2599 const AttributeDefinitionList *adl = ElementChunk::attDefList();
2600 size_t nAtts = adl->size();
2601 const AttributeValue **atts = (const AttributeValue **)(this + 1);
2602 for (size_t i = 0; i < nAtts; i++)
2603 if (adl->def(i)->isConref() && atts[i] && atts[i]->text())
2604 return 1;
2605 return 0;
2606 }
2607
after() const2608 const Chunk *ElementChunk::after() const
2609 {
2610 return this + 1;
2611 }
2612
2613 const AttributeValue *
attributeValue(size_t attIndex,const GroveImpl & grove) const2614 ElementChunk::attributeValue(size_t attIndex, const GroveImpl &grove) const
2615 {
2616 return attDefList()->def(attIndex)->defaultValue(grove.impliedAttributeValue());
2617 }
2618
mustOmitEndTag() const2619 Boolean ElementChunk::mustOmitEndTag() const
2620 {
2621 return type->definition()->declaredContent() == ElementDefinition::empty;
2622 }
2623
included() const2624 Boolean IncludedElementChunk::included() const
2625 {
2626 return 1;
2627 }
2628
included() const2629 Boolean IncludedAttElementChunk::included() const
2630 {
2631 return 1;
2632 }
2633
included() const2634 Boolean ElementChunk::included() const
2635 {
2636 return 0;
2637 }
2638
2639 AccessResult
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2640 ElementChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const
2641 {
2642 ptr.assign(new ElementNode(node->grove(), this));
2643 return accessOK;
2644 }
2645
2646 AccessResult
setNodePtrFirst(NodePtr & ptr,const ElementNode * node) const2647 ElementChunk::setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const
2648 {
2649 if (node->canReuse(ptr))
2650 ((ElementNode *)node)->reuseFor(this);
2651 else
2652 ptr.assign(new ElementNode(node->grove(), this));
2653 return accessOK;
2654 }
2655
2656 AccessResult
setNodePtrFirst(NodePtr & ptr,const DataNode * node) const2657 ElementChunk::setNodePtrFirst(NodePtr &ptr, const DataNode *node) const
2658 {
2659 ptr.assign(new ElementNode(node->grove(), this));
2660 return accessOK;
2661 }
2662
ElementAttributeOrigin(const ElementChunk * chunk)2663 ElementAttributeOrigin::ElementAttributeOrigin(const ElementChunk *chunk)
2664 : chunk_(chunk)
2665 {
2666 }
2667
attDefList() const2668 const AttributeDefinitionList *ElementAttributeOrigin::attDefList() const
2669 {
2670 return chunk_->attDefList();
2671 }
2672
2673
2674 const AttributeValue *
attributeValue(size_t attIndex,const GroveImpl & grove) const2675 ElementAttributeOrigin::attributeValue(size_t attIndex, const GroveImpl &grove) const
2676 {
2677 return chunk_->attributeValue(attIndex, grove);
2678 }
2679
2680
2681 AccessResult
setNodePtrAttributeOrigin(NodePtr & ptr,const BaseNode * node) const2682 ElementAttributeOrigin::setNodePtrAttributeOrigin(NodePtr &ptr,
2683 const BaseNode *node) const
2684 {
2685 return chunk_->setNodePtrFirst(ptr, node);
2686 }
2687
2688
2689 Node *ElementAttributeOrigin
makeCdataAttributeValueNode(const GroveImpl * grove,const AttributeValue * value,size_t attIndex,const TextIter & iter,size_t charIndex) const2690 ::makeCdataAttributeValueNode(const GroveImpl *grove,
2691 const AttributeValue *value,
2692 size_t attIndex,
2693 const TextIter &iter,
2694 size_t charIndex) const
2695 {
2696 return new ElementCdataAttributeValueNode(grove, value, attIndex, iter,
2697 charIndex, chunk_);
2698 }
2699
2700
2701 Node *ElementAttributeOrigin
makeAttributeValueTokenNode(const GroveImpl * grove,const TokenizedAttributeValue * value,size_t attIndex,size_t tokenIndex) const2702 ::makeAttributeValueTokenNode(const GroveImpl *grove,
2703 const TokenizedAttributeValue *value,
2704 size_t attIndex,
2705 size_t tokenIndex) const
2706 {
2707 return new ElementAttributeValueTokenNode(grove, value, attIndex,
2708 tokenIndex, chunk_);
2709 }
2710
2711 Node *ElementAttributeOrigin
makeAttributeAsgnNode(const GroveImpl * grove,size_t attIndex) const2712 ::makeAttributeAsgnNode(const GroveImpl *grove,
2713 size_t attIndex) const
2714 {
2715 return new ElementAttributeAsgnNode(grove, attIndex, chunk_);
2716 }
2717
attributeOriginId() const2718 const void *ElementAttributeOrigin::attributeOriginId() const
2719 {
2720 return chunk_;
2721 }
2722
same(const BaseNode & node) const2723 bool DataNode::same(const BaseNode &node) const
2724 {
2725 return node.same2(this);
2726 }
2727
same2(const DataNode * node) const2728 bool DataNode::same2(const DataNode *node) const
2729 {
2730 return chunk_ == node->chunk_ && index_ == node->index_;
2731 }
2732
chunkContains(const Node & node) const2733 bool DataNode::chunkContains(const Node &node) const
2734 {
2735 if (!sameGrove(node))
2736 return 0;
2737 return ((const BaseNode &)node).inChunk(this);
2738 }
2739
inChunk(const DataNode * node) const2740 bool DataNode::inChunk(const DataNode *node) const
2741 {
2742 return chunk_ == node->chunk_ && index_ >= node->index_;
2743 }
2744
charChunk(const SdataMapper &,GroveString & str) const2745 AccessResult DataNode::charChunk(const SdataMapper &, GroveString &str) const
2746 {
2747 str.assign(chunk()->data() + index_, chunk()->size - index_);
2748 return accessOK;
2749 }
2750
accept(NodeVisitor & visitor)2751 void DataNode::accept(NodeVisitor &visitor)
2752 {
2753 visitor.dataChar(*this);
2754 }
2755
hash() const2756 unsigned long DataNode::hash() const
2757 {
2758 return secondHash(ChunkNode::hash() + index_);
2759 }
2760
getNonSgml(unsigned long &) const2761 AccessResult DataNode::getNonSgml(unsigned long &) const
2762 {
2763 return accessNull;
2764 }
2765
nextSibling(NodePtr & ptr) const2766 AccessResult DataNode::nextSibling(NodePtr &ptr) const
2767 {
2768 if (index_ + 1 < chunk()->size) {
2769 if (canReuse(ptr))
2770 ((DataNode *)this)->index_ += 1;
2771 else
2772 ptr.assign(new DataNode(grove(), chunk(), index_ + 1));
2773 return accessOK;
2774 }
2775 return DataNode::nextChunkSibling(ptr);
2776 }
2777
nextChunkAfter(NodePtr & nd) const2778 AccessResult DataNode::nextChunkAfter(NodePtr &nd) const
2779 {
2780 const Chunk *p = chunk_->after();
2781 while (p == grove()->completeLimit())
2782 if (!grove()->waitForMoreNodes())
2783 return accessTimeout;
2784 return p->setNodePtrFirst(nd, this);
2785 }
2786
followSiblingRef(unsigned long i,NodePtr & ptr) const2787 AccessResult DataNode::followSiblingRef(unsigned long i, NodePtr &ptr) const
2788 {
2789 if (i < chunk()->size - index_ - 1) {
2790 if (canReuse(ptr))
2791 ((DataNode *)this)->index_ += 1 + size_t(i);
2792 else
2793 ptr.assign(new DataNode(grove(), chunk(), index_ + size_t(i) + 1));
2794 return accessOK;
2795 }
2796 return ChunkNode::followSiblingRef(i - (chunk()->size - index_ - 1), ptr);
2797 }
2798
siblingsIndex(unsigned long & i) const2799 AccessResult DataNode::siblingsIndex(unsigned long &i) const
2800 {
2801 AccessResult ret = ChunkNode::siblingsIndex(i);
2802 if (ret == accessOK)
2803 i += index_;
2804 return ret;
2805 }
2806
getLocation(Location & loc) const2807 AccessResult DataNode::getLocation(Location &loc) const
2808 {
2809 AccessResult ret = ChunkNode::getLocation(loc);
2810 if (ret == accessOK)
2811 loc += index_;
2812 return ret;
2813 }
2814
getFollowing(const GroveImpl * grove,const Chunk * & f,unsigned long & i) const2815 AccessResult DataChunk::getFollowing(const GroveImpl *grove,
2816 const Chunk *&f,
2817 unsigned long &i) const
2818 {
2819 // We could call Chunk::getFollowing to do most of
2820 // the work, but that would cost us a couple of extra
2821 // virtual function calls.
2822 const Chunk *p = CharsChunk::after();
2823 while (p == grove->completeLimit())
2824 if (!grove->waitForMoreNodes())
2825 return accessTimeout;
2826 if (p->origin != origin)
2827 return accessNull;
2828 i = size;
2829 f = p;
2830 return accessOK;
2831 }
2832
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2833 AccessResult DataChunk::setNodePtrFirst(NodePtr &ptr,
2834 const BaseNode *node) const
2835 {
2836 ptr.assign(new DataNode(node->grove(), this, 0));
2837 return accessOK;
2838 }
2839
2840 // This just saves us a virtual function call in a common case
setNodePtrFirst(NodePtr & ptr,const ElementNode * node) const2841 AccessResult DataChunk::setNodePtrFirst(NodePtr &ptr,
2842 const ElementNode *node) const
2843 {
2844 ptr.assign(new DataNode(node->grove(), this, 0));
2845 return accessOK;
2846 }
2847
setNodePtrFirst(NodePtr & ptr,const DataNode * node) const2848 AccessResult DataChunk::setNodePtrFirst(NodePtr &ptr, const DataNode *node)
2849 const
2850 {
2851 if (node->canReuse(ptr))
2852 ((DataNode *)node)->reuseFor(this, 0);
2853 else
2854 ptr.assign(new DataNode(node->grove(), this, 0));
2855 return accessOK;
2856 }
2857
getSystemData(GroveString & str) const2858 AccessResult PiNode::getSystemData(GroveString &str) const
2859 {
2860 str.assign(chunk()->data(), chunk()->size);
2861 return accessOK;
2862 }
2863
add(GroveImpl & grove,const PiEvent & event)2864 void PiNode::add(GroveImpl &grove, const PiEvent &event)
2865 {
2866 const Entity *entity = event.entity();
2867 if (entity)
2868 PiEntityNode::add(grove, entity, event.location());
2869 else {
2870 grove.setLocOrigin(event.location().origin());
2871 size_t dataLen = event.dataLength();
2872 void *mem = grove.allocChunk(CharsChunk::allocSize(dataLen));
2873 PiChunk *chunk;
2874 if (grove.haveRootOrigin()) {
2875 if (grove.root()->documentElement)
2876 chunk = new (mem) EpilogPiChunk;
2877 else
2878 chunk = new (mem) PrologPiChunk;
2879 }
2880 else
2881 chunk = new (mem) PiChunk;
2882 chunk->size = dataLen;
2883 chunk->locIndex = event.location().index();
2884 memcpy(chunk + 1, event.data(), dataLen * sizeof(Char));
2885 grove.appendSibling(chunk);
2886 }
2887 }
2888
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2889 AccessResult PiChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const
2890 {
2891 ptr.assign(new PiNode(node->grove(), this));
2892 return accessOK;
2893 }
2894
getFirstSibling(const GroveImpl * grove,const::Chunk * & p) const2895 AccessResult PrologPiChunk::getFirstSibling(const GroveImpl *grove, const ::Chunk *&p) const
2896 {
2897 p = grove->root()->prolog;
2898 return accessOK;
2899 }
2900
getFirstSibling(const GroveImpl * grove,const::Chunk * & p) const2901 AccessResult EpilogPiChunk::getFirstSibling(const GroveImpl *grove, const ::Chunk *&p) const
2902 {
2903 p = grove->root()->epilog;
2904 return accessOK;
2905 }
2906
charChunk(const SdataMapper & mapper,GroveString & str) const2907 AccessResult SdataNode::charChunk(const SdataMapper &mapper, GroveString &str) const
2908 {
2909 const StringC &name = chunk()->entity->name();
2910 const StringC &text = chunk()->entity->asInternalEntity()->string();
2911 Char *cp = (Char *)&c_;
2912 if (mapper.sdataMap(GroveString(name.data(), name.size()), GroveString(text.data(), text.size()), *cp)) {
2913 str.assign(&c_, 1);
2914 return accessOK;
2915 }
2916 else
2917 return accessNull;
2918 }
2919
getSystemData(GroveString & str) const2920 AccessResult SdataNode::getSystemData(GroveString &str) const
2921 {
2922 setString(str, chunk()->entity->asInternalEntity()->string());
2923 return accessOK;
2924 }
2925
add(GroveImpl & grove,const SdataEntityEvent & event)2926 void SdataNode::add(GroveImpl &grove, const SdataEntityEvent &event)
2927 {
2928 const Location &loc = event.location().origin()->parent();
2929 grove.setLocOrigin(loc.origin());
2930 SdataChunk *chunk = new (grove.allocChunk(sizeof(SdataChunk))) SdataChunk;
2931 chunk->entity = event.entity();
2932 chunk->locIndex = loc.index();
2933 grove.appendSibling(chunk);
2934 }
2935
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2936 AccessResult SdataChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node)
2937 const
2938 {
2939 ptr.assign(new SdataNode(node->grove(), this));
2940 return accessOK;
2941 }
2942
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2943 AccessResult NonSgmlChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node)
2944 const
2945 {
2946 ptr.assign(new NonSgmlNode(node->grove(), this));
2947 return accessOK;
2948 }
2949
getNonSgml(unsigned long & n) const2950 AccessResult NonSgmlNode::getNonSgml(unsigned long &n) const
2951 {
2952 n = chunk()->c;
2953 return accessOK;
2954 }
2955
charChunk(const SdataMapper &,GroveString &) const2956 AccessResult NonSgmlNode::charChunk(const SdataMapper &, GroveString &) const
2957 {
2958 return accessNull;
2959 }
2960
add(GroveImpl & grove,const NonSgmlCharEvent & event)2961 void NonSgmlNode::add(GroveImpl &grove, const NonSgmlCharEvent &event)
2962 {
2963 grove.setLocOrigin(event.location().origin());
2964 NonSgmlChunk *chunk = new (grove.allocChunk(sizeof(NonSgmlChunk))) NonSgmlChunk;
2965 chunk->c = event.character();
2966 chunk->locIndex = event.location().index();
2967 grove.appendSibling(chunk);
2968 }
2969
add(GroveImpl & grove,const ExternalDataEntityEvent & event)2970 void ExternalDataNode::add(GroveImpl &grove, const ExternalDataEntityEvent &event)
2971 {
2972 grove.setLocOrigin(event.location().origin());
2973 ExternalDataChunk *chunk = new (grove.allocChunk(sizeof(ExternalDataChunk))) ExternalDataChunk;
2974 chunk->entity = event.entity();
2975 chunk->locIndex = event.location().index();
2976 grove.appendSibling(chunk);
2977 }
2978
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2979 AccessResult ExternalDataChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node)
2980 const
2981 {
2982 ptr.assign(new ExternalDataNode(node->grove(), this));
2983 return accessOK;
2984 }
2985
add(GroveImpl & grove,const SubdocEntityEvent & event)2986 void SubdocNode::add(GroveImpl &grove, const SubdocEntityEvent &event)
2987 {
2988 grove.setLocOrigin(event.location().origin());
2989 SubdocChunk *chunk = new (grove.allocChunk(sizeof(SubdocChunk))) SubdocChunk;
2990 chunk->entity = event.entity();
2991 chunk->locIndex = event.location().index();
2992 grove.appendSibling(chunk);
2993 }
2994
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const2995 AccessResult SubdocChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node)
2996 const
2997 {
2998 ptr.assign(new SubdocNode(node->grove(), this));
2999 return accessOK;
3000 }
3001
getSystemData(GroveString & str) const3002 AccessResult PiEntityNode::getSystemData(GroveString &str) const
3003 {
3004 setString(str, chunk()->entity->asInternalEntity()->string());
3005 return accessOK;
3006 }
3007
add(GroveImpl & grove,const Entity * entity,const Location & loc)3008 void PiEntityNode::add(GroveImpl &grove, const Entity *entity,
3009 const Location &loc)
3010 {
3011 // FIXME use parent?
3012 grove.setLocOrigin(loc.origin());
3013 PiEntityChunk *chunk = new (grove.allocChunk(sizeof(PiEntityChunk))) PiEntityChunk;
3014 chunk->entity = entity;
3015 chunk->locIndex = loc.index();
3016 grove.appendSibling(chunk);
3017 }
3018
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const3019 AccessResult PiEntityChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node)
3020 const
3021 {
3022 ptr.assign(new PiEntityNode(node->grove(), this));
3023 return accessOK;
3024 }
3025
getEntity(NodePtr & ptr) const3026 AccessResult EntityRefNode::getEntity(NodePtr &ptr) const
3027 {
3028 ptr.assign(new EntityNode(grove(), chunk()->entity));
3029 return accessOK;
3030 }
3031
getEntityName(GroveString & str) const3032 AccessResult EntityRefNode::getEntityName(GroveString &str) const
3033 {
3034 setString(str, chunk()->entity->name());
3035 return accessOK;
3036 }
3037
AttributeAsgnNode(const GroveImpl * grove,size_t attIndex)3038 AttributeAsgnNode::AttributeAsgnNode(const GroveImpl *grove,
3039 size_t attIndex)
3040 : BaseNode(grove),
3041 attIndex_(attIndex)
3042 {
3043 }
3044
nextChunkSibling(NodePtr & ptr) const3045 AccessResult ChunkNode::nextChunkSibling(NodePtr &ptr) const
3046 {
3047 // The forwarding chunk has origin = 0, so it will stop
3048 // the iteration before after() can return 0.
3049 const Chunk *p = chunk_->after();
3050 while (p == grove()->completeLimit())
3051 if (!grove()->waitForMoreNodes())
3052 return accessTimeout;
3053 if (p->origin != chunk_->origin)
3054 return accessNull;
3055 return p->setNodePtrFirst(ptr, this);
3056 }
3057
nextChunkAfter(NodePtr & nd) const3058 AccessResult ChunkNode::nextChunkAfter(NodePtr &nd) const
3059 {
3060 const Chunk *p = chunk_->after();
3061 while (p == grove()->completeLimit())
3062 if (!grove()->waitForMoreNodes())
3063 return accessTimeout;
3064 return p->setNodePtrFirst(nd, this);
3065 }
3066
firstSibling(NodePtr & ptr) const3067 AccessResult ChunkNode::firstSibling(NodePtr &ptr) const
3068 {
3069 const Chunk *first;
3070 AccessResult ret = chunk_->getFirstSibling(grove(), first);
3071 if (ret != accessOK)
3072 return ret;
3073 return first->setNodePtrFirst(ptr, this);
3074 }
3075
siblingsIndex(unsigned long & i) const3076 AccessResult ChunkNode::siblingsIndex(unsigned long &i) const
3077 {
3078 const Chunk *p;
3079 AccessResult ret = chunk_->getFirstSibling(grove(), p);
3080 if (ret != accessOK)
3081 return ret;
3082 i = 0;
3083 while (p != chunk_) {
3084 unsigned long tem;
3085 if (p->getFollowing(grove(), p, tem) != accessOK)
3086 CANNOT_HAPPEN();
3087 i += tem;
3088 }
3089 return accessOK;
3090 }
3091
followSiblingRef(unsigned long i,NodePtr & ptr) const3092 AccessResult ChunkNode::followSiblingRef(unsigned long i, NodePtr &ptr) const
3093 {
3094 const Chunk *p;
3095 unsigned long count;
3096 AccessResult ret = chunk()->getFollowing(grove(), p, count);
3097 if (ret != accessOK)
3098 return ret;
3099 while (i > 0) {
3100 const Chunk *lastP = p;
3101 ret = p->getFollowing(grove(), p, count);
3102 if (ret == accessOK && count <= i)
3103 i -= count;
3104 else if (ret == accessOK || ret == accessNull) {
3105 lastP->setNodePtrFirst(ptr, this);
3106 return ptr->followSiblingRef(i - 1, ptr);
3107 }
3108 else
3109 return ret;
3110 }
3111 return p->setNodePtrFirst(ptr, this);
3112 }
3113
getOrigin(NodePtr & ptr) const3114 AccessResult AttributeAsgnNode::getOrigin(NodePtr &ptr) const
3115 {
3116 return setNodePtrAttributeOrigin(ptr, this);
3117 }
3118
getName(GroveString & str) const3119 AccessResult AttributeAsgnNode::getName(GroveString &str) const
3120 {
3121 setString(str, attDefList()->def(attIndex_)->name());
3122 return accessOK;
3123 }
3124
getImplied(bool & implied) const3125 AccessResult AttributeAsgnNode::getImplied(bool &implied) const
3126 {
3127 const AttributeValue *value = attributeValue(attIndex_, *grove());
3128 implied = (value != 0 && value->text() == 0);
3129 return accessOK;
3130 }
3131
getValue(NodeListPtr & ptr) const3132 AccessResult AttributeAsgnNode::getValue(NodeListPtr &ptr) const
3133 {
3134 return children(ptr);
3135 }
3136
nextChunkSibling(NodePtr & ptr) const3137 AccessResult AttributeAsgnNode::nextChunkSibling(NodePtr &ptr) const
3138 {
3139 return followSiblingRef(0, ptr);
3140 }
3141
followSiblingRef(unsigned long i,NodePtr & ptr) const3142 AccessResult AttributeAsgnNode::followSiblingRef(unsigned long i, NodePtr &ptr) const
3143 {
3144 // Do it like this to avoid overflow.
3145 if (i >= attDefList()->size() - attIndex_ - 1)
3146 return accessNull;
3147 if (canReuse(ptr))
3148 ((AttributeAsgnNode *)this)->attIndex_ += size_t(i) + 1;
3149 else
3150 ptr.assign(makeAttributeAsgnNode(grove(), attIndex_ + 1 + size_t(i)));
3151 return accessOK;
3152 }
3153
firstSibling(NodePtr & ptr) const3154 AccessResult AttributeAsgnNode::firstSibling(NodePtr &ptr) const
3155 {
3156 if (canReuse(ptr))
3157 ((AttributeAsgnNode *)this)->attIndex_ = 0;
3158 else
3159 ptr.assign(makeAttributeAsgnNode(grove(), 0));
3160 return accessOK;
3161 }
3162
siblingsIndex(unsigned long & i) const3163 AccessResult AttributeAsgnNode::siblingsIndex(unsigned long &i) const
3164 {
3165 i = attIndex_;
3166 return accessOK;
3167 }
3168
accept(NodeVisitor & visitor)3169 void AttributeAsgnNode::accept(NodeVisitor &visitor)
3170 {
3171 visitor.attributeAssignment(*this);
3172 }
3173
firstChild(NodePtr & ptr) const3174 AccessResult AttributeAsgnNode::firstChild(NodePtr &ptr) const
3175 {
3176 const AttributeValue *value = attributeValue(attIndex_, *grove());
3177 if (value) {
3178 const Text *text;
3179 const StringC *str;
3180 switch (value->info(text, str)) {
3181 case AttributeValue::tokenized:
3182 ptr.assign(makeAttributeValueTokenNode(grove(),
3183 (const TokenizedAttributeValue *)value,
3184 attIndex_, 0));
3185 return accessOK;
3186 case AttributeValue::cdata:
3187 {
3188 TextIter iter(*text);
3189 if (!CdataAttributeValueNode::skipBoring(iter))
3190 break;
3191 ptr.assign(makeCdataAttributeValueNode(grove(), value,
3192 attIndex_, iter));
3193 return accessOK;
3194 }
3195 default:
3196 break;
3197 }
3198 }
3199 return accessNull;
3200 }
3201
children(NodeListPtr & ptr) const3202 AccessResult AttributeAsgnNode::children(NodeListPtr &ptr) const
3203 {
3204 const AttributeValue *value = attributeValue(attIndex_, *grove());
3205 if (value) {
3206 const Text *text;
3207 const StringC *str;
3208 switch (value->info(text, str)) {
3209 case AttributeValue::tokenized:
3210 ptr.assign(new SiblingNodeList(makeAttributeValueTokenNode(grove(),
3211 (const TokenizedAttributeValue *)value,
3212 attIndex_, 0)));
3213 return accessOK;
3214 case AttributeValue::cdata:
3215 {
3216 TextIter iter(*text);
3217 if (!CdataAttributeValueNode::skipBoring(iter))
3218 ptr.assign(new BaseNodeList);
3219 else
3220 ptr.assign(new SiblingNodeList(makeCdataAttributeValueNode(grove(), value,
3221 attIndex_, iter)));
3222 return accessOK;
3223 }
3224 default:
3225 break;
3226 }
3227 }
3228 return accessNull;
3229 }
3230
getTokenSep(Char & ch) const3231 AccessResult AttributeAsgnNode::getTokenSep(Char &ch) const
3232 {
3233 const AttributeValue *value = attributeValue(attIndex_, *grove());
3234 if (!value)
3235 return accessNull;
3236 const Text *text;
3237 const StringC *str;
3238 if (value->info(text, str) != AttributeValue::tokenized)
3239 return accessNull;
3240 const TokenizedAttributeValue *tValue =
3241 (const TokenizedAttributeValue *)value;
3242 if (tValue->nTokens() <= 1)
3243 return accessNull;
3244 const Char *ptr;
3245 size_t len;
3246 tValue->token(0, ptr, len);
3247 // the character following the token is a space
3248 ch = ptr[len];
3249 return accessOK;
3250 }
3251
tokens(GroveString & s) const3252 AccessResult AttributeAsgnNode::tokens(GroveString &s) const
3253 {
3254 const AttributeValue *value = attributeValue(attIndex_, *grove());
3255 if (!value)
3256 return accessNull;
3257 const Text *text;
3258 const StringC *str;
3259 if (value->info(text, str) != AttributeValue::tokenized)
3260 return accessNull;
3261 setString(s, *str);
3262 return accessOK;
3263 }
3264
same(const BaseNode & node) const3265 bool AttributeAsgnNode::same(const BaseNode &node) const
3266 {
3267 return node.same2(this);
3268 }
3269
same2(const AttributeAsgnNode * node) const3270 bool AttributeAsgnNode::same2(const AttributeAsgnNode *node)
3271 const
3272 {
3273 return (attributeOriginId() == node->attributeOriginId()
3274 && attIndex_ == node->attIndex_);
3275 }
3276
hash() const3277 unsigned long AttributeAsgnNode::hash() const
3278 {
3279 unsigned long n = (unsigned long)attributeOriginId();
3280 return secondHash(n + attIndex_);
3281 }
3282
3283 ElementAttributeAsgnNode
ElementAttributeAsgnNode(const GroveImpl * grove,size_t attIndex,const ElementChunk * chunk)3284 ::ElementAttributeAsgnNode(const GroveImpl *grove, size_t attIndex,
3285 const ElementChunk *chunk)
3286 : AttributeAsgnNode(grove, attIndex), ElementAttributeOrigin(chunk)
3287 {
3288 }
3289
3290 EntityAttributeAsgnNode
EntityAttributeAsgnNode(const GroveImpl * grove,size_t attIndex,const ExternalDataEntity * entity)3291 ::EntityAttributeAsgnNode(const GroveImpl *grove, size_t attIndex,
3292 const ExternalDataEntity *entity)
3293 : AttributeAsgnNode(grove, attIndex), EntityAttributeOrigin(entity)
3294 {
3295 }
3296
3297 CdataAttributeValueNode
CdataAttributeValueNode(const GroveImpl * grove,const AttributeValue * value,size_t attIndex,const TextIter & iter,size_t charIndex)3298 ::CdataAttributeValueNode(const GroveImpl *grove,
3299 const AttributeValue *value,
3300 size_t attIndex,
3301 const TextIter &iter,
3302 size_t charIndex)
3303 : BaseNode(grove),
3304 value_(value),
3305 attIndex_(attIndex),
3306 iter_(iter),
3307 charIndex_(charIndex)
3308 {
3309 }
3310
skipBoring(TextIter & iter)3311 bool CdataAttributeValueNode::skipBoring(TextIter &iter)
3312 {
3313 while (iter.valid()) {
3314 switch (iter.type()) {
3315 case TextItem::data:
3316 case TextItem::cdata:
3317 case TextItem::sdata:
3318 {
3319 size_t length;
3320 iter.chars(length);
3321 if (length > 0)
3322 return 1;
3323 }
3324 // fall through
3325 default:
3326 iter.advance();
3327 break;
3328 }
3329 }
3330 return 0;
3331 }
3332
getParent(NodePtr & ptr) const3333 AccessResult CdataAttributeValueNode::getParent(NodePtr &ptr) const
3334 {
3335 ptr.assign(makeAttributeAsgnNode(grove(), attIndex_));
3336 return accessOK;
3337 }
3338
charChunk(const SdataMapper & mapper,GroveString & str) const3339 AccessResult CdataAttributeValueNode::charChunk(const SdataMapper &mapper, GroveString &str) const
3340 {
3341 if (iter_.type() == TextItem::sdata) {
3342 const Entity *entity = iter_.location().origin()->asEntityOrigin()->entity();
3343 const StringC &name = entity->name();
3344 const StringC &text = entity->asInternalEntity()->string();
3345 Char *cp = (Char *)&c_;
3346 if (mapper.sdataMap(GroveString(name.data(), name.size()), GroveString(text.data(), text.size()), *cp)) {
3347 str.assign(&c_, 1);
3348 return accessOK;
3349 }
3350 else
3351 return accessNull;
3352 }
3353 size_t len;
3354 const Char *s = iter_.chars(len);
3355 str.assign(s + charIndex_, len - charIndex_);
3356 return accessOK;
3357 }
3358
siblingsIndex(unsigned long & n) const3359 AccessResult CdataAttributeValueNode::siblingsIndex(unsigned long &n) const
3360 {
3361 TextIter copy(iter_);
3362 size_t tem;
3363 const Char *iterChars = iter_.chars(tem);
3364 copy.rewind();
3365 skipBoring(copy);
3366 n = 0;
3367 while (copy.chars(tem) != iterChars) {
3368 if (copy.type() == TextItem::sdata)
3369 n += 1;
3370 else
3371 n += tem;
3372 copy.advance();
3373 skipBoring(copy);
3374 }
3375 n += charIndex_;
3376 return accessOK;
3377 }
3378
getEntity(NodePtr & ptr) const3379 AccessResult CdataAttributeValueNode::getEntity(NodePtr &ptr) const
3380 {
3381 if (iter_.type() != TextItem::sdata)
3382 return accessNotInClass;
3383 const Entity *entity
3384 = iter_.location().origin()->asEntityOrigin()->entity();
3385 ptr.assign(new EntityNode(grove(), entity));
3386 return accessOK;
3387 }
3388
getEntityName(GroveString & str) const3389 AccessResult CdataAttributeValueNode::getEntityName(GroveString &str) const
3390 {
3391 if (iter_.type() != TextItem::sdata)
3392 return accessNotInClass;
3393 const Entity *entity
3394 = iter_.location().origin()->asEntityOrigin()->entity();
3395 setString(str, entity->name());
3396 return accessOK;
3397 }
3398
getSystemData(GroveString & str) const3399 AccessResult CdataAttributeValueNode::getSystemData(GroveString &str) const
3400 {
3401 if (iter_.type() != TextItem::sdata)
3402 return accessNotInClass;
3403 size_t len;
3404 const Char *ptr = iter_.chars(len);
3405 str.assign(ptr, len);
3406 return accessOK;
3407 }
3408
firstSibling(NodePtr & ptr) const3409 AccessResult CdataAttributeValueNode::firstSibling(NodePtr &ptr) const
3410 {
3411 TextIter copy(iter_);
3412 copy.rewind();
3413 skipBoring(copy);
3414 if (canReuse(ptr)) {
3415 CdataAttributeValueNode *node = (CdataAttributeValueNode *)this;
3416 node->iter_ = copy;
3417 node->charIndex_ = 0;
3418 }
3419 else
3420 ptr.assign(makeCdataAttributeValueNode(grove(), value_, attIndex_, copy));
3421 return accessOK;
3422 }
3423
nextChunkSibling(NodePtr & ptr) const3424 AccessResult CdataAttributeValueNode::nextChunkSibling(NodePtr &ptr) const
3425 {
3426 TextIter copy(iter_);
3427 copy.advance();
3428 if (!skipBoring(copy))
3429 return accessNull;
3430 if (canReuse(ptr)) {
3431 CdataAttributeValueNode *node = (CdataAttributeValueNode *)this;
3432 node->iter_ = copy;
3433 node->charIndex_ = 0;
3434 }
3435 else
3436 ptr.assign(makeCdataAttributeValueNode(grove(), value_, attIndex_, copy));
3437 return accessOK;
3438 }
3439
nextSibling(NodePtr & ptr) const3440 AccessResult CdataAttributeValueNode::nextSibling(NodePtr &ptr) const
3441 {
3442 if (iter_.type() != TextItem::sdata) {
3443 size_t length;
3444 iter_.chars(length);
3445 if (charIndex_ + 1 < length) {
3446 if (canReuse(ptr))
3447 ((CdataAttributeValueNode *)this)->charIndex_ += 1;
3448 else
3449 ptr.assign(makeCdataAttributeValueNode(grove(), value_,
3450 attIndex_, iter_,
3451 charIndex_ + 1));
3452 return accessOK;
3453 }
3454 }
3455 return CdataAttributeValueNode::nextChunkSibling(ptr);
3456 }
3457
getLocation(Location & loc) const3458 AccessResult CdataAttributeValueNode::getLocation(Location &loc) const
3459 {
3460 if (iter_.type() == TextItem::sdata)
3461 return grove()->proxifyLocation(iter_.location().origin()->parent(), loc);
3462 else
3463 return grove()->proxifyLocation(iter_.location(), loc);
3464 }
3465
accept(NodeVisitor & visitor)3466 void CdataAttributeValueNode::accept(NodeVisitor &visitor)
3467 {
3468 if (iter_.type() == TextItem::sdata)
3469 visitor.sdata(*this);
3470 else
3471 visitor.dataChar(*this);
3472 }
3473
hash() const3474 unsigned long CdataAttributeValueNode::hash() const
3475 {
3476 unsigned long n;
3477 CdataAttributeValueNode::siblingsIndex(n);
3478 return secondHash(secondHash((unsigned long)attributeOriginId() + attIndex_) + n);
3479 }
3480
classDef() const3481 const ClassDef &CdataAttributeValueNode::classDef() const
3482 {
3483 if (iter_.type() == TextItem::sdata)
3484 return ClassDef::sdata;
3485 else
3486 return ClassDef::dataChar;
3487 }
3488
same(const BaseNode & node) const3489 bool CdataAttributeValueNode::same(const BaseNode &node) const
3490 {
3491 return node.same2(this);
3492 }
3493
same2(const CdataAttributeValueNode * node) const3494 bool CdataAttributeValueNode::same2(const CdataAttributeValueNode *node)
3495 const
3496 {
3497 size_t tem;
3498 return (attributeOriginId() == node->attributeOriginId()
3499 && attIndex_ == node->attIndex_
3500 && charIndex_ == node->charIndex_
3501 && iter_.chars(tem) == node->iter_.chars(tem));
3502 }
3503
chunkContains(const Node & node) const3504 bool CdataAttributeValueNode::chunkContains(const Node &node) const
3505 {
3506 if (!sameGrove(node))
3507 return 0;
3508 return ((const BaseNode &)node).inChunk(this);
3509 }
3510
inChunk(const CdataAttributeValueNode * node) const3511 bool CdataAttributeValueNode::inChunk(const CdataAttributeValueNode *node) const
3512 {
3513 size_t tem;
3514 return (attributeOriginId() == node->attributeOriginId()
3515 && attIndex_ == node->attIndex_
3516 && iter_.chars(tem) == node->iter_.chars(tem)
3517 && charIndex_ >= node->charIndex_);
3518 }
3519
3520 ElementCdataAttributeValueNode
ElementCdataAttributeValueNode(const GroveImpl * grove,const AttributeValue * value,size_t attIndex,const TextIter & iter,size_t charIndex,const ElementChunk * chunk)3521 ::ElementCdataAttributeValueNode(const GroveImpl *grove,
3522 const AttributeValue *value,
3523 size_t attIndex,
3524 const TextIter &iter,
3525 size_t charIndex,
3526 const ElementChunk *chunk)
3527 : CdataAttributeValueNode(grove, value, attIndex, iter, charIndex),
3528 ElementAttributeOrigin(chunk)
3529 {
3530 }
3531
3532 EntityCdataAttributeValueNode
EntityCdataAttributeValueNode(const GroveImpl * grove,const AttributeValue * value,size_t attIndex,const TextIter & iter,size_t charIndex,const ExternalDataEntity * entity)3533 ::EntityCdataAttributeValueNode(const GroveImpl *grove,
3534 const AttributeValue *value,
3535 size_t attIndex,
3536 const TextIter &iter,
3537 size_t charIndex,
3538 const ExternalDataEntity *entity)
3539 : CdataAttributeValueNode(grove, value, attIndex, iter, charIndex),
3540 EntityAttributeOrigin(entity)
3541 {
3542 }
3543
3544 AttributeValueTokenNode
AttributeValueTokenNode(const GroveImpl * grove,const TokenizedAttributeValue * value,size_t attIndex,size_t tokenIndex)3545 ::AttributeValueTokenNode(const GroveImpl *grove,
3546 const TokenizedAttributeValue *value,
3547 size_t attIndex, size_t tokenIndex)
3548 : BaseNode(grove),
3549 value_(value),
3550 attIndex_(attIndex),
3551 tokenIndex_(tokenIndex)
3552 {
3553 }
3554
getParent(NodePtr & ptr) const3555 AccessResult AttributeValueTokenNode::getParent(NodePtr &ptr) const
3556 {
3557 ptr.assign(makeAttributeAsgnNode(grove(), attIndex_));
3558 return accessOK;
3559 }
3560
nextChunkSibling(NodePtr & ptr) const3561 AccessResult AttributeValueTokenNode::nextChunkSibling(NodePtr &ptr) const
3562 {
3563 return followSiblingRef(0, ptr);
3564 }
3565
followSiblingRef(unsigned long i,NodePtr & ptr) const3566 AccessResult AttributeValueTokenNode::followSiblingRef(unsigned long i, NodePtr &ptr) const
3567 {
3568 // Do it like this to avoid possibility of overflow
3569 if (i >= value_->nTokens() - tokenIndex_ - 1)
3570 return accessNull;
3571 if (canReuse(ptr)) {
3572 AttributeValueTokenNode *node = (AttributeValueTokenNode *)this;
3573 node->tokenIndex_ += size_t(i) + 1;
3574 }
3575 else
3576 ptr.assign(makeAttributeValueTokenNode(grove(), value_, attIndex_,
3577 tokenIndex_ + size_t(i) + 1));
3578 return accessOK;
3579 }
3580
firstSibling(NodePtr & ptr) const3581 AccessResult AttributeValueTokenNode::firstSibling(NodePtr &ptr) const
3582 {
3583 if (canReuse(ptr))
3584 ((AttributeValueTokenNode *)this)->tokenIndex_ = 0;
3585 else
3586 ptr.assign(makeAttributeValueTokenNode(grove(), value_, attIndex_, 0));
3587 return accessOK;
3588 }
3589
siblingsIndex(unsigned long & i) const3590 AccessResult AttributeValueTokenNode::siblingsIndex(unsigned long &i) const
3591 {
3592 i = tokenIndex_;
3593 return accessOK;
3594 }
3595
getToken(GroveString & str) const3596 AccessResult AttributeValueTokenNode::getToken(GroveString &str) const
3597 {
3598 const Char *ptr;
3599 size_t len;
3600 value_->token(tokenIndex_, ptr, len);
3601 str.assign(ptr, len);
3602 return accessOK;
3603 }
3604
getEntity(NodePtr & ptr) const3605 AccessResult AttributeValueTokenNode::getEntity(NodePtr &ptr) const
3606 {
3607 if (!attDefList()->def(attIndex_)->isEntity())
3608 return accessNull;
3609 StringC token(value_->token(tokenIndex_));
3610 const Entity *entity = grove()->governingDtd()->lookupEntityTemp(0, token);
3611 if (!entity) {
3612 entity = grove()->lookupDefaultedEntity(token);
3613 if (!entity)
3614 return accessNull;
3615 }
3616 ptr.assign(new EntityNode(grove(), entity));
3617 return accessOK;
3618 }
3619
getNotation(NodePtr & ptr) const3620 AccessResult AttributeValueTokenNode::getNotation(NodePtr &ptr) const
3621 {
3622 if (!attDefList()->def(attIndex_)->isNotation())
3623 return accessNull;
3624 StringC token(value_->token(tokenIndex_));
3625 const Notation *notation = grove()->governingDtd()->lookupNotationTemp(token);
3626 if (!notation)
3627 return accessNull;
3628 ptr.assign(new NotationNode(grove(), notation));
3629 return accessOK;
3630 }
3631
getReferent(NodePtr & ptr) const3632 AccessResult AttributeValueTokenNode::getReferent(NodePtr &ptr) const
3633 {
3634 if (!attDefList()->def(attIndex_)->isIdref())
3635 return accessNull;
3636 StringC token(value_->token(tokenIndex_));
3637 for (;;) {
3638 Boolean complete = grove()->complete();
3639 const ElementChunk *element = grove()->lookupElement(token);
3640 if (element) {
3641 ptr.assign(new ElementNode(grove(), element));
3642 break;
3643 }
3644 if (complete)
3645 return accessNull;
3646 if (!grove()->waitForMoreNodes())
3647 return accessTimeout;
3648 }
3649 return accessOK;
3650 }
3651
accept(NodeVisitor & visitor)3652 void AttributeValueTokenNode::accept(NodeVisitor &visitor)
3653 {
3654 visitor.attributeValueToken(*this);
3655 }
3656
hash() const3657 unsigned long AttributeValueTokenNode::hash() const
3658 {
3659 return secondHash(secondHash((unsigned long)attributeOriginId() + attIndex_) + tokenIndex_);
3660 }
3661
same(const BaseNode & node) const3662 bool AttributeValueTokenNode::same(const BaseNode &node) const
3663 {
3664 return node.same2(this);
3665 }
3666
same2(const AttributeValueTokenNode * node) const3667 bool AttributeValueTokenNode::same2(const AttributeValueTokenNode *node) const
3668 {
3669 return (attributeOriginId() == node->attributeOriginId()
3670 && attIndex_ == node->attIndex_
3671 && tokenIndex_ == node->tokenIndex_);
3672 }
3673
getLocation(Location & loc) const3674 AccessResult AttributeValueTokenNode::getLocation(Location &loc) const
3675 {
3676 const ConstPtr<Origin> *originP;
3677 Index index;
3678 if (!value_->tokenLocation(tokenIndex_, originP, index)
3679 && originP->pointer()) {
3680 loc = Location(new GroveImplProxyOrigin(grove(), originP->pointer()), index);
3681 return accessOK;
3682 }
3683 return accessNull;
3684 }
3685
3686 ElementAttributeValueTokenNode
ElementAttributeValueTokenNode(const GroveImpl * grove,const TokenizedAttributeValue * value,size_t attIndex,size_t tokenIndex,const ElementChunk * chunk)3687 ::ElementAttributeValueTokenNode(const GroveImpl *grove,
3688 const TokenizedAttributeValue *value,
3689 size_t attIndex,
3690 size_t tokenIndex,
3691 const ElementChunk *chunk)
3692 : AttributeValueTokenNode(grove, value, attIndex, tokenIndex),
3693 ElementAttributeOrigin(chunk)
3694 {
3695 }
3696
3697 EntityAttributeValueTokenNode
EntityAttributeValueTokenNode(const GroveImpl * grove,const TokenizedAttributeValue * value,size_t attIndex,size_t tokenIndex,const ExternalDataEntity * entity)3698 ::EntityAttributeValueTokenNode(const GroveImpl *grove,
3699 const TokenizedAttributeValue *value,
3700 size_t attIndex,
3701 size_t tokenIndex,
3702 const ExternalDataEntity *entity)
3703 : AttributeValueTokenNode(grove, value, attIndex, tokenIndex),
3704 EntityAttributeOrigin(entity)
3705 {
3706 }
3707
EntityNode(const GroveImpl * grove,const Entity * entity)3708 EntityNode::EntityNode(const GroveImpl *grove, const Entity *entity)
3709 : BaseNode(grove), entity_(entity)
3710 {
3711 }
3712
getOrigin(NodePtr & ptr) const3713 AccessResult EntityNode::getOrigin(NodePtr &ptr) const
3714 {
3715 if (entity_->defaulted() && grove()->lookupDefaultedEntity(entity_->name()))
3716 ptr.assign(new SgmlDocumentNode(grove(), grove()->root()));
3717 else
3718 ptr.assign(new DocumentTypeNode(grove(), grove()->governingDtd()));
3719 return accessOK;
3720 }
3721
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const3722 AccessResult EntityNode::getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const
3723 {
3724 if (entity_->defaulted() && grove()->lookupDefaultedEntity(entity_->name()))
3725 name = ComponentName::idDefaultedEntities;
3726 else
3727 name = ComponentName::idGeneralEntities;
3728 return accessOK;
3729 }
3730
getName(GroveString & str) const3731 AccessResult EntityNode::getName(GroveString &str) const
3732 {
3733 setString(str, entity_->name());
3734 return accessOK;
3735 }
3736
getExternalId(NodePtr & ptr) const3737 AccessResult EntityNode::getExternalId(NodePtr &ptr) const
3738 {
3739 const ExternalEntity *x = entity_->asExternalEntity();
3740 if (!x)
3741 return accessNull;
3742 ptr.assign(new EntityExternalIdNode(grove(), x));
3743 return accessOK;
3744 }
3745
getNotation(NodePtr & ptr) const3746 AccessResult EntityNode::getNotation(NodePtr &ptr) const
3747 {
3748 const ExternalDataEntity *x = entity_->asExternalDataEntity();
3749 if (!x || !x->notation())
3750 return accessNull;
3751 ptr.assign(new NotationNode(grove(), x->notation()));
3752 return accessOK;
3753 }
3754
getNotationName(GroveString & str) const3755 AccessResult EntityNode::getNotationName(GroveString &str) const
3756 {
3757 const ExternalDataEntity *x = entity_->asExternalDataEntity();
3758 if (!x || !x->notation())
3759 return accessNull;
3760 setString(str, x->notation()->name());
3761 return accessOK;
3762 }
3763
getText(GroveString & str) const3764 AccessResult EntityNode::getText(GroveString &str) const
3765 {
3766 const InternalEntity *i = entity_->asInternalEntity();
3767 if (!i)
3768 return accessNull;
3769 setString(str, i->string());
3770 return accessOK;
3771 }
3772
getEntityType(EntityType & entityType) const3773 AccessResult EntityNode::getEntityType(EntityType &entityType) const
3774 {
3775 switch (entity_->dataType()) {
3776 case EntityDecl::sgmlText:
3777 entityType = text;
3778 break;
3779 case EntityDecl::pi:
3780 entityType = pi;
3781 break;
3782 case EntityDecl::cdata:
3783 entityType = cdata;
3784 break;
3785 case EntityDecl::sdata:
3786 entityType = sdata;
3787 break;
3788 case EntityDecl::ndata:
3789 entityType = ndata;
3790 break;
3791 case EntityDecl::subdoc:
3792 entityType = subdocument;
3793 break;
3794 default:
3795 CANNOT_HAPPEN();
3796 }
3797 return accessOK;
3798 }
3799
getDefaulted(bool & dflted) const3800 AccessResult EntityNode::getDefaulted(bool &dflted) const
3801 {
3802 dflted = entity_->defaulted();
3803 return accessOK;
3804 }
3805
getAttributes(NamedNodeListPtr & ptr) const3806 AccessResult EntityNode::getAttributes(NamedNodeListPtr &ptr) const
3807 {
3808 const ExternalDataEntity *x = entity_->asExternalDataEntity();
3809 if (!x)
3810 return accessNull;
3811 ptr.assign(new EntityAttributesNamedNodeList(grove(), x));
3812 return accessOK;
3813 }
3814
attributeRef(unsigned long i,NodePtr & ptr) const3815 AccessResult EntityNode::attributeRef(unsigned long i, NodePtr &ptr) const
3816 {
3817 const ExternalDataEntity *x = entity_->asExternalDataEntity();
3818 if (!x || i >= x->attributes().size())
3819 return accessNull;
3820 ptr.assign(new EntityAttributeAsgnNode(grove(), size_t(i), x));
3821 return accessOK;
3822 }
3823
getLocation(Location & loc) const3824 AccessResult EntityNode::getLocation(Location &loc) const
3825 {
3826 return grove()->proxifyLocation(entity_->defLocation(), loc);
3827 }
3828
same(const BaseNode & node) const3829 bool EntityNode::same(const BaseNode &node) const
3830 {
3831 return node.same2(this);
3832 }
3833
same2(const EntityNode * node) const3834 bool EntityNode::same2(const EntityNode *node) const
3835 {
3836 return entity_ == node->entity_;
3837 }
3838
accept(NodeVisitor & visitor)3839 void EntityNode::accept(NodeVisitor &visitor)
3840 {
3841 visitor.entity(*this);
3842 }
3843
hash() const3844 unsigned long EntityNode::hash() const
3845 {
3846 return (unsigned long)entity_;
3847 }
3848
3849 EntityAttributeOrigin
EntityAttributeOrigin(const ExternalDataEntity * entity)3850 ::EntityAttributeOrigin(const ExternalDataEntity *entity)
3851 : entity_(entity)
3852 {
3853 }
3854
3855 const AttributeDefinitionList *
attDefList() const3856 EntityAttributeOrigin::attDefList() const
3857 {
3858 return entity_->notation()->attributeDefTemp();
3859 }
3860
3861
3862 const AttributeValue *
attributeValue(size_t attIndex,const GroveImpl &) const3863 EntityAttributeOrigin::attributeValue(size_t attIndex, const GroveImpl &) const
3864 {
3865 return entity_->attributes().value(attIndex);
3866 }
3867
3868 AccessResult
setNodePtrAttributeOrigin(NodePtr & ptr,const BaseNode * node) const3869 EntityAttributeOrigin::setNodePtrAttributeOrigin(NodePtr &ptr,
3870 const BaseNode *node) const
3871 {
3872 ptr.assign(new EntityNode(node->grove(), entity_));
3873 return accessOK;
3874 }
3875
3876 Node *EntityAttributeOrigin
makeCdataAttributeValueNode(const GroveImpl * grove,const AttributeValue * value,size_t attIndex,const TextIter & iter,size_t charIndex) const3877 ::makeCdataAttributeValueNode(const GroveImpl *grove,
3878 const AttributeValue *value,
3879 size_t attIndex,
3880 const TextIter &iter,
3881 size_t charIndex) const
3882 {
3883 return new EntityCdataAttributeValueNode(grove, value, attIndex, iter,
3884 charIndex, entity_);
3885 }
3886
3887
3888 Node *EntityAttributeOrigin
makeAttributeValueTokenNode(const GroveImpl * grove,const TokenizedAttributeValue * value,size_t attIndex,size_t tokenIndex) const3889 ::makeAttributeValueTokenNode(const GroveImpl *grove,
3890 const TokenizedAttributeValue *value,
3891 size_t attIndex,
3892 size_t tokenIndex) const
3893 {
3894 return new EntityAttributeValueTokenNode(grove, value, attIndex,
3895 tokenIndex, entity_);
3896 }
3897
3898 Node *EntityAttributeOrigin
makeAttributeAsgnNode(const GroveImpl * grove,size_t attIndex) const3899 ::makeAttributeAsgnNode(const GroveImpl *grove,
3900 size_t attIndex) const
3901 {
3902 return new EntityAttributeAsgnNode(grove, attIndex, entity_);
3903 }
3904
attributeOriginId() const3905 const void *EntityAttributeOrigin::attributeOriginId() const
3906 {
3907 return entity_;
3908 }
3909
3910 DoctypesAndLinktypesNamedNodeList
DoctypesAndLinktypesNamedNodeList(const GroveImpl * grove)3911 ::DoctypesAndLinktypesNamedNodeList(const GroveImpl *grove)
3912 : BaseNamedNodeList(grove, grove->generalSubstTable())
3913 {
3914 }
3915
nodeList() const3916 NodeListPtr DoctypesAndLinktypesNamedNodeList::nodeList() const
3917 {
3918 NodePtr tem(new DocumentTypeNode(grove(), grove()->governingDtd()));
3919 return new SiblingNodeList(tem);
3920 }
3921
3922 AccessResult
3923 DoctypesAndLinktypesNamedNodeList
namedNodeU(const StringC & str,NodePtr & ptr) const3924 ::namedNodeU(const StringC &str, NodePtr &ptr) const
3925 {
3926 if (grove()->governingDtd()->name() != str)
3927 return accessNull;
3928 ptr.assign(new DocumentTypeNode(grove(), grove()->governingDtd()));
3929 return accessOK;
3930 }
3931
3932 GeneralEntitiesNamedNodeList
GeneralEntitiesNamedNodeList(const GroveImpl * grove,const Dtd * dtd)3933 ::GeneralEntitiesNamedNodeList(const GroveImpl *grove, const Dtd *dtd)
3934 : BaseNamedNodeList(grove, grove->entitySubstTable()), dtd_(dtd)
3935 {
3936 }
3937
nodeList() const3938 NodeListPtr GeneralEntitiesNamedNodeList::nodeList() const
3939 {
3940 return new EntitiesNodeList(grove(),
3941 dtd_->generalEntityIter());
3942 }
3943
3944 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const3945 GeneralEntitiesNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
3946 {
3947 const Entity *entity
3948 = dtd_->lookupEntityTemp(0, str);
3949 if (!entity)
3950 return accessNull;
3951 ptr.assign(new EntityNode(grove(), entity));
3952 return accessOK;
3953 }
3954
3955 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const3956 DefaultedEntitiesNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
3957 {
3958 const Entity *entity
3959 = grove()->lookupDefaultedEntity(str);
3960 if (!entity)
3961 return accessNull;
3962 ptr.assign(new EntityNode(grove(), entity));
3963 return accessOK;
3964 }
3965
3966 NodeListPtr
nodeList() const3967 DefaultedEntitiesNamedNodeList::nodeList() const
3968 {
3969 return new EntitiesNodeList(grove(), grove()->defaultedEntityIter());
3970 }
3971
nodeList() const3972 NodeListPtr DocEntitiesNamedNodeList::nodeList() const
3973 {
3974 return new DocEntitiesNodeList(grove());
3975 }
3976
3977 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const3978 DocEntitiesNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
3979 {
3980 const Entity *entity
3981 = grove()->governingDtd()->lookupEntityTemp(0, str);
3982 // How I hate the default entity.
3983 while (!entity) {
3984 if (!grove()->hasDefaultEntity())
3985 return accessNull;
3986 // Make sure that the value of complete
3987 // we look at is that before we looked up
3988 // the entity.
3989 Boolean complete = grove()->complete();
3990 entity = grove()->lookupDefaultedEntity(str);
3991 if (entity)
3992 break;
3993 if (complete)
3994 return accessNull;
3995 if (!grove()->waitForMoreNodes())
3996 return accessTimeout;
3997 }
3998 ptr.assign(new EntityNode(grove(), entity));
3999 return accessOK;
4000 }
4001
4002 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const4003 ElementsNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
4004 {
4005 for (;;) {
4006 Boolean complete = grove()->complete();
4007 const ElementChunk *element = grove()->lookupElement(str);
4008 if (element) {
4009 ptr.assign(new ElementNode(grove(), element));
4010 break;
4011 }
4012 if (complete)
4013 return accessNull;
4014 if (!grove()->waitForMoreNodes())
4015 return accessTimeout;
4016 }
4017 return accessOK;
4018 }
4019
nodeList() const4020 NodeListPtr ElementsNamedNodeList::nodeList() const
4021 {
4022 return new ElementsNodeList(grove(), grove()->root()->documentElement);
4023 }
4024
ElementsNodeList(const GroveImpl * grove,const Chunk * first)4025 ElementsNodeList::ElementsNodeList(const GroveImpl *grove,
4026 const Chunk *first)
4027 : grove_(grove), first_(first)
4028 {
4029 }
4030
first(NodePtr & ptr) const4031 AccessResult ElementsNodeList::first(NodePtr &ptr) const
4032 {
4033 const Chunk *p = first_;
4034 while (p) {
4035 while (p == grove_->completeLimit()) {
4036 if (!grove_->waitForMoreNodes())
4037 return accessTimeout;
4038 }
4039 if (p->id()) {
4040 ((ElementsNodeList *)this)->first_ = p;
4041 ptr.assign(new ElementNode(grove_, (const ElementChunk *)p));
4042 return accessOK;
4043 }
4044 p = p->after();
4045 }
4046 return accessNull;
4047 }
4048
chunkRest(NodeListPtr & ptr) const4049 AccessResult ElementsNodeList::chunkRest(NodeListPtr &ptr) const
4050 {
4051 const Chunk *p = first_;
4052 while (p) {
4053 while (p == grove_->completeLimit()) {
4054 if (!grove_->waitForMoreNodes())
4055 return accessTimeout;
4056 }
4057 if (p->id()) {
4058 if (canReuse(ptr))
4059 ((ElementsNodeList *)this)->first_ = p->after();
4060 else
4061 ptr.assign(new ElementsNodeList(grove_, p->after()));
4062 return accessOK;
4063 }
4064 p = p->after();
4065 }
4066 return accessNull;
4067 }
4068
4069 // iter.next() gives first member of list that this represents
4070
EntitiesNodeList(const GroveImpl * grove,const Dtd::ConstEntityIter & iter)4071 EntitiesNodeList::EntitiesNodeList(const GroveImpl *grove,
4072 const Dtd::ConstEntityIter &iter)
4073 : grove_(grove), iter_(iter)
4074 {
4075 }
4076
first(NodePtr & ptr) const4077 AccessResult EntitiesNodeList::first(NodePtr &ptr) const
4078 {
4079 Dtd::ConstEntityIter tem(iter_);
4080 const Entity *entity = tem.nextTemp();
4081 if (!entity)
4082 return accessNull;
4083 ptr.assign(new EntityNode(grove_, entity));
4084 return accessOK;
4085 }
4086
chunkRest(NodeListPtr & ptr) const4087 AccessResult EntitiesNodeList::chunkRest(NodeListPtr &ptr) const
4088 {
4089 if (canReuse(ptr)) {
4090 EntitiesNodeList *list = (EntitiesNodeList *)this;
4091 if (list->iter_.nextTemp() == 0)
4092 return accessNull;
4093 return accessOK;
4094 }
4095 Dtd::ConstEntityIter tem(iter_);
4096 if (tem.nextTemp() == 0)
4097 return accessNull;
4098 ptr.assign(new EntitiesNodeList(grove_, tem));
4099 return accessOK;
4100 }
4101
DocEntitiesNodeList(const GroveImpl * grove)4102 DocEntitiesNodeList::DocEntitiesNodeList(const GroveImpl *grove)
4103 : EntitiesNodeList(grove, grove->governingDtd()->generalEntityIter())
4104 {
4105 }
4106
first(NodePtr & ptr) const4107 AccessResult DocEntitiesNodeList::first(NodePtr &ptr) const
4108 {
4109 AccessResult ret = EntitiesNodeList::first(ptr);
4110 if (ret != accessNull || !grove()->hasDefaultEntity())
4111 return ret;
4112 while (!grove()->complete())
4113 if (!grove()->waitForMoreNodes())
4114 return accessTimeout;
4115 Dtd::ConstEntityIter tem(grove()->defaultedEntityIter());
4116 const Entity *entity = tem.nextTemp();
4117 if (!entity)
4118 return accessNull;
4119 ptr.assign(new EntityNode(grove(), entity));
4120 return accessOK;
4121 }
4122
chunkRest(NodeListPtr & ptr) const4123 AccessResult DocEntitiesNodeList::chunkRest(NodeListPtr &ptr) const
4124 {
4125 AccessResult ret = EntitiesNodeList::chunkRest(ptr);
4126 if (ret != accessNull || !grove()->hasDefaultEntity())
4127 return ret;
4128 while (!grove()->complete())
4129 if (!grove()->waitForMoreNodes())
4130 return accessTimeout;
4131 Dtd::ConstEntityIter tem(grove()->defaultedEntityIter());
4132 const Entity *entity = tem.nextTemp();
4133 if (!entity)
4134 return accessNull;
4135 ptr.assign(new EntitiesNodeList(grove(), tem));
4136 return accessOK;
4137 }
4138
4139 NotationsNamedNodeList
NotationsNamedNodeList(const GroveImpl * grove,const Dtd * dtd)4140 ::NotationsNamedNodeList(const GroveImpl *grove, const Dtd *dtd)
4141 : BaseNamedNodeList(grove, grove->generalSubstTable()), dtd_(dtd)
4142 {
4143 }
4144
nodeList() const4145 NodeListPtr NotationsNamedNodeList::nodeList() const
4146 {
4147 return new NotationsNodeList(grove(),
4148 dtd_->notationIter());
4149 }
4150
4151 AccessResult
namedNodeU(const StringC & str,NodePtr & ptr) const4152 NotationsNamedNodeList::namedNodeU(const StringC &str, NodePtr &ptr) const
4153 {
4154 const Notation *notation
4155 = dtd_->lookupNotationTemp(str);
4156 if (!notation)
4157 return accessNull;
4158 ptr.assign(new NotationNode(grove(), notation));
4159 return accessOK;
4160 }
4161
4162
4163 // iter.next() gives first member of list that this represents
4164
NotationsNodeList(const GroveImpl * grove,const Dtd::ConstNotationIter & iter)4165 NotationsNodeList::NotationsNodeList(const GroveImpl *grove,
4166 const Dtd::ConstNotationIter &iter)
4167 : grove_(grove), iter_(iter)
4168 {
4169 }
4170
first(NodePtr & ptr) const4171 AccessResult NotationsNodeList::first(NodePtr &ptr) const
4172 {
4173 Dtd::ConstNotationIter tem(iter_);
4174 const Notation *notation = tem.nextTemp();
4175 if (!notation)
4176 return accessNull;
4177 ptr.assign(new NotationNode(grove_, notation));
4178 return accessOK;
4179 }
4180
chunkRest(NodeListPtr & ptr) const4181 AccessResult NotationsNodeList::chunkRest(NodeListPtr &ptr) const
4182 {
4183 if (canReuse(ptr)) {
4184 NotationsNodeList *list = (NotationsNodeList *)this;
4185 if (list->iter_.next().isNull())
4186 return accessNull;
4187 return accessOK;
4188 }
4189 Dtd::ConstNotationIter tem(iter_);
4190 if (tem.nextTemp() == 0)
4191 return accessNull;
4192 ptr.assign(new NotationsNodeList(grove_, tem));
4193 return accessOK;
4194 }
4195
NotationNode(const GroveImpl * grove,const Notation * notation)4196 NotationNode::NotationNode(const GroveImpl *grove,
4197 const Notation *notation)
4198 : BaseNode(grove), notation_(notation)
4199 {
4200 }
4201
getOrigin(NodePtr & ptr) const4202 AccessResult NotationNode::getOrigin(NodePtr &ptr) const
4203 {
4204 ptr.assign(new DocumentTypeNode(grove(), grove()->governingDtd()));
4205 return accessOK;
4206 }
4207
getName(GroveString & str) const4208 AccessResult NotationNode::getName(GroveString &str) const
4209 {
4210 setString(str, notation_->name());
4211 return accessOK;
4212 }
4213
getExternalId(NodePtr & ptr) const4214 AccessResult NotationNode::getExternalId(NodePtr &ptr) const
4215 {
4216 ptr.assign(new NotationExternalIdNode(grove(), notation_));
4217 return accessOK;
4218 }
4219
getLocation(Location & loc) const4220 AccessResult NotationNode::getLocation(Location &loc) const
4221 {
4222 return grove()->proxifyLocation(notation_->defLocation(), loc);
4223 }
4224
same(const BaseNode & node) const4225 bool NotationNode::same(const BaseNode &node) const
4226 {
4227 return node.same2(this);
4228 }
4229
same2(const NotationNode * node) const4230 bool NotationNode::same2(const NotationNode *node) const
4231 {
4232 return notation_ == node->notation_;
4233 }
4234
accept(NodeVisitor & visitor)4235 void NotationNode::accept(NodeVisitor &visitor)
4236 {
4237 visitor.notation(*this);
4238 }
4239
hash() const4240 unsigned long NotationNode::hash() const
4241 {
4242 return (unsigned long)notation_;
4243 }
4244
ExternalIdNode(const GroveImpl * grove)4245 ExternalIdNode::ExternalIdNode(const GroveImpl *grove)
4246 : BaseNode(grove)
4247 {
4248 }
4249
getPublicId(GroveString & str) const4250 AccessResult ExternalIdNode::getPublicId(GroveString &str) const
4251 {
4252 const StringC *s = externalId().publicIdString();
4253 if (!s)
4254 return accessNull;
4255 setString(str, *s);
4256 return accessOK;
4257 }
4258
getSystemId(GroveString & str) const4259 AccessResult ExternalIdNode::getSystemId(GroveString &str) const
4260 {
4261 const StringC *s = externalId().systemIdString();
4262 if (!s)
4263 return accessNull;
4264 setString(str, *s);
4265 return accessOK;
4266 }
4267
getGeneratedSystemId(GroveString & str) const4268 AccessResult ExternalIdNode::getGeneratedSystemId(GroveString &str) const
4269 {
4270 const StringC &s = externalId().effectiveSystemId();
4271 if (!s.size())
4272 return accessNull;
4273 setString(str, s);
4274 return accessOK;
4275 }
4276
accept(NodeVisitor & visitor)4277 void ExternalIdNode::accept(NodeVisitor &visitor)
4278 {
4279 visitor.externalId(*this);
4280 }
4281
same(const BaseNode & node) const4282 bool ExternalIdNode::same(const BaseNode &node) const
4283 {
4284 return node.same2(this);
4285 }
4286
same2(const ExternalIdNode * node) const4287 bool ExternalIdNode::same2(const ExternalIdNode *node) const
4288 {
4289 return &externalId() == &node->externalId();
4290 }
4291
EntityExternalIdNode(const GroveImpl * grove,const ExternalEntity * entity)4292 EntityExternalIdNode::EntityExternalIdNode(const GroveImpl *grove,
4293 const ExternalEntity *entity)
4294 : ExternalIdNode(grove), entity_(entity)
4295 {
4296 }
4297
externalId() const4298 const ExternalId &EntityExternalIdNode::externalId() const
4299 {
4300 return entity_->externalId();
4301 }
4302
getOrigin(NodePtr & ptr) const4303 AccessResult EntityExternalIdNode::getOrigin(NodePtr &ptr) const
4304 {
4305 ptr.assign(new EntityNode(grove(), entity_));
4306 return accessOK;
4307 }
4308
hash() const4309 unsigned long EntityExternalIdNode::hash() const
4310 {
4311 return secondHash((unsigned long)entity_);
4312 }
4313
NotationExternalIdNode(const GroveImpl * grove,const Notation * notation)4314 NotationExternalIdNode::NotationExternalIdNode(const GroveImpl *grove,
4315 const Notation *notation)
4316 : ExternalIdNode(grove), notation_(notation)
4317 {
4318 }
4319
externalId() const4320 const ExternalId &NotationExternalIdNode::externalId() const
4321 {
4322 return notation_->externalId();
4323 }
4324
getOrigin(NodePtr & ptr) const4325 AccessResult NotationExternalIdNode::getOrigin(NodePtr &ptr) const
4326 {
4327 ptr.assign(new NotationNode(grove(), notation_));
4328 return accessOK;
4329 }
4330
hash() const4331 unsigned long NotationExternalIdNode::hash() const
4332 {
4333 return secondHash((unsigned long)notation_);
4334 }
4335
getParent(NodePtr & ptr) const4336 AccessResult ChunkNode::getParent(NodePtr &ptr) const
4337 {
4338 if (!chunk_->origin)
4339 return accessNull;
4340 // This is needed because PiNodes in the prolog and
4341 // epilog don't have a parent but do have an origin.
4342 // Also for the document element.
4343 if ((const Chunk *)chunk()->origin == grove()->root())
4344 return accessNull;
4345 chunk_->origin->setNodePtrFirst(ptr, this);
4346 return accessOK;
4347 }
4348
getTreeRoot(NodePtr & ptr) const4349 AccessResult ChunkNode::getTreeRoot(NodePtr &ptr) const
4350 {
4351 if (chunk()->origin
4352 && (const Chunk *)chunk()->origin != grove()->root()
4353 // With invalid documents we might have elements in the epilog
4354 && !grove()->root()->epilog
4355 && grove()->root()->documentElement)
4356 return grove()->root()->documentElement->setNodePtrFirst(ptr, this);
4357 return Node::getTreeRoot(ptr);
4358 }
4359
getOrigin(NodePtr & ptr) const4360 AccessResult ChunkNode::getOrigin(NodePtr &ptr) const
4361 {
4362 if (!chunk_->origin)
4363 return accessNull;
4364 chunk_->origin->setNodePtrFirst(ptr, this);
4365 return accessOK;
4366 }
4367
getOriginToSubnodeRelPropertyName(ComponentName::Id & name) const4368 AccessResult ChunkNode::getOriginToSubnodeRelPropertyName(ComponentName::Id &name) const
4369 {
4370 if ((const Chunk *)chunk()->origin != grove()->root())
4371 name = ComponentName::idContent;
4372 else if ((const Chunk *)chunk() == grove()->root()->documentElement)
4373 name = ComponentName::idDocumentElement;
4374 else {
4375 const Chunk *tem;
4376 if (chunk()->getFirstSibling(grove(), tem) == accessOK && tem == grove()->root()->prolog)
4377 name = ComponentName::idProlog;
4378 else
4379 name = ComponentName::idEpilog;
4380 }
4381 return accessOK;
4382 }
4383
hash() const4384 unsigned long ChunkNode::hash() const
4385 {
4386 return (unsigned long)chunk_;
4387 }
4388
same(const BaseNode & node) const4389 bool ChunkNode::same(const BaseNode &node) const
4390 {
4391 return node.same2(this);
4392 }
4393
same2(const ChunkNode * node) const4394 bool ChunkNode::same2(const ChunkNode *node) const
4395 {
4396 return chunk_ == node->chunk_;
4397 }
4398
~BaseNode()4399 BaseNode::~BaseNode()
4400 {
4401 }
4402
addRef()4403 void BaseNode::addRef()
4404 {
4405 ++refCount_;
4406 }
4407
release()4408 void BaseNode::release()
4409 {
4410 ASSERT(refCount_ != 0);
4411 if (--refCount_ == 0)
4412 delete this;
4413 }
4414
groveIndex() const4415 unsigned BaseNode::groveIndex() const
4416 {
4417 return grove_->groveIndex();
4418 }
4419
operator ==(const Node & node) const4420 bool BaseNode::operator==(const Node &node) const
4421 {
4422 if (!sameGrove(node))
4423 return 0;
4424 return same((const BaseNode &)node);
4425 }
4426
chunkContains(const Node & node) const4427 bool BaseNode::chunkContains(const Node &node) const
4428 {
4429 if (!sameGrove(node))
4430 return 0;
4431 return same((const BaseNode &)node);
4432 }
4433
inChunk(const DataNode *) const4434 bool BaseNode::inChunk(const DataNode *) const
4435 {
4436 return 0;
4437 }
4438
inChunk(const CdataAttributeValueNode *) const4439 bool BaseNode::inChunk(const CdataAttributeValueNode *) const
4440 {
4441 return 0;
4442 }
4443
same2(const ChunkNode *) const4444 bool BaseNode::same2(const ChunkNode *) const
4445 {
4446 return 0;
4447 }
4448
same2(const DataNode *) const4449 bool BaseNode::same2(const DataNode *) const
4450 {
4451 return 0;
4452 }
4453
same2(const AttributeAsgnNode *) const4454 bool BaseNode::same2(const AttributeAsgnNode *) const
4455 {
4456 return 0;
4457 }
4458
same2(const AttributeValueTokenNode *) const4459 bool BaseNode::same2(const AttributeValueTokenNode *) const
4460 {
4461 return 0;
4462 }
4463
same2(const CdataAttributeValueNode *) const4464 bool BaseNode::same2(const CdataAttributeValueNode *) const
4465 {
4466 return 0;
4467 }
4468
same2(const EntityNode *) const4469 bool BaseNode::same2(const EntityNode *) const
4470 {
4471 return 0;
4472 }
4473
same2(const NotationNode *) const4474 bool BaseNode::same2(const NotationNode *) const
4475 {
4476 return 0;
4477 }
4478
same2(const ExternalIdNode *) const4479 bool BaseNode::same2(const ExternalIdNode *) const
4480 {
4481 return 0;
4482 }
4483
same2(const DocumentTypeNode *) const4484 bool BaseNode::same2(const DocumentTypeNode *) const
4485 {
4486 return 0;
4487 }
4488
same2(const SgmlConstantsNode *) const4489 bool BaseNode::same2(const SgmlConstantsNode *) const
4490 {
4491 return 0;
4492 }
4493
same2(const MessageNode *) const4494 bool BaseNode::same2(const MessageNode *) const
4495 {
4496 return 0;
4497 }
4498
nextSibling(NodePtr & ptr) const4499 AccessResult BaseNode::nextSibling(NodePtr &ptr) const
4500 {
4501 return nextChunkSibling(ptr);
4502 }
4503
follow(NodeListPtr & ptr) const4504 AccessResult BaseNode::follow(NodeListPtr &ptr) const
4505 {
4506 NodePtr nd;
4507 AccessResult ret = nextSibling(nd);
4508 switch (ret) {
4509 case accessOK:
4510 ptr.assign(new SiblingNodeList(nd));
4511 break;
4512 case accessNull:
4513 ptr.assign(new BaseNodeList);
4514 ret = accessOK;
4515 break;
4516 default:
4517 break;
4518 }
4519 return ret;
4520 }
4521
children(NodeListPtr & ptr) const4522 AccessResult BaseNode::children(NodeListPtr &ptr) const
4523 {
4524 NodePtr head;
4525 AccessResult ret = firstChild(head);
4526 switch (ret) {
4527 case accessOK:
4528 ptr.assign(new SiblingNodeList(head));
4529 break;
4530 case accessNull:
4531 ptr.assign(new BaseNodeList);
4532 ret = accessOK;
4533 break;
4534 default:
4535 break;
4536 }
4537 return ret;
4538 }
4539
getOrigin(NodePtr & ptr) const4540 AccessResult BaseNode::getOrigin(NodePtr &ptr) const
4541 {
4542 return getParent(ptr);
4543 }
4544
getGroveRoot(NodePtr & ptr) const4545 AccessResult BaseNode::getGroveRoot(NodePtr &ptr) const
4546 {
4547 ptr.assign(new SgmlDocumentNode(grove(), grove()->root()));
4548 return accessOK;
4549 }
4550
getLocation(Location &) const4551 AccessResult BaseNode::getLocation(Location &) const
4552 {
4553 return accessNull;
4554 }
4555
queryInterface(IID iid,const void * & p) const4556 bool BaseNode::queryInterface(IID iid, const void *&p) const
4557 {
4558 if (iid == LocNode::iid) {
4559 const LocNode *ip = this;
4560 p = ip;
4561 return 1;
4562 }
4563 return 0;
4564 }
4565
4566 AccessResult
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const4567 ForwardingChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const
4568 {
4569 if (forwardTo == 0)
4570 return accessNull;
4571 ASSERT(origin == forwardTo->origin);
4572 return forwardTo->setNodePtrFirst(ptr, node);
4573 }
4574
4575 AccessResult
getFollowing(const GroveImpl * grove,const Chunk * & p,unsigned long & nNodes) const4576 ForwardingChunk::getFollowing(const GroveImpl *grove,
4577 const Chunk *&p, unsigned long &nNodes)
4578 const
4579 {
4580 AccessResult ret = Chunk::getFollowing(grove, p, nNodes);
4581 if (ret == accessOK)
4582 nNodes = 0;
4583 return ret;
4584 }
4585
4586 AccessResult
getFollowing(const GroveImpl * grove,const Chunk * & p,unsigned long & nNodes) const4587 LocOriginChunk::getFollowing(const GroveImpl *grove,
4588 const Chunk *&p, unsigned long &nNodes)
4589 const
4590 {
4591 AccessResult ret = Chunk::getFollowing(grove, p, nNodes);
4592 if (ret == accessOK)
4593 nNodes = 0;
4594 return ret;
4595 }
4596
setNodePtrFirst(NodePtr & ptr,const BaseNode * node) const4597 AccessResult LocOriginChunk::setNodePtrFirst(NodePtr &ptr, const BaseNode *node) const
4598 {
4599 return ((const Chunk *)(this + 1))->setNodePtrFirst(ptr, node);
4600 }
4601
setNodePtrFirst(NodePtr & ptr,const ElementNode * node) const4602 AccessResult LocOriginChunk::setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const
4603 {
4604 return ((const Chunk *)(this + 1))->setNodePtrFirst(ptr, node);
4605 }
4606
setNodePtrFirst(NodePtr & ptr,const DataNode * node) const4607 AccessResult LocOriginChunk::setNodePtrFirst(NodePtr &ptr, const DataNode *node) const
4608 {
4609 return ((const Chunk *)(this + 1))->setNodePtrFirst(ptr, node);
4610 }
4611
after() const4612 const Chunk *LocOriginChunk::after() const
4613 {
4614 return this + 1;
4615 }
4616
getLocOrigin(const Origin * & ret) const4617 Boolean LocOriginChunk::getLocOrigin(const Origin *&ret) const
4618 {
4619 ret = locOrigin;
4620 return 1;
4621 }
4622
4623 AccessResult
setNodePtrFirst(NodePtr & ptr,const ElementNode * node) const4624 Chunk::setNodePtrFirst(NodePtr &ptr, const ElementNode *node) const
4625 {
4626 return setNodePtrFirst(ptr, (const BaseNode *)node);
4627 }
4628
4629 AccessResult
setNodePtrFirst(NodePtr & ptr,const DataNode * node) const4630 Chunk::setNodePtrFirst(NodePtr &ptr, const DataNode *node) const
4631 {
4632 return setNodePtrFirst(ptr, (const BaseNode *)node);
4633 }
4634
id() const4635 const StringC *Chunk::id() const
4636 {
4637 return 0;
4638 }
4639
getFollowing(const GroveImpl * grove,const Chunk * & f,unsigned long & n) const4640 AccessResult Chunk::getFollowing(const GroveImpl *grove,
4641 const Chunk *&f, unsigned long &n) const
4642 {
4643 const Chunk *p = after();
4644 while (p == grove->completeLimit())
4645 if (!grove->waitForMoreNodes())
4646 return accessTimeout;
4647 if (p->origin != origin)
4648 return accessNull;
4649 n = 1;
4650 f = p;
4651 return accessOK;
4652 }
4653
getFirstSibling(const GroveImpl * grove,const Chunk * & p) const4654 AccessResult Chunk::getFirstSibling(const GroveImpl *grove,
4655 const Chunk *&p) const
4656 {
4657 if ((const Chunk *)origin == grove->root())
4658 return accessNotInClass;
4659 p = origin->after();
4660 return accessOK;
4661 }
4662
getLocOrigin(const Origin * &) const4663 Boolean Chunk::getLocOrigin(const Origin *&) const
4664 {
4665 return 0;
4666 }
4667
4668 #ifdef SP_NAMESPACE
4669 }
4670 #endif
4671
4672 #include "grove_inst.cxx"
4673