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#include "config.h"
21
22#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
23#define WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS 1
24#else
25#define QNAME_DEFAULT_CONSTRUCTOR
26#endif
27
28#include "QualifiedName.h"
29#include "HTMLNames.h"
30#include "XLinkNames.h"
31#include "XMLNSNames.h"
32#include "XMLNames.h"
33#include <wtf/Assertions.h>
34#include <wtf/HashSet.h>
35#include <wtf/StaticConstructors.h>
36
37#if ENABLE(MATHML)
38#include "MathMLNames.h"
39#endif
40
41#if ENABLE(SVG)
42#include "SVGNames.h"
43#endif
44
45namespace WebCore {
46
47static const int staticQualifiedNamesCount = HTMLNames::HTMLTagsCount + HTMLNames::HTMLAttrsCount
48#if ENABLE(MATHML)
49    + MathMLNames::MathMLTagsCount + MathMLNames::MathMLAttrsCount
50#endif
51#if ENABLE(SVG)
52    + SVGNames::SVGTagsCount + SVGNames::SVGAttrsCount
53#endif
54    + XLinkNames::XLinkAttrsCount
55    + XMLNSNames::XMLNSAttrsCount
56    + XMLNames::XMLAttrsCount;
57
58struct QualifiedNameHashTraits : public HashTraits<QualifiedName::QualifiedNameImpl*> {
59    static const int minimumTableSize = WTF::HashTableCapacityForSize<staticQualifiedNamesCount>::value;
60};
61
62typedef HashSet<QualifiedName::QualifiedNameImpl*, QualifiedNameHash, QualifiedNameHashTraits> QNameSet;
63
64struct QNameComponentsTranslator {
65    static unsigned hash(const QualifiedNameComponents& components)
66    {
67        return hashComponents(components);
68    }
69    static bool equal(QualifiedName::QualifiedNameImpl* name, const QualifiedNameComponents& c)
70    {
71        return c.m_prefix == name->m_prefix.impl() && c.m_localName == name->m_localName.impl() && c.m_namespace == name->m_namespace.impl();
72    }
73    static void translate(QualifiedName::QualifiedNameImpl*& location, const QualifiedNameComponents& components, unsigned)
74    {
75        location = QualifiedName::QualifiedNameImpl::create(components.m_prefix, components.m_localName, components.m_namespace).leakRef();
76    }
77};
78
79static QNameSet* gNameCache;
80
81QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n)
82{
83    if (!gNameCache)
84        gNameCache = new QNameSet;
85    QualifiedNameComponents components = { p.impl(), l.impl(), n.isEmpty() ? nullAtom.impl() : n.impl() };
86    QNameSet::AddResult addResult = gNameCache->add<QualifiedNameComponents, QNameComponentsTranslator>(components);
87    m_impl = *addResult.iterator;
88    if (!addResult.isNewEntry)
89        m_impl->ref();
90}
91
92QualifiedName::~QualifiedName()
93{
94    deref();
95}
96
97void QualifiedName::deref()
98{
99#ifdef QNAME_DEFAULT_CONSTRUCTOR
100    if (!m_impl)
101        return;
102#endif
103    ASSERT(!isHashTableDeletedValue());
104    m_impl->deref();
105}
106
107QualifiedName::QualifiedNameImpl::~QualifiedNameImpl()
108{
109    gNameCache->remove(this);
110}
111
112String QualifiedName::toString() const
113{
114    String local = localName();
115    if (hasPrefix()) {
116        String result = prefix().string();
117        result.append(":");
118        result.append(local);
119        return result;
120    }
121    return local;
122}
123
124// Global init routines
125DEFINE_GLOBAL(QualifiedName, anyName, nullAtom, starAtom, starAtom)
126
127void QualifiedName::init()
128{
129    static bool initialized;
130    if (!initialized) {
131        // Use placement new to initialize the globals.
132
133        AtomicString::init();
134        new (NotNull, (void*)&anyName) QualifiedName(nullAtom, starAtom, starAtom);
135        initialized = true;
136    }
137}
138
139const QualifiedName& nullQName()
140{
141    DEFINE_STATIC_LOCAL(QualifiedName, nullName, (nullAtom, nullAtom, nullAtom));
142    return nullName;
143}
144
145const AtomicString& QualifiedName::localNameUpper() const
146{
147    if (!m_impl->m_localNameUpper)
148        m_impl->m_localNameUpper = m_impl->m_localName.upper();
149    return m_impl->m_localNameUpper;
150}
151
152unsigned QualifiedName::QualifiedNameImpl::computeHash() const
153{
154    QualifiedNameComponents components = { m_prefix.impl(), m_localName.impl(), m_namespace.impl() };
155    return hashComponents(components);
156}
157
158void createQualifiedName(void* targetAddress, StringImpl* name, const AtomicString& nameNamespace)
159{
160    new (NotNull, reinterpret_cast<void*>(targetAddress)) QualifiedName(nullAtom, AtomicString(name), nameNamespace);
161}
162
163void createQualifiedName(void* targetAddress, StringImpl* name)
164{
165    new (NotNull, reinterpret_cast<void*>(targetAddress)) QualifiedName(nullAtom, AtomicString(name), nullAtom);
166}
167
168}
169