File indexing completed on 2024-04-28 15:24:50

0001 /*
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
0005  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
0006  *           (C) 2001 Peter Kelly (pmk@post.com)
0007  *           (C) 2001 Dirk Mueller (mueller@kde.org)
0008  *           (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
0009  *
0010  * This library is free software; you can redistribute it and/or
0011  * modify it under the terms of the GNU Library General Public
0012  * License as published by the Free Software Foundation; either
0013  * version 2 of the License, or (at your option) any later version.
0014  *
0015  * This library is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018  * Library General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Library General Public License
0021  * along with this library; see the file COPYING.LIB.  If not, write to
0022  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023  * Boston, MA 02110-1301, USA.
0024  *
0025  */
0026 #ifndef _DOM_ELEMENTImpl_h_
0027 #define _DOM_ELEMENTImpl_h_
0028 
0029 #include "dom_nodeimpl.h"
0030 #include "dom/dom_exception.h"
0031 #include "dom/dom_element.h"
0032 #include "xml/dom_stringimpl.h"
0033 #include "misc/shared.h"
0034 #include "wtf/Vector.h"
0035 #include "xml/ClassNames.h"
0036 
0037 // WebCore SVG
0038 #include "dom/QualifiedName.h"
0039 // End WebCore SVG
0040 
0041 namespace khtml
0042 {
0043 class CSSStyleSelector;
0044 }
0045 
0046 namespace DOM
0047 {
0048 
0049 class ElementImpl;
0050 class DocumentImpl;
0051 class NamedAttrMapImpl;
0052 class ElementRareDataImpl;
0053 class CSSInlineStyleDeclarationImpl;
0054 
0055 // Attr can have Text and EntityReference children
0056 // therefore it has to be a fullblown Node. The plan
0057 // is to dynamically allocate a textchild and store the
0058 // resulting nodevalue in the AttributeImpl upon
0059 // destruction. however, this is not yet implemented.
0060 class AttrImpl : public NodeBaseImpl
0061 {
0062     friend class ElementImpl;
0063     friend class NamedAttrMapImpl;
0064 
0065 public:
0066     AttrImpl(ElementImpl *element, DocumentImpl *docPtr, NamespaceName namespaceName, LocalName localName, PrefixName prefix, DOMStringImpl *value);
0067     ~AttrImpl();
0068 
0069 private:
0070     AttrImpl(const AttrImpl &other);
0071     AttrImpl &operator = (const AttrImpl &other);
0072     void createTextChild();
0073 public:
0074 
0075     // DOM methods & attributes for Attr
0076     bool specified() const
0077     {
0078         return true; /* we don't yet support default attributes*/
0079     }
0080     ElementImpl *ownerElement() const
0081     {
0082         return m_element;
0083     }
0084     void setOwnerElement(ElementImpl *impl)
0085     {
0086         m_element = impl;
0087     }
0088     DOMString name() const;
0089 
0090     //DOMString value() const;
0091     void setValue(const DOMString &v, int &exceptioncode);
0092 
0093     // DOM methods overridden from  parent classes
0094     DOMString nodeName() const override;
0095     unsigned short nodeType() const override;
0096     DOMString prefix() const override;
0097     void setPrefix(const DOMString &refix, int &exceptioncode) override;
0098     DOMString namespaceURI() const override;
0099     DOMString localName() const override;
0100 
0101     inline const PrefixName &prefixName() const
0102     {
0103         return m_prefix;
0104     }
0105 
0106     DOMString nodeValue() const override;
0107     void setNodeValue(const DOMString &, int &exceptioncode) override;
0108     WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override;
0109 
0110     // Other methods (not part of DOM)
0111     bool isAttributeNode() const override
0112     {
0113         return true;
0114     }
0115     bool childAllowed(NodeImpl *newChild) override;
0116     bool childTypeAllowed(unsigned short type) override;
0117     NodeImpl::Id id() const override
0118     {
0119         return makeId(m_namespace.id(), m_localName.id());
0120     }
0121     void childrenChanged() override;
0122 
0123     // non-virtual id, for faster attribute look-ups
0124     inline NodeImpl::Id fastId() const
0125     {
0126         return makeId(m_namespace.id(), m_localName.id());
0127     }
0128 
0129     // This is used for when the value is normalized on setting by
0130     // parseAttribute; it silently updates it w/o issuing any events, etc.
0131     // Doesn't work for ATTR_ID!
0132     void rewriteValue(const DOMString &newValue);
0133 
0134     DOMString toString() const override;
0135 
0136     void setElement(ElementImpl *element);
0137     DOMStringImpl *val() const
0138     {
0139         return m_value;
0140     }
0141 
0142 protected:
0143     ElementImpl *m_element;
0144     LocalName m_localName;
0145     NamespaceName m_namespace;
0146     PrefixName m_prefix;
0147     DOMStringImpl *m_value;
0148 };
0149 
0150 // Mini version of AttrImpl internal to NamedAttrMapImpl.
0151 // Stores either the id (LocalName and NamespaceName) and value of an attribute
0152 // (in the case of m_localName.id() != 0), or a pointer to an AttrImpl (if m_localName.id() == 0)
0153 // The latter case only happens when the Attr node is requested by some DOM
0154 // code or is an XML attribute.
0155 // In most cases the id and value is all we need to store, which is more
0156 // memory efficient.
0157 // FIXME: update comment - no longer create mini version for only html attributes
0158 struct AttributeImpl {
0159     inline NodeImpl::Id id() const
0160     {
0161         return m_localName.id() ? makeId(m_namespace.id(), m_localName.id()) : m_data.attr->fastId();
0162     }
0163     DOMStringImpl *val() const
0164     {
0165         if (m_localName.id()) {
0166             return m_data.value;
0167         } else {
0168             return m_data.attr->val();
0169         }
0170     }
0171     DOMString value() const
0172     {
0173         return val();
0174     }
0175     AttrImpl *attr() const
0176     {
0177         return m_localName.id() ? nullptr : m_data.attr;
0178     }
0179     DOMString namespaceURI() const
0180     {
0181         return m_localName.id() ? m_namespace.toString() : m_data.attr->namespaceURI();
0182     }
0183     DOMString prefix() const
0184     {
0185         return m_localName.id() ? m_prefix.toString() : m_data.attr->prefix();
0186     }
0187     DOMString localName() const
0188     {
0189         return m_localName.id() ? m_localName.toString() : m_data.attr->localName();
0190     }
0191     const PrefixName &prefixName() const
0192     {
0193         return m_localName.id() ? m_prefix : m_data.attr->prefixName();
0194     }
0195 
0196     // for WebCore api compat
0197     QualifiedName name() const
0198     {
0199         return m_localName.id() ? QualifiedName(m_prefix, m_localName, m_namespace) : QualifiedName(id(), PrefixName::fromString(prefix()));
0200     }
0201 
0202     void setValue(DOMStringImpl *value, ElementImpl *element);
0203     AttrImpl *createAttr(ElementImpl *element, DocumentImpl *docPtr);
0204     void free();
0205 
0206     // See the description for AttrImpl.
0207     void rewriteValue(const DOMString &newValue);
0208 
0209     LocalName m_localName;
0210     NamespaceName m_namespace;
0211     PrefixName m_prefix;
0212     union {
0213         DOMStringImpl *value;
0214         AttrImpl *attr;
0215     } m_data;
0216 };
0217 
0218 struct CombinedStyleDecl {
0219     DOM::CSSInlineStyleDeclarationImpl *inlineDecls;
0220     DOM::CSSStyleDeclarationImpl *nonCSSDecls;
0221 };
0222 
0223 class ElementImpl : public NodeBaseImpl
0224 {
0225     friend class DocumentImpl;
0226     friend class NamedAttrMapImpl;
0227     friend class AttrImpl;
0228     friend class NodeImpl;
0229     friend class khtml::CSSStyleSelector;
0230 public:
0231     ElementImpl(DocumentImpl *doc);
0232     ~ElementImpl();
0233 
0234     // stuff for WebCore DOM & SVG api compatibility
0235     bool hasTagName(const QualifiedName &name) const override
0236     {
0237         return qualifiedName() == name;/*should be matches here*/
0238     }
0239     QualifiedName qualifiedName() const
0240     {
0241         return QualifiedName(id(), m_prefix);
0242     }
0243     CSSInlineStyleDeclarationImpl *style()
0244     {
0245         return getInlineStyleDecls();
0246     }
0247     void setAttribute(const QualifiedName &name, const DOMString &value)
0248     {
0249         setAttribute(name.id(), value); /* is it enough for SVG or should the full setAttribute() be called? */
0250     }
0251     bool hasAttribute(const QualifiedName &name) const
0252     {
0253         return hasAttribute(name.tagName());
0254     }
0255     DOMString getAttribute(const QualifiedName &name) const
0256     {
0257         int ec;
0258         return const_cast<ElementImpl *>(this)->getAttributeNS(name.namespaceURI(), name.localName(), ec);
0259     }
0260     DOMString getAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptionCode) const
0261     {
0262         return const_cast<ElementImpl *>(this)->getAttributeNS(namespaceURI, localName, exceptionCode);
0263     }
0264     // FIXME: get rid of const_cast hacks (the const qualifiers of getAttribute should be reviewed
0265     // as for external API it should look like const,hower we can replace AttributeImpl (small version)
0266     // with normal AttrImpl (NodeImpl)
0267     // END OF FIXME
0268     // enf of WC api compatibility stuff
0269 
0270     //Higher-level DOM stuff
0271     bool hasAttributes() const override;
0272     bool hasAttribute(const DOMString &name) const;
0273     bool hasAttributeNS(const DOMString &namespaceURI, const DOMString &localName) const;
0274     DOMString getAttribute(const DOMString &name);
0275     void setAttribute(const DOMString &name, const DOMString &value, int &exceptioncode);
0276     void removeAttribute(const DOMString &name, int &exceptioncode);
0277     void removeAttribute(NodeImpl::Id id, int &exceptioncode);
0278     AttrImpl *getAttributeNode(const DOMString &name);
0279     Attr setAttributeNode(AttrImpl *newAttr, int &exceptioncode);
0280     Attr removeAttributeNode(AttrImpl *oldAttr, int &exceptioncode);
0281 
0282     DOMString getAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode);
0283     void removeAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode);
0284     AttrImpl *getAttributeNodeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode);
0285     Attr setAttributeNodeNS(AttrImpl *newAttr, int &exceptioncode);
0286 
0287     // At this level per WAI-ARIA
0288     void blur();
0289     void focus();
0290 
0291     //Lower-level implementation primitives
0292     inline DOMString getAttribute(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const
0293     {
0294         return DOMString(getAttributeImpl(id, prefix, nsAware));
0295     }
0296     inline DOMStringImpl *getAttributeImpl(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const;
0297     void setAttribute(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, const DOMString &value, int &exceptioncode);
0298     void setAttributeNS(const DOMString &namespaceURI, const DOMString &localName, const DOMString &value, int &exceptioncode);
0299 
0300     inline DOMStringImpl *getAttributeImplById(NodeImpl::Id id) const;
0301 
0302     // WebCore API
0303     DOMString getIDAttribute() const
0304     {
0305         return getAttribute(ATTR_ID);
0306     }
0307     // End
0308 
0309     bool hasAttribute(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const
0310     {
0311         return getAttributeImpl(id, prefix, nsAware) != nullptr;
0312     }
0313     DOMString prefix() const override
0314     {
0315         return m_prefix.toString();
0316     }
0317     void setPrefix(const DOMString &_prefix, int &exceptioncode) override;
0318     DOMString namespaceURI() const override;
0319     inline const PrefixName &prefixName() const
0320     {
0321         return m_prefix;
0322     }
0323 
0324     short tabIndex() const override;
0325     void setTabIndex(short _tabIndex);
0326     void setNoTabIndex();
0327     bool hasTabIndex() const;
0328 
0329     // DOM methods overridden from  parent classes
0330     virtual DOMString tagName() const;
0331     DOMString localName() const override;
0332 
0333     // Internal version of tagName for elements that doesn't
0334     // do case normalization
0335     DOMString nonCaseFoldedTagName() const;
0336 
0337     unsigned short nodeType() const override;
0338     WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override;
0339     DOMString nodeName() const override;
0340     NodeImpl::Id id() const override = 0;
0341     bool isElementNode() const override
0342     {
0343         return true;
0344     }
0345     void insertedIntoDocument() override;
0346     void removedFromDocument() override;
0347 
0348     // ElementTraversal API
0349     ElementImpl *firstElementChild() const;
0350     ElementImpl *lastElementChild() const;
0351     ElementImpl *previousElementSibling() const;
0352     ElementImpl *nextElementSibling() const;
0353     unsigned childElementCount() const;
0354 
0355     // convenience methods which ignore exceptions
0356     void setAttribute(NodeImpl::Id id, const DOMString &value);
0357     void setBooleanAttribute(NodeImpl::Id id, bool b);
0358 
0359     NamedAttrMapImpl *attributes(bool readonly = false) const
0360     {
0361         if (m_needsStyleAttributeUpdate) {
0362             synchronizeStyleAttribute();
0363         }
0364         if (!readonly && !namedAttrMap) {
0365             createAttributeMap();
0366         }
0367         return namedAttrMap;
0368     }
0369 
0370     //This is always called, whenever an attribute changed
0371     virtual void parseAttribute(AttributeImpl *) {}
0372     void parseNullAttribute(NodeImpl::Id id, PrefixName prefix)
0373     {
0374         AttributeImpl aimpl;
0375         aimpl.m_localName = LocalName::fromId(localNamePart(id));
0376         aimpl.m_namespace = NamespaceName::fromId(namespacePart(id));
0377         aimpl.m_prefix = prefix;
0378         aimpl.m_data.value = nullptr;
0379         parseAttribute(&aimpl);
0380     }
0381 
0382     void parseAttribute(AttrImpl *fullAttr)
0383     {
0384         AttributeImpl aimpl;
0385         aimpl.m_localName = emptyLocalName;
0386         aimpl.m_data.attr = fullAttr;
0387         parseAttribute(&aimpl);
0388     }
0389 
0390     inline const ClassNames &classNames() const;
0391 
0392     // not part of the DOM
0393     void setAttributeMap(NamedAttrMapImpl *list);
0394 
0395     // State of the element.
0396     QString state() override
0397     {
0398         return QString();
0399     }
0400 
0401     virtual void copyNonAttributeProperties(const ElementImpl * /*source*/) {}
0402 
0403     void attach() override;
0404     void close() override;
0405     void detach() override;
0406     void structureChanged() override;
0407     void backwardsStructureChanged() override;
0408     virtual void attributeChanged(NodeImpl::Id attrId);
0409     // for WebCore API compatibility
0410     virtual void attributeChanged(AttributeImpl *attribute, bool /*preserveDecls*/)
0411     {
0412         attributeChanged(attribute->id());
0413     }
0414 
0415     void defaultEventHandler(EventImpl *evt) override;
0416 
0417     khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent) override;
0418     khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *) override;
0419     void recalcStyle(StyleChange = NoChange) override;
0420     khtml::RenderStyle *computedStyle() override;
0421 
0422     virtual void mouseEventHandler(MouseEvent * /*ev*/, bool /*inside*/) {}
0423 
0424     bool childAllowed(NodeImpl *newChild) override;
0425     bool childTypeAllowed(unsigned short type) override;
0426     DOM::CSSInlineStyleDeclarationImpl *inlineStyleDecls() const
0427     {
0428         return m_hasCombinedStyle ? m_style.combinedDecls->inlineDecls : m_style.inlineDecls;
0429     }
0430     DOM::CSSStyleDeclarationImpl *nonCSSStyleDecls() const
0431     {
0432         return m_hasCombinedStyle ? m_style.combinedDecls->nonCSSDecls : nullptr;
0433     }
0434     DOM::CSSInlineStyleDeclarationImpl *getInlineStyleDecls();
0435 
0436     void dispatchAttrRemovalEvent(NodeImpl::Id id, DOMStringImpl *value);
0437     void dispatchAttrAdditionEvent(NodeImpl::Id id, DOMStringImpl *value);
0438 
0439     DOMString toString() const override;
0440     DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const override;
0441 
0442     bool isFocusableImpl(FocusType ft) const override;
0443     bool isContentEditable() const override;
0444     void setContentEditable(bool enabled);
0445 
0446     void scrollIntoView(bool alignToTop);
0447 
0448     /** Returns the opening tag and properties.
0449      *  Examples:  '<b', '<img alt="hello" src="image.png"
0450      *
0451      *  For security reasons, passwords are stripped out of all src= and
0452      *  href=  tags if expandurls is turned on.
0453      *
0454      *  @param expandurls If this is set then in the above example, it would give
0455      *                    src="http://website.com/image.png".  Note that the password
0456      *                    is stripped out of the url.
0457      *
0458      *  DOM::RangeImpl uses this which is why it is public.
0459      */
0460     DOMString openTagStartToString(bool expandurls = false) const;
0461 
0462     void updateId(DOMStringImpl *oldId, DOMStringImpl *newId);
0463     //Called when mapping from id to this node in document should be removed
0464     virtual void removeId(const DOMString &id);
0465     //Called when mapping from id to this node in document should be added
0466     virtual void addId(const DOMString &id);
0467 
0468     // Synchronize style attribute after it was changed via CSSOM
0469     void synchronizeStyleAttribute() const;
0470 
0471 protected:
0472     void createAttributeMap() const;
0473     void createInlineDecl(); // for inline styles
0474     void createNonCSSDecl(); // for presentational styles
0475     void finishCloneNode(ElementImpl *clone, bool deep);
0476 
0477 private:
0478     // There is some information such as computed style for display:none
0479     // elements that is needed only for a few elements. We store it
0480     // in one of these.
0481     ElementRareDataImpl *rareData();
0482     const ElementRareDataImpl *rareData() const;
0483     ElementRareDataImpl *createRareData();
0484 
0485 protected: // member variables
0486     mutable NamedAttrMapImpl *namedAttrMap;
0487 
0488     union {
0489         DOM::CSSInlineStyleDeclarationImpl *inlineDecls;
0490         CombinedStyleDecl *combinedDecls;
0491     } m_style;
0492     PrefixName m_prefix;
0493 };
0494 
0495 class XMLElementImpl : public ElementImpl
0496 {
0497 
0498 public:
0499     XMLElementImpl(DocumentImpl *doc, NamespaceName namespacename, LocalName localName, PrefixName prefix);
0500     ~XMLElementImpl();
0501 
0502     void parseAttribute(AttributeImpl *attr) override;
0503 
0504     WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override;
0505 
0506     // Other methods (not part of DOM)
0507     bool isXMLElementNode() const override
0508     {
0509         return true;
0510     }
0511     Id id() const override
0512     {
0513         return makeId(m_namespace.id(), m_localName.id());
0514     }
0515 
0516 protected:
0517     LocalName m_localName;
0518     NamespaceName m_namespace;
0519 };
0520 
0521 // the map of attributes of an element
0522 class NamedAttrMapImpl : public NamedNodeMapImpl
0523 {
0524     friend class ElementImpl;
0525 public:
0526     NamedAttrMapImpl(ElementImpl *element);
0527     virtual ~NamedAttrMapImpl();
0528 
0529     // DOM methods & attributes for NamedNodeMap
0530     NodeImpl *getNamedItem(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) override;
0531     Node removeNamedItem(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, int &exceptioncode) override;
0532     Node setNamedItem(NodeImpl *arg, const PrefixName &prefix, bool nsAware, int &exceptioncode) override;
0533 
0534     // for WebCore api compat
0535     virtual NodeImpl *getNamedItem(const QualifiedName &name)
0536     {
0537         return getNamedItem(name.id(), name.prefixId(), true);
0538     }
0539 
0540     NodeImpl *item(unsigned index) override;
0541     unsigned length() const override
0542     {
0543         return m_attrs.size();
0544     }
0545 
0546     // Other methods (not part of DOM)
0547     bool isReadOnly() override
0548     {
0549         return false;
0550     }
0551     bool htmlCompat() override
0552     {
0553         return m_element ? m_element->m_htmlCompat : false;
0554     }
0555 
0556     AttributeImpl &attributeAt(unsigned index)
0557     {
0558         return m_attrs[index];
0559     }
0560     const AttributeImpl &attributeAt(unsigned index) const
0561     {
0562         return m_attrs[index];
0563     }
0564     AttrImpl *attrAt(unsigned index) const
0565     {
0566         return m_attrs[index].attr();
0567     }
0568     // ### replace idAt and getValueAt with attrAt
0569     NodeImpl::Id idAt(unsigned index) const;
0570     DOMStringImpl *valueAt(unsigned index) const;
0571     DOMStringImpl *getValue(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const;
0572     void setValue(NodeImpl::Id id, DOMStringImpl *value, const PrefixName &prefix = emptyPrefixName, bool nsAware = false);
0573     Attr removeAttr(AttrImpl *attr);
0574     void copyAttributes(NamedAttrMapImpl *other);
0575     void setElement(ElementImpl *element);
0576     void detachFromElement();
0577 
0578     int find(NodeImpl::Id id, const PrefixName &prefix, bool nsAware) const;
0579     inline DOMStringImpl *fastFind(NodeImpl::Id id) const;
0580 
0581     inline void clearClass()
0582     {
0583         m_classNames.clear();
0584     }
0585     void setClass(const DOMString &string);
0586     inline const ClassNames &classNames() const
0587     {
0588         return m_classNames;
0589     }
0590 
0591     // Rewrites value if attribute already exists or adds a new attribute otherwise
0592     // @important: any changes won't be propagated to parent Element
0593     void setValueWithoutElementUpdate(NodeImpl::Id id, DOMStringImpl *value);
0594 
0595 protected:
0596     ElementImpl *m_element;
0597     WTF::Vector<AttributeImpl> m_attrs;
0598     ClassNames m_classNames;
0599 };
0600 
0601 // ------------  inline DOM helper functions ---------------
0602 
0603 inline bool checkQualifiedName(const DOMString &qualifiedName, const DOMString &namespaceURI, int *colonPos,
0604                                bool nameCanBeNull, bool nameCanBeEmpty, int *pExceptioncode)
0605 {
0606 
0607     // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
0608     if (!nameCanBeNull && qualifiedName.isNull()) {
0609         if (pExceptioncode) {
0610             *pExceptioncode = DOMException::NAMESPACE_ERR;
0611         }
0612         return false;
0613     }
0614 
0615     // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
0616     if (!qualifiedName.isNull() && !Element::khtmlValidQualifiedName(qualifiedName)
0617             && (!qualifiedName.isEmpty() || !nameCanBeEmpty)) {
0618         if (pExceptioncode) {
0619             *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
0620         }
0621         return false;
0622     }
0623 
0624     // NAMESPACE_ERR:
0625     // - Raised if the qualifiedName is malformed,
0626     // - if the qualifiedName has a prefix and the namespaceURI is null, or
0627     // - if the qualifiedName is null and the namespaceURI is different from null
0628     // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different
0629     //   from "http://www.w3.org/XML/1998/namespace" [Namespaces].
0630     int colonpos = -1;
0631     uint i;
0632     DOMStringImpl *qname = qualifiedName.implementation();
0633     for (i = 0; i < (qname ? qname->l : 0); i++) {
0634         if ((*qname)[i] == QLatin1Char(':')) {
0635             colonpos = i;
0636             break;
0637         }
0638     }
0639 
0640     bool hasXMLPrefix = colonpos == 3 && (*qname)[0] == QLatin1Char('x') &&
0641                         (*qname)[1] == QLatin1Char('m') && (*qname)[2] == QLatin1Char('l');
0642     bool hasXMLNSPrefix = colonpos == 5 && (*qname)[0] == QLatin1Char('x') &&
0643                           (*qname)[1] == QLatin1Char('m') && (*qname)[2] == QLatin1Char('l') &&
0644                           (*qname)[3] == QLatin1Char('n') && (*qname)[4] == QLatin1Char('s');
0645 
0646     if ((!qualifiedName.isNull() && Element::khtmlMalformedQualifiedName(qualifiedName)) ||
0647             (colonpos >= 0 && namespaceURI.isNull()) ||
0648             colonpos == 0 || // prefix has to consist of at least a letter
0649             (qualifiedName.isNull() && !namespaceURI.isNull()) ||
0650             (hasXMLPrefix && namespaceURI != XML_NAMESPACE) ||
0651             (hasXMLNSPrefix && namespaceURI != XMLNS_NAMESPACE) ||
0652             (namespaceURI == XMLNS_NAMESPACE && !hasXMLNSPrefix && qualifiedName != "xmlns")) {
0653         if (pExceptioncode) {
0654             *pExceptioncode = DOMException::NAMESPACE_ERR;
0655         }
0656         return false;
0657     }
0658     if (colonPos) {
0659         *colonPos = colonpos;
0660     }
0661     return true;
0662 }
0663 
0664 inline void splitPrefixLocalName(DOMStringImpl *qualifiedName, DOMString &prefix, DOMString &localName, int colonPos = -2)
0665 {
0666     if (colonPos == -2)
0667         for (uint i = 0; i < qualifiedName->l; ++i)
0668             if (qualifiedName->s[i] == QLatin1Char(':')) {
0669                 colonPos = i;
0670                 break;
0671             }
0672     if (colonPos >= 0) {
0673         prefix = qualifiedName->copy();
0674         localName = prefix.split(colonPos + 1);
0675         prefix.implementation()->truncate(colonPos);
0676     } else {
0677         localName = qualifiedName;
0678     }
0679 }
0680 
0681 inline void splitPrefixLocalName(const DOMString &qualifiedName, PrefixName &prefix, LocalName &localName, bool htmlCompat = false, int colonPos = -2)
0682 {
0683     DOMString localname, prefixname;
0684     splitPrefixLocalName(qualifiedName.implementation(), prefixname, localname, colonPos);
0685     if (htmlCompat) {
0686         prefix = PrefixName::fromString(prefixname, khtml::IDS_NormalizeLower);
0687         localName = LocalName::fromString(localname, khtml::IDS_NormalizeLower);
0688     } else {
0689         prefix = PrefixName::fromString(prefixname);
0690         localName = LocalName::fromString(localname);
0691     }
0692 }
0693 
0694 // methods that could be very hot and therefore need to be inlined
0695 inline DOMStringImpl *ElementImpl::getAttributeImpl(NodeImpl::Id id, const PrefixName &prefix, bool nsAware) const
0696 {
0697     if (m_needsStyleAttributeUpdate && (id == ATTR_STYLE)) {
0698         synchronizeStyleAttribute();
0699     }
0700     return namedAttrMap ? namedAttrMap->getValue(id, prefix, nsAware) : nullptr;
0701 }
0702 
0703 inline const ClassNames &ElementImpl::classNames() const
0704 {
0705     // hasClass() should be called on element first as in CSSStyleSelector::checkSimpleSelector
0706     return namedAttrMap->classNames();
0707 }
0708 
0709 inline DOMStringImpl *ElementImpl::getAttributeImplById(NodeImpl::Id id) const
0710 {
0711     return namedAttrMap ? namedAttrMap->fastFind(id) : nullptr;
0712 }
0713 
0714 inline DOMStringImpl *NamedAttrMapImpl::fastFind(NodeImpl::Id id) const
0715 {
0716     unsigned mask = anyQName;
0717     if (namespacePart(id) == anyNamespace) {
0718         mask = anyLocalName;
0719         id = localNamePart(id);
0720     }
0721     unsigned len = m_attrs.size();
0722     for (unsigned i = 0; i < len; ++i)
0723         if (id == (m_attrs[i].id() & mask)) {
0724             return m_attrs[i].val();
0725         }
0726     return nullptr;
0727 }
0728 
0729 } //namespace
0730 
0731 #endif