DOM Level 1 Conformance fixes found with first pass of W3C conf tests

This commit is contained in:
jez 2010-12-09 11:35:54 +00:00
parent 244217f8f1
commit 33d08c77a1
20 changed files with 89 additions and 21 deletions

View file

@ -31,6 +31,8 @@ class Attr : public Node<stringT, string_adaptorT>
Attr(const Attr& rhs) : NodeT(rhs) { }
explicit Attr(const NodeT& rhs) : NodeT(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != NodeT::ATTRIBUTE_NODE)
throw std::bad_cast();
} // Attr

View file

@ -25,6 +25,8 @@ class CDATASection : public Text<stringT, string_adaptorT>
CDATASection(const CDATASection& rhs) : Text<stringT, string_adaptorT>(rhs) { }
explicit CDATASection(const Node<stringT, string_adaptorT>& rhs) : Text<stringT, string_adaptorT>(rhs, 0)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node_base::CDATA_SECTION_NODE)
//throw std::runtime_error("bad_cast: Cannot convert Node to CDATA section");
throw std::bad_cast();

View file

@ -27,6 +27,8 @@ class CharacterData : public Node<stringT, string_adaptorT>
CharacterData(const CharacterData& rhs) : NodeT(rhs) { }
explicit CharacterData(const NodeT& rhs) : NodeT(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
typename NodeT::Type type = rhs.getNodeType();
if((type != NodeT::TEXT_NODE) && (type != NodeT::CDATA_SECTION_NODE))
throw std::runtime_error("bad_cast: Cannot cast Node to Character Data");

View file

@ -24,7 +24,9 @@ class Comment : public CharacterData<stringT, string_adaptorT>
Comment(const Comment& rhs) : CharacterData<stringT, string_adaptorT>(rhs) { }
explicit Comment(const Node<stringT, string_adaptorT>& rhs) : CharacterData<stringT, string_adaptorT>(rhs)
{
if(dynamic_cast<Comment_impl<stringT, string_adaptorT>*>(rhs.impl()) == 0)
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node<stringT, string_adaptorT>::COMMENT_NODE)
throw std::bad_cast();
} // Comment
}; // class Comment

View file

@ -45,6 +45,8 @@ class Document : public Node<stringT, string_adaptorT>
Document(const Document& rhs) : Node<stringT, string_adaptorT>(rhs) { }
explicit Document(const Node<stringT, string_adaptorT>& rhs) : Node<stringT, string_adaptorT>(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node<stringT, string_adaptorT>::DOCUMENT_NODE)
throw std::bad_cast();
} // Document

View file

@ -26,6 +26,8 @@ class DocumentFragment : public Node<stringT, string_adaptorT>
DocumentFragment(const DocumentFragment& rhs) : Node<stringT, string_adaptorT>(rhs) { }
explicit DocumentFragment(const Node<stringT, string_adaptorT>& rhs) : Node<stringT, string_adaptorT>(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node<stringT, string_adaptorT>::DOCUMENT_FRAGMENT_NODE)
throw std::bad_cast();
}

View file

@ -33,6 +33,8 @@ class DocumentType : public Node<stringT, string_adaptorT>
DocumentType(const DocumentType& rhs) : NodeT(rhs) { }
explicit DocumentType(const NodeT& rhs) : NodeT(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != NodeT::DOCUMENT_TYPE_NODE)
throw std::bad_cast();
} // DocumentType

View file

@ -34,6 +34,8 @@ class Element : public Node<stringT, string_adaptorT>
Element(const Element& rhs) : NodeT(rhs) { }
explicit Element(const NodeT& rhs) : NodeT(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != NodeT::ELEMENT_NODE)
throw std::bad_cast();
} // Element

View file

@ -24,22 +24,24 @@ class Entity : public Node<stringT, string_adaptorT>
typedef Entity_impl<stringT, string_adaptorT> Entity_implT;
Entity() : Node<stringT, string_adaptorT>() { }
explicit Entity(Entity_impl<stringT, string_adaptorT>* impl) : Node<stringT>(impl) { }
explicit Entity(Entity_impl<stringT, string_adaptorT>* impl) : Node<stringT, string_adaptorT>(impl) { }
Entity(const Entity& rhs) : Node<stringT, string_adaptorT>(rhs) { }
explicit Entity(const Node<stringT, string_adaptorT>& rhs) : Node<stringT>(rhs)
explicit Entity(const Node<stringT, string_adaptorT>& rhs) : Node<stringT, string_adaptorT>(rhs)
{
if(rhs.getNodeType() != Node<stringT, string_adaptorT>::Entity_NODE)
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node_base::ENTITY_NODE)
throw std::bad_cast();
}
stringT getPublicId() const { nImpl()->getPublicId(); }
stringT getPublicId() const { return nImpl()->getPublicId(); }
stringT getSystemId() const { nImpl()->getSystemId(); }
stringT getSystemId() const { return nImpl()->getSystemId(); }
stringT getNotationName() const { nImpl()->getNotationName(); }
stringT getNotationName() const { return nImpl()->getNotationName(); }
private:
Entity_implT* nImpl() { return dynamic_cast<Entity_implT*>(NodeT::impl()); }
Entity_implT* nImpl() const { return dynamic_cast<Entity_implT*>(*NodeT::impl_); }
}; // class Entity
//////////////////////////////////////////////////////////

View file

@ -28,7 +28,9 @@ class EntityReference : public Node<stringT, string_adaptorT>
EntityReference(const EntityReference& rhs) : NodeT(rhs) { }
explicit EntityReference(const NodeT& rhs) : NodeT(rhs)
{
if(dynamic_cast<EntityReference_implT*>(rhs.impl()) == 0)
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node_base::ENTITY_REFERENCE_NODE)
throw std::bad_cast();
} // EntityReference
}; // class EntityReference

View file

@ -39,7 +39,12 @@ class NodeList
Node<stringT, string_adaptorT> item(unsigned int index) const { return impl_->item(index); }
unsigned int getLength() const { return impl_->getLength(); }
unsigned int getLength() const
{
if(impl_ == 0)
return 0;
return impl_->getLength();
} // getLength
private:
Proxy<NodeList_impl<stringT, string_adaptorT> > impl_;

View file

@ -29,16 +29,18 @@ class Notation : public Node<stringT, string_adaptorT>
Notation(const Notation& rhs) : NodeT(rhs) { }
explicit Notation(const NodeT& rhs) : NodeT(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node_base::NOTATION_NODE)
throw std::bad_cast();
}
stringT getPublicId() const { nImpl()->getPublicId(); }
stringT getPublicId() const { return nImpl()->getPublicId(); }
stringT getSystemId() const { nImpl()->getSystemId(); }
stringT getSystemId() const { return nImpl()->getSystemId(); }
private:
Notation_implT* nImpl() { return dynamic_cast<Notation_implT*>(NodeT::impl()); }
Notation_implT* nImpl() const { return dynamic_cast<Notation_implT*>(*NodeT::impl_); }
}; // class Notation
//////////////////////////////////////////////////////////

View file

@ -26,6 +26,8 @@ class ProcessingInstruction : public Node<stringT, string_adaptorT>
ProcessingInstruction(const ProcessingInstruction& rhs) : Node<stringT, string_adaptorT>(rhs) { }
explicit ProcessingInstruction(const Node<stringT, string_adaptorT>& rhs) : Node<stringT, string_adaptorT>(rhs)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
if(rhs.getNodeType() != Node<stringT, string_adaptorT>::PROCESSING_INSTRUCTION_NODE)
throw std::bad_cast();
}

View file

@ -134,6 +134,14 @@ class AttrImpl : public DOM::Attr_impl<stringT, string_adaptorT>,
void setSpecified(bool specified) { specified_ = specified; }
bool isOrphaned()
{
if(!ownerElement_)
return true;
return NodeT::ownerDoc_->isOrphaned(this);
} // isOrphaned
protected:
void cloneChildren(AttrImpl* clone) const
{

View file

@ -61,9 +61,15 @@ class AttrMap : public NamedNodeMapImpl<stringT, string_adaptorT>
DOMAttr_implT* setAttributeNode(DOMAttr_implT* newAttr)
{
return dynamic_cast<DOMAttr_implT*>(setNamedItem(newAttr));
} // setAttributeNode
virtual DOMNode_implT* setNamedItem(DOMNode_implT* newAttr)
{
throwIfReadOnly();
checkNotInUse(newAttr);
dynamic_cast<AttrImplT*>(newAttr)->setOwnerElement(ownerElement_);
return dynamic_cast<DOMAttr_implT*>(NamedNodeMapImplT::setNamedItem(newAttr));
} // setAttributeNode
} // setNamedItem
DOMAttr_implT* removeAttributeNode(DOMAttr_implT* oldAttr)
{
@ -103,9 +109,15 @@ class AttrMap : public NamedNodeMapImpl<stringT, string_adaptorT>
DOMAttr_implT* setAttributeNodeNS(DOMAttr_implT* newAttr)
{
return dynamic_cast<DOMAttr_implT*>(setNamedItemNS(newAttr));
} // setAttributeNodeNS
virtual DOMNode_implT* setNamedItemNS(DOMNode_implT* newAttr)
{
throwIfReadOnly();
checkNotInUse(newAttr);
dynamic_cast<AttrImplT*>(newAttr)->setOwnerElement(ownerElement_);
return dynamic_cast<DOMAttr_implT*>(NamedNodeMapImplT::setNamedItemNS(newAttr));
} // setAttributeNodeNS
} // setNamedItem
bool hasAttribute(const stringT& name) const
{
@ -181,6 +193,13 @@ class AttrMap : public NamedNodeMapImpl<stringT, string_adaptorT>
return 0;
} // getDefaultAttrs
void checkNotInUse(DOMNode_implT* newAttr)
{
AttrImplT* attr = dynamic_cast<AttrImplT*>(newAttr);
if(!attr->isOrphaned())
throw DOM::DOMException(DOM::DOMException::INUSE_ATTRIBUTE_ERR);
} // checkNotInUse
ElementImplT* ownerElement_;
}; // class AttrMap

View file

@ -437,6 +437,11 @@ class DocumentImpl : public DOM::Document_impl<stringT, string_adaptorT>,
orphans_.insert(node);
} // orphaned
bool isOrphaned(NodeImplT* node) const
{
return orphans_.find(node) != orphans_.end();
} // isOrphaned
void purge(NodeImplT* node)
{
orphans_.erase(node);

View file

@ -94,10 +94,10 @@ class ElementByTagList : public DOM::NodeList_impl<stringT, string_adaptorT>
private:
void populate() const
{
NodeListT dummy;
NodeListT dummy;
nodes_.swap(dummy);
checkNode(rootNode_);
checkChildren(rootNode_);
changes_ = ownerDoc_->changes();
} // populate
@ -116,11 +116,15 @@ class ElementByTagList : public DOM::NodeList_impl<stringT, string_adaptorT>
if((tagName_ == node->getNodeName()) || (allNames_ && node->getNodeType() == DOM::Node<stringT, string_adaptorT>::ELEMENT_NODE))
nodes_.push_back(node);
checkChildren(node);
} // checkNode
void checkChildren(DOM::Node_impl<stringT, string_adaptorT>* node) const
{
for(DOM::Node_impl<stringT, string_adaptorT>* child = node->getFirstChild(); child != 0; child = child->getNextSibling())
if(child->getNodeType() == DOM::Node<stringT, string_adaptorT>::ELEMENT_NODE)
checkNode(child);
} // checkNode
} // checkChildren
typedef std::deque<DOM::Node_impl<stringT, string_adaptorT>*> NodeListT;
mutable NodeListT nodes_;

View file

@ -160,13 +160,14 @@ class NamedNodeMapImpl : public DOM::NamedNodeMap_impl<stringT, string_adaptorT>
return nodes_[index];
} // item
private:
protected:
void throwIfReadOnly() const
{
if(readOnly_)
throw DOM::DOMException(DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR);
} // throwIfReadOnly
private:
typedef std::deque<NodeImplT*> NodeListT;
NodeImplT* getNode(typename NodeListT::const_iterator n) const

View file

@ -416,8 +416,8 @@ class NodeImplWithChildren : public NodeImpl<stringT, string_adaptorT>,
} // if ...
checkCanAdd(newChild);
typename std::deque<NodeImplT*>::iterator result = findChild(oldChild);
removeIfRequired(newChild);
typename std::deque<NodeImplT*>::iterator result = findChild(oldChild);
*result = newChild;
newChild->setParentNode(this);

View file

@ -28,6 +28,8 @@ class Text : public CharacterData<stringT, string_adaptorT>
Text(const Text& rhs) : CharacterDataT(rhs) { }
explicit Text(const NodeT& rhs) : CharacterDataT(rhs, 0)
{
if(NodeT::impl_ == 0) // null nodes can always be cast
return;
typename Text::Type type = rhs.getNodeType();
if((type != Text::TEXT_NODE) && (type != Text::CDATA_SECTION_NODE))
//throw std::runtime_error("bad_cast: Cannot cast Node to Text");