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 blink {
     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         void ref()
     59         {
     60             if (m_isStatic)
     61                 return;
     62             RefCounted<QualifiedNameImpl>::ref();
     63         }
     64 
     65         void deref()
     66         {
     67             if (m_isStatic)
     68                 return;
     69             RefCounted<QualifiedNameImpl>::deref();
     70         }
     71 
     72         // We rely on StringHasher's hashMemory clearing out the top 8 bits when
     73         // doing hashing and use one of the bits for the m_isStatic value.
     74         mutable unsigned m_existingHash : 24;
     75         unsigned m_isStatic : 1;
     76         const AtomicString m_prefix;
     77         const AtomicString m_localName;
     78         const AtomicString m_namespace;
     79         mutable AtomicString m_localNameUpper;
     80 
     81     private:
     82         QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic)
     83             : m_existingHash(0)
     84             , m_isStatic(isStatic)
     85             , m_prefix(prefix)
     86             , m_localName(localName)
     87             , m_namespace(namespaceURI)
     88 
     89         {
     90             ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull());
     91         }
     92     };
     93 
     94     QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI);
     95     ~QualifiedName();
     96 
     97     QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { }
     98     const QualifiedName& operator=(const QualifiedName& other) { m_impl = other.m_impl; return *this; }
     99 
    100     // Hash table deleted values, which are only constructed and never copied or destroyed.
    101     QualifiedName(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
    102     bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
    103 
    104     bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; }
    105     bool operator!=(const QualifiedName& other) const { return !(*this == other); }
    106 
    107     bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); }
    108 
    109     bool matchesPossiblyIgnoringCase(const QualifiedName& other, bool shouldIgnoreCase) const { return m_impl == other.m_impl || (equalPossiblyIgnoringCase(localName(), other.localName(), shouldIgnoreCase) && namespaceURI() == other.namespaceURI()); }
    110 
    111     bool hasPrefix() const { return m_impl->m_prefix != nullAtom; }
    112     void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); }
    113 
    114     const AtomicString& prefix() const { return m_impl->m_prefix; }
    115     const AtomicString& localName() const { return m_impl->m_localName; }
    116     const AtomicString& namespaceURI() const { return m_impl->m_namespace; }
    117 
    118     // Uppercased localName, cached for efficiency
    119     const AtomicString& localNameUpper() const;
    120 
    121     String toString() const;
    122 
    123     QualifiedNameImpl* impl() const { return m_impl.get(); }
    124 
    125     // Init routine for globals
    126     static void init();
    127 
    128     static const QualifiedName& null();
    129 
    130     // The below methods are only for creating static global QNames that need no ref counting.
    131     static void createStatic(void* targetAddress, StringImpl* name);
    132     static void createStatic(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace);
    133 
    134 private:
    135     // This constructor is used only to create global/static QNames that don't require any ref counting.
    136     QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic);
    137 
    138     RefPtr<QualifiedNameImpl> m_impl;
    139 };
    140 
    141 extern const QualifiedName& anyName;
    142 inline const QualifiedName& anyQName() { return anyName; }
    143 
    144 inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); }
    145 inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); }
    146 inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); }
    147 inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); }
    148 
    149 inline unsigned hashComponents(const QualifiedNameComponents& buf)
    150 {
    151     return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
    152 }
    153 
    154 struct QualifiedNameHash {
    155     static unsigned hash(const QualifiedName& name) { return hash(name.impl()); }
    156 
    157     static unsigned hash(const QualifiedName::QualifiedNameImpl* name)
    158     {
    159         if (!name->m_existingHash)
    160             name->m_existingHash = name->computeHash();
    161         return name->m_existingHash;
    162     }
    163 
    164     static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; }
    165     static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; }
    166 
    167     static const bool safeToCompareToEmptyOrDeleted = false;
    168 };
    169 
    170 } // namespace blink
    171 
    172 namespace WTF {
    173 
    174     template<typename T> struct DefaultHash;
    175 
    176     template<> struct DefaultHash<blink::QualifiedName> {
    177         typedef blink::QualifiedNameHash Hash;
    178     };
    179 
    180     template<> struct HashTraits<blink::QualifiedName> : SimpleClassHashTraits<blink::QualifiedName> {
    181         static const bool emptyValueIsZero = false;
    182         static blink::QualifiedName emptyValue() { return blink::QualifiedName::null(); }
    183     };
    184 }
    185 
    186 #endif
    187