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 <wtf/Assertions.h>
30#include <wtf/HashSet.h>
31#include <wtf/StaticConstructors.h>
32
33namespace WebCore {
34
35typedef HashSet<QualifiedName::QualifiedNameImpl*, QualifiedNameHash> QNameSet;
36
37struct QNameComponentsTranslator {
38    static unsigned hash(const QualifiedNameComponents& components)
39    {
40        return hashComponents(components);
41    }
42    static bool equal(QualifiedName::QualifiedNameImpl* name, const QualifiedNameComponents& c)
43    {
44        return c.m_prefix == name->m_prefix.impl() && c.m_localName == name->m_localName.impl() && c.m_namespace == name->m_namespace.impl();
45    }
46    static void translate(QualifiedName::QualifiedNameImpl*& location, const QualifiedNameComponents& components, unsigned)
47    {
48        location = QualifiedName::QualifiedNameImpl::create(components.m_prefix, components.m_localName, components.m_namespace).releaseRef();
49    }
50};
51
52static QNameSet* gNameCache;
53
54void QualifiedName::init(const AtomicString& p, const AtomicString& l, const AtomicString& n)
55{
56    if (!gNameCache)
57        gNameCache = new QNameSet;
58    QualifiedNameComponents components = { p.impl(), l.impl(), n.isEmpty() ? nullAtom.impl() : n.impl() };
59    pair<QNameSet::iterator, bool> addResult = gNameCache->add<QualifiedNameComponents, QNameComponentsTranslator>(components);
60    m_impl = *addResult.first;
61    if (!addResult.second)
62        m_impl->ref();
63}
64
65QualifiedName::QualifiedName(const AtomicString& p, const AtomicString& l, const AtomicString& n)
66{
67    init(p, l, n);
68}
69
70QualifiedName::QualifiedName(const AtomicString& p, const char* l, const AtomicString& n)
71{
72    init(p, AtomicString(l), n);
73}
74
75QualifiedName::~QualifiedName()
76{
77    deref();
78}
79
80void QualifiedName::deref()
81{
82#ifdef QNAME_DEFAULT_CONSTRUCTOR
83    if (!m_impl)
84        return;
85#endif
86    ASSERT(!isHashTableDeletedValue());
87
88    if (m_impl->hasOneRef())
89        gNameCache->remove(m_impl);
90    m_impl->deref();
91}
92
93String QualifiedName::toString() const
94{
95    String local = localName();
96    if (hasPrefix()) {
97        String result = prefix().string();
98        result.append(":");
99        result.append(local);
100        return result;
101    }
102    return local;
103}
104
105// Global init routines
106DEFINE_GLOBAL(QualifiedName, anyName, nullAtom, starAtom, starAtom)
107
108void QualifiedName::init()
109{
110    static bool initialized;
111    if (!initialized) {
112        // Use placement new to initialize the globals.
113
114        AtomicString::init();
115        new ((void*)&anyName) QualifiedName(nullAtom, starAtom, starAtom);
116        initialized = true;
117    }
118}
119
120const AtomicString& QualifiedName::localNameUpper() const
121{
122    if (!m_impl->m_localNameUpper)
123        m_impl->m_localNameUpper = m_impl->m_localName.upper();
124    return m_impl->m_localNameUpper;
125}
126
127}
128