ContentState.cxx revision 7c478bd95313f5f23a4c958a745db2134aa03244
// Copyright (c) 1994, 1996 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 "ContentState.h"
#include "IListIter.h"
#include "NCVector.h"
#include "macros.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
const ShortReferenceMap ContentState::theEmptyMap;
#ifdef __GNUG__
typedef IListIter<OpenElement> Dummy_IListIter_OpenElement;
#endif
ContentState::ContentState()
: documentElementContainer_(StringC(), size_t(-1))
{
}
void ContentState::startContent(const Dtd &dtd)
{
NCVector<Owner<ContentToken> > tokens(1);
tokens[0] = new ElementToken(dtd.documentElementType(),
ContentToken::none);
Owner<ModelGroup> model(new SeqModelGroup(tokens, ContentToken::none));
Owner<CompiledModelGroup> compiledModel(new CompiledModelGroup(model));
Vector<ContentModelAmbiguity> ambiguities;
Boolean pcdataUnreachable;
compiledModel->compile(dtd.nElementTypeIndex(), ambiguities,
pcdataUnreachable);
ASSERT(ambiguities.size() == 0);
ConstPtr<ElementDefinition> def
= new ElementDefinition(Location(),
0,
0,
ElementDefinition::modelGroup,
compiledModel);
documentElementContainer_.setElementDefinition(def, 0);
tagLevel_ = 0;
while (!openElements_.empty())
delete openElements_.get();
openElements_.insert(new OpenElement(&documentElementContainer_,
0,
0,
&theEmptyMap,
Location()));
includeCount_.assign(dtd.nElementTypeIndex(), 0);
excludeCount_.assign(dtd.nElementTypeIndex(), 0);
openElementCount_.assign(dtd.nElementTypeIndex(), 0);
netEnablingCount_ = 0;
totalExcludeCount_ = 0;
lastEndedElementType_ = 0;
nextIndex_ = 0;
}
void ContentState::pushElement(OpenElement *e)
{
tagLevel_++;
openElementCount_[e->type()->index()]++;
const ElementDefinition *def = e->type()->definition();
if (def) {
size_t i;
for (i = 0; i < def->nInclusions(); i++)
includeCount_[def->inclusion(i)->index()]++;
for (i = 0; i < def->nExclusions(); i++) {
excludeCount_[def->exclusion(i)->index()]++;
totalExcludeCount_++;
}
}
if (e->netEnabling())
netEnablingCount_++;
e->setIndex(nextIndex_++);
openElements_.insert(e);
}
OpenElement *ContentState::popSaveElement()
{
ASSERT(tagLevel_ > 0);
OpenElement *e = openElements_.get();
tagLevel_--;
openElementCount_[e->type()->index()]--;
const ElementDefinition *def = e->type()->definition();
if (def) {
size_t i;
for (i = 0; i < def->nInclusions(); i++)
includeCount_[def->inclusion(i)->index()]--;
for (i = 0; i < def->nExclusions(); i++) {
excludeCount_[def->exclusion(i)->index()]--;
totalExcludeCount_--;
}
}
if (e->netEnabling())
netEnablingCount_--;
lastEndedElementType_ = e->type();
return e;
}
void ContentState::popElement()
{
delete popSaveElement();
}
Boolean ContentState::checkImplyLoop(unsigned count)
{
for (IListIter<OpenElement> iter(openElements_);
count > 0;
iter.next(), count--)
if (iter.cur()->type() == openElements_.head()->type()
// I'm not sure whether this is necessary.
&& iter.cur()->matchState() == openElements_.head()->matchState())
return 0;
return 1;
}
void ContentState::getOpenElementInfo(Vector<OpenElementInfo> &v,
const StringC &rniPcdata) const
{
v.clear();
v.resize(tagLevel_);
unsigned i = tagLevel_;
for (IListIter<OpenElement> iter(openElements_);
!iter.done() && i > 0;
iter.next()) {
OpenElementInfo &e = v[--i];
e.gi = iter.cur()->type()->name();
const LeafContentToken *token = iter.cur()->currentPosition();
if (token && !token->isInitial()) {
e.matchIndex = token->typeIndex() + 1;
const ElementType *type = token->elementType();
e.matchType = type ? type->name() : rniPcdata;
}
e.included = iter.cur()->included();
}
}
ElementType *
ContentState::lookupCreateUndefinedElement(const StringC &name,
const Location &loc,
Dtd &dtd)
{
ElementType *p = new ElementType(name,
dtd.allocElementTypeIndex());
dtd.insertUndefinedElementType(p);
p->setElementDefinition(new ElementDefinition(loc,
size_t(ElementDefinition::undefinedIndex),
0,
ElementDefinition::any),
0);
p->setAttributeDef(dtd.implicitElementAttributeDef());
includeCount_.push_back(0);
excludeCount_.push_back(0);
openElementCount_.push_back(0);
return p;
}
#ifdef SP_NAMESPACE
}
#endif