// Copyright (c) 1994 James Clark // See the file COPYING for copying permission. #ifndef Attribute_INCLUDED #define Attribute_INCLUDED 1 #ifdef __GNUG__ #pragma interface #endif #include #include "Resource.h" #include "Owner.h" #include "StringC.h" #include "Vector.h" #include "CopyOwner.h" #include "Boolean.h" #include "Text.h" #include "Ptr.h" #include "Message.h" #ifdef SP_NAMESPACE namespace SP_NAMESPACE { #endif class Entity; class Notation; class DeclaredValue; class AttributeValue; class TokenizedAttributeValue; class AttributeSemantics; class AttributeContext; class Syntax; class SP_API AttributeValue : public Resource { public: enum Type { implied, cdata, tokenized }; AttributeValue(); virtual ~AttributeValue(); virtual AttributeSemantics *makeSemantics(const DeclaredValue *, AttributeContext &, const StringC &, unsigned &, unsigned &) const; virtual Type info(const Text *&, const StringC *&) const = 0; virtual const Text *text() const; virtual Boolean recoverUnquoted(const StringC &, const Location &, AttributeContext &, const StringC &); static Boolean handleAsUnterminated(const Text &, AttributeContext &); }; class SP_API AttributeDefinitionDesc { public: AttributeDefinitionDesc() { } enum DeclaredValue { cdata, name, number, nmtoken, nutoken, entity, idref, names, numbers, nmtokens, nutokens, entities, idrefs, id, notation, nameTokenGroup }; DeclaredValue declaredValue; enum DefaultValueType { required, current, implied, conref, defaulted, fixed }; DefaultValueType defaultValueType; ConstPtr defaultValue; Vector allowedValues; Vector origAllowedValues; // Attribute definitions whose default value type is current and // which have the same currentIndex share current values. size_t currentIndex; private: AttributeDefinitionDesc(const AttributeDefinitionDesc &); // undefined void operator=(const AttributeDefinitionDesc &); // undefined }; class DeclaredValue { public: DeclaredValue(); virtual ~DeclaredValue(); // This performs syntactic checking on the value. virtual AttributeValue *makeValue(Text &, AttributeContext &, const StringC &name, unsigned &specLength) const = 0; // This is used to avoid unnecessary syntactic checking in the // case where the attribute name and vi have been omitted. virtual AttributeValue *makeValueFromToken(Text &, AttributeContext &, const StringC &name, unsigned &specLength) const; // This performs semantic checking on the value. virtual AttributeSemantics *makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &nIdrefs, unsigned &nEntityNames) const; virtual Boolean containsToken(const StringC &) const; virtual Boolean tokenized() const = 0; virtual Boolean isNotation() const; virtual Boolean isEntity() const; virtual Boolean isId() const; virtual Boolean isIdref() const; virtual const Vector *getTokens() const; virtual const Vector *getOrigTokens() const; virtual void buildDesc(AttributeDefinitionDesc &) const = 0; virtual DeclaredValue *copy() const = 0; }; class CdataDeclaredValue : public DeclaredValue { public: CdataDeclaredValue(); Boolean tokenized() const; AttributeValue *makeValue(Text &, AttributeContext &, const StringC &, unsigned &) const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; protected: void checkNormalizedLength(Text &, AttributeContext &, unsigned &) const; }; class TokenizedDeclaredValue : public DeclaredValue { public: // must be in same order as AttributeDefinitionDesc enum TokenType { name, number, nameToken, numberToken, entityName }; TokenizedDeclaredValue(TokenType type, Boolean isList); AttributeValue *makeValue(Text &, AttributeContext &, const StringC &, unsigned &) const; TokenizedAttributeValue *makeTokenizedValue(Text &, AttributeContext &, const StringC &, unsigned &) const; Boolean tokenized() const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; private: TokenType type_; Boolean isList_; unsigned initialCategories_; unsigned subsequentCategories_; }; class GroupDeclaredValue : public TokenizedDeclaredValue { public: GroupDeclaredValue(TokenType, Vector &); Boolean containsToken(const StringC &) const; AttributeValue *makeValue(Text &, AttributeContext &, const StringC &, unsigned &) const; AttributeValue *makeValueFromToken(Text &, AttributeContext &, const StringC &name, unsigned &) const; const Vector *getTokens() const; const Vector *getOrigTokens() const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; void setOrigAllowedValues(Vector &origAllowedValues); private: Vector allowedValues_; Vector origAllowedValues_; }; class NameTokenGroupDeclaredValue : public GroupDeclaredValue { public: NameTokenGroupDeclaredValue(Vector &); void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; }; class NotationDeclaredValue : public GroupDeclaredValue { public: NotationDeclaredValue(Vector &); AttributeSemantics *makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &nIdrefs, unsigned &nEntityNames) const; Boolean isNotation() const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; }; class EntityDeclaredValue : public TokenizedDeclaredValue { public: EntityDeclaredValue(Boolean isList); AttributeSemantics *makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &nIdrefs, unsigned &nEntityNames) const; Boolean isEntity() const; DeclaredValue *copy() const; }; class IdDeclaredValue : public TokenizedDeclaredValue { public: IdDeclaredValue(); AttributeSemantics *makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &nIdrefs, unsigned &nEntityNames) const; Boolean isId() const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; }; class IdrefDeclaredValue : public TokenizedDeclaredValue { public: IdrefDeclaredValue(Boolean isList); AttributeSemantics *makeSemantics(const TokenizedAttributeValue &, AttributeContext &, const StringC &, unsigned &nIdrefs, unsigned &nEntityNames) const; Boolean isIdref() const; void buildDesc(AttributeDefinitionDesc &) const; DeclaredValue *copy() const; }; class SP_API AttributeDefinition { public: AttributeDefinition(const StringC &, DeclaredValue *); virtual ~AttributeDefinition(); virtual ConstPtr makeMissingValue(AttributeContext &) const = 0; virtual Boolean missingValueWouldMatch(const Text &, const AttributeContext &) const; virtual const AttributeValue * defaultValue(const AttributeValue *impliedValue) const; AttributeValue *makeValue(Text &, AttributeContext &, unsigned &) const; AttributeValue *makeValueFromToken(Text &, AttributeContext &, unsigned &) const; virtual Boolean isConref() const; virtual Boolean isCurrent() const; virtual Boolean isFixed() const; AttributeSemantics *makeSemantics(const AttributeValue *, AttributeContext &, unsigned &nIdrefs, unsigned &nEntityNames) const; Boolean tokenized() const; const StringC &name() const; const StringC &origName() const; Boolean containsToken(const StringC &) const; Boolean isNotation() const; Boolean isEntity() const; Boolean isId() const; Boolean isIdref() const; void getDesc(AttributeDefinitionDesc &) const; const Vector *getTokens() const; const Vector *getOrigTokens() const; virtual AttributeDefinition *copy() const = 0; void setDeclaredValue(DeclaredValue *); void setSpecified(Boolean implicit); Boolean isSpecified(Boolean &implicit); void setOrigName(StringC &origName); private: virtual void buildDesc(AttributeDefinitionDesc &) const = 0; virtual AttributeValue *checkValue(AttributeValue *, AttributeContext &) const; PackedBoolean implicit_; PackedBoolean all_; StringC name_; StringC origName_; CopyOwner declaredValue_; }; class RequiredAttributeDefinition : public AttributeDefinition { public: RequiredAttributeDefinition(const StringC &, DeclaredValue *); ConstPtr makeMissingValue(AttributeContext &) const; void buildDesc(AttributeDefinitionDesc &) const; AttributeDefinition *copy() const; }; class CurrentAttributeDefinition : public AttributeDefinition { public: CurrentAttributeDefinition(const StringC &, DeclaredValue *, size_t index); ConstPtr makeMissingValue(AttributeContext &) const; Boolean missingValueWouldMatch(const Text &, const AttributeContext &) const; AttributeValue *checkValue(AttributeValue *, AttributeContext &) const; void buildDesc(AttributeDefinitionDesc &) const; Boolean isCurrent() const; AttributeDefinition *copy() const; private: size_t currentIndex_; }; class ImpliedAttributeDefinition : public AttributeDefinition { public: ImpliedAttributeDefinition(const StringC &, DeclaredValue *); ConstPtr makeMissingValue(AttributeContext &) const; const AttributeValue *defaultValue(const AttributeValue *) const; void buildDesc(AttributeDefinitionDesc &) const; AttributeDefinition *copy() const; }; class ConrefAttributeDefinition : public ImpliedAttributeDefinition { public: ConrefAttributeDefinition(const StringC &, DeclaredValue *); Boolean isConref() const; void buildDesc(AttributeDefinitionDesc &) const; AttributeDefinition *copy() const; }; class DefaultAttributeDefinition : public AttributeDefinition { public: DefaultAttributeDefinition(const StringC &, DeclaredValue *, AttributeValue *); ConstPtr makeMissingValue(AttributeContext &) const; Boolean missingValueWouldMatch(const Text &, const AttributeContext &) const; void buildDesc(AttributeDefinitionDesc &) const; AttributeDefinition *copy() const; const AttributeValue *defaultValue(const AttributeValue *) const; private: ConstPtr value_; }; class FixedAttributeDefinition : public DefaultAttributeDefinition { public: FixedAttributeDefinition(const StringC &, DeclaredValue *, AttributeValue *); // check that it's equal to the default AttributeValue *checkValue(AttributeValue *, AttributeContext &) const; void buildDesc(AttributeDefinitionDesc &) const; Boolean isFixed() const; AttributeDefinition *copy() const; }; class SP_API AttributeDefinitionList : public Resource { public: AttributeDefinitionList(Vector > &, size_t listIndex, Boolean anyCurrent = 0, size_t idIndex = size_t(-1), size_t notationIndex = size_t(-1)); AttributeDefinitionList(const ConstPtr &); ~AttributeDefinitionList(); size_t size() const; AttributeDefinition *def(size_t); const AttributeDefinition *def(size_t) const; Boolean tokenIndex(const StringC &, unsigned &) const; Boolean tokenIndexUnique(const StringC &, unsigned) const; Boolean attributeIndex(const StringC &, unsigned &) const; size_t index() const; size_t idIndex() const; size_t notationIndex() const; Boolean anyCurrent() const; void setIndex(size_t); void append(AttributeDefinition *); private: Vector > defs_; size_t index_; size_t idIndex_; // -1 if no ID attribute size_t notationIndex_; // -1 if no notation attribute Boolean anyCurrent_; ConstPtr prev_; }; class AttributeSemantics { public: AttributeSemantics(); virtual ~AttributeSemantics(); virtual size_t nEntities() const; virtual ConstPtr entity(size_t) const; virtual ConstPtr notation() const; virtual AttributeSemantics *copy() const = 0; }; class EntityAttributeSemantics : public AttributeSemantics { public: EntityAttributeSemantics(Vector > &); size_t nEntities() const; ConstPtr entity(size_t) const; AttributeSemantics *copy() const; private: Vector > entity_; }; class NotationAttributeSemantics : public AttributeSemantics { public: NotationAttributeSemantics(const ConstPtr &); ConstPtr notation() const; AttributeSemantics *copy() const; private: ConstPtr notation_; }; class SP_API ImpliedAttributeValue : public AttributeValue { public: ImpliedAttributeValue(); Type info(const Text *&, const StringC *&) const; }; class CdataAttributeValue : public AttributeValue { public: CdataAttributeValue(Text &); Type info(const Text *&, const StringC *&) const; const Text *text() const; Boolean recoverUnquoted(const StringC &, const Location &, AttributeContext &, const StringC &); virtual const Notation *notation() const; private: Text text_; }; class TokenizedAttributeValue : public AttributeValue { public: TokenizedAttributeValue(Text &, const Vector &); size_t nTokens() const; AttributeSemantics *makeSemantics(const DeclaredValue *, AttributeContext &, const StringC &, unsigned &, unsigned &) const; Type info(const Text *&, const StringC *&) const; const Text *text() const; const StringC &string() const; StringC token(size_t) const; void token(size_t, const Char *&, size_t &) const; Location tokenLocation(size_t) const; Boolean tokenLocation(size_t, const ConstPtr *&, Index &) const; Boolean recoverUnquoted(const StringC &, const Location &, AttributeContext &, const StringC &); private: TokenizedAttributeValue(const TokenizedAttributeValue &); // undefined void operator=(const TokenizedAttributeValue &); // undefined Text text_; // index into value of each space // length is number of tokens - 1 Vector spaceIndex_; }; class SP_API Attribute { public: Attribute(); Attribute(const Attribute&); ~Attribute(); Attribute& operator=(const Attribute&); Boolean specified() const; size_t specIndex() const; const AttributeValue *value() const; const ConstPtr &valuePointer() const; const AttributeSemantics *semantics() const; void setSpec(size_t); void setValue(const ConstPtr &); void setSemantics(AttributeSemantics *); void clear(); private: size_t specIndexPlus_; ConstPtr value_; CopyOwner semantics_; }; class SP_API AttributeList { public: AttributeList(); AttributeList(const ConstPtr &); inline ~AttributeList() {} void init(const ConstPtr &); // was a conref attribute specified? Boolean conref() const; size_t size() const; const StringC &name(unsigned) const; const AttributeValue *value(unsigned) const; size_t specIndex(size_t) const; const ConstPtr &valuePointer(unsigned) const; const AttributeSemantics *semantics(unsigned) const; Boolean tokenized(unsigned index) const; Boolean tokenIndex(const StringC &, unsigned &) const; Boolean tokenIndexUnique(const StringC &, unsigned) const; Boolean attributeIndex(const StringC &, unsigned &) const; void finish(AttributeContext &); Boolean setValue(unsigned index, Text &, AttributeContext &, unsigned &specLength); void setValueToken(unsigned index, Text &, AttributeContext &, unsigned &specLength); void setSpec(unsigned index, AttributeContext &); Boolean recoverUnquoted(const StringC &, const Location &, AttributeContext &); Boolean handleAsUnterminated(AttributeContext &context); void swap(AttributeList &); size_t nSpec() const; size_t defIndex() const; // is the attribute #current Boolean current(unsigned) const; Boolean anyCurrent() const; Boolean specified(unsigned) const; Boolean id(unsigned) const; Boolean idref(unsigned) const; const Vector *getAllowedTokens(unsigned) const; const StringC *getId() const; // null if none Boolean idIndex(unsigned &) const; void noteInvalidSpec(); void changeDef(const ConstPtr &); const ConstPtr &def() const; private: const AttributeDefinition *def(size_t) const; PackedBoolean conref_; unsigned nIdrefs_; unsigned nEntityNames_; size_t nSpec_; Vector vec_; ConstPtr def_; }; class DataDeclaredValue : public CdataDeclaredValue { public: DataDeclaredValue(const ConstPtr &, AttributeList &); AttributeValue *makeValue(Text &, AttributeContext &, const StringC &, unsigned &) const; DeclaredValue *copy() const; private: ConstPtr notation_; AttributeList attributes_; }; class SP_API DataAttributeValue : public CdataAttributeValue { public: DataAttributeValue(Text &, const ConstPtr &, const AttributeList &); const AttributeList &attributes() const; const Notation *notation() const; private: const ConstPtr notation_; const AttributeList *attributes_; }; class SP_API AttributeContext : public Messenger { public: AttributeContext(); virtual ~AttributeContext(); virtual Boolean defineId(const StringC &, const Location &, Location &); virtual void noteIdref(const StringC &, const Location &); virtual void noteCurrentAttribute(size_t, AttributeValue *); virtual ConstPtr getCurrentAttribute(size_t) const; virtual ConstPtr getAttributeEntity(const StringC &, const Location &); virtual ConstPtr getAttributeNotation(const StringC &, const Location &); virtual const Syntax &attributeSyntax() const = 0; ConstPtr makeImpliedAttributeValue(); Boolean mayDefaultAttribute() const; Boolean validate() const; protected: Boolean mayDefaultAttribute_; Boolean validate_; private: ConstPtr impliedAttributeValue_; }; inline Boolean AttributeDefinition::tokenized() const { return declaredValue_->tokenized(); } inline Boolean AttributeDefinition::isNotation() const { return declaredValue_->isNotation(); } inline Boolean AttributeDefinition::isEntity() const { return declaredValue_->isEntity(); } inline Boolean AttributeDefinition::isId() const { return declaredValue_->isId(); } inline Boolean AttributeDefinition::isIdref() const { return declaredValue_->isIdref(); } inline const Vector *AttributeDefinition::getTokens() const { return declaredValue_->getTokens(); } inline const Vector *AttributeDefinition::getOrigTokens() const { return declaredValue_->getOrigTokens(); } inline AttributeSemantics * AttributeDefinition::makeSemantics(const AttributeValue *value, AttributeContext &context, unsigned &nIdrefs, unsigned &nEntityNames) const { return value->makeSemantics(declaredValue_.pointer(), context, name_, nIdrefs, nEntityNames); } inline AttributeValue *AttributeDefinition::makeValue(Text &text, AttributeContext &context, unsigned &specLength) const { return checkValue(declaredValue_->makeValue(text, context, name_, specLength), context); } inline AttributeValue * AttributeDefinition::makeValueFromToken(Text &text, AttributeContext &context, unsigned &specLength) const { return checkValue(declaredValue_->makeValueFromToken(text, context, name_, specLength), context); } inline Boolean AttributeDefinition::containsToken(const StringC &token) const { return declaredValue_->containsToken(token); } inline const StringC &AttributeDefinition::name() const { return name_; } inline const StringC &AttributeDefinition::origName() const { return origName_; } inline void AttributeDefinition::setDeclaredValue(DeclaredValue *declaredValue) { declaredValue_ = declaredValue; } inline size_t AttributeDefinitionList::size() const { return defs_.size(); } inline size_t AttributeDefinitionList::index() const { return index_; } inline void AttributeDefinitionList::setIndex(size_t index) { index_ = index; } inline size_t AttributeDefinitionList::idIndex() const { return idIndex_; } inline size_t AttributeDefinitionList::notationIndex() const { return notationIndex_; } inline Boolean AttributeDefinitionList::anyCurrent() const { return anyCurrent_; } inline AttributeDefinition *AttributeDefinitionList::def(size_t i) { return defs_[i].pointer(); } inline const AttributeDefinition *AttributeDefinitionList::def(size_t i) const { return defs_[i].pointer(); } inline size_t TokenizedAttributeValue::nTokens() const { return spaceIndex_.size() + 1; } inline const StringC &TokenizedAttributeValue::string() const { return text_.string(); } inline void TokenizedAttributeValue::token(size_t i, const Char *&ptr, size_t &len) const { size_t startIndex = i == 0 ? 0 : spaceIndex_[i - 1] + 1; ptr = text_.string().data() + startIndex; len = (i == spaceIndex_.size() ? text_.size() : spaceIndex_[i]) - startIndex; } inline StringC TokenizedAttributeValue::token(size_t i) const { const Char *ptr; size_t len; token(i, ptr, len); return StringC(ptr, len); } inline Location TokenizedAttributeValue::tokenLocation(size_t i) const { return text_.charLocation(i == 0 ? 0 : spaceIndex_[i - 1] + 1); } inline Boolean TokenizedAttributeValue::tokenLocation(size_t i, const ConstPtr *&origin, Index &index) const { return text_.charLocation(i == 0 ? 0 : spaceIndex_[i - 1] + 1, origin, index); } inline size_t Attribute::specIndex() const { return specIndexPlus_ - 1; } inline Boolean Attribute::specified() const { return specIndexPlus_ != 0; } inline const AttributeValue *Attribute::value() const { return value_.pointer(); } inline const ConstPtr &Attribute::valuePointer() const { return value_; } inline const AttributeSemantics *Attribute::semantics() const { return semantics_.pointer(); } inline void Attribute::setSpec(size_t index) { specIndexPlus_ = index + 1; } inline void Attribute::setValue(const ConstPtr &value) { value_ = value; } inline void Attribute::setSemantics(AttributeSemantics *semantics) { semantics_ = semantics; } inline size_t AttributeList::size() const { return vec_.size(); } inline const AttributeDefinition *AttributeList::def(size_t i) const { return def_->def(i); } inline const ConstPtr &AttributeList::def() const { return def_; } inline Boolean AttributeList::tokenized(unsigned i) const { return def(i)->tokenized(); } inline Boolean AttributeList::tokenIndex(const StringC &name, unsigned &index) const { return !def_.isNull() && def_->tokenIndex(name, index); } inline Boolean AttributeList::tokenIndexUnique(const StringC &name, unsigned index) const { return def_->tokenIndexUnique(name, index); } inline Boolean AttributeList::attributeIndex(const StringC &name, unsigned &index) const { return !def_.isNull() && def_->attributeIndex(name, index); } inline const StringC &AttributeList::name(unsigned i) const { return def(i)->name(); } inline const Vector *AttributeList::getAllowedTokens(unsigned i) const { return def(i)->getTokens(); } inline const AttributeValue *AttributeList::value(unsigned i) const { return vec_[i].value(); } inline const ConstPtr &AttributeList::valuePointer(unsigned i) const { return vec_[i].valuePointer(); } inline const AttributeSemantics *AttributeList::semantics(unsigned i) const { return vec_[i].semantics(); } inline size_t AttributeList::specIndex(size_t i) const { return vec_[i].specIndex(); } inline size_t AttributeList::nSpec() const { return nSpec_; } inline Boolean AttributeList::conref() const { return conref_; } inline size_t AttributeList::defIndex() const { return def_.isNull() ? size_t(-1) : def_->index(); } inline Boolean AttributeList::current(unsigned i) const { return def(i)->isCurrent(); } inline Boolean AttributeList::anyCurrent() const { return !def_.isNull() && def_->anyCurrent(); } inline const AttributeValue * DefaultAttributeDefinition::defaultValue(const AttributeValue *) const { return value_.pointer(); } inline Boolean AttributeList::idIndex(unsigned &ind) const { if (def_.isNull() || def_->idIndex() == size_t(-1)) return 0; else { ind = def_->idIndex(); return 1; } } inline Boolean AttributeList::id(unsigned i) const { return def(i)->isId(); } inline Boolean AttributeList::idref(unsigned i) const { return def(i)->isIdref(); } inline Boolean AttributeList::specified(unsigned i) const { return vec_[i].specified(); } inline Boolean AttributeContext::mayDefaultAttribute() const { return mayDefaultAttribute_; } inline Boolean AttributeContext::validate() const { return validate_; } #ifdef SP_NAMESPACE } #endif #endif /* not Attribute_INCLUDED */