Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef QualifiedName_h
     22 #define QualifiedName_h
     23 
     24 #include "wtf/HashTableDeletedValueType.h"
     25 #include "wtf/HashTraits.h"
     26 #include "wtf/RefCounted.h"
     27 #include "wtf/text/AtomicString.h"
     28 
     29 namespace WebCore {
     30 
     31 struct QualifiedNameComponents {
     32     StringImpl* m_prefix;
     33     StringImpl* m_localName;
     34     StringImpl* m_namespace;
     35 };
     36 
     37 // This struct is used to pass data between QualifiedName and the QNameTranslator.
     38 // For hashing and equality only the QualifiedNameComponents fields are used.
     39 struct QualifiedNameData {
     40     QualifiedNameComponents m_components;
     41     bool m_isStatic;
     42 };
     43 
     44 class QualifiedName {
     45     WTF_MAKE_FAST_ALLOCATED;
     46 public:
     47     class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> {
     48     public:
     49         static PassRefPtr<QualifiedNameImpl> create(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic)
     50         {
     51             return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI, isStatic));
     52         }
     53 
     54         ~QualifiedNameImpl();
     55 
     56         unsigned computeHash() const;
     57 
     58         bool hasOneRef() const
     59         {
     60             return m_isStatic || RefCounted<QualifiedNameImpl>::hasOneRef();
     61         }
     62 
     63         void ref()
     64         {
     65             if (m_isStatic)
     66                 return;
     67             RefCounted<QualifiedNameImpl>::ref();
     68         }
     69 
     70         void deref()
     71         {
     72             if (m_isStatic)
     73                 return;
     74             RefCounted<QualifiedNameImpl>::deref();
     75         }
     76 
     77         const AtomicString m_prefix;
     78         const AtomicString m_localName;
     79         const AtomicString m_namespace;
     80         mutable AtomicString m_localNameUpper;
     81         // We rely on StringHasher's hashMemory clearing out the top 8 bits when
     82         // doing hashing and use one of the bits for the m_isStatic value.
     83         mutable unsigned m_existingHash : 24;
     84         unsigned m_isStatic : 1;
     85 
     86     private:
     87         QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic)
     88             : m_prefix(prefix)
     89             , m_localName(localName)
     90             , m_namespace(namespaceURI)
     91             , m_existingHash(0)
     92             , m_isStatic(isStatic)
     93 
     94         {
     95             ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull());
     96         }
     97     };
     98 
     99     QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI);
    100     ~QualifiedName();
    101 #ifdef QNAME_DEFAULT_CONSTRUCTOR
    102     QualifiedName() { }
    103 #endif
    104 
    105     QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { }
    106     const QualifiedName& operator=(const QualifiedName& other) { m_impl = other.m_impl; return *this; }
    107 
    108     // Hash table deleted values, which are only constructed and never copied or destroyed.
    109     QualifiedName(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
    110     bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
    111 
    112     bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; }
    113     bool operator!=(const QualifiedName& other) const { return !(*this == other); }
    114 
    115     bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); }
    116 
    117     bool matchesPossiblyIgnoringCase(const QualifiedName& other, bool shouldIgnoreCase) const { return m_impl == other.m_impl || (equalPossiblyIgnoringCase(localName(), other.localName(), shouldIgnoreCase) && namespaceURI() == other.namespaceURI()); }
    118 
    119     bool hasPrefix() const { return m_impl->m_prefix != nullAtom; }
    120     void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); }
    121 
    122     const AtomicString& prefix() const { return m_impl->m_prefix; }
    123     const AtomicString& localName() const { return m_impl->m_localName; }
    124     const AtomicString& namespaceURI() const { return m_impl->m_namespace; }
    125 
    126     // Uppercased localName, cached for efficiency
    127     const AtomicString& localNameUpper() const;
    128 
    129     String toString() const;
    130 
    131     QualifiedNameImpl* impl() const { return m_impl.get(); }
    132 
    133     // Init routine for globals
    134     static void init();
    135 
    136     static const QualifiedName& null();
    137 
    138     // The below methods are only for creating static global QNames that need no ref counting.
    139     static void createStatic(void* targetAddress, StringImpl* name);
    140     static void createStatic(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace);
    141 
    142 private:
    143     // This constructor is used only to create global/static QNames that don't require any ref counting.
    144     QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic);
    145 
    146     RefPtr<QualifiedNameImpl> m_impl;
    147 };
    148 
    149 #ifndef WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS
    150 extern const QualifiedName anyName;
    151 inline const QualifiedName& anyQName() { return anyName; }
    152 #endif
    153 
    154 inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); }
    155 inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); }
    156 inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); }
    157 inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); }
    158 
    159 inline unsigned hashComponents(const QualifiedNameComponents& buf)
    160 {
    161     return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
    162 }
    163 
    164 struct QualifiedNameHash {
    165     static unsigned hash(const QualifiedName& name) { return hash(name.impl()); }
    166 
    167     static unsigned hash(const QualifiedName::QualifiedNameImpl* name)
    168     {
    169         if (!name->m_existingHash)
    170             name->m_existingHash = name->computeHash();
    171         return name->m_existingHash;
    172     }
    173 
    174     static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; }
    175     static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; }
    176 
    177     static const bool safeToCompareToEmptyOrDeleted = false;
    178 };
    179 
    180 }
    181 
    182 namespace WTF {
    183 
    184     template<typename T> struct DefaultHash;
    185 
    186     template<> struct DefaultHash<WebCore::QualifiedName> {
    187         typedef WebCore::QualifiedNameHash Hash;
    188     };
    189 
    190     template<> struct HashTraits<WebCore::QualifiedName> : SimpleClassHashTraits<WebCore::QualifiedName> {
    191         static const bool emptyValueIsZero = false;
    192         static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName::null(); }
    193     };
    194 }
    195 
    196 #endif
    197