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