#ifndef ARABICA_ATTRIBUTES_IMPL_H #define ARABICA_ATTRIBUTES_IMPL_H // AttributesImpl.h - default implementation of Attributes. // $Id$ #include #include #include namespace SAX { /** * Default implementation of the Attributes interface. * *

This class provides a default implementation of the SAX2 * {@link basic_Attributes Attributes} interface, with the * addition of manipulators so that the list can be modified or * reused.

* *

There are two typical uses of this class:

* *
    *
  1. to take a persistent snapshot of an Attributes object * in a {@link basic_ContentHandler#startElement startElement} event; or
  2. *
  3. to construct or modify an Attributes object in a SAX2 driver or filter.
  4. *
* *

This class replaces the now-deprecated SAX1 {@link * basic_AttributeListImpl AttributeListImpl} * class.

* * @since SAX 2.0 * @author Jez Higgins, * jez@jezuk.co.uk * @version 2.0 */ template class basic_AttributesImpl : public basic_Attributes { public: typedef string_type stringT; typedef basic_Attributes AttributesT; //////////////////////////////////////////////////////////////////// // Constructors. basic_AttributesImpl() { } basic_AttributesImpl(const AttributesT& atts) { setAttributes(atts); } // basic_AttributesImpl //////////////////////////////////////////////////////////////////// // Implementation of SAX::Attributes. /** * Return the number of attributes in the list. * * @return The number of attributes in the list. * @see basic_Attributes#getLength */ virtual int getLength() const { return static_cast(attributes_.size()); } // getLength /** * Return an attribute's Namespace URI. * * @param index The attribute's index (zero-based). * @return The Namespace URI, the empty string if none is * available, or if the index is out of range. * @see basic_Attributes#getURI */ virtual stringT getURI(unsigned int index) const { if(index < attributes_.size()) return attributes_[index].uri_; return emptyString_; } // getUri /** * Return an attribute's local name. * * @param index The attribute's index (zero-based). * @return The attribute's local name, the empty string if * none is available, or if the index if out of range. * @see basic_Attributes#getLocalName */ virtual stringT getLocalName(unsigned int index) const { if(index < attributes_.size()) return attributes_[index].localName_; return emptyString_; } // getLocalName /** * Return an attribute's qualified (prefixed) name. * * @param index The attribute's index (zero-based). * @return The attribute's qualified name, the empty string if * none is available, or if the index is out of bounds. * @see basic_Attributes#getQName */ virtual stringT getQName(unsigned int index) const { if(index < attributes_.size()) return attributes_[index].qName_; return emptyString_; } // getQName /** * Return an attribute's type by index. * * @param index The attribute's index (zero-based). * @return The attribute's type, "CDATA" if the type is unknown, or an empty * string if the index is out of bounds. * @see basic_Attributes#getType(int) */ virtual stringT getType(unsigned int index) const { if(index < attributes_.size()) return attributes_[index].type_; return emptyString_; } // getType /** * Return an attribute's value by index. * * @param index The attribute's index (zero-based). * @return The attribute's value or an empty string if the index is out of bounds. * @see basic_Attributes#getValue(int) */ virtual stringT getValue(unsigned int index) const { if(index < attributes_.size()) return attributes_[index].value_; return emptyString_; } // getValue /** * Look up an attribute's index by Namespace name. * *

In many cases, it will be more efficient to look up the name once and * use the index query methods rather than using the name query methods * repeatedly.

* * @param uri The attribute's Namespace URI, or the empty * string if none is available. * @param localName The attribute's local name. * @return The attribute's index, or -1 if none matches. * @see basic_Attributes#getIndex(const stringT&,const stringT&) */ virtual int getIndex(const stringT& uri, const stringT& localName) const { typename AttrList::const_iterator a = std::find_if(attributes_.begin(), attributes_.end(), AttributeNamed(uri, localName)); if(a != attributes_.end()) return static_cast(std::distance(a, attributes_.end())); return -1; } // getIndex /** * Look up an attribute's index by qualified (prefixed) name. * * @param qName The qualified name. * @return The attribute's index, or -1 if none matches. * @see basic_Attributes#getIndex(const stringT&) */ virtual int getIndex(const stringT& qName) const { size_t max = attributes_.size(); for(size_t i = 0; i < max; ++i) { if(attributes_[i].qName_ == qName) return static_cast(i); } return -1; } // getIndex /** * Look up an attribute's type by Namespace-qualified name. * * @param uri The Namespace URI, or the empty string for a name * with no explicit Namespace URI. * @param localName The local name. * @return The attribute's type, or an empty string if there is no * matching attribute. * @see basic_Attributes#getType(const stringT&,const stringT&) */ virtual stringT getType(const stringT& uri, const stringT& localName) const { typename AttrList::const_iterator a = std::find_if(attributes_.begin(), attributes_.end(), AttributeNamed(uri, localName)); if(a != attributes_.end()) return a->type_; return emptyString_; } // getType /** * Look up an attribute's type by qualified (prefixed) name. * * @param qName The qualified name. * @return The attribute's type, or an empty string if there is no * matching attribute. * @see basic_Attributes#getType(const stringT&) */ virtual stringT getType(const stringT& qName) const { size_t max = attributes_.size(); for(size_t i = 0; i < max; ++i) { if(attributes_[i].qName_ == qName) return attributes_[i].type_; } // for ... return emptyString_; } // getType /** * Look up an attribute's value by Namespace-qualified name. * * @param uri The Namespace URI, or the empty string for a name * with no explicit Namespace URI. * @param localName The local name. * @return The attribute's value, or an empty string if there is no * matching attribute. * @see basic_Attributes#getValue(const stringT&,const stringT&) */ virtual stringT getValue(const stringT& uri, const stringT& localName) const { typename AttrList::const_iterator a = std::find_if(attributes_.begin(), attributes_.end(), AttributeNamed(uri, localName)); if(a != attributes_.end()) return a->value_; return emptyString_; } // getType /** * Look up an attribute's value by qualified (prefixed) name. * * @param qName The qualified name. * @return The attribute's value, or an empty string if there is no * matching attribute. * @see basic_Attributes#getValue(const stringT&) */ virtual stringT getValue(const stringT& qName) const { size_t max = attributes_.size(); for(size_t i = 0; i < max; ++i) { if(attributes_[i].qName_ == qName) return attributes_[i].value_; } // for ... return emptyString_; } // getValue //////////////////////////////////////////////////////////////////// // Manipulators. /** * Clear the attribute list for reuse. */ void clear() { attributes_.erase(attributes_.begin(), attributes_.end()); } // clear /** * Copy an entire Attributes object. * *

It may be more efficient to reuse an existing object * rather than constantly allocating new ones.

* * @param atts The attributes to copy. */ void setAttributes(const Attributes& atts) { clear(); int max = atts.getLength(); for(int i = 0; i < max; ++i) attributes_.push_back(Attr(atts.getURI(i), atts.getLocalName(i), atts.getQName(i), atts.getType(i), atts.getValue(i))); } // setAttributes /** * Add an attribute to the end of the list. * *

For the sake of speed, this method does no checking * to see if the attribute is already in the list: that is * the responsibility of the application.

* * @param uri The Namespace URI, or the empty string if * none is available or Namespace processing is not * being performed. * @param localName The local name, or the empty string if * Namespace processing is not being performed. * @param qName The qualified (prefixed) name, or the empty string * if qualified names are not available. * @param type The attribute type as a string. * @param value The attribute value. */ void addAttribute(const stringT& uri, const stringT& localName, const stringT& qName, const stringT& type, const stringT& value) { attributes_.push_back(Attr(uri, localName, qName, type, value)); } // addAttribute /** * Add an attribute to the end of the list. * * @param uri The Namespace URI, or the empty string if * none is available or Namespace processing is not * being performed. * @param localName The local name, or the empty string if * Namespace processing is not being performed. * @param qName The qualified (prefixed) name, or the empty string * if qualified names are not available. * @param type The attribute type as a string. * @param value The attribute value. */ void addOrReplaceAttribute(const stringT& uri, const stringT& localName, const stringT& qName, const stringT& type, const stringT& value) { typename AttrList::iterator a = std::find_if(attributes_.begin(), attributes_.end(), AttributeNamed(uri, localName)); if(a != attributes_.end()) { a->value_ = value; return; } // if ... attributes_.push_back(Attr(uri, localName, qName, type, value)); } // addOrReplaceAttribute /** * Set an attribute in the list. * *

For the sake of speed, this method does no checking * for name conflicts or well-formedness: such checks are the * responsibility of the application.

* * @param index The index of the attribute (zero-based). * @param uri The Namespace URI, or the empty string if * none is available or Namespace processing is not * being performed. * @param localName The local name, or the empty string if * Namespace processing is not being performed. * @param qName The qualified name, or the empty string * if qualified names are not available. * @param type The attribute type as a string. * @param value The attribute value. * @exception java.lang.ArrayIndexOutOfBoundsException When the * supplied index does not point to an attribute * in the list. */ void setAttribute(unsigned int index, const stringT& uri, const stringT& localName, const stringT& qName, const stringT& type, const stringT& value) { if(index >= 0 && index < attributes_.size()) { Attr& a = attributes_[index]; a.uri_ = uri; a.localName_ = localName; a.qName_ = qName; a.type_ = type; a.value_ = value; } else badIndex(index); } // setAttribute /** * Remove an attribute from the list. * * @param index The index of the attribute (zero-based). * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void removeAttribute(unsigned int index) { if(index >= 0 && index < attributes_.size()) attributes_.erase(attributes_.begin() + index); else badIndex(index); } // removeAttribute /** * Set the Namespace URI of a specific attribute. * * @param index The index of the attribute (zero-based). * @param uri The attribute's Namespace URI, or the empty * string for none. * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void setURI(unsigned int index, const stringT& uri) { if(index < attributes_.size()) attributes_[index].uri_ = uri; else badIndex(index); } // setURI /** * Set the local name of a specific attribute. * * @param index The index of the attribute (zero-based). * @param localName The attribute's local name, or the empty * string for none. * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void setLocalName(unsigned int index, const stringT& localName) { if(index < attributes_.size()) attributes_[index].localName_ = localName; else badIndex(index); } // setLocalName /** * Set the qualified name of a specific attribute. * * @param index The index of the attribute (zero-based). * @param qName The attribute's qualified name, or the empty * string for none. * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void setQName(unsigned int index, const stringT& qName) { if(index >= 0 && index < attributes_.size()) attributes_[index].qName_ = qName; else badIndex(index); } // setQName /** * Set the type of a specific attribute. * * @param index The index of the attribute (zero-based). * @param type The attribute's type. * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void setType(unsigned int index, const stringT& type) { if(index >= 0 && index < attributes_.size()) attributes_[index].type_ = type; else badIndex(index); } // setType /** * Set the value of a specific attribute. * * @param index The index of the attribute (zero-based). * @param value The attribute's value. * @exception std::out_of_range When the * supplied index does not point to an attribute * in the list. */ void setValue(unsigned int index, const stringT& value) { if(index >= 0 && index < attributes_.size()) attributes_[index].value_ = value; else badIndex(index); } // setURI private: //////////////////////////////////////////////////////////////////// // Internal methods. //////////////////////////////////////////////////////////////////// void badIndex(unsigned int index) { // sort out std::string msg = "Attempt to modify attribute at illegal index: " + index; throw std::out_of_range(msg); } struct Attr { Attr(const stringT& uri, const stringT& localName, const stringT& qName, const stringT& type, const stringT& value) : uri_(uri), localName_(localName), qName_(qName), type_(type), value_(value) { } Attr() { } Attr& operator=(const Attr& rhs) { uri_ = rhs.uri_; localName_ = rhs.localName_; qName_ = rhs.qName_; type_ = rhs.type_; value_ = rhs.value_; return *this; } // operator= stringT uri_; stringT localName_; stringT qName_; stringT type_; stringT value_; }; // Attr class AttributeNamed { public: AttributeNamed(const stringT& uri, const stringT& localName) : uri_(uri), localName_(localName) { } AttributeNamed(const AttributeNamed& rhs) : uri_(rhs.uri_), localName_(rhs.localName_) { } ~AttributeNamed() { } bool operator()(const Attr& attr) const { return (attr.uri_ == uri_) && (attr.localName_ == localName_); } // operator() private: const stringT& uri_; const stringT& localName_; AttributeNamed& operator=(const AttributeNamed&); bool operator==(const AttributeNamed&) const; }; // class AttributeNamed typedef typename std::deque AttrList; AttrList attributes_; stringT emptyString_; }; // class AttributesImpl typedef basic_AttributesImpl AttributesImpl; #ifndef ARABICA_NO_WCHAR_T typedef basic_AttributesImpl wAttributesImpl; #endif } // namespace SAX #endif