[MediaStream] Avoid roundoff error when setting AVCapture min/max frame rate
[WebKit-https.git] / Source / WTF / wtf / text / AtomicString.cpp
1 /*
2  * Copyright (C) 2004-2017 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 <wtf/text/AtomicString.h>
25
26 #include <mutex>
27 #include <wtf/MainThread.h>
28 #include <wtf/text/IntegerToStringConversion.h>
29
30 #include <wtf/dtoa.h>
31
32 namespace WTF {
33
34 template<AtomicString::CaseConvertType type>
35 ALWAYS_INLINE AtomicString AtomicString::convertASCIICase() const
36 {
37     StringImpl* impl = this->impl();
38     if (UNLIKELY(!impl))
39         return nullAtom();
40
41     // Convert short strings without allocating a new StringImpl, since
42     // there's a good chance these strings are already in the atomic
43     // string table and so no memory allocation will be required.
44     unsigned length;
45     const unsigned localBufferSize = 100;
46     if (impl->is8Bit() && (length = impl->length()) <= localBufferSize) {
47         const LChar* characters = impl->characters8();
48         unsigned failingIndex;
49         for (unsigned i = 0; i < length; ++i) {
50             if (type == CaseConvertType::Lower ? UNLIKELY(isASCIIUpper(characters[i])) : LIKELY(isASCIILower(characters[i]))) {
51                 failingIndex = i;
52                 goto SlowPath;
53             }
54         }
55         return *this;
56 SlowPath:
57         LChar localBuffer[localBufferSize];
58         for (unsigned i = 0; i < failingIndex; ++i)
59             localBuffer[i] = characters[i];
60         for (unsigned i = failingIndex; i < length; ++i)
61             localBuffer[i] = type == CaseConvertType::Lower ? toASCIILower(characters[i]) : toASCIIUpper(characters[i]);
62         return AtomicString(localBuffer, length);
63     }
64
65     Ref<StringImpl> convertedString = type == CaseConvertType::Lower ? impl->convertToASCIILowercase() : impl->convertToASCIIUppercase();
66     if (LIKELY(convertedString.ptr() == impl))
67         return *this;
68
69     AtomicString result;
70     result.m_string = AtomicStringImpl::add(convertedString.ptr());
71     return result;
72 }
73
74 AtomicString AtomicString::convertToASCIILowercase() const
75 {
76     return convertASCIICase<CaseConvertType::Lower>();
77 }
78
79 AtomicString AtomicString::convertToASCIIUppercase() const
80 {
81     return convertASCIICase<CaseConvertType::Upper>();
82 }
83
84 AtomicString AtomicString::number(int number)
85 {
86     return numberToStringSigned<AtomicString>(number);
87 }
88
89 AtomicString AtomicString::number(unsigned number)
90 {
91     return numberToStringUnsigned<AtomicString>(number);
92 }
93
94 AtomicString AtomicString::number(unsigned long number)
95 {
96     return numberToStringUnsigned<AtomicString>(number);
97 }
98
99 AtomicString AtomicString::number(unsigned long long number)
100 {
101     return numberToStringUnsigned<AtomicString>(number);
102 }
103
104 AtomicString AtomicString::number(float number)
105 {
106     NumberToStringBuffer buffer;
107     return numberToString(number, buffer);
108 }
109
110 AtomicString AtomicString::number(double number)
111 {
112     NumberToStringBuffer buffer;
113     return numberToString(number, buffer);
114 }
115
116 AtomicString AtomicString::fromUTF8Internal(const char* start, const char* end)
117 {
118     ASSERT(start);
119
120     // Caller needs to handle empty string.
121     ASSERT(!end || end > start);
122     ASSERT(end || start[0]);
123
124     return AtomicStringImpl::addUTF8(start, end ? end : start + std::strlen(start));
125 }
126
127 #ifndef NDEBUG
128
129 void AtomicString::show() const
130 {
131     m_string.show();
132 }
133
134 #endif
135
136 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> nullAtomData;
137 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> emptyAtomData;
138 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> starAtomData;
139 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> xmlAtomData;
140 WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomicString> xmlnsAtomData;
141
142 void AtomicString::init()
143 {
144     static std::once_flag initializeKey;
145     std::call_once(initializeKey, [] {
146         // Initialization is not thread safe, so this function must be called from the main thread first.
147         ASSERT(isUIThread());
148
149         nullAtomData.construct();
150         emptyAtomData.construct("");
151         starAtomData.construct("*", AtomicString::ConstructFromLiteral);
152         xmlAtomData.construct("xml", AtomicString::ConstructFromLiteral);
153         xmlnsAtomData.construct("xmlns", AtomicString::ConstructFromLiteral);
154     });
155 }
156
157 } // namespace WTF