summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/ElementAttributeData.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/ElementAttributeData.h')
-rw-r--r--Source/WebCore/dom/ElementAttributeData.h94
1 files changed, 91 insertions, 3 deletions
diff --git a/Source/WebCore/dom/ElementAttributeData.h b/Source/WebCore/dom/ElementAttributeData.h
index 408065981..be145617c 100644
--- a/Source/WebCore/dom/ElementAttributeData.h
+++ b/Source/WebCore/dom/ElementAttributeData.h
@@ -26,8 +26,10 @@
#ifndef ElementAttributeData_h
#define ElementAttributeData_h
+#include "Attribute.h"
#include "SpaceSplitString.h"
#include "StylePropertySet.h"
+#include <wtf/NotFound.h>
namespace WebCore {
@@ -35,6 +37,8 @@ class Element;
class ElementAttributeData {
public:
+ ~ElementAttributeData();
+
void clearClass() { m_classNames.clear(); }
void setClass(const String& className, bool shouldFoldCase);
const SpaceSplitString& classNames() const { return m_classNames; }
@@ -43,25 +47,109 @@ public:
void setIdForStyleResolution(const AtomicString& newId) { m_idForStyleResolution = newId; }
StylePropertySet* inlineStyleDecl() { return m_inlineStyleDecl.get(); }
- StylePropertySet* ensureInlineStyleDecl(Element*);
- void destroyInlineStyleDecl();
+ StylePropertySet* ensureInlineStyleDecl(StyledElement*);
+ void destroyInlineStyleDecl(StyledElement* element);
StylePropertySet* attributeStyle() const { return m_attributeStyle.get(); }
- StylePropertySet* ensureAttributeStyle(StyledElement*);
+ void setAttributeStyle(PassRefPtr<StylePropertySet> style) { m_attributeStyle = style; }
+
+ size_t length() const { return m_attributes.size(); }
+ bool isEmpty() const { return m_attributes.isEmpty(); }
+
+ // Internal interface.
+ Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); }
+ Attribute* getAttributeItem(const QualifiedName&) const;
+ size_t getAttributeItemIndex(const QualifiedName&) const;
+
+ // These functions do no error checking.
+ void addAttribute(PassRefPtr<Attribute>, Element*);
+ void removeAttribute(const QualifiedName&, Element*);
+ void removeAttribute(size_t index, Element*);
+
+ bool hasID() const { return !m_idForStyleResolution.isNull(); }
+ bool hasClass() const { return !m_classNames.isNull(); }
private:
+ friend class Element;
friend class NamedNodeMap;
ElementAttributeData()
{
}
+ void detachAttributesFromElement();
+ void copyAttributesToVector(Vector<RefPtr<Attribute> >&);
+ Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
+ size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const;
+ size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
+ void setAttributes(const ElementAttributeData& other, Element*);
+ void clearAttributes();
+ void replaceAttribute(size_t index, PassRefPtr<Attribute>, Element*);
+
RefPtr<StylePropertySet> m_inlineStyleDecl;
RefPtr<StylePropertySet> m_attributeStyle;
SpaceSplitString m_classNames;
AtomicString m_idForStyleResolution;
+ Vector<RefPtr<Attribute>, 4> m_attributes;
};
+inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element)
+{
+ size_t index = getAttributeItemIndex(name);
+ if (index == notFound)
+ return;
+
+ removeAttribute(index, element);
+}
+
+inline Attribute* ElementAttributeData::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
+{
+ size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
+ if (index != notFound)
+ return m_attributes[index].get();
+ return 0;
+}
+
+inline Attribute* ElementAttributeData::getAttributeItem(const QualifiedName& name) const
+{
+ size_t index = getAttributeItemIndex(name);
+ if (index != notFound)
+ return m_attributes[index].get();
+ return 0;
+}
+
+// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
+// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
+inline size_t ElementAttributeData::getAttributeItemIndex(const QualifiedName& name) const
+{
+ size_t len = length();
+ for (unsigned i = 0; i < len; ++i) {
+ if (m_attributes[i]->name().matches(name))
+ return i;
+ }
+ return notFound;
+}
+
+inline size_t ElementAttributeData::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const
+{
+ unsigned len = length();
+ bool doSlowCheck = shouldIgnoreAttributeCase;
+
+ // Optimize for the case where the attribute exists and its name exactly matches.
+ for (unsigned i = 0; i < len; ++i) {
+ const QualifiedName& attrName = m_attributes[i]->name();
+ if (!attrName.hasPrefix()) {
+ if (name == attrName.localName())
+ return i;
+ } else
+ doSlowCheck = true;
+ }
+
+ if (doSlowCheck)
+ return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
+ return notFound;
+}
+
}
#endif // ElementAttributeData_h