cd8ef8ffcbc4702c5f07f2cbcbab75a10a811407
[WebKit-https.git] / Source / WTF / wtf / text / AtomicString.cpp
1 /*
2  * Copyright (C) 2004-2008, 2013-2014, 2016 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 template<AtomicString::CaseConvertType type>
36 ALWAYS_INLINE AtomicString AtomicString::convertASCIICase() const
37 {
38     StringImpl* impl = this->impl();
39     if (UNLIKELY(!impl))
40         return nullAtom;
41
42     // Convert short strings without allocating a new StringImpl, since
43     // there's a good chance these strings are already in the atomic
44     // string table and so no memory allocation will be required.
45     unsigned length;
46     const unsigned localBufferSize = 100;
47     if (impl->is8Bit() && (length = impl->length()) <= localBufferSize) {
48         const LChar* characters = impl->characters8();
49         unsigned failingIndex;
50         for (unsigned i = 0; i < length; ++i) {
51             if (type == CaseConvertType::Lower ? UNLIKELY(isASCIIUpper(characters[i])) : LIKELY(isASCIILower(characters[i]))) {
52                 failingIndex = i;
53                 goto SlowPath;
54             }
55         }
56         return *this;
57 SlowPath:
58         LChar localBuffer[localBufferSize];
59         for (unsigned i = 0; i < failingIndex; ++i)
60             localBuffer[i] = characters[i];
61         for (unsigned i = failingIndex; i < length; ++i)
62             localBuffer[i] = type == CaseConvertType::Lower ? toASCIILower(characters[i]) : toASCIIUpper(characters[i]);
63         return AtomicString(localBuffer, length);
64     }
65
66     Ref<StringImpl> convertedString = type == CaseConvertType::Lower ? impl->convertToASCIILowercase() : impl->convertToASCIIUppercase();
67     if (LIKELY(convertedString.ptr() == impl))
68         return *this;
69
70     AtomicString result;
71     result.m_string = AtomicStringImpl::add(convertedString.ptr());
72     return result;
73 }
74
75 AtomicString AtomicString::convertToASCIILowercase() const
76 {
77     return convertASCIICase<CaseConvertType::Lower>();
78 }
79
80 AtomicString AtomicString::convertToASCIIUppercase() const
81 {
82     return convertASCIICase<CaseConvertType::Upper>();
83 }
84
85 AtomicString AtomicString::number(int number)
86 {
87     return numberToStringSigned<AtomicString>(number);
88 }
89
90 AtomicString AtomicString::number(unsigned number)
91 {
92     return numberToStringUnsigned<AtomicString>(number);
93 }
94
95 AtomicString AtomicString::number(unsigned long number)
96 {
97     return numberToStringUnsigned<AtomicString>(number);
98 }
99
100 AtomicString AtomicString::number(unsigned long long number)
101 {
102     return numberToStringUnsigned<AtomicString>(number);
103 }
104
105 AtomicString AtomicString::number(double number)
106 {
107     NumberToStringBuffer buffer;
108     return String(numberToFixedPrecisionString(number, 6, buffer, true));
109 }
110
111 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
112 {
113     auto impl = AtomicStringImpl::addUTF8(charactersStart, charactersEnd);
114     if (!impl)
115         return nullAtom;
116     return impl.get();
117 }
118
119 #ifndef NDEBUG
120 void AtomicString::show() const
121 {
122     m_string.show();
123 }
124 #endif
125
126 } // namespace WTF