Replace PassRef with Ref/Ref&& across the board.
[WebKit-https.git] / Source / WTF / wtf / text / AtomicString.h
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2008, 2014 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/WTFString.h>
27
28 // Define 'NO_IMPLICIT_ATOMICSTRING' before including this header,
29 // to disallow (expensive) implicit String-->AtomicString conversions.
30 #ifdef NO_IMPLICIT_ATOMICSTRING
31 #define ATOMICSTRING_CONVERSION explicit
32 #else
33 #define ATOMICSTRING_CONVERSION
34 #endif
35
36 namespace WTF {
37
38 class AtomicStringTable;
39 struct AtomicStringHash;
40
41 class AtomicString {
42 public:
43     WTF_EXPORT_PRIVATE static void init();
44
45     AtomicString() { }
46     AtomicString(const LChar* s) : m_string(add(s)) { }
47     AtomicString(const char* s) : m_string(add(s)) { }
48     AtomicString(const LChar* s, unsigned length) : m_string(add(s, length)) { }
49     AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { }
50     AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { }
51     AtomicString(const UChar* s) : m_string(add(s)) { }
52
53     template<size_t inlineCapacity>
54     explicit AtomicString(const Vector<UChar, inlineCapacity>& characters)
55         : m_string(add(characters.data(), characters.size()))
56     {
57     }
58
59     ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
60     AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
61     ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
62     AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { }
63
64     enum ConstructFromLiteralTag { ConstructFromLiteral };
65     AtomicString(const char* characters, unsigned length, ConstructFromLiteralTag)
66         : m_string(addFromLiteralData(characters, length))
67     {
68     }
69
70     template<unsigned charactersCount>
71     ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], ConstructFromLiteralTag)
72         : m_string(addFromLiteralData(characters, charactersCount - 1))
73     {
74         COMPILE_ASSERT(charactersCount > 1, AtomicStringFromLiteralNotEmpty);
75         COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow);
76     }
77
78     // We have to declare the copy constructor and copy assignment operator as well, otherwise
79     // they'll be implicitly deleted by adding the move constructor and move assignment operator.
80     AtomicString(const AtomicString& other) : m_string(other.m_string) { }
81     AtomicString(AtomicString&& other) : m_string(WTF::move(other.m_string)) { }
82     AtomicString& operator=(const AtomicString& other) { m_string = other.m_string; return *this; }
83     AtomicString& operator=(AtomicString&& other) { m_string = WTF::move(other.m_string); return *this; }
84
85     // Hash table deleted values, which are only constructed and never copied or destroyed.
86     AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
87     bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
88
89     WTF_EXPORT_STRING_API static AtomicStringImpl* find(LChar*, unsigned length);
90     WTF_EXPORT_STRING_API static AtomicStringImpl* find(UChar*, unsigned length);
91     static AtomicStringImpl* find(StringImpl* string)
92     {
93         if (!string || string->isAtomic())
94             return static_cast<AtomicStringImpl*>(string);
95         return findSlowCase(*string);
96     }
97
98     operator const String&() const { return m_string; }
99     const String& string() const { return m_string; };
100
101     AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
102
103     bool is8Bit() const { return m_string.is8Bit(); }
104     const LChar* characters8() const { return m_string.characters8(); }
105     const UChar* characters16() const { return m_string.characters16(); }
106     unsigned length() const { return m_string.length(); }
107     
108     UChar operator[](unsigned int i) const { return m_string[i]; }
109
110     WTF_EXPORT_STRING_API static AtomicString number(int);
111     WTF_EXPORT_STRING_API static AtomicString number(unsigned);
112     WTF_EXPORT_STRING_API static AtomicString number(double);
113     // 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.
114
115     bool contains(UChar c) const { return m_string.contains(c); }
116     bool contains(const LChar* s, bool caseSensitive = true) const
117         { return m_string.contains(s, caseSensitive); }
118     bool contains(const String& s, bool caseSensitive = true) const
119         { return m_string.contains(s, caseSensitive); }
120
121     size_t find(UChar c, unsigned start = 0) const { return m_string.find(c, start); }
122     size_t find(const LChar* s, unsigned start = 0, bool caseSentitive = true) const
123         { return m_string.find(s, start, caseSentitive); }
124     size_t find(const String& s, unsigned start = 0, bool caseSentitive = true) const
125         { return m_string.find(s, start, caseSentitive); }
126     size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
127         { return m_string.find(matchFunction, start); }
128
129     bool startsWith(const String& s, bool caseSensitive = true) const
130         { return m_string.startsWith(s, caseSensitive); }
131     bool startsWith(UChar character) const
132         { return m_string.startsWith(character); }
133     template<unsigned matchLength>
134     bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
135         { return m_string.startsWith<matchLength>(prefix, caseSensitive); }
136
137     bool endsWith(const String& s, bool caseSensitive = true) const
138         { return m_string.endsWith(s, caseSensitive); }
139     bool endsWith(UChar character) const
140         { return m_string.endsWith(character); }
141     template<unsigned matchLength>
142     bool endsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
143         { return m_string.endsWith<matchLength>(prefix, caseSensitive); }
144     
145     WTF_EXPORT_STRING_API AtomicString convertToASCIILowercase() const;
146     WTF_EXPORT_STRING_API AtomicString lower() const;
147     AtomicString upper() const { return AtomicString(impl()->upper()); }
148
149     int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
150     double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
151     float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
152     bool percentage(int& p) const { return m_string.percentage(p); }
153
154     bool isNull() const { return m_string.isNull(); }
155     bool isEmpty() const { return m_string.isEmpty(); }
156
157     static void remove(StringImpl*);
158     
159 #if USE(CF)
160     AtomicString(CFStringRef s) :  m_string(add(s)) { }
161 #endif    
162 #ifdef __OBJC__
163     AtomicString(NSString* s) : m_string(add((CFStringRef)s)) { }
164     operator NSString*() const { return m_string; }
165 #endif
166
167     // AtomicString::fromUTF8 will return a null string if
168     // the input data contains invalid UTF-8 sequences.
169     static AtomicString fromUTF8(const char*, size_t);
170     static AtomicString fromUTF8(const char*);
171
172 #ifndef NDEBUG
173     void show() const;
174 #endif
175
176     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(const LChar*);
177     ALWAYS_INLINE static RefPtr<StringImpl> add(const char* s) { return add(reinterpret_cast<const LChar*>(s)); };
178     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(const LChar*, unsigned length);
179     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(const UChar*, unsigned length);
180     ALWAYS_INLINE static RefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const LChar*>(s), length); };
181     WTF_EXPORT_STRING_API static Ref<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
182     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(const UChar*);
183     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length);
184     ALWAYS_INLINE static RefPtr<StringImpl> add(StringImpl* string)
185     {
186         if (!string || string->isAtomic()) {
187             ASSERT_WITH_MESSAGE(!string || !string->length() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
188             return string;
189         }
190         return addSlowCase(*string);
191     }
192     WTF_EXPORT_STRING_API static Ref<StringImpl> addFromLiteralData(const char* characters, unsigned length);
193 #if USE(CF)
194     WTF_EXPORT_STRING_API static RefPtr<StringImpl> add(CFStringRef);
195 #endif
196
197     template<typename StringTableProvider>
198     ALWAYS_INLINE static RefPtr<StringImpl> addWithStringTableProvider(StringTableProvider& stringTableProvider, StringImpl* string)
199     {
200         if (!string || string->isAtomic()) {
201             ASSERT_WITH_MESSAGE(!string || !string->length() || isInAtomicStringTable(string), "The atomic string comes from an other thread!");
202             return string;
203         }
204         return addSlowCase(*stringTableProvider.atomicStringTable(), *string);
205     }
206
207 #if !ASSERT_DISABLED
208     WTF_EXPORT_STRING_API static bool isInAtomicStringTable(StringImpl*);
209 #endif
210
211 private:
212     // The explicit constructors with AtomicString::ConstructFromLiteral must be used for literals.
213     AtomicString(ASCIILiteral);
214
215     String m_string;
216     
217     WTF_EXPORT_STRING_API static Ref<StringImpl> addSlowCase(StringImpl&);
218     WTF_EXPORT_STRING_API static Ref<StringImpl> addSlowCase(AtomicStringTable&, StringImpl&);
219
220     WTF_EXPORT_STRING_API static AtomicStringImpl* findSlowCase(StringImpl&);
221     WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, const char*);
222 };
223
224 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
225 bool operator==(const AtomicString&, const LChar*);
226 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
227 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }    
228 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
229 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
230 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
231 inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
232
233 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
234 inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); }
235 inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b); }
236 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
237 inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
238 inline bool operator!=(const LChar* a, const AtomicString& b) { return !(b == a); }
239 inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
240 inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
241
242 inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
243 inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); }
244 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); }
245 inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
246 inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
247 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
248 inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
249
250 // Define external global variables for the commonly used atomic strings.
251 // These are only usable from the main thread.
252 #ifndef ATOMICSTRING_HIDE_GLOBALS
253 extern const WTF_EXPORTDATA AtomicString nullAtom;
254 extern const WTF_EXPORTDATA AtomicString emptyAtom;
255 extern const WTF_EXPORTDATA AtomicString textAtom;
256 extern const WTF_EXPORTDATA AtomicString commentAtom;
257 extern const WTF_EXPORTDATA AtomicString starAtom;
258 extern const WTF_EXPORTDATA AtomicString xmlAtom;
259 extern const WTF_EXPORTDATA AtomicString xmlnsAtom;
260 extern const WTF_EXPORTDATA AtomicString xlinkAtom;
261
262 inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length)
263 {
264     if (!characters)
265         return nullAtom;
266     if (!length)
267         return emptyAtom;
268     return fromUTF8Internal(characters, characters + length);
269 }
270
271 inline AtomicString AtomicString::fromUTF8(const char* characters)
272 {
273     if (!characters)
274         return nullAtom;
275     if (!*characters)
276         return emptyAtom;
277     return fromUTF8Internal(characters, 0);
278 }
279 #endif
280
281 // AtomicStringHash is the default hash for AtomicString
282 template<typename T> struct DefaultHash;
283 template<> struct DefaultHash<AtomicString> {
284     typedef AtomicStringHash Hash;
285 };
286
287 } // namespace WTF
288
289 #ifndef ATOMICSTRING_HIDE_GLOBALS
290 using WTF::AtomicString;
291 using WTF::nullAtom;
292 using WTF::emptyAtom;
293 using WTF::textAtom;
294 using WTF::commentAtom;
295 using WTF::starAtom;
296 using WTF::xmlAtom;
297 using WTF::xmlnsAtom;
298 using WTF::xlinkAtom;
299 #endif
300
301 #include <wtf/text/StringConcatenate.h>
302 #endif // AtomicString_h