2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: Attribute.C /main/1 1996/07/29 16:46:34 cde-hp $ */
24 // Copyright (c) 1994 James Clark
25 // See the file COPYING for copying permission.
28 #pragma implementation
31 #include "Attribute.h"
32 #include "MessageArg.h"
34 #include "ParserMessages.h"
35 #include "StringVectorMessageArg.h"
41 namespace SP_NAMESPACE {
44 DeclaredValue::DeclaredValue()
48 DeclaredValue::~DeclaredValue()
52 AttributeValue *DeclaredValue::makeValueFromToken(Text &text,
53 AttributeContext &context,
55 unsigned &specLength) const
57 return makeValue(text, context, name, specLength);
60 AttributeSemantics *DeclaredValue::makeSemantics(const TokenizedAttributeValue &,
69 Boolean DeclaredValue::containsToken(const StringC &) const
74 Boolean DeclaredValue::isNotation() const
79 Boolean DeclaredValue::isEntity() const
84 Boolean DeclaredValue::isId() const
89 Boolean DeclaredValue::isIdref() const
94 const Vector<StringC> *DeclaredValue::getTokens() const
100 CdataDeclaredValue::CdataDeclaredValue()
104 Boolean CdataDeclaredValue::tokenized() const
109 AttributeValue *CdataDeclaredValue::makeValue(Text &text, AttributeContext &context,
111 unsigned &specLength) const
113 const Syntax &syntax = context.attributeSyntax();
114 size_t normsep = syntax.normsep();
115 size_t normalizedLength = text.size() + (normsep
116 * (1 + text.nDataEntities()));
117 specLength += normalizedLength;
118 size_t litlen = syntax.litlen();
119 // A length error will already have been given if
120 // length > litlen - normsep.
121 if (litlen >= normsep && text.size() <= litlen - normsep
122 && normalizedLength > litlen)
123 context.message(ParserMessages::normalizedAttributeValueLength,
124 NumberMessageArg(litlen),
125 NumberMessageArg(normalizedLength));
126 return new CdataAttributeValue(text);
129 void CdataDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
131 desc.declaredValue = AttributeDefinitionDesc::cdata;
134 DeclaredValue *CdataDeclaredValue::copy() const
136 return new CdataDeclaredValue(*this);
139 TokenizedDeclaredValue::TokenizedDeclaredValue(TokenType type,
141 : type_(type), isList_(isList)
146 initialCategories_ = Syntax::nameStartCategory;
147 subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
148 | Syntax::otherNameCategory);
151 initialCategories_ = Syntax::digitCategory;
152 subsequentCategories_ = Syntax::digitCategory;
155 initialCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
156 | Syntax::otherNameCategory);
157 subsequentCategories_ = initialCategories_;
160 initialCategories_ = Syntax::digitCategory;
161 subsequentCategories_ = (Syntax::nameStartCategory|Syntax::digitCategory
162 | Syntax::otherNameCategory);
167 Boolean TokenizedDeclaredValue::tokenized() const
172 AttributeValue *TokenizedDeclaredValue::makeValue(Text &text,
173 AttributeContext &context,
175 unsigned &specLength) const
177 return makeTokenizedValue(text, context, str, specLength);
180 TokenizedAttributeValue *
181 TokenizedDeclaredValue::makeTokenizedValue(Text &text,
182 AttributeContext &context,
184 unsigned &specLength) const
186 const Syntax &syntax = context.attributeSyntax();
187 Vector<size_t> spaceIndex;
188 Char space = syntax.space();
189 text.subst(*(type_ == entityName
190 ? syntax.entitySubstTable()
191 : syntax.generalSubstTable()),
193 const StringC &value = text.string();
195 size_t length = value.size();
199 // ends with a space (which would have to have been entered
200 // via a numeric character reference)
201 context.message(ParserMessages::attributeValueSyntax);
204 if (!(syntax.charCategory(value[i]) & initialCategories_)) {
205 context.Messenger::setNextLocation(text.charLocation(i));
207 if (!(syntax.charCategory(value[i]) & subsequentCategories_))
208 context.message(ParserMessages::attributeValueChar,
209 StringMessageArg(StringC(&c, 1)),
210 StringMessageArg(name));
211 else if (initialCategories_ == Syntax::digitCategory)
212 context.message(ParserMessages::attributeValueNumberToken,
213 StringMessageArg(StringC(&c, 1)),
214 StringMessageArg(name));
216 context.message(ParserMessages::attributeValueName,
217 StringMessageArg(StringC(&c, 1)),
218 StringMessageArg(name));
221 size_t startIndex = i;
224 && (syntax.charCategory(value[i]) & subsequentCategories_);
227 if (i - startIndex > syntax.namelen()) {
228 context.Messenger::setNextLocation(text.charLocation(i));
229 context.message(ParserMessages::nameTokenLength,
230 NumberMessageArg(syntax.namelen()));
234 if (value[i] == space) {
236 context.Messenger::setNextLocation(text.charLocation(i));
237 context.message(ParserMessages::attributeValueMultiple,
238 StringMessageArg(name));
241 spaceIndex.push_back(i);
246 // character value[i] is not allowed anywhere in the value
247 context.Messenger::setNextLocation(text.charLocation(i));
248 context.message(ParserMessages::attributeValueChar,
249 StringMessageArg(StringC(&c, 1)),
250 StringMessageArg(name));
254 size_t normsep = syntax.normsep();
255 size_t litlen = syntax.litlen();
256 size_t normalizedLength = normsep + length;
257 // should we count CDATA and SDATA entities here?
259 normalizedLength += 1;
260 // length is now the number of characters in each token in the list
261 // + 1 for each token in the list; so add normsep - 1 for each
262 // token in the list.
264 normalizedLength += (normsep - 1)*(spaceIndex.size() + 1);
266 normalizedLength -= spaceIndex.size() + 1;
268 specLength += normalizedLength;
269 // A length error will already have been given if
270 // length > litlen - normsep.
271 if (litlen >= normsep && length <= litlen - normsep
272 && normalizedLength > litlen)
273 context.message(ParserMessages::normalizedAttributeValueLength,
274 NumberMessageArg(litlen),
275 NumberMessageArg(normalizedLength));
276 return new TokenizedAttributeValue(text, spaceIndex);
279 Boolean TokenizedAttributeValue::recoverUnquoted(const StringC &str,
280 const Location &strLoc,
281 AttributeContext &context,
284 TextIter iter(text_);
289 if (iter.next(type, s, len, loc)
290 && type == TextItem::data
291 && len == text_.size()
292 && loc->origin().pointer() == strLoc.origin().pointer()
293 && loc->index() + len == strLoc.index()
294 && !iter.next(type, s, len, loc)) {
295 context.Messenger::setNextLocation(strLoc);
296 context.message(ParserMessages::attributeValueChar,
297 StringMessageArg(StringC(str.data(), 1)),
298 StringMessageArg(name));
304 void TokenizedDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
306 desc.declaredValue = AttributeDefinitionDesc::DeclaredValue(
307 type_ - name + (isList_
308 ? AttributeDefinitionDesc::names
309 : AttributeDefinitionDesc::name));
312 DeclaredValue *TokenizedDeclaredValue::copy() const
314 return new TokenizedDeclaredValue(*this);
317 GroupDeclaredValue::GroupDeclaredValue(TokenType type,
318 Vector<StringC> &vec)
319 : TokenizedDeclaredValue(type, 0)
321 vec.swap(allowedValues_);
324 void GroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
326 desc.allowedValues = allowedValues_;
329 DeclaredValue *GroupDeclaredValue::copy() const
331 return new GroupDeclaredValue(*this);
334 AttributeValue *GroupDeclaredValue::makeValue(Text &text,
335 AttributeContext &context,
337 unsigned &specLength) const
339 TokenizedAttributeValue *val = makeTokenizedValue(text, context, name,
343 for (size_t i = 0; i < allowedValues_.size(); i++)
344 if (val->string() == allowedValues_[i])
346 context.message(ParserMessages::attributeValueNotInGroup,
347 StringMessageArg(val->string()),
348 StringMessageArg(name),
349 StringVectorMessageArg(allowedValues_));
354 AttributeValue *GroupDeclaredValue::makeValueFromToken(Text &text,
355 AttributeContext &context,
357 unsigned &specLength)
360 const Syntax &syntax = context.attributeSyntax();
361 size_t litlen = syntax.litlen();
362 size_t normsep = syntax.normsep();
363 if (normsep > litlen || text.size() > litlen - normsep)
364 context.message(ParserMessages::normalizedAttributeValueLength,
365 NumberMessageArg(litlen),
366 NumberMessageArg(text.size() + normsep));
367 specLength += text.size() + normsep;
368 return new TokenizedAttributeValue(text, Vector<size_t>());
371 Boolean GroupDeclaredValue::containsToken(const StringC &token) const
373 for (size_t i = 0; i < allowedValues_.size(); i++)
374 if (allowedValues_[i] == token)
379 const Vector<StringC> *GroupDeclaredValue::getTokens() const
381 return &allowedValues_;
384 NameTokenGroupDeclaredValue::NameTokenGroupDeclaredValue(Vector<StringC> &vec)
385 : GroupDeclaredValue(nameToken, vec)
389 void NameTokenGroupDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
391 GroupDeclaredValue::buildDesc(desc);
392 desc.declaredValue = AttributeDefinitionDesc::nameTokenGroup;
395 DeclaredValue *NameTokenGroupDeclaredValue::copy() const
397 return new NameTokenGroupDeclaredValue(*this);
400 NotationDeclaredValue::NotationDeclaredValue(Vector<StringC> &vec)
401 : GroupDeclaredValue(name, vec)
405 Boolean NotationDeclaredValue::isNotation() const
411 NotationDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
412 AttributeContext &context,
417 ConstPtr<Notation> notation
418 = context.getAttributeNotation(value.string(),
419 value.tokenLocation(0));
420 if (notation.isNull()) {
421 context.setNextLocation(value.tokenLocation(0));
422 context.message(ParserMessages::invalidNotationAttribute,
423 StringMessageArg(value.string()));
426 return new NotationAttributeSemantics(notation);
429 void NotationDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
431 GroupDeclaredValue::buildDesc(desc);
432 desc.declaredValue = AttributeDefinitionDesc::notation;
435 DeclaredValue *NotationDeclaredValue::copy() const
437 return new NotationDeclaredValue(*this);
440 EntityDeclaredValue::EntityDeclaredValue(Boolean isList)
441 : TokenizedDeclaredValue(entityName, isList)
445 Boolean EntityDeclaredValue::isEntity() const
451 EntityDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
452 AttributeContext &context,
455 unsigned &nEntityNames) const
458 size_t nTokens = value.nTokens();
459 nEntityNames += nTokens;
460 Vector<ConstPtr<Entity> > entities(nTokens);
461 for (size_t i = 0; i < nTokens; i++) {
462 entities[i] = context.getAttributeEntity(value.token(i),
463 value.tokenLocation(i));
464 if (entities[i].isNull()) {
465 context.setNextLocation(value.tokenLocation(i));
466 context.message(ParserMessages::invalidEntityAttribute,
467 StringMessageArg(value.token(i)));
470 else if (!entities[i]->isDataOrSubdoc()) {
471 context.Messenger::setNextLocation(value.tokenLocation(i));
472 context.message(ParserMessages::notDataOrSubdocEntity,
473 StringMessageArg(value.token(i)));
478 return new EntityAttributeSemantics(entities);
483 DeclaredValue *EntityDeclaredValue::copy() const
485 return new EntityDeclaredValue(*this);
488 IdDeclaredValue::IdDeclaredValue()
489 : TokenizedDeclaredValue(name, 0)
493 Boolean IdDeclaredValue::isId() const
499 IdDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
500 AttributeContext &context,
506 if (!context.defineId(value.string(), value.tokenLocation(0), prevLoc)) {
507 context.setNextLocation(value.tokenLocation(0));
508 context.message(ParserMessages::duplicateId,
509 StringMessageArg(value.string()),
515 void IdDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
517 desc.declaredValue = AttributeDefinitionDesc::id;
520 DeclaredValue *IdDeclaredValue::copy() const
522 return new IdDeclaredValue(*this);
525 IdrefDeclaredValue::IdrefDeclaredValue(Boolean isList)
526 : TokenizedDeclaredValue(name, isList)
531 IdrefDeclaredValue::makeSemantics(const TokenizedAttributeValue &value,
532 AttributeContext &context,
537 size_t nTokens = value.nTokens();
539 for (size_t i = 0; i < nTokens; i++)
540 context.noteIdref(value.token(i), value.tokenLocation(i));
544 Boolean IdrefDeclaredValue::isIdref() const
549 void IdrefDeclaredValue::buildDesc(AttributeDefinitionDesc &desc) const
551 TokenizedDeclaredValue::buildDesc(desc);
552 if (desc.declaredValue == AttributeDefinitionDesc::name)
553 desc.declaredValue = AttributeDefinitionDesc::idref;
555 desc.declaredValue = AttributeDefinitionDesc::idrefs;
558 DeclaredValue *IdrefDeclaredValue::copy() const
560 return new IdrefDeclaredValue(*this);
564 AttributeDefinition::AttributeDefinition(const StringC &name,
565 DeclaredValue *value)
566 : name_(name), declaredValue_(value)
570 AttributeDefinition::~AttributeDefinition()
574 AttributeValue *AttributeDefinition::checkValue(AttributeValue *p,
575 AttributeContext &) const
580 Boolean AttributeDefinition::missingValueWouldMatch(const Text &,
581 const AttributeContext &) const
586 const AttributeValue *
587 AttributeDefinition::defaultValue(const AttributeValue *) const
592 void AttributeDefinition::getDesc(AttributeDefinitionDesc &desc) const
594 desc.allowedValues.clear();
595 desc.defaultValue.clear();
596 desc.currentIndex = 0;
598 declaredValue_->buildDesc(desc);
601 Boolean AttributeDefinition::isConref() const
606 Boolean AttributeDefinition::isCurrent() const
611 Boolean AttributeDefinition::isFixed() const
616 RequiredAttributeDefinition::RequiredAttributeDefinition(const StringC &name,
617 DeclaredValue *value)
618 : AttributeDefinition(name, value)
622 ConstPtr<AttributeValue>
623 RequiredAttributeDefinition::makeMissingValue(AttributeContext &context) const
625 context.message(ParserMessages::requiredAttributeMissing,
626 StringMessageArg(name()));
630 void RequiredAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
632 desc.defaultValueType = AttributeDefinitionDesc::required;
635 AttributeDefinition *RequiredAttributeDefinition::copy() const
637 return new RequiredAttributeDefinition(*this);
640 CurrentAttributeDefinition::CurrentAttributeDefinition(const StringC &name, DeclaredValue *value, size_t index)
641 : AttributeDefinition(name, value), currentIndex_(index)
645 ConstPtr<AttributeValue>
646 CurrentAttributeDefinition::makeMissingValue(AttributeContext &context) const
648 if (context.mayDefaultAttribute()) {
649 ConstPtr<AttributeValue> currentValue
650 = context.getCurrentAttribute(currentIndex_);
651 if (currentValue.isNull())
652 context.message(ParserMessages::currentAttributeMissing,
653 StringMessageArg(name()));
657 context.message(ParserMessages::attributeMissing,
658 StringMessageArg(name()));
663 Boolean CurrentAttributeDefinition::missingValueWouldMatch(const Text &text,
664 const AttributeContext &context) const
666 if (!context.mayDefaultAttribute())
668 ConstPtr<AttributeValue> currentValue
669 = context.getCurrentAttribute(currentIndex_);
670 if (currentValue.isNull())
672 return text.fixedEqual(*currentValue->text());
676 CurrentAttributeDefinition::checkValue(AttributeValue *value,
677 AttributeContext &context) const
679 context.noteCurrentAttribute(currentIndex_, value);
683 void CurrentAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
685 desc.defaultValueType = AttributeDefinitionDesc::current;
686 desc.currentIndex = currentIndex_;
689 AttributeDefinition *CurrentAttributeDefinition::copy() const
691 return new CurrentAttributeDefinition(*this);
694 Boolean CurrentAttributeDefinition::isCurrent() const
699 ImpliedAttributeDefinition::ImpliedAttributeDefinition(const StringC &name,
700 DeclaredValue *value)
701 : AttributeDefinition(name, value)
705 ConstPtr<AttributeValue>
706 ImpliedAttributeDefinition::makeMissingValue(AttributeContext &context) const
708 return context.makeImpliedAttributeValue();
711 void ImpliedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
713 desc.defaultValueType = AttributeDefinitionDesc::implied;
716 AttributeDefinition *ImpliedAttributeDefinition::copy() const
718 return new ImpliedAttributeDefinition(*this);
721 const AttributeValue *
722 ImpliedAttributeDefinition::defaultValue(const AttributeValue *impliedValue)
728 ConrefAttributeDefinition::ConrefAttributeDefinition(const StringC &name,
729 DeclaredValue *value)
730 : ImpliedAttributeDefinition(name, value)
734 Boolean ConrefAttributeDefinition::isConref() const
739 void ConrefAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
741 desc.defaultValueType = AttributeDefinitionDesc::conref;
744 AttributeDefinition *ConrefAttributeDefinition::copy() const
746 return new ConrefAttributeDefinition(*this);
749 DefaultAttributeDefinition::DefaultAttributeDefinition(const StringC &name,
750 DeclaredValue *declaredValue,
751 AttributeValue *defaultValue)
752 : AttributeDefinition(name, declaredValue),
757 ConstPtr<AttributeValue>
758 DefaultAttributeDefinition::makeMissingValue(AttributeContext &context) const
760 if (context.mayDefaultAttribute())
763 context.message(ParserMessages::attributeMissing,
764 StringMessageArg(name()));
769 Boolean DefaultAttributeDefinition::missingValueWouldMatch(const Text &text,
770 const AttributeContext &context) const
772 return context.mayDefaultAttribute() && text.fixedEqual(*value_->text());
775 void DefaultAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
777 desc.defaultValueType = AttributeDefinitionDesc::defaulted;
778 desc.defaultValue = value_;
781 AttributeDefinition *DefaultAttributeDefinition::copy() const
783 return new DefaultAttributeDefinition(*this);
786 FixedAttributeDefinition:: FixedAttributeDefinition(const StringC &name,
787 DeclaredValue *declaredValue,
788 AttributeValue *defaultValue)
789 : DefaultAttributeDefinition(name, declaredValue, defaultValue)
793 Boolean FixedAttributeDefinition::isFixed() const
798 AttributeValue *FixedAttributeDefinition::checkValue(AttributeValue *value,
799 AttributeContext &context)
802 const AttributeValue *fixedValue
803 = DefaultAttributeDefinition::defaultValue(0);
804 if (value && fixedValue) {
807 const Text *fixedText;
808 const StringC *fixedStr;
809 switch (value->info(text, str)) {
810 case AttributeValue::implied:
812 case AttributeValue::cdata:
813 if (fixedValue->info(fixedText, fixedStr) == AttributeValue::cdata) {
814 if (!text->fixedEqual(*fixedText))
815 context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
818 case AttributeValue::tokenized:
819 if (fixedValue->info(fixedText, fixedStr) == AttributeValue::tokenized) {
820 if (*str != *fixedStr)
821 context.message(ParserMessages::notFixedValue, StringMessageArg(name()));
829 void FixedAttributeDefinition::buildDesc(AttributeDefinitionDesc &desc) const
831 // get the fixed value
832 DefaultAttributeDefinition::buildDesc(desc);
833 desc.defaultValueType = AttributeDefinitionDesc::fixed;
836 AttributeDefinition *FixedAttributeDefinition::copy() const
838 return new FixedAttributeDefinition(*this);
841 AttributeDefinitionList
842 ::AttributeDefinitionList(Vector<CopyOwner<AttributeDefinition> > &vec,
846 size_t notationIndex)
847 : index_(index), anyCurrent_(anyCurrent), idIndex_(idIndex),
848 notationIndex_(notationIndex)
853 Boolean AttributeDefinitionList::tokenIndex(const StringC &token, unsigned &index) const
855 for (size_t i = 0; i < defs_.size(); i++)
856 if (defs_[i]->containsToken(token)) {
863 Boolean AttributeDefinitionList::attributeIndex(const StringC &name,
864 unsigned &index) const
866 for (size_t i = 0; i < defs_.size(); i++)
867 if (defs_[i]->name() == name) {
874 void AttributeDefinitionList::append(AttributeDefinition *def)
876 if (def->isId() && idIndex_ == size_t(-1))
877 idIndex_ = defs_.size();
878 if (def->isNotation() && notationIndex_ == size_t(-1))
879 notationIndex_ = defs_.size();
880 if (def->isCurrent())
882 defs_.resize(defs_.size() + 1);
886 AttributeSemantics::AttributeSemantics()
890 AttributeSemantics::~AttributeSemantics()
894 size_t AttributeSemantics::nEntities() const
899 ConstPtr<Entity> AttributeSemantics::entity(size_t) const
904 ConstPtr<Notation> AttributeSemantics::notation() const
910 NotationAttributeSemantics::NotationAttributeSemantics(const ConstPtr<Notation> ¬ation)
911 : notation_(notation)
915 ConstPtr<Notation> NotationAttributeSemantics::notation() const
920 AttributeSemantics *NotationAttributeSemantics::copy() const
922 return new NotationAttributeSemantics(*this);
925 EntityAttributeSemantics::EntityAttributeSemantics(Vector<ConstPtr<Entity> > &entity)
927 entity.swap(entity_);
930 size_t EntityAttributeSemantics::nEntities() const
932 return entity_.size();
935 ConstPtr<Entity> EntityAttributeSemantics::entity(size_t i) const
940 AttributeSemantics *EntityAttributeSemantics::copy() const
942 return new EntityAttributeSemantics(*this);
945 AttributeValue::AttributeValue()
949 AttributeValue::~AttributeValue()
953 AttributeSemantics *AttributeValue::makeSemantics(const DeclaredValue *,
962 const Text *AttributeValue::text() const
967 Boolean AttributeValue::recoverUnquoted(const StringC &, const Location &,
968 AttributeContext &, const StringC &)
973 ImpliedAttributeValue::ImpliedAttributeValue()
977 AttributeValue::Type ImpliedAttributeValue::info(const Text *&,
978 const StringC *&) const
983 TokenizedAttributeValue::TokenizedAttributeValue(Text &text,
984 const Vector<size_t> &spaceIndex)
985 : spaceIndex_(spaceIndex)
990 AttributeValue::Type TokenizedAttributeValue::info(const Text *&,
991 const StringC *&string) const
993 string = &text_.string();
997 const Text *TokenizedAttributeValue::text() const
1002 AttributeSemantics *
1003 TokenizedAttributeValue::makeSemantics(const DeclaredValue *value,
1004 AttributeContext &context,
1005 const StringC &name,
1007 unsigned &nEntityNames) const
1009 return value->makeSemantics(*this, context, name, nIdrefs, nEntityNames);
1012 CdataAttributeValue::CdataAttributeValue(Text &text)
1017 AttributeValue::Type CdataAttributeValue::info(const Text *&text,
1018 const StringC *&) const
1024 const Text *CdataAttributeValue::text() const
1029 Boolean CdataAttributeValue::recoverUnquoted(const StringC &str,
1030 const Location &strLoc,
1031 AttributeContext &context,
1034 TextIter iter(text_);
1035 TextItem::Type type;
1038 const Location *loc;
1039 if (iter.next(type, s, len, loc)
1040 && type == TextItem::data
1041 && len == text_.size()
1042 && loc->origin().pointer() == strLoc.origin().pointer()
1043 && loc->index() + len == strLoc.index()
1044 && !iter.next(type, s, len, loc)) {
1045 text_.addChars(str, strLoc);
1046 context.Messenger::setNextLocation(strLoc);
1047 context.message(ParserMessages::unquotedAttributeValue);
1053 Attribute::Attribute()
1058 void Attribute::clear()
1065 AttributeList::AttributeList(const ConstPtr<AttributeDefinitionList> &def)
1066 : def_(def), vec_(def.isNull() ? 0 : def->size()), nSpec_(0), conref_(0),
1067 nIdrefs_(0), nEntityNames_(0)
1071 AttributeList::AttributeList()
1072 : nSpec_(0), conref_(0)
1076 void AttributeList::init(const ConstPtr<AttributeDefinitionList> &def)
1086 size_t newLength = def_->size();
1087 size_t clearLim = vec_.size();
1088 if (clearLim > newLength)
1089 clearLim = newLength;
1090 vec_.resize(newLength);
1091 for (size_t i = 0; i < clearLim; i++)
1096 void AttributeList::swap(AttributeList &to)
1101 unsigned tem = to.nIdrefs_;
1102 to.nIdrefs_ = nIdrefs_;
1106 unsigned tem = to.nEntityNames_;
1107 to.nEntityNames_ = nEntityNames_;
1108 nEntityNames_ = tem;
1111 size_t tem = to.nSpec_;
1116 PackedBoolean tem = to.conref_;
1117 to.conref_ = conref_;
1122 void AttributeList::finish(AttributeContext &context)
1124 for (size_t i = 0; i < vec_.size(); i++)
1125 if (!vec_[i].specified()) {
1126 ConstPtr<AttributeValue> value
1127 = def(i)->makeMissingValue(context);
1128 vec_[i].setValue(value);
1129 if (!value.isNull())
1130 vec_[i].setSemantics(def(i)->makeSemantics(value.pointer(),
1135 const Syntax &syntax = context.attributeSyntax();
1136 if (nIdrefs_ > syntax.grpcnt())
1137 context.message(ParserMessages::idrefGrpcnt,
1138 NumberMessageArg(syntax.grpcnt()));
1139 if (nEntityNames_ > syntax.grpcnt())
1140 context.message(ParserMessages::entityNameGrpcnt,
1141 NumberMessageArg(syntax.grpcnt()));
1143 && def_->notationIndex() != size_t(-1)
1144 && specified(def_->notationIndex()))
1145 context.message(ParserMessages::conrefNotation);
1148 void AttributeList::setSpec(unsigned i, AttributeContext &context)
1150 if (vec_[i].specified())
1151 context.message(ParserMessages::duplicateAttributeSpec,
1152 StringMessageArg(def(i)->name()));
1154 vec_[i].setSpec(nSpec_++);
1157 void AttributeList::noteInvalidSpec()
1162 Boolean AttributeList::setValue(unsigned i, Text &text,
1163 AttributeContext &context,
1164 unsigned &specLength)
1166 AttributeValue *value = def(i)->makeValue(text, context, specLength);
1167 if (def(i)->isConref())
1169 vec_[i].setValue(value);
1171 vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1172 nIdrefs_, nEntityNames_));
1173 else if (AttributeValue::handleAsUnterminated(text, context))
1178 void AttributeList::setValueToken(unsigned i, Text &text,
1179 AttributeContext &context,
1180 unsigned &specLength)
1182 AttributeValue *value = def(i)->makeValueFromToken(text, context,
1184 if (def(i)->isConref())
1186 vec_[i].setValue(value);
1188 vec_[i].setSemantics(def(i)->makeSemantics(value, context,
1189 nIdrefs_, nEntityNames_));
1192 const StringC *AttributeList::getId() const
1194 // Check for no attributes
1197 // Check for no ID declared
1198 size_t i = def_->idIndex();
1199 if (i == size_t(-1))
1201 // Check for invalid value
1202 const AttributeValue *v = value(i);
1205 // Check for implied value
1206 const Text *t = v->text();
1209 return &t->string();
1212 Boolean AttributeList::recoverUnquoted(const StringC &str,
1213 const Location &strLoc,
1214 AttributeContext &context)
1217 for (size_t i = 0; i < vec_.size(); i++)
1218 if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1219 const AttributeValue *val = vec_[i].value();
1221 // I wish I could avoid casting away const here.
1222 return ((AttributeValue *)val)->recoverUnquoted(str, strLoc, context,
1231 Boolean AttributeList::handleAsUnterminated(AttributeContext &context)
1234 for (size_t i = 0; i < vec_.size(); i++) {
1235 if (vec_[i].specified() && vec_[i].specIndex() == nSpec_ - 1) {
1236 const AttributeValue *val = vec_[i].value();
1238 if (val && (ptr = val->text()) != 0
1239 && AttributeValue::handleAsUnterminated(*ptr, context))
1248 // This tries to guess this attribute value looks like if it had
1249 // a missing ending quote.
1251 Boolean AttributeValue::handleAsUnterminated(const Text &text,
1252 AttributeContext &context)
1254 TextIter iter(text);
1255 const Char *lastStr = 0;
1258 const Location *loc;
1259 TextItem::Type type;
1262 while (iter.next(type, str, len, loc)) {
1263 if (startLoc.origin().isNull() && !loc->origin().isNull())
1266 case TextItem::data:
1267 if (len != 1 || *str != context.attributeSyntax().space()) {
1272 case TextItem::endDelim:
1273 case TextItem::endDelimA:
1274 case TextItem::ignore:
1283 && lastStr[lastLen - 1] == context.attributeSyntax().space())
1285 const StringC &vi = context.attributeSyntax().delimGeneral(Syntax::dVI);
1286 if (lastLen >= vi.size()
1288 == StringC(lastStr + (lastLen - vi.size()), vi.size()))) {
1289 context.Messenger::setNextLocation(startLoc);
1290 context.message(ParserMessages::literalClosingDelimiter);
1297 AttributeContext::AttributeContext()
1298 : mayDefaultAttribute_(0)
1302 AttributeContext::~AttributeContext()
1306 Boolean AttributeContext::defineId(const StringC &, const Location &,
1312 void AttributeContext::noteIdref(const StringC &, const Location &)
1316 void AttributeContext::noteCurrentAttribute(size_t, AttributeValue *)
1320 ConstPtr<AttributeValue> AttributeContext::getCurrentAttribute(size_t) const
1325 ConstPtr<Entity> AttributeContext::getAttributeEntity(const StringC &,
1331 ConstPtr<Notation> AttributeContext::getAttributeNotation(const StringC &,
1337 ConstPtr<AttributeValue> AttributeContext::makeImpliedAttributeValue()
1339 if (impliedAttributeValue_.isNull())
1340 impliedAttributeValue_ = new ImpliedAttributeValue;
1341 return impliedAttributeValue_;