Element & attribute names and namespace URIs are now held in a

string pool attached the owning document.
The string pool is just a std::list, because it gives us stable pointers
into the contents.  Easy!
This commit is contained in:
jez_higgins 2005-12-09 11:49:03 +00:00
parent 03661daaf8
commit 9fc4a8b000
5 changed files with 64 additions and 45 deletions

View file

@ -20,7 +20,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name) : AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name) :
DOM::Attr_impl<stringT>(), DOM::Attr_impl<stringT>(),
NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc), NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc),
name_(name), name_(ownerDoc->stringPool(name)),
ownerElement_(0), ownerElement_(0),
specified_(true) specified_(true)
{ {
@ -29,7 +29,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name, const stringT& value) : AttrImpl(DocumentImpl<stringT, string_adaptorT>* ownerDoc, const stringT& name, const stringT& value) :
DOM::Attr_impl<stringT>(), DOM::Attr_impl<stringT>(),
NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc), NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc),
name_(name), name_(ownerDoc->stringPool(name)),
ownerElement_(0), ownerElement_(0),
specified_(true) specified_(true)
{ {
@ -68,7 +68,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const
{ {
AttrImpl* a = dynamic_cast<AttrImpl*>(NodeT::ownerDoc_->createAttribute(name_)); AttrImpl* a = dynamic_cast<AttrImpl*>(NodeT::ownerDoc_->createAttribute(*name_));
cloneChildren(a); cloneChildren(a);
a->setSpecified(getSpecified()); a->setSpecified(getSpecified());
return a; return a;
@ -76,7 +76,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
virtual stringT getNodeName() const virtual stringT getNodeName() const
{ {
return name_; return *name_;
} // getNodeName } // getNodeName
virtual stringT getNodeValue() const virtual stringT getNodeValue() const
@ -113,7 +113,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
if(!docType || docType->getElementIds()->empty()) if(!docType || docType->getElementIds()->empty())
return; return;
std::vector<stringT>* elemIds = docType->getElementIds(); std::vector<stringT>* elemIds = docType->getElementIds();
if(std::find(elemIds->begin(), elemIds->end(), name_) != elemIds->end()) if(std::find(elemIds->begin(), elemIds->end(), *name_) != elemIds->end())
NodeT::ownerDoc_->setElementId(this); NodeT::ownerDoc_->setElementId(this);
} // if(ownerDoc_) } // if(ownerDoc_)
} // setOwnerElement } // setOwnerElement
@ -137,7 +137,7 @@ class AttrImpl : public DOM::Attr_impl<stringT>,
} // checkChildType } // checkChildType
protected: protected:
stringT name_; stringT const* name_;
ElementImpl<stringT, string_adaptorT>* ownerElement_; ElementImpl<stringT, string_adaptorT>* ownerElement_;
bool specified_; bool specified_;
}; // class CDATAImpl }; // class CDATAImpl

View file

@ -27,25 +27,25 @@ class AttrNSImpl : public AttrImpl<stringT, string_adaptorT>
if(index == string_adaptorT::npos) if(index == string_adaptorT::npos)
{ //qualifiedName contains no ':' { //qualifiedName contains no ':'
localName_ = qualifiedName; localName_ = AttrT::ownerDoc_->stringPool(qualifiedName);
if(localName_ == string_adaptorT::construct_from_utf8("xmlns")) if(*localName_ == string_adaptorT::construct_from_utf8("xmlns"))
{ {
hasPrefix = true; hasPrefix = true;
prefix = localName_; prefix = *localName_;
} // if ... } // if ...
} }
else else
{ {
hasPrefix = true; hasPrefix = true;
prefix = string_adaptorT::substr(qualifiedName, 0, index); prefix = string_adaptorT::substr(qualifiedName, 0, index);
localName_ = string_adaptorT::substr(qualifiedName, index+1); localName_ = AttrT::ownerDoc_->stringPool(string_adaptorT::substr(qualifiedName, index+1));
} // if(index == string_adaptorT::npos) } // if(index == string_adaptorT::npos)
std::pair<bool, stringT> mappedURI = std::pair<bool, stringT> mappedURI =
checkPrefixAndNamespace<stringT, string_adaptorT>(hasPrefix, prefix, hasNamespaceURI, namespaceURI, DOM::Node<stringT>::ATTRIBUTE_NODE); checkPrefixAndNamespace<stringT, string_adaptorT>(hasPrefix, prefix, hasNamespaceURI, namespaceURI, DOM::Node<stringT>::ATTRIBUTE_NODE);
hasNamespaceURI_ = mappedURI.first; hasNamespaceURI_ = mappedURI.first;
namespaceURI_ = mappedURI.second; namespaceURI_ = AttrT::ownerDoc_->stringPool(mappedURI.second);
} // AttrImpl } // AttrImpl
virtual ~AttrNSImpl() { } virtual ~AttrNSImpl() { }
@ -54,7 +54,7 @@ class AttrNSImpl : public AttrImpl<stringT, string_adaptorT>
// DOM::Node methods // DOM::Node methods
virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const
{ {
AttrNSImpl* clone = dynamic_cast<AttrNSImpl*>(AttrT::ownerDoc_->createAttributeNS(namespaceURI_, AttrT::name_)); AttrNSImpl* clone = dynamic_cast<AttrNSImpl*>(AttrT::ownerDoc_->createAttributeNS(*namespaceURI_, *AttrT::name_));
AttrT::cloneChildren(clone); AttrT::cloneChildren(clone);
clone->setSpecified(AttrT::getSpecified()); clone->setSpecified(AttrT::getSpecified());
return clone; return clone;
@ -62,13 +62,13 @@ class AttrNSImpl : public AttrImpl<stringT, string_adaptorT>
virtual stringT getNamespaceURI() const virtual stringT getNamespaceURI() const
{ {
return namespaceURI_; return *namespaceURI_;
} // getNamespaceURI } // getNamespaceURI
virtual stringT getPrefix() const virtual stringT getPrefix() const
{ {
size_type index = string_adaptorT::find(AttrT::name_, string_adaptorT::construct_from_utf8(":")); size_type index = string_adaptorT::find(*AttrT::name_, string_adaptorT::construct_from_utf8(":"));
return (index != string_adaptorT::npos) ? string_adaptorT::substr(AttrT::name_, 0, index) : stringT(); return (index != string_adaptorT::npos) ? string_adaptorT::substr(*AttrT::name_, 0, index) : stringT();
} // getPrefix } // getPrefix
virtual void setPrefix(const stringT& prefix) virtual void setPrefix(const stringT& prefix)
@ -82,16 +82,18 @@ class AttrNSImpl : public AttrImpl<stringT, string_adaptorT>
return; return;
} // empty prefix } // empty prefix
checkPrefixAndNamespace<stringT, string_adaptorT>(true, prefix, true, namespaceURI_, DOM::Node<stringT>::ATTRIBUTE_NODE); checkPrefixAndNamespace<stringT, string_adaptorT>(true, prefix, true, *namespaceURI_, DOM::Node<stringT>::ATTRIBUTE_NODE);
AttrT::name_ = prefix; stringT newName = prefix;
string_adaptorT::append(AttrT::name_, string_adaptorT::construct_from_utf8(":")); string_adaptorT::append(newName, string_adaptorT::construct_from_utf8(":"));
string_adaptorT::append(AttrT::name_, localName_); string_adaptorT::append(newName, *localName_);
AttrT::name_ = AttrT::ownerDoc_->stringPool(newName);
} // setPrefix } // setPrefix
virtual stringT getLocalName() const virtual stringT getLocalName() const
{ {
return localName_; return *localName_;
} // getLocalName } // getLocalName
// additional three methods - since C++ std::string (and by implication // additional three methods - since C++ std::string (and by implication
@ -107,12 +109,12 @@ class AttrNSImpl : public AttrImpl<stringT, string_adaptorT>
virtual bool hasPrefix() const virtual bool hasPrefix() const
{ {
return (string_adaptorT::find(AttrT::name_, string_adaptorT::construct_from_utf8(":")) != string_adaptorT::npos); return (string_adaptorT::find(*AttrT::name_, string_adaptorT::construct_from_utf8(":")) != string_adaptorT::npos);
} // hasPrefix } // hasPrefix
private: private:
stringT namespaceURI_; stringT const* namespaceURI_;
stringT localName_; stringT const* localName_;
bool hasNamespaceURI_; bool hasNamespaceURI_;
}; // class AttrNSImpl }; // class AttrNSImpl

View file

@ -17,6 +17,8 @@
#include <DOM/Simple/NodeImpl.h> #include <DOM/Simple/NodeImpl.h>
#include <set> #include <set>
#include <list>
#include <algorithm>
namespace SimpleDOM namespace SimpleDOM
{ {
@ -129,7 +131,8 @@ class DocumentImpl : public DOM::Document_impl<stringT>,
virtual DOM::Element_impl<stringT>* createElement(const stringT& tagName) const virtual DOM::Element_impl<stringT>* createElement(const stringT& tagName) const
{ {
ElementImpl<stringT, string_adaptorT>* n = new ElementImpl<stringT, string_adaptorT>(const_cast<DocumentImpl*>(this), tagName); ElementImpl<stringT, string_adaptorT>* n =
new ElementImpl<stringT, string_adaptorT>(const_cast<DocumentImpl*>(this), tagName);
orphaned(n); orphaned(n);
return n; return n;
} // createElement } // createElement
@ -296,7 +299,8 @@ class DocumentImpl : public DOM::Document_impl<stringT>,
virtual DOM::Element_impl<stringT>* createElementNS(const stringT& namespaceURI, const stringT& qualifiedName) const virtual DOM::Element_impl<stringT>* createElementNS(const stringT& namespaceURI, const stringT& qualifiedName) const
{ {
ElementNSImpl<stringT, string_adaptorT>* n = new ElementNSImpl<stringT, string_adaptorT>(const_cast<DocumentImpl*>(this), namespaceURI, !string_adaptorT::empty(namespaceURI), qualifiedName); ElementNSImpl<stringT, string_adaptorT>* n =
new ElementNSImpl<stringT, string_adaptorT>(const_cast<DocumentImpl*>(this), namespaceURI, !string_adaptorT::empty(namespaceURI), qualifiedName);
orphaned(n); orphaned(n);
return n; return n;
} // createElementNS } // createElementNS
@ -438,6 +442,7 @@ class DocumentImpl : public DOM::Document_impl<stringT>,
{ {
idNodes_.insert(attr); idNodes_.insert(attr);
} // setElementId } // setElementId
void removeElementId(AttrImplT* attr) void removeElementId(AttrImplT* attr)
{ {
typename std::set<AttrImplT*>::iterator n = idNodes_.find(attr); typename std::set<AttrImplT*>::iterator n = idNodes_.find(attr);
@ -445,8 +450,17 @@ class DocumentImpl : public DOM::Document_impl<stringT>,
idNodes_.erase(n); idNodes_.erase(n);
} // removeElementId } // removeElementId
stringT const* const stringPool(const stringT& str) const
{
std::list<stringT>::const_iterator i = std::find(stringPool_.begin(), stringPool_.end(), str);
if(i != stringPool_.end())
return &(*i);
stringPool_.push_back(str);
return &(stringPool_.back());
} // stringPool
private: private:
virtual void checkChildType(typename DOM::Node_impl<stringT>* child) void checkChildType(typename DOM::Node_impl<stringT>* child)
{ {
typename DOM::Node<stringT>::Type type = child->getNodeType(); typename DOM::Node<stringT>::Type type = child->getNodeType();
if((type != DOM::Node<stringT>::ELEMENT_NODE) && if((type != DOM::Node<stringT>::ELEMENT_NODE) &&
@ -467,6 +481,7 @@ class DocumentImpl : public DOM::Document_impl<stringT>,
mutable std::set<NodeImplT*> orphans_; mutable std::set<NodeImplT*> orphans_;
std::set<AttrImplT*> idNodes_; std::set<AttrImplT*> idNodes_;
mutable std::list<stringT> stringPool_;
}; // class DocumentImpl }; // class DocumentImpl

View file

@ -21,7 +21,7 @@ class ElementImpl : public DOM::Element_impl<stringT>,
DOM::Element_impl<stringT>(), DOM::Element_impl<stringT>(),
NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc), NodeImplWithChildren<stringT, string_adaptorT>(ownerDoc),
attributes_(ownerDoc), attributes_(ownerDoc),
tagName_(tagName) tagName_(ownerDoc->stringPool(tagName))
{ {
attributes_.setOwnerElement(this); attributes_.setOwnerElement(this);
} // ElementImpl } // ElementImpl
@ -122,7 +122,7 @@ class ElementImpl : public DOM::Element_impl<stringT>,
virtual stringT getNodeName() const virtual stringT getNodeName() const
{ {
return tagName_; return *tagName_;
} // getNodeName } // getNodeName
virtual DOM::NamedNodeMap_impl<stringT>* getAttributes() const virtual DOM::NamedNodeMap_impl<stringT>* getAttributes() const
@ -132,7 +132,7 @@ class ElementImpl : public DOM::Element_impl<stringT>,
virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const
{ {
ElementImpl* clone = dynamic_cast<ElementImpl*>(NodeT::ownerDoc_->createElement(tagName_)); ElementImpl* clone = dynamic_cast<ElementImpl*>(NodeT::ownerDoc_->createElement(*tagName_));
cloneChildren(clone, deep); cloneChildren(clone, deep);
return clone; return clone;
} // cloneNode } // cloneNode
@ -190,7 +190,7 @@ class ElementImpl : public DOM::Element_impl<stringT>,
AttrMap<stringT, string_adaptorT> attributes_; AttrMap<stringT, string_adaptorT> attributes_;
protected: protected:
stringT tagName_; stringT const* tagName_;
}; // class ElementImpl }; // class ElementImpl

View file

@ -26,20 +26,20 @@ class ElementNSImpl : public ElementImpl<stringT, string_adaptorT>
if(index == string_adaptorT::npos) if(index == string_adaptorT::npos)
{ //qualifiedName contains no ':' { //qualifiedName contains no ':'
localName_ = qualifiedName; localName_ = ElementImplT::ownerDoc_->stringPool(qualifiedName);
} }
else else
{ {
hasPrefix = true; hasPrefix = true;
prefix = string_adaptorT::substr(qualifiedName, 0, index); prefix = string_adaptorT::substr(qualifiedName, 0, index);
localName_ = string_adaptorT::substr(qualifiedName, index+1); localName_ = ElementImplT::ownerDoc_->stringPool(string_adaptorT::substr(qualifiedName, index+1));
} }
std::pair<bool, stringT> mappedURI = std::pair<bool, stringT> mappedURI =
checkPrefixAndNamespace<stringT, string_adaptorT>(hasPrefix, prefix, hasNamespaceURI, namespaceURI, DOM::Node<stringT>::ELEMENT_NODE); checkPrefixAndNamespace<stringT, string_adaptorT>(hasPrefix, prefix, hasNamespaceURI, namespaceURI, DOM::Node<stringT>::ELEMENT_NODE);
hasNamespaceURI_ = mappedURI.first; hasNamespaceURI_ = mappedURI.first;
namespaceURI_ = mappedURI.second; namespaceURI_ = ElementImplT::ownerDoc_->stringPool(mappedURI.second);
} // ElementImpl } // ElementImpl
virtual ~ElementNSImpl() { } virtual ~ElementNSImpl() { }
@ -48,20 +48,20 @@ class ElementNSImpl : public ElementImpl<stringT, string_adaptorT>
// DOM::Node methods // DOM::Node methods
virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const virtual DOM::Node_impl<stringT>* cloneNode(bool deep) const
{ {
ElementNSImpl* clone = dynamic_cast<ElementNSImpl*>(ElementImplT::ownerDoc_->createElementNS(namespaceURI_, ElementImplT::tagName_)); ElementNSImpl* clone = dynamic_cast<ElementNSImpl*>(ElementImplT::ownerDoc_->createElementNS(*namespaceURI_, ElementImplT::getNodeName()));
ElementImplT::cloneChildren(clone, deep); ElementImplT::cloneChildren(clone, deep);
return clone; return clone;
} // cloneNode } // cloneNode
virtual stringT getNamespaceURI() const virtual stringT getNamespaceURI() const
{ {
return namespaceURI_; return *namespaceURI_;
} // getNamespaceURI } // getNamespaceURI
virtual stringT getPrefix() const virtual stringT getPrefix() const
{ {
size_type index = string_adaptorT::find(ElementImplT::tagName_, string_adaptorT::construct_from_utf8(":")); size_type index = string_adaptorT::find(ElementImplT::getNodeName(), string_adaptorT::construct_from_utf8(":"));
return (index != string_adaptorT::npos) ? string_adaptorT::substr(ElementImplT::tagName_, 0, index) : stringT(); return (index != string_adaptorT::npos) ? string_adaptorT::substr(ElementImplT::getNodeName(), 0, index) : stringT();
} // getPrefix } // getPrefix
virtual void setPrefix(const stringT& prefix) virtual void setPrefix(const stringT& prefix)
@ -77,16 +77,18 @@ class ElementNSImpl : public ElementImpl<stringT, string_adaptorT>
return; return;
} // empty prefix } // empty prefix
checkPrefixAndNamespace<stringT, string_adaptorT>(true, prefix, true, namespaceURI_, DOM::Node<stringT>::ELEMENT_NODE); checkPrefixAndNamespace<stringT, string_adaptorT>(true, prefix, true, *namespaceURI_, DOM::Node<stringT>::ELEMENT_NODE);
ElementImplT::tagName_ = prefix; stringT newTagName = prefix;
string_adaptorT::append(ElementImplT::tagName_, string_adaptorT::construct_from_utf8(":")); string_adaptorT::append(newTagName, string_adaptorT::construct_from_utf8(":"));
string_adaptorT::append(ElementImplT::tagName_, localName_); string_adaptorT::append(newTagName, *localName_);
ElementImplT::tagName_ = ElementImplT::ownerDoc_->stringPool(newTagName);
} // setPrefix } // setPrefix
virtual stringT getLocalName() const virtual stringT getLocalName() const
{ {
return localName_; return *localName_;
} // getLocalName } // getLocalName
// additional three methods - since C++ std::string (and by implication // additional three methods - since C++ std::string (and by implication
@ -102,12 +104,12 @@ class ElementNSImpl : public ElementImpl<stringT, string_adaptorT>
virtual bool hasPrefix() const virtual bool hasPrefix() const
{ {
return (string_adaptorT::find(ElementImplT::tagName_, string_adaptorT::construct_from_utf8(":")) != string_adaptorT::npos); return (string_adaptorT::find(ElementImplT::getNodeName(), string_adaptorT::construct_from_utf8(":")) != string_adaptorT::npos);
} // hasPrefix } // hasPrefix
private: private:
stringT namespaceURI_; stringT const* namespaceURI_;
stringT localName_; stringT const* localName_;
bool hasNamespaceURI_; bool hasNamespaceURI_;
}; // class ElementImpl }; // class ElementImpl