HTMLElement::nodeName should not upper case non-ASCII characters
[WebKit.git] / Source / WTF / wtf / text / AtomicString.cpp
1 /*
2  * Copyright (C) 2004-2008, 2013-2014 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4  * Copyright (C) 2012 Google Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "AtomicString.h"
25
26 #include "IntegerToStringConversion.h"
27 #include "dtoa.h"
28
29 #if USE(WEB_THREAD)
30 #include "Lock.h"
31 #endif
32
33 namespace WTF {
34
35 AtomicString AtomicString::lower() const
36 {
37     // Note: This is a hot function in the Dromaeo benchmark.
38     StringImpl* impl = this->impl();
39     if (UNLIKELY(!impl))
40         return AtomicString();
41
42     RefPtr<StringImpl> lowercasedString = impl->lower();
43     if (LIKELY(lowercasedString == impl))
44         return *this;
45
46     AtomicString result;
47     result.m_string = AtomicStringImpl::add(lowercasedString.get());
48     return result;
49 }
50
51 template<AtomicString::CaseConvertType type>
52 ALWAYS_INLINE AtomicString AtomicString::convertASCIICase() const
53 {
54     StringImpl* impl = this->impl();
55     if (UNLIKELY(!impl))
56         return AtomicString();
57
58     // Convert short strings without allocating a new StringImpl, since
59     // there's a good chance these strings are already in the atomic
60     // string table and so no memory allocation will be required.
61     unsigned length;
62     const unsigned localBufferSize = 100;
63     if (impl->is8Bit() && (length = impl->length()) <= localBufferSize) {
64         const LChar* characters = impl->characters8();
65         unsigned failingIndex;
66         for (unsigned i = 0; i < length; ++i) {
67             if (type == CaseConvertType::Lower ? UNLIKELY(isASCIIUpper(characters[i])) : LIKELY(isASCIILower(characters[i]))) {
68                 failingIndex = i;
69                 goto SlowPath;
70             }
71         }
72         return *this;
73 SlowPath:
74         LChar localBuffer[localBufferSize];
75         for (unsigned i = 0; i < failingIndex; ++i)
76             localBuffer[i] = characters[i];
77         for (unsigned i = failingIndex; i < length; ++i)
78             localBuffer[i] = type == CaseConvertType::Lower ? toASCIILower(characters[i]) : toASCIIUpper(characters[i]);
79         return AtomicString(localBuffer, length);
80     }
81
82     Ref<StringImpl> convertedString = type == CaseConvertType::Lower ? impl->convertToASCIILowercase() : impl->convertToASCIIUppercase();
83     if (LIKELY(convertedString.ptr() == impl))
84         return *this;
85
86     AtomicString result;
87     result.m_string = AtomicStringImpl::add(convertedString.ptr());
88     return result;
89 }
90
91 AtomicString AtomicString::convertToASCIILowercase() const
92 {
93     return convertASCIICase<CaseConvertType::Lower>();
94 }
95
96 AtomicString AtomicString::convertToASCIIUppercase() const
97 {
98     return convertASCIICase<CaseConvertType::Upper>();
99 }
100
101 AtomicString AtomicString::number(int number)
102 {
103     return numberToStringSigned<AtomicString>(number);
104 }
105
106 AtomicString AtomicString::number(unsigned number)
107 {
108     return numberToStringUnsigned<AtomicString>(number);
109 }
110
111 AtomicString AtomicString::number(double number)
112 {
113     NumberToStringBuffer buffer;
114     return String(numberToFixedPrecisionString(number, 6, buffer, true));
115 }
116
117 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
118 {
119     auto impl = AtomicStringImpl::addUTF8(charactersStart, charactersEnd);
120     if (!impl)
121         return nullAtom;
122     return impl.get();
123 }
124
125 #ifndef NDEBUG
126 void AtomicString::show() const
127 {
128     m_string.show();
129 }
130 #endif
131
132 } // namespace WTF