2 * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved.
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.
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.
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.
22 #include "core/dom/QualifiedName.h"
24 #include "core/HTMLNames.h"
25 #include "core/MathMLNames.h"
26 #include "core/SVGNames.h"
27 #include "core/XLinkNames.h"
28 #include "core/XMLNSNames.h"
29 #include "core/XMLNames.h"
30 #include "wtf/Assertions.h"
31 #include "wtf/HashSet.h"
32 #include "wtf/MainThread.h"
33 #include "wtf/StaticConstructors.h"
37 struct SameSizeAsQualifiedNameImpl
: public RefCounted
<SameSizeAsQualifiedNameImpl
> {
42 static_assert(sizeof(QualifiedName::QualifiedNameImpl
) == sizeof(SameSizeAsQualifiedNameImpl
), "QualifiedNameImpl should stay small");
44 static const int staticQualifiedNamesCount
= HTMLNames::HTMLTagsCount
+ HTMLNames::HTMLAttrsCount
45 + MathMLNames::MathMLTagsCount
+ MathMLNames::MathMLAttrsCount
46 + SVGNames::SVGTagsCount
+ SVGNames::SVGAttrsCount
47 + XLinkNames::XLinkAttrsCount
48 + XMLNSNames::XMLNSAttrsCount
49 + XMLNames::XMLAttrsCount
;
51 struct QualifiedNameHashTraits
: public HashTraits
<QualifiedName::QualifiedNameImpl
*> {
52 static const unsigned minimumTableSize
= WTF::HashTableCapacityForSize
<staticQualifiedNamesCount
>::value
;
55 typedef HashSet
<QualifiedName::QualifiedNameImpl
*, QualifiedNameHash
, QualifiedNameHashTraits
> QualifiedNameCache
;
57 static QualifiedNameCache
& qualifiedNameCache()
59 // This code is lockless and thus assumes it all runs on one thread!
60 ASSERT(isMainThread());
61 static QualifiedNameCache
* gNameCache
= new QualifiedNameCache
;
65 struct QNameComponentsTranslator
{
66 static unsigned hash(const QualifiedNameData
& data
)
68 return hashComponents(data
.m_components
);
70 static bool equal(QualifiedName::QualifiedNameImpl
* name
, const QualifiedNameData
& data
)
72 return data
.m_components
.m_prefix
== name
->m_prefix
.impl()
73 && data
.m_components
.m_localName
== name
->m_localName
.impl()
74 && data
.m_components
.m_namespace
== name
->m_namespace
.impl();
76 static void translate(QualifiedName::QualifiedNameImpl
*& location
, const QualifiedNameData
& data
, unsigned)
78 const QualifiedNameComponents
& components
= data
.m_components
;
79 location
= QualifiedName::QualifiedNameImpl::create(AtomicString(components
.m_prefix
), AtomicString(components
.m_localName
), AtomicString(components
.m_namespace
), data
.m_isStatic
).leakRef();
83 QualifiedName::QualifiedName(const AtomicString
& p
, const AtomicString
& l
, const AtomicString
& n
)
85 QualifiedNameData data
= { { p
.impl(), l
.impl(), n
.isEmpty() ? nullAtom
.impl() : n
.impl() }, false };
86 QualifiedNameCache::AddResult addResult
= qualifiedNameCache().add
<QNameComponentsTranslator
>(data
);
87 m_impl
= addResult
.isNewEntry
? adoptRef(*addResult
.storedValue
) : *addResult
.storedValue
;
90 QualifiedName::QualifiedName(const AtomicString
& p
, const AtomicString
& l
, const AtomicString
& n
, bool isStatic
)
92 QualifiedNameData data
= { { p
.impl(), l
.impl(), n
.impl() }, isStatic
};
93 QualifiedNameCache::AddResult addResult
= qualifiedNameCache().add
<QNameComponentsTranslator
>(data
);
94 m_impl
= addResult
.isNewEntry
? adoptRef(*addResult
.storedValue
) : *addResult
.storedValue
;
97 QualifiedName::~QualifiedName()
101 QualifiedName::QualifiedNameImpl::~QualifiedNameImpl()
103 qualifiedNameCache().remove(this);
106 String
QualifiedName::toString() const
108 String local
= localName();
110 return prefix().string() + ":" + local
;
114 // Global init routines
115 DEFINE_GLOBAL(QualifiedName
, anyName
, nullAtom
, starAtom
, starAtom
)
116 DEFINE_GLOBAL(QualifiedName
, nullName
, nullAtom
, nullAtom
, nullAtom
)
118 void QualifiedName::init()
120 ASSERT(starAtom
.impl());
121 new ((void*)&anyName
) QualifiedName(nullAtom
, starAtom
, starAtom
, true );
122 new ((void*)&nullName
) QualifiedName(nullAtom
, nullAtom
, nullAtom
, true );
125 const QualifiedName
& QualifiedName::null()
130 const AtomicString
& QualifiedName::localNameUpper() const
132 if (!m_impl
->m_localNameUpper
)
133 m_impl
->m_localNameUpper
= m_impl
->m_localName
.upper();
134 return m_impl
->m_localNameUpper
;
137 unsigned QualifiedName::QualifiedNameImpl::computeHash() const
139 QualifiedNameComponents components
= { m_prefix
.impl(), m_localName
.impl(), m_namespace
.impl() };
140 return hashComponents(components
);
143 void QualifiedName::createStatic(void* targetAddress
, StringImpl
* name
, const AtomicString
& nameNamespace
)
145 new (targetAddress
) QualifiedName(nullAtom
, AtomicString(name
), nameNamespace
, true);
148 void QualifiedName::createStatic(void* targetAddress
, StringImpl
* name
)
150 new (targetAddress
) QualifiedName(nullAtom
, AtomicString(name
), nullAtom
, true);