Location.cxx revision 7c478bd95313f5f23a4c958a745db2134aa03244
// Copyright (c) 1994 James Clark
// See the file COPYING for copying permission.
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __GNUG__
#pragma implementation
#endif
#include "splib.h"
#include "Location.h"
#include "Entity.h"
#include "Mutex.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
class InputSourceOriginImpl : public EntityOrigin {
public:
InputSourceOriginImpl();
InputSourceOriginImpl(const Location &refLocation);
const Location &parent() const;
const ExternalInfo *externalInfo() const;
Offset startOffset(Index ind) const;
void noteCharRef(Index replacementIndex, const NamedCharRef &);
Boolean isNamedCharRef(Index ind, NamedCharRef &ref) const;
void setExternalInfo(ExternalInfo *);
virtual InputSourceOrigin *copy() const;
const InputSourceOrigin *asInputSourceOrigin() const;
private:
InputSourceOriginImpl(const InputSourceOriginImpl &); // undefined
void operator=(const InputSourceOriginImpl &); // undefined
size_t nPrecedingCharRefs(Index ind) const;
Vector<InputSourceOriginNamedCharRef> charRefs_;
StringC charRefOrigNames_;
Owner<ExternalInfo> externalInfo_; // 0 for internal entities
Location refLocation_; // where referenced from
Mutex mutex_;
};
class EntityOriginImpl : public InputSourceOriginImpl {
public:
void *operator new(size_t sz, Allocator &alloc) {
return alloc.alloc(sz);
}
void *operator new(size_t sz) {
return Allocator::allocSimple(sz);
}
void operator delete(void *p) {
Allocator::free(p);
}
EntityOriginImpl(const ConstPtr<Entity> &);
EntityOriginImpl(const ConstPtr<Entity> &,
const Location &refLocation);
EntityOriginImpl(const ConstPtr<Entity> &,
const Location &refLocation, Index refLength,
Owner<Markup> &markup);
~EntityOriginImpl();
InputSourceOrigin *copy() const;
const Entity *entity() const { return entity_.pointer(); }
const EntityDecl *entityDecl() const;
const EntityOrigin *asEntityOrigin() const;
Boolean defLocation(Offset off, const Origin *&, Index &) const;
Index refLength() const;
const Markup *markup() const;
private:
EntityOriginImpl(const EntityOriginImpl &); // undefined
void operator=(const EntityOriginImpl &); // undefined
ConstPtr<Entity> entity_; // 0 for document entity
// total length of reference
// (characters that were replaced by the entity)
Index refLength_;
Owner<Markup> markup_;
};
const size_t EntityOrigin::allocSize = sizeof(EntityOriginImpl);
Location::Location()
{
}
Location::Location(Origin *origin, Index i)
: origin_(origin), index_(i)
{
}
Location::Location(ConstPtr<Origin> origin, Index i)
: origin_(origin), index_(i)
{
}
Origin::~Origin()
{
}
const EntityOrigin *Origin::asEntityOrigin() const
{
return 0;
}
const InputSourceOrigin *Origin::asInputSourceOrigin() const
{
return 0;
}
Index Origin::refLength() const
{
return 0;
}
Boolean Origin::origChars(const Char *&) const
{
return 0;
}
Boolean Origin::inBracketedTextOpenDelim() const
{
return 0;
}
Boolean Origin::inBracketedTextCloseDelim() const
{
return 0;
}
Boolean Origin::isNumericCharRef(const Markup *&) const
{
return 0;
}
Boolean Origin::isNamedCharRef(Index, NamedCharRef &) const
{
return 0;
}
const EntityDecl *Origin::entityDecl() const
{
return 0;
}
const Markup *Origin::markup() const
{
return 0;
}
const Entity *Origin::entity() const
{
return 0;
}
Boolean Origin::defLocation(Offset, const Origin *&, Index &) const
{
return 0;
}
const ExternalInfo *Origin::externalInfo() const
{
return 0;
}
Offset Origin::startOffset(Index ind) const
{
return ind;
}
const StringC *Origin::entityName() const
{
const EntityDecl *ent = entityDecl();
if (ent)
return &ent->name();
else
return 0;
}
BracketOrigin::BracketOrigin(const Location &loc, Position pos)
: loc_(loc), pos_(pos)
{
}
const Location &BracketOrigin::parent() const
{
return loc_;
}
Boolean BracketOrigin::inBracketedTextOpenDelim() const
{
return pos_ == open;
}
Boolean BracketOrigin::inBracketedTextCloseDelim() const
{
return pos_ == close;
}
InputSourceOrigin *InputSourceOrigin::make()
{
return new InputSourceOriginImpl;
}
InputSourceOrigin *InputSourceOrigin::make(const Location &refLocation)
{
return new InputSourceOriginImpl(refLocation);
}
InputSourceOriginImpl::InputSourceOriginImpl()
{
}
InputSourceOriginImpl::InputSourceOriginImpl(const Location &refLocation)
: refLocation_(refLocation)
{
}
const InputSourceOrigin *InputSourceOriginImpl::asInputSourceOrigin() const
{
return this;
}
const ExternalInfo *InputSourceOriginImpl::externalInfo() const
{
return externalInfo_.pointer();
}
InputSourceOrigin *InputSourceOriginImpl::copy() const
{
return new InputSourceOriginImpl(refLocation_);
}
const Location &InputSourceOriginImpl::parent() const
{
return refLocation_;
}
void InputSourceOriginImpl::setExternalInfo(ExternalInfo *info)
{
externalInfo_ = info;
}
void InputSourceOriginImpl::noteCharRef(Index replacementIndex,
const NamedCharRef &ref)
{
Mutex::Lock lock(&mutex_);
charRefs_.resize(charRefs_.size() + 1);
charRefs_.back().replacementIndex = replacementIndex;
charRefs_.back().refStartIndex = ref.refStartIndex();
charRefs_.back().refEndType = ref.refEndType();
charRefs_.back().origNameOffset = charRefOrigNames_.size();
charRefOrigNames_ += ref.origName();
}
// Number of character references whose replacement index < ind.
size_t InputSourceOriginImpl::nPrecedingCharRefs(Index ind) const
{
size_t i;
// Find i such that
// charRefs_[I].replacementIndex >= ind
// charRefs_[i - 1].replacementIndex < ind
if (charRefs_.size() == 0
|| ind > charRefs_.back().replacementIndex)
// This will be a common case, so optimize it.
i = charRefs_.size();
else {
// Binary search
// Invariant:
// charRefs_ < i have replacementIndex < ind
// charRefs_ >= lim have replacementIndex >= ind
i = 0;
size_t lim = charRefs_.size();
while (i < lim) {
size_t mid = i + (lim - i)/2;
if (charRefs_[mid].replacementIndex >= ind)
lim = mid;
else
i = mid + 1;
}
}
return i;
}
Offset InputSourceOriginImpl::startOffset(Index ind) const
{
Mutex::Lock lock(&((InputSourceOriginImpl *)this)->mutex_);
size_t n = nPrecedingCharRefs(ind);
if (n < charRefs_.size()
&& ind == charRefs_[n].replacementIndex) {
for (;;) {
ind = charRefs_[n].refStartIndex;
if (n == 0 || charRefs_[n - 1].replacementIndex != ind)
break;
--n;
}
}
// charRefs[n - 1].replacementIndex < ind
return Offset(ind - n);
}
Boolean InputSourceOriginImpl::isNamedCharRef(Index ind, NamedCharRef &ref) const
{
Mutex::Lock lock(&((InputSourceOriginImpl *)this)->mutex_);
size_t n = nPrecedingCharRefs(ind);
if (n < charRefs_.size() && ind == charRefs_[n].replacementIndex) {
ref.set(charRefs_[n].refStartIndex,
charRefs_[n].refEndType,
charRefOrigNames_.data() + charRefs_[n].origNameOffset,
(n + 1 < charRefs_.size()
? charRefs_[n + 1].origNameOffset
: charRefOrigNames_.size())
- charRefs_[n].origNameOffset);
return 1;
}
return 0;
}
EntityOrigin *EntityOrigin::make(Allocator &alloc,
const ConstPtr<Entity> &entity)
{
return new (alloc) EntityOriginImpl(entity);
}
EntityOrigin *EntityOrigin::make(Allocator &alloc,
const ConstPtr<Entity> &entity,
const Location &refLocation)
{
return new (alloc) EntityOriginImpl(entity, refLocation);
}
EntityOrigin *EntityOrigin::make(Allocator &alloc,
const ConstPtr<Entity> &entity,
const Location &refLocation,
Index refLength,
Owner<Markup> &markup)
{
return new (alloc) EntityOriginImpl(entity, refLocation, refLength, markup);
}
EntityOrigin *EntityOrigin::make(const ConstPtr<Entity> &entity,
const Location &refLocation,
Index refLength,
Owner<Markup> &markup)
{
return new EntityOriginImpl(entity, refLocation, refLength, markup);
}
EntityOrigin *EntityOrigin::make(const ConstPtr<Entity> &entity,
const Location &refLocation)
{
return new EntityOriginImpl(entity, refLocation);
}
EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity)
: refLength_(0), entity_(entity)
{
}
EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity,
const Location &refLocation)
: InputSourceOriginImpl(refLocation), refLength_(0), entity_(entity)
{
}
EntityOriginImpl::EntityOriginImpl(const ConstPtr<Entity> &entity,
const Location &refLocation,
Index refLength,
Owner<Markup> &markup)
: InputSourceOriginImpl(refLocation), refLength_(refLength), entity_(entity)
{
markup.swap(markup_);
}
EntityOriginImpl::~EntityOriginImpl()
{
}
InputSourceOrigin *EntityOriginImpl::copy() const
{
Owner<Markup> m;
if (markup_)
m = new Markup(*markup_);
return new EntityOriginImpl(entity_, parent(), refLength_, m);
}
Index EntityOriginImpl::refLength() const
{
return refLength_;
}
const EntityOrigin *EntityOriginImpl::asEntityOrigin() const
{
return this;
}
Boolean EntityOriginImpl::defLocation(Offset off, const Origin *&origin, Index &index) const
{
if (entity_.isNull())
return 0;
const InternalEntity *internal = entity_->asInternalEntity();
if (!internal)
return 0;
return internal->text().charLocation(off, origin, index);
}
const EntityDecl *EntityOriginImpl::entityDecl() const
{
return entity_.pointer();
}
const Markup *EntityOriginImpl::markup() const
{
return markup_.pointer();
}
ReplacementOrigin::ReplacementOrigin(const Location &loc, Char origChar)
: loc_(loc), origChar_(origChar)
{
}
const Location &ReplacementOrigin::parent() const
{
return loc_;
}
Boolean ReplacementOrigin::origChars(const Char *&s) const
{
if (loc_.origin().isNull() || !loc_.origin()->origChars(s))
s = &origChar_;
return 1;
}
MultiReplacementOrigin::MultiReplacementOrigin(const Location &loc,
StringC &origChars)
: loc_(loc)
{
origChars.swap(origChars_);
}
const Location &MultiReplacementOrigin::parent() const
{
return loc_;
}
Boolean MultiReplacementOrigin::origChars(const Char *&s) const
{
if (loc_.origin().isNull() || !loc_.origin()->origChars(s))
s = origChars_.data();
return 1;
}
ProxyOrigin::ProxyOrigin(const Origin *origin)
: origin_(origin)
{
}
const EntityOrigin *ProxyOrigin::asEntityOrigin() const
{
return origin_->asEntityOrigin();
}
const InputSourceOrigin *ProxyOrigin::asInputSourceOrigin() const
{
return origin_->asInputSourceOrigin();
}
const Location &ProxyOrigin::parent() const
{
return origin_->parent();
}
Index ProxyOrigin::refLength() const
{
return origin_->refLength();
}
Boolean ProxyOrigin::origChars(const Char *&p) const
{
return origin_->origChars(p);
}
Boolean ProxyOrigin::inBracketedTextOpenDelim() const
{
return origin_->inBracketedTextOpenDelim();
}
Boolean ProxyOrigin::inBracketedTextCloseDelim() const
{
return origin_->inBracketedTextCloseDelim();
}
Boolean ProxyOrigin::isNumericCharRef(const Markup *&markup) const
{
return origin_->isNumericCharRef(markup);
}
Boolean ProxyOrigin::isNamedCharRef(Index ind, NamedCharRef &ref) const
{
return origin_->isNamedCharRef(ind, ref);
}
const EntityDecl *ProxyOrigin::entityDecl() const
{
return origin_->entityDecl();
}
Boolean ProxyOrigin::defLocation(Offset off, const Origin *&origin, Index &index) const
{
return origin_->defLocation(off, origin, index);
}
const Markup *ProxyOrigin::markup() const
{
return origin_->markup();
}
const Entity *ProxyOrigin::entity() const
{
return origin_->entity();
}
const ExternalInfo *ProxyOrigin::externalInfo() const
{
return origin_->externalInfo();
}
Offset ProxyOrigin::startOffset(Index ind) const
{
return origin_->startOffset(ind);
}
ExternalInfo::~ExternalInfo()
{
}
RTTI_DEF0(ExternalInfo)
NamedCharRef::NamedCharRef()
{
}
NamedCharRef::NamedCharRef(Index refStartIndex, RefEndType refEndType,
const StringC &origName)
: refStartIndex_(refStartIndex),
refEndType_(refEndType),
origName_(origName)
{
}
void NamedCharRef::set(Index refStartIndex, RefEndType refEndType,
const Char *s, size_t n)
{
refStartIndex_ = refStartIndex;
refEndType_ = refEndType;
origName_.assign(s, n);
}
#ifdef SP_NAMESPACE
}
#endif