1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident "%Z%%M% %I% %E% SMI"
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8 #include "splib.h"
9 #include "Location.h"
10 #include "Entity.h"
11 #include "Mutex.h"
12
13 #ifdef SP_NAMESPACE
14 namespace SP_NAMESPACE {
15 #endif
16
17 class InputSourceOriginImpl : public EntityOrigin {
18 public:
19 InputSourceOriginImpl();
20 InputSourceOriginImpl(const Location &refLocation);
21 const Location &parent() const;
22 const ExternalInfo *externalInfo() const;
23 Offset startOffset(Index ind) const;
24 void noteCharRef(Index replacementIndex, const NamedCharRef &);
25 Boolean isNamedCharRef(Index ind, NamedCharRef &ref) const;
26 void setExternalInfo(ExternalInfo *);
27 virtual InputSourceOrigin *copy() const;
28 const InputSourceOrigin *asInputSourceOrigin() const;
29 private:
30 InputSourceOriginImpl(const InputSourceOriginImpl &); // undefined
31 void operator=(const InputSourceOriginImpl &); // undefined
32 size_t nPrecedingCharRefs(Index ind) const;
33 Vector<InputSourceOriginNamedCharRef> charRefs_;
34 StringC charRefOrigNames_;
35 Owner<ExternalInfo> externalInfo_; // 0 for internal entities
36 Location refLocation_; // where referenced from
37 Mutex mutex_;
38 };
39
40 class EntityOriginImpl : public InputSourceOriginImpl {
41 public:
operator new(size_t sz,Allocator & alloc)42 void *operator new(size_t sz, Allocator &alloc) {
43 return alloc.alloc(sz);
44 }
operator new(size_t sz)45 void *operator new(size_t sz) {
46 return Allocator::allocSimple(sz);
47 }
operator delete(void * p)48 void operator delete(void *p) {
49 Allocator::free(p);
50 }
51 EntityOriginImpl(const ConstPtr<Entity> &);
52 EntityOriginImpl(const ConstPtr<Entity> &,
53 const Location &refLocation);
54 EntityOriginImpl(const ConstPtr<Entity> &,
55 const Location &refLocation, Index refLength,
56 Owner<Markup> &markup);
57 ~EntityOriginImpl();
58 InputSourceOrigin *copy() const;
entity() const59 const Entity *entity() const { return entity_.pointer(); }
60 const EntityDecl *entityDecl() const;
61 const EntityOrigin *asEntityOrigin() const;
62 Boolean defLocation(Offset off, const Origin *&, Index &) const;
63 Index refLength() const;
64 const Markup *markup() const;
65 private:
66 EntityOriginImpl(const EntityOriginImpl &); // undefined
67 void operator=(const EntityOriginImpl &); // undefined
68 ConstPtr<Entity> entity_; // 0 for document entity
69 // total length of reference
70 // (characters that were replaced by the entity)
71 Index refLength_;
72 Owner<Markup> markup_;
73 };
74
75 const size_t EntityOrigin::allocSize = sizeof(EntityOriginImpl);
76
Location()77 Location::Location()
78 {
79 }
80
Location(Origin * origin,Index i)81 Location::Location(Origin *origin, Index i)
82 : origin_(origin), index_(i)
83 {
84 }
85
Location(ConstPtr<Origin> origin,Index i)86 Location::Location(ConstPtr<Origin> origin, Index i)
87 : origin_(origin), index_(i)
88 {
89 }
90
~Origin()91 Origin::~Origin()
92 {
93 }
94
asEntityOrigin() const95 const EntityOrigin *Origin::asEntityOrigin() const
96 {
97 return 0;
98 }
99
asInputSourceOrigin() const100 const InputSourceOrigin *Origin::asInputSourceOrigin() const
101 {
102 return 0;
103 }
104
refLength() const105 Index Origin::refLength() const
106 {
107 return 0;
108 }
109
origChars(const Char * &) const110 Boolean Origin::origChars(const Char *&) const
111 {
112 return 0;
113 }
114
inBracketedTextOpenDelim() const115 Boolean Origin::inBracketedTextOpenDelim() const
116 {
117 return 0;
118 }
119
inBracketedTextCloseDelim() const120 Boolean Origin::inBracketedTextCloseDelim() const
121 {
122 return 0;
123 }
124
isNumericCharRef(const Markup * &) const125 Boolean Origin::isNumericCharRef(const Markup *&) const
126 {
127 return 0;
128 }
129
isNamedCharRef(Index,NamedCharRef &) const130 Boolean Origin::isNamedCharRef(Index, NamedCharRef &) const
131 {
132 return 0;
133 }
134
entityDecl() const135 const EntityDecl *Origin::entityDecl() const
136 {
137 return 0;
138 }
139
markup() const140 const Markup *Origin::markup() const
141 {
142 return 0;
143 }
144
entity() const145 const Entity *Origin::entity() const
146 {
147 return 0;
148 }
149
defLocation(Offset,const Origin * &,Index &) const150 Boolean Origin::defLocation(Offset, const Origin *&, Index &) const
151 {
152 return 0;
153 }
154
externalInfo() const155 const ExternalInfo *Origin::externalInfo() const
156 {
157 return 0;
158 }
159
startOffset(Index ind) const160 Offset Origin::startOffset(Index ind) const
161 {
162 return ind;
163 }
164
entityName() const165 const StringC *Origin::entityName() const
166 {
167 const EntityDecl *ent = entityDecl();
168 if (ent)
169 return &ent->name();
170 else
171 return 0;
172 }
173
BracketOrigin(const Location & loc,Position pos)174 BracketOrigin::BracketOrigin(const Location &loc, Position pos)
175 : loc_(loc), pos_(pos)
176 {
177 }
178
parent() const179 const Location &BracketOrigin::parent() const
180 {
181 return loc_;
182 }
183
inBracketedTextOpenDelim() const184 Boolean BracketOrigin::inBracketedTextOpenDelim() const
185 {
186 return pos_ == open;
187 }
188
inBracketedTextCloseDelim() const189 Boolean BracketOrigin::inBracketedTextCloseDelim() const
190 {
191 return pos_ == close;
192 }
193
make()194 InputSourceOrigin *InputSourceOrigin::make()
195 {
196 return new InputSourceOriginImpl;
197 }
198
make(const Location & refLocation)199 InputSourceOrigin *InputSourceOrigin::make(const Location &refLocation)
200 {
201 return new InputSourceOriginImpl(refLocation);
202 }
203
InputSourceOriginImpl()204 InputSourceOriginImpl::InputSourceOriginImpl()
205 {
206 }
207
InputSourceOriginImpl(const Location & refLocation)208 InputSourceOriginImpl::InputSourceOriginImpl(const Location &refLocation)
209 : refLocation_(refLocation)
210 {
211 }
212
asInputSourceOrigin() const213 const InputSourceOrigin *InputSourceOriginImpl::asInputSourceOrigin() const
214 {
215 return this;
216 }
217
externalInfo() const218 const ExternalInfo *InputSourceOriginImpl::externalInfo() const
219 {
220 return externalInfo_.pointer();
221 }
222
copy() const223 InputSourceOrigin *InputSourceOriginImpl::copy() const
224 {
225 return new InputSourceOriginImpl(refLocation_);
226 }
227
parent() const228 const Location &InputSourceOriginImpl::parent() const
229 {
230 return refLocation_;
231 }
232
setExternalInfo(ExternalInfo * info)233 void InputSourceOriginImpl::setExternalInfo(ExternalInfo *info)
234 {
235 externalInfo_ = info;
236 }
237
noteCharRef(Index replacementIndex,const NamedCharRef & ref)238 void InputSourceOriginImpl::noteCharRef(Index replacementIndex,
239 const NamedCharRef &ref)
240 {
241 Mutex::Lock lock(&mutex_);
242 charRefs_.resize(charRefs_.size() + 1);
243 charRefs_.back().replacementIndex = replacementIndex;
244 charRefs_.back().refStartIndex = ref.refStartIndex();
245 charRefs_.back().refEndType = ref.refEndType();
246 charRefs_.back().origNameOffset = charRefOrigNames_.size();
247 charRefOrigNames_ += ref.origName();
248 }
249
250 // Number of character references whose replacement index < ind.
251
nPrecedingCharRefs(Index ind) const252 size_t InputSourceOriginImpl::nPrecedingCharRefs(Index ind) const
253 {
254 size_t i;
255 // Find i such that
256 // charRefs_[I].replacementIndex >= ind
257 // charRefs_[i - 1].replacementIndex < ind
258 if (charRefs_.size() == 0
259 || ind > charRefs_.back().replacementIndex)
260 // This will be a common case, so optimize it.
261 i = charRefs_.size();
262 else {
263 // Binary search
264 // Invariant:
265 // charRefs_ < i have replacementIndex < ind
266 // charRefs_ >= lim have replacementIndex >= ind
267 i = 0;
268 size_t lim = charRefs_.size();
269 while (i < lim) {
270 size_t mid = i + (lim - i)/2;
271 if (charRefs_[mid].replacementIndex >= ind)
272 lim = mid;
273 else
274 i = mid + 1;
275 }
276 }
277 return i;
278 }
279
startOffset(Index ind) const280 Offset InputSourceOriginImpl::startOffset(Index ind) const
281 {
282 Mutex::Lock lock(&((InputSourceOriginImpl *)this)->mutex_);
283 size_t n = nPrecedingCharRefs(ind);
284 if (n < charRefs_.size()
285 && ind == charRefs_[n].replacementIndex) {
286 for (;;) {
287 ind = charRefs_[n].refStartIndex;
288 if (n == 0 || charRefs_[n - 1].replacementIndex != ind)
289 break;
290 --n;
291 }
292 }
293 // charRefs[n - 1].replacementIndex < ind
294 return Offset(ind - n);
295 }
296
isNamedCharRef(Index ind,NamedCharRef & ref) const297 Boolean InputSourceOriginImpl::isNamedCharRef(Index ind, NamedCharRef &ref) const
298 {
299 Mutex::Lock lock(&((InputSourceOriginImpl *)this)->mutex_);
300 size_t n = nPrecedingCharRefs(ind);
301 if (n < charRefs_.size() && ind == charRefs_[n].replacementIndex) {
302 ref.set(charRefs_[n].refStartIndex,
303 charRefs_[n].refEndType,
304 charRefOrigNames_.data() + charRefs_[n].origNameOffset,
305 (n + 1 < charRefs_.size()
306 ? charRefs_[n + 1].origNameOffset
307 : charRefOrigNames_.size())
308 - charRefs_[n].origNameOffset);
309 return 1;
310 }
311 return 0;
312 }
313
make(Allocator & alloc,const ConstPtr<Entity> & entity)314 EntityOrigin *EntityOrigin::make(Allocator &alloc,
315 const ConstPtr<Entity> &entity)
316 {
317 return new (alloc) EntityOriginImpl(entity);
318 }
319
make(Allocator & alloc,const ConstPtr<Entity> & entity,const Location & refLocation)320 EntityOrigin *EntityOrigin::make(Allocator &alloc,
321 const ConstPtr<Entity> &entity,
322 const Location &refLocation)
323 {
324 return new (alloc) EntityOriginImpl(entity, refLocation);
325 }
326
make(Allocator & alloc,const ConstPtr<Entity> & entity,const Location & refLocation,Index refLength,Owner<Markup> & markup)327 EntityOrigin *EntityOrigin::make(Allocator &alloc,
328 const ConstPtr<Entity> &entity,
329 const Location &refLocation,
330 Index refLength,
331 Owner<Markup> &markup)
332 {
333 return new (alloc) EntityOriginImpl(entity, refLocation, refLength, markup);
334 }
335
make(const ConstPtr<Entity> & entity,const Location & refLocation,Index refLength,Owner<Markup> & markup)336 EntityOrigin *EntityOrigin::make(const ConstPtr<Entity> &entity,
337 const Location &refLocation,
338 Index refLength,
339 Owner<Markup> &markup)
340 {
341 return new EntityOriginImpl(entity, refLocation, refLength, markup);
342 }
343
make(const ConstPtr<Entity> & entity,const Location & refLocation)344 EntityOrigin *EntityOrigin::make(const ConstPtr<Entity> &entity,
345 const Location &refLocation)
346 {
347 return new EntityOriginImpl(entity, refLocation);
348 }
349
EntityOriginImpl(const ConstPtr<Entity> & entity)350 EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity)
351 : refLength_(0), entity_(entity)
352 {
353 }
354
EntityOriginImpl(const ConstPtr<Entity> & entity,const Location & refLocation)355 EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity,
356 const Location &refLocation)
357 : InputSourceOriginImpl(refLocation), refLength_(0), entity_(entity)
358 {
359 }
360
EntityOriginImpl(const ConstPtr<Entity> & entity,const Location & refLocation,Index refLength,Owner<Markup> & markup)361 EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity,
362 const Location &refLocation,
363 Index refLength,
364 Owner<Markup> &markup)
365 : InputSourceOriginImpl(refLocation), refLength_(refLength), entity_(entity)
366 {
367 markup.swap(markup_);
368 }
369
~EntityOriginImpl()370 EntityOriginImpl::~EntityOriginImpl()
371 {
372 }
373
copy() const374 InputSourceOrigin *EntityOriginImpl::copy() const
375 {
376 Owner<Markup> m;
377 if (markup_)
378 m = new Markup(*markup_);
379 return new EntityOriginImpl(entity_, parent(), refLength_, m);
380 }
381
refLength() const382 Index EntityOriginImpl::refLength() const
383 {
384 return refLength_;
385 }
386
asEntityOrigin() const387 const EntityOrigin *EntityOriginImpl::asEntityOrigin() const
388 {
389 return this;
390 }
391
defLocation(Offset off,const Origin * & origin,Index & index) const392 Boolean EntityOriginImpl::defLocation(Offset off, const Origin *&origin, Index &index) const
393 {
394 if (entity_.isNull())
395 return 0;
396 const InternalEntity *internal = entity_->asInternalEntity();
397 if (!internal)
398 return 0;
399 return internal->text().charLocation(off, origin, index);
400 }
401
entityDecl() const402 const EntityDecl *EntityOriginImpl::entityDecl() const
403 {
404 return entity_.pointer();
405 }
406
markup() const407 const Markup *EntityOriginImpl::markup() const
408 {
409 return markup_.pointer();
410 }
411
412
ReplacementOrigin(const Location & loc,Char origChar)413 ReplacementOrigin::ReplacementOrigin(const Location &loc, Char origChar)
414 : loc_(loc), origChar_(origChar)
415 {
416 }
417
parent() const418 const Location &ReplacementOrigin::parent() const
419 {
420 return loc_;
421 }
422
origChars(const Char * & s) const423 Boolean ReplacementOrigin::origChars(const Char *&s) const
424 {
425 if (loc_.origin().isNull() || !loc_.origin()->origChars(s))
426 s = &origChar_;
427 return 1;
428 }
429
MultiReplacementOrigin(const Location & loc,StringC & origChars)430 MultiReplacementOrigin::MultiReplacementOrigin(const Location &loc,
431 StringC &origChars)
432 : loc_(loc)
433 {
434 origChars.swap(origChars_);
435 }
436
parent() const437 const Location &MultiReplacementOrigin::parent() const
438 {
439 return loc_;
440 }
441
origChars(const Char * & s) const442 Boolean MultiReplacementOrigin::origChars(const Char *&s) const
443 {
444 if (loc_.origin().isNull() || !loc_.origin()->origChars(s))
445 s = origChars_.data();
446 return 1;
447 }
448
ProxyOrigin(const Origin * origin)449 ProxyOrigin::ProxyOrigin(const Origin *origin)
450 : origin_(origin)
451 {
452 }
453
asEntityOrigin() const454 const EntityOrigin *ProxyOrigin::asEntityOrigin() const
455 {
456 return origin_->asEntityOrigin();
457 }
458
asInputSourceOrigin() const459 const InputSourceOrigin *ProxyOrigin::asInputSourceOrigin() const
460 {
461 return origin_->asInputSourceOrigin();
462 }
463
parent() const464 const Location &ProxyOrigin::parent() const
465 {
466 return origin_->parent();
467 }
468
refLength() const469 Index ProxyOrigin::refLength() const
470 {
471 return origin_->refLength();
472 }
473
origChars(const Char * & p) const474 Boolean ProxyOrigin::origChars(const Char *&p) const
475 {
476 return origin_->origChars(p);
477 }
478
inBracketedTextOpenDelim() const479 Boolean ProxyOrigin::inBracketedTextOpenDelim() const
480 {
481 return origin_->inBracketedTextOpenDelim();
482 }
483
inBracketedTextCloseDelim() const484 Boolean ProxyOrigin::inBracketedTextCloseDelim() const
485 {
486 return origin_->inBracketedTextCloseDelim();
487 }
488
isNumericCharRef(const Markup * & markup) const489 Boolean ProxyOrigin::isNumericCharRef(const Markup *&markup) const
490 {
491 return origin_->isNumericCharRef(markup);
492 }
493
isNamedCharRef(Index ind,NamedCharRef & ref) const494 Boolean ProxyOrigin::isNamedCharRef(Index ind, NamedCharRef &ref) const
495 {
496 return origin_->isNamedCharRef(ind, ref);
497 }
498
entityDecl() const499 const EntityDecl *ProxyOrigin::entityDecl() const
500 {
501 return origin_->entityDecl();
502 }
503
defLocation(Offset off,const Origin * & origin,Index & index) const504 Boolean ProxyOrigin::defLocation(Offset off, const Origin *&origin, Index &index) const
505 {
506 return origin_->defLocation(off, origin, index);
507 }
508
markup() const509 const Markup *ProxyOrigin::markup() const
510 {
511 return origin_->markup();
512 }
513
entity() const514 const Entity *ProxyOrigin::entity() const
515 {
516 return origin_->entity();
517 }
518
externalInfo() const519 const ExternalInfo *ProxyOrigin::externalInfo() const
520 {
521 return origin_->externalInfo();
522 }
523
startOffset(Index ind) const524 Offset ProxyOrigin::startOffset(Index ind) const
525 {
526 return origin_->startOffset(ind);
527 }
528
~ExternalInfo()529 ExternalInfo::~ExternalInfo()
530 {
531 }
532
RTTI_DEF0(ExternalInfo)533 RTTI_DEF0(ExternalInfo)
534
535 NamedCharRef::NamedCharRef()
536 {
537 }
538
NamedCharRef(Index refStartIndex,RefEndType refEndType,const StringC & origName)539 NamedCharRef::NamedCharRef(Index refStartIndex, RefEndType refEndType,
540 const StringC &origName)
541 : refStartIndex_(refStartIndex),
542 refEndType_(refEndType),
543 origName_(origName)
544 {
545 }
546
set(Index refStartIndex,RefEndType refEndType,const Char * s,size_t n)547 void NamedCharRef::set(Index refStartIndex, RefEndType refEndType,
548 const Char *s, size_t n)
549 {
550 refStartIndex_ = refStartIndex;
551 refEndType_ = refEndType;
552 origName_.assign(s, n);
553 }
554
555 #ifdef SP_NAMESPACE
556 }
557 #endif
558