91bb20a8babbce365e9ff0d0b54e6764e8bfa97e
[WebKit-https.git] / Source / WTF / wtf / text / AtomicString.h
1 /*
2  * Copyright (C) 2004-2006, 2008, 2014-2016 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
21 #ifndef AtomicString_h
22 #define AtomicString_h
23
24 #include <utility>
25 #include <wtf/text/AtomicStringImpl.h>
26 #include <wtf/text/IntegerToStringConversion.h>
27 #include <wtf/text/WTFString.h>
28
29 // Define 'NO_IMPLICIT_ATOMICSTRING' before including this header,
30 // to disallow (expensive) implicit String-->AtomicString conversions.
31 #ifdef NO_IMPLICIT_ATOMICSTRING
32 #define ATOMICSTRING_CONVERSION explicit
33 #else
34 #define ATOMICSTRING_CONVERSION
35 #endif
36
37 namespace WTF {
38
39 struct AtomicStringHash;
40
41 class AtomicString {
42 public:
43     WTF_EXPORT_PRIVATE static void init();
44
45     AtomicString();
46     AtomicString(const LChar*);
47     AtomicString(const char*);
48     AtomicString(const LChar*, unsigned length);
49     AtomicString(const UChar*, unsigned length);
50     AtomicString(const UChar*, unsigned length, unsigned existingHash);
51     AtomicString(const UChar*);
52
53     template<size_t inlineCapacity>
54     explicit AtomicString(const Vector<UChar, inlineCapacity>& characters)
55         : m_string(AtomicStringImpl::add(characters.data(), characters.size()))
56     {
57     }
58
59     AtomicString(AtomicStringImpl*);
60     AtomicString(RefPtr<AtomicStringImpl>&&);
61     ATOMICSTRING_CONVERSION AtomicString(StringImpl*);
62     ATOMICSTRING_CONVERSION AtomicString(const String&);
63     AtomicString(StringImpl* baseString, unsigned start, unsigned length);
64
65     // FIXME: AtomicString doesn’t always have AtomicStringImpl, so one of those two names needs to change..
66     AtomicString(UniquedStringImpl* uid);
67
68     enum ConstructFromLiteralTag { ConstructFromLiteral };
69     AtomicString(const char* characters, unsigned length, ConstructFromLiteralTag)
70         : m_string(AtomicStringImpl::addLiteral(characters, length))
71     {
72     }
73
74     template<unsigned charactersCount>
75     ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], ConstructFromLiteralTag)
76         : m_string(AtomicStringImpl::addLiteral(characters, charactersCount - 1))
77     {
78         COMPILE_ASSERT(charactersCount > 1, AtomicStringFromLiteralNotEmpty);
79         COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow);
80     }
81
82     // We have to declare the copy constructor and copy assignment operator as well, otherwise
83     // they'll be implicitly deleted by adding the move constructor and move assignment operator.
84     AtomicString(const AtomicString& other) : m_string(other.m_string) { }
85     AtomicString(AtomicString&& other) : m_string(WTFMove(other.m_string)) { }
86     AtomicString& operator=(const AtomicString& other) { m_string = other.m_string; return *this; }
87     AtomicString& operator=(AtomicString&& other) { m_string = WTFMove(other.m_string); return *this; }
88
89     // Hash table deleted values, which are only constructed and never copied or destroyed.
90     AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
91     bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
92
93     unsigned existingHash() const { return isNull() ? 0 : impl()->existingHash(); }
94
95     operator const String&() const { return m_string; }
96     const String& string() const { return m_string; };
97
98     AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
99
100     bool is8Bit() const { return m_string.is8Bit(); }
101     const LChar* characters8() const { return m_string.characters8(); }
102     const UChar* characters16() const { return m_string.characters16(); }
103     unsigned length() const { return m_string.length(); }
104
105     UChar operator[](unsigned int i) const { return m_string[i]; }
106
107     WTF_EXPORT_STRING_API static AtomicString number(int);
108     WTF_EXPORT_STRING_API static AtomicString number(unsigned);
109     WTF_EXPORT_STRING_API static AtomicString number(unsigned long);
110     WTF_EXPORT_STRING_API static AtomicString number(unsigned long long);
111     WTF_EXPORT_STRING_API static AtomicString number(double);
112     // If we need more overloads of the number function, we can add all the others that String has, but these seem to do for now.
113
114     bool contains(UChar c) const { return m_string.contains(c); }
115     bool contains(const LChar* s, bool caseSensitive = true) const
116         { return m_string.contains(s, caseSensitive); }
117     bool contains(const String& s) const
118         { return m_string.contains(s); }
119     bool contains(const String& s, bool caseSensitive) const
120         { return m_string.contains(s, caseSensitive); }
121     bool containsIgnoringASCIICase(const String& s) const
122         { return m_string.containsIgnoringASCIICase(s); }
123
124     size_t find(UChar c, unsigned start = 0) const { return m_string.find(c, start); }
125     size_t find(const LChar* s, unsigned start = 0, bool caseSentitive = true) const
126         { return m_string.find(s, start, caseSentitive); }
127     size_t find(const String& s, unsigned start = 0, bool caseSentitive = true) const
128         { return m_string.find(s, start, caseSentitive); }
129     size_t findIgnoringASCIICase(const String& s) const
130         { return m_string.findIgnoringASCIICase(s); }
131     size_t findIgnoringASCIICase(const String& s, unsigned startOffset) const
132         { return m_string.findIgnoringASCIICase(s, startOffset); }
133     size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
134         { return m_string.find(matchFunction, start); }
135
136     bool startsWith(const String& s) const
137         { return m_string.startsWith(s); }
138     bool startsWithIgnoringASCIICase(const String& s) const
139         { return m_string.startsWithIgnoringASCIICase(s); }
140     bool startsWith(const String& s, bool caseSensitive) const
141         { return m_string.startsWith(s, caseSensitive); }
142     bool startsWith(UChar character) const
143         { return m_string.startsWith(character); }
144     template<unsigned matchLength>
145     bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
146         { return m_string.startsWith<matchLength>(prefix, caseSensitive); }
147
148     bool endsWith(const String& s) const
149         { return m_string.endsWith(s); }
150     bool endsWithIgnoringASCIICase(const String& s) const
151         { return m_string.endsWithIgnoringASCIICase(s); }
152     bool endsWith(const String& s, bool caseSensitive) const
153         { return m_string.endsWith(s, caseSensitive); }
154     bool endsWith(UChar character) const
155         { return m_string.endsWith(character); }
156     template<unsigned matchLength>
157     bool endsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
158         { return m_string.endsWith<matchLength>(prefix, caseSensitive); }
159
160     WTF_EXPORT_STRING_API AtomicString convertToASCIILowercase() const;
161     WTF_EXPORT_STRING_API AtomicString convertToASCIIUppercase() const;
162
163     int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
164     double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
165     float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
166     bool percentage(int& p) const { return m_string.percentage(p); }
167
168     bool isNull() const { return m_string.isNull(); }
169     bool isEmpty() const { return m_string.isEmpty(); }
170
171 #if USE(CF)
172     AtomicString(CFStringRef);
173 #endif
174 #ifdef __OBJC__
175     AtomicString(NSString*);
176     operator NSString*() const { return m_string; }
177 #endif
178
179     // AtomicString::fromUTF8 will return a null string if
180     // the input data contains invalid UTF-8 sequences.
181     static AtomicString fromUTF8(const char*, size_t);
182     static AtomicString fromUTF8(const char*);
183
184 #ifndef NDEBUG
185     void show() const;
186 #endif
187
188 private:
189     // The explicit constructors with AtomicString::ConstructFromLiteral must be used for literals.
190     AtomicString(ASCIILiteral);
191
192     enum class CaseConvertType { Upper, Lower };
193     template<CaseConvertType> AtomicString convertASCIICase() const;
194
195     WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, const char*);
196
197     String m_string;
198 };
199
200 static_assert(sizeof(AtomicString) == sizeof(String), "AtomicString and String must be same size!");
201
202 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
203 bool operator==(const AtomicString&, const LChar*);
204 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
205 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }    
206 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
207 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
208 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
209 inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
210
211 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
212 inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); }
213 inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b); }
214 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
215 inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
216 inline bool operator!=(const LChar* a, const AtomicString& b) { return !(b == a); }
217 inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
218 inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
219
220 bool equalIgnoringASCIICase(const AtomicString&, const AtomicString&);
221 bool equalIgnoringASCIICase(const AtomicString&, const String&);
222 bool equalIgnoringASCIICase(const String&, const AtomicString&);
223 bool equalIgnoringASCIICase(const AtomicString&, const char*);
224
225 template<unsigned length> bool equalLettersIgnoringASCIICase(const AtomicString&, const char (&lowercaseLetters)[length]);
226
227 inline AtomicString::AtomicString()
228 {
229 }
230
231 inline AtomicString::AtomicString(const LChar* s)
232     : m_string(AtomicStringImpl::add(s))
233 {
234 }
235
236 inline AtomicString::AtomicString(const char* s)
237     : m_string(AtomicStringImpl::add(s))
238 {
239 }
240
241 inline AtomicString::AtomicString(const LChar* s, unsigned length)
242     : m_string(AtomicStringImpl::add(s, length))
243 {
244 }
245
246 inline AtomicString::AtomicString(const UChar* s, unsigned length)
247     : m_string(AtomicStringImpl::add(s, length))
248 {
249 }
250
251 inline AtomicString::AtomicString(const UChar* s, unsigned length, unsigned existingHash)
252     : m_string(AtomicStringImpl::add(s, length, existingHash))
253 {
254 }
255
256 inline AtomicString::AtomicString(const UChar* s)
257     : m_string(AtomicStringImpl::add(s))
258 {
259 }
260
261 inline AtomicString::AtomicString(AtomicStringImpl* imp)
262     : m_string(imp)
263 {
264 }
265
266 inline AtomicString::AtomicString(RefPtr<AtomicStringImpl>&& imp)
267     : m_string(WTFMove(imp))
268 {
269 }
270
271 inline AtomicString::AtomicString(StringImpl* imp)
272     : m_string(AtomicStringImpl::add(imp))
273 {
274 }
275
276 inline AtomicString::AtomicString(const String& s)
277     : m_string(AtomicStringImpl::add(s.impl()))
278 {
279 }
280
281 inline AtomicString::AtomicString(StringImpl* baseString, unsigned start, unsigned length)
282     : m_string(AtomicStringImpl::add(baseString, start, length))
283 {
284 }
285
286 inline AtomicString::AtomicString(UniquedStringImpl* uid)
287     : m_string(uid)
288 {
289 }
290
291 #if USE(CF)
292 inline AtomicString::AtomicString(CFStringRef s)
293     :  m_string(AtomicStringImpl::add(s))
294 {
295 }
296 #endif
297
298 #ifdef __OBJC__
299 inline AtomicString::AtomicString(NSString* s)
300     : m_string(AtomicStringImpl::add((__bridge CFStringRef)s))
301 {
302 }
303 #endif
304
305 // Define external global variables for the commonly used atomic strings.
306 // These are only usable from the main thread.
307 #ifndef ATOMICSTRING_HIDE_GLOBALS
308 extern const WTF_EXPORTDATA AtomicString nullAtom;
309 extern const WTF_EXPORTDATA AtomicString emptyAtom;
310 extern const WTF_EXPORTDATA AtomicString starAtom;
311 extern const WTF_EXPORTDATA AtomicString xmlAtom;
312 extern const WTF_EXPORTDATA AtomicString xmlnsAtom;
313
314 inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length)
315 {
316     if (!characters)
317         return nullAtom;
318     if (!length)
319         return emptyAtom;
320     return fromUTF8Internal(characters, characters + length);
321 }
322
323 inline AtomicString AtomicString::fromUTF8(const char* characters)
324 {
325     if (!characters)
326         return nullAtom;
327     if (!*characters)
328         return emptyAtom;
329     return fromUTF8Internal(characters, nullptr);
330 }
331 #endif
332
333 // AtomicStringHash is the default hash for AtomicString
334 template<typename T> struct DefaultHash;
335 template<> struct DefaultHash<AtomicString> {
336     typedef AtomicStringHash Hash;
337 };
338
339 template<unsigned length> inline bool equalLettersIgnoringASCIICase(const AtomicString& string, const char (&lowercaseLetters)[length])
340 {
341     return equalLettersIgnoringASCIICase(string.string(), lowercaseLetters);
342 }
343
344 inline bool equalIgnoringASCIICase(const AtomicString& a, const AtomicString& b)
345 {
346     return equalIgnoringASCIICase(a.string(), b.string());
347 }
348
349 inline bool equalIgnoringASCIICase(const AtomicString& a, const String& b)
350 {
351     return equalIgnoringASCIICase(a.string(), b);
352 }
353
354 inline bool equalIgnoringASCIICase(const String& a, const AtomicString& b)
355 {
356     return equalIgnoringASCIICase(a, b.string());
357 }
358
359 inline bool equalIgnoringASCIICase(const AtomicString& a, const char* b)
360 {
361     return equalIgnoringASCIICase(a.string(), b);
362 }
363
364 template<> struct IntegerToStringConversionTrait<AtomicString> {
365     using ReturnType = AtomicString;
366     using AdditionalArgumentType = void;
367     static AtomicString flush(LChar* characters, unsigned length, void*) { return { characters, length }; }
368 };
369
370 } // namespace WTF
371
372 #ifndef ATOMICSTRING_HIDE_GLOBALS
373 using WTF::AtomicString;
374 using WTF::nullAtom;
375 using WTF::emptyAtom;
376 using WTF::starAtom;
377 using WTF::xmlAtom;
378 using WTF::xmlnsAtom;
379 #endif
380
381 #include <wtf/text/StringConcatenate.h>
382
383 #endif // AtomicString_h