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