15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef QualifiedName_h
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define QualifiedName_h
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
240019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch#include "wtf/HashTableDeletedValueType.h"
25e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/HashTraits.h"
26e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/RefCounted.h"
27e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/text/AtomicString.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct QualifiedNameComponents {
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringImpl* m_prefix;
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringImpl* m_localName;
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StringImpl* m_namespace;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// This struct is used to pass data between QualifiedName and the QNameTranslator.
385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)// For hashing and equality only the QualifiedNameComponents fields are used.
395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)struct QualifiedNameData {
405d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    QualifiedNameComponents m_components;
415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    bool m_isStatic;
425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)};
435d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class QualifiedName {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WTF_MAKE_FAST_ALLOCATED;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        static PassRefPtr<QualifiedNameImpl> create(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI, isStatic));
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ~QualifiedNameImpl();
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned computeHash() const;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        void ref()
595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        {
605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            if (m_isStatic)
615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                return;
625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            RefCounted<QualifiedNameImpl>::ref();
635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        void deref()
665d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        {
675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            if (m_isStatic)
685d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                return;
695d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            RefCounted<QualifiedNameImpl>::deref();
705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        }
715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // We rely on StringHasher's hashMemory clearing out the top 8 bits when
735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // doing hashing and use one of the bits for the m_isStatic value.
745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        mutable unsigned m_existingHash : 24;
755d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        unsigned m_isStatic : 1;
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        const AtomicString m_prefix;
777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        const AtomicString m_localName;
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        const AtomicString m_namespace;
797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        mutable AtomicString m_localNameUpper;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic)
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            : m_existingHash(0)
847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            , m_isStatic(isStatic)
857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            , m_prefix(prefix)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_localName(localName)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            , m_namespace(namespaceURI)
885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull());
9102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        }
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ~QualifiedName();
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { }
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const QualifiedName& operator=(const QualifiedName& other) { m_impl = other.m_impl; return *this; }
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Hash table deleted values, which are only constructed and never copied or destroyed.
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    QualifiedName(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; }
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator!=(const QualifiedName& other) const { return !(*this == other); }
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); }
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
109e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    bool matchesPossiblyIgnoringCase(const QualifiedName& other, bool shouldIgnoreCase) const { return m_impl == other.m_impl || (equalPossiblyIgnoringCase(localName(), other.localName(), shouldIgnoreCase) && namespaceURI() == other.namespaceURI()); }
110e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool hasPrefix() const { return m_impl->m_prefix != nullAtom; }
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); }
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& prefix() const { return m_impl->m_prefix; }
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& localName() const { return m_impl->m_localName; }
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& namespaceURI() const { return m_impl->m_namespace; }
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Uppercased localName, cached for efficiency
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const AtomicString& localNameUpper() const;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String toString() const;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    QualifiedNameImpl* impl() const { return m_impl.get(); }
12402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Init routine for globals
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static void init();
12702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static const QualifiedName& null();
1295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // The below methods are only for creating static global QNames that need no ref counting.
1315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static void createStatic(void* targetAddress, StringImpl* name);
1325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    static void createStatic(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace);
1335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // This constructor is used only to create global/static QNames that don't require any ref counting.
1365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI, bool isStatic);
1375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<QualifiedNameImpl> m_impl;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)extern const QualifiedName& anyName;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline const QualifiedName& anyQName() { return anyName; }
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); }
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); }
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); }
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); }
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline unsigned hashComponents(const QualifiedNameComponents& buf)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct QualifiedNameHash {
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static unsigned hash(const QualifiedName& name) { return hash(name.impl()); }
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    static unsigned hash(const QualifiedName::QualifiedNameImpl* name)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!name->m_existingHash)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            name->m_existingHash = name->computeHash();
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return name->m_existingHash;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; }
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; }
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static const bool safeToCompareToEmptyOrDeleted = false;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
170e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace blink
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WTF {
17302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    template<typename T> struct DefaultHash;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
176c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    template<> struct DefaultHash<blink::QualifiedName> {
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        typedef blink::QualifiedNameHash Hash;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
17902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    template<> struct HashTraits<blink::QualifiedName> : SimpleClassHashTraits<blink::QualifiedName> {
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        static const bool emptyValueIsZero = false;
182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        static blink::QualifiedName emptyValue() { return blink::QualifiedName::null(); }
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
187