OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2004, 2005, 2006, 2008 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 <wtf/text/AtomicStringImpl.h> | |
25 #include <wtf/text/WTFString.h> | |
26 | |
27 // Define 'NO_IMPLICIT_ATOMICSTRING' before including this header, | |
28 // to disallow (expensive) implicit String-->AtomicString conversions. | |
29 #ifdef NO_IMPLICIT_ATOMICSTRING | |
30 #define ATOMICSTRING_CONVERSION explicit | |
31 #else | |
32 #define ATOMICSTRING_CONVERSION | |
33 #endif | |
34 | |
35 namespace WTF { | |
36 | |
37 struct AtomicStringHash; | |
38 class MemoryObjectInfo; | |
39 | |
40 class AtomicString { | |
41 public: | |
42 WTF_EXPORT_PRIVATE static void init(); | |
43 | |
44 AtomicString() { } | |
45 AtomicString(const LChar* s) : m_string(add(s)) { } | |
46 AtomicString(const char* s) : m_string(add(s)) { } | |
47 AtomicString(const LChar* s, unsigned length) : m_string(add(s, length)) { } | |
48 AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { } | |
49 AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_str
ing(add(s, length, existingHash)) { } | |
50 AtomicString(const UChar* s) : m_string(add(s)) { } | |
51 | |
52 template<size_t inlineCapacity> | |
53 explicit AtomicString(const Vector<UChar, inlineCapacity>& characters) | |
54 : m_string(add(characters.data(), characters.size())) | |
55 { | |
56 } | |
57 | |
58 ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) {
} | |
59 AtomicString(AtomicStringImpl* imp) : m_string(imp) { } | |
60 ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl(
))) { } | |
61 AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_st
ring(add(baseString, start, length)) { } | |
62 | |
63 enum ConstructFromLiteralTag { ConstructFromLiteral }; | |
64 AtomicString(const char* characters, unsigned length, ConstructFromLiteralTa
g) | |
65 : m_string(addFromLiteralData(characters, length)) | |
66 { | |
67 } | |
68 | |
69 template<unsigned charactersCount> | |
70 ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], Constr
uctFromLiteralTag) | |
71 : m_string(addFromLiteralData(characters, charactersCount - 1)) | |
72 { | |
73 COMPILE_ASSERT(charactersCount > 1, AtomicStringFromLiteralNotEmpty); | |
74 COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImp
l)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow); | |
75 } | |
76 | |
77 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | |
78 // We have to declare the copy constructor and copy assignment operator as w
ell, otherwise | |
79 // they'll be implicitly deleted by adding the move constructor and move ass
ignment operator. | |
80 // FIXME: Instead of explicitly casting to String&& here, we should use std:
:move, but that requires us to | |
81 // have a standard library that supports move semantics. | |
82 AtomicString(const AtomicString& other) : m_string(other.m_string) { } | |
83 AtomicString(AtomicString&& other) : m_string(static_cast<String&&>(other.m_
string)) { } | |
84 AtomicString& operator=(const AtomicString& other) { m_string = other.m_stri
ng; return *this; } | |
85 AtomicString& operator=(AtomicString&& other) { m_string = static_cast<Strin
g&&>(other.m_string); return *this; } | |
86 #endif | |
87 | |
88 // Hash table deleted values, which are only constructed and never copied or
destroyed. | |
89 AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDelete
dValue) { } | |
90 bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedVal
ue(); } | |
91 | |
92 WTF_EXPORT_STRING_API static AtomicStringImpl* find(const StringImpl*); | |
93 | |
94 operator const String&() const { return m_string; } | |
95 const String& string() const { return m_string; }; | |
96 | |
97 AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_st
ring.impl()); } | |
98 | |
99 bool is8Bit() const { return m_string.is8Bit(); } | |
100 const UChar* characters() const { return m_string.characters(); } | |
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 bool contains(UChar c) const { return m_string.contains(c); } | |
108 bool contains(const LChar* s, bool caseSensitive = true) const | |
109 { return m_string.contains(s, caseSensitive); } | |
110 bool contains(const String& s, bool caseSensitive = true) const | |
111 { return m_string.contains(s, caseSensitive); } | |
112 | |
113 size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start
); } | |
114 size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) con
st | |
115 { return m_string.find(s, start, caseSentitive); } | |
116 size_t find(const String& s, size_t start = 0, bool caseSentitive = true) co
nst | |
117 { return m_string.find(s, start, caseSentitive); } | |
118 | |
119 bool startsWith(const String& s, bool caseSensitive = true) const | |
120 { return m_string.startsWith(s, caseSensitive); } | |
121 bool startsWith(UChar character) const | |
122 { return m_string.startsWith(character); } | |
123 template<unsigned matchLength> | |
124 bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true
) const | |
125 { return m_string.startsWith<matchLength>(prefix, caseSensitive); } | |
126 | |
127 bool endsWith(const String& s, bool caseSensitive = true) const | |
128 { return m_string.endsWith(s, caseSensitive); } | |
129 bool endsWith(UChar character) const | |
130 { return m_string.endsWith(character); } | |
131 template<unsigned matchLength> | |
132 bool endsWith(const char (&prefix)[matchLength], bool caseSensitive = true)
const | |
133 { return m_string.endsWith<matchLength>(prefix, caseSensitive); } | |
134 | |
135 WTF_EXPORT_STRING_API AtomicString lower() const; | |
136 AtomicString upper() const { return AtomicString(impl()->upper()); } | |
137 | |
138 int toInt(bool* ok = 0) const { return m_string.toInt(ok); } | |
139 double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); } | |
140 float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); } | |
141 bool percentage(int& p) const { return m_string.percentage(p); } | |
142 | |
143 bool isNull() const { return m_string.isNull(); } | |
144 bool isEmpty() const { return m_string.isEmpty(); } | |
145 | |
146 static void remove(StringImpl*); | |
147 | |
148 #if USE(CF) | |
149 AtomicString(CFStringRef s) : m_string(add(s)) { } | |
150 #endif | |
151 #ifdef __OBJC__ | |
152 AtomicString(NSString* s) : m_string(add((CFStringRef)s)) { } | |
153 operator NSString*() const { return m_string; } | |
154 #endif | |
155 // AtomicString::fromUTF8 will return a null string if | |
156 // the input data contains invalid UTF-8 sequences. | |
157 static AtomicString fromUTF8(const char*, size_t); | |
158 static AtomicString fromUTF8(const char*); | |
159 | |
160 #ifndef NDEBUG | |
161 void show() const; | |
162 #endif | |
163 | |
164 private: | |
165 // The explicit constructors with AtomicString::ConstructFromLiteral must be
used for literals. | |
166 AtomicString(ASCIILiteral); | |
167 | |
168 String m_string; | |
169 | |
170 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const LChar*); | |
171 ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s) { return add(
reinterpret_cast<const LChar*>(s)); }; | |
172 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const LChar*, unsign
ed length); | |
173 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*, unsign
ed length); | |
174 ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned leng
th) { return add(reinterpret_cast<const LChar*>(s), length); }; | |
175 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*, unsign
ed length, unsigned existingHash); | |
176 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*); | |
177 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(StringImpl*, unsigne
d offset, unsigned length); | |
178 ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r) | |
179 { | |
180 if (!r || r->isAtomic()) | |
181 return r; | |
182 return addSlowCase(r); | |
183 } | |
184 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addFromLiteralData(const
char* characters, unsigned length); | |
185 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addSlowCase(StringImpl*)
; | |
186 #if USE(CF) | |
187 static PassRefPtr<StringImpl> add(CFStringRef); | |
188 #endif | |
189 | |
190 WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, cons
t char*); | |
191 }; | |
192 | |
193 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.
impl() == b.impl(); } | |
194 bool operator==(const AtomicString&, const LChar*); | |
195 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal
(a.impl(), reinterpret_cast<const LChar*>(b)); } | |
196 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a
.impl() && equal(a.impl(), b.data(), b.size()); } | |
197 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.
impl(), b.impl()); } | |
198 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; } | |
199 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.
impl(), b.impl()); } | |
200 inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b
== a; } | |
201 | |
202 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.
impl() != b.impl(); } | |
203 inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b)
; } | |
204 inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b);
} | |
205 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a
.impl(), b.impl()); } | |
206 inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !
(a == b); } | |
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 !
(a == b); } | |
210 | |
211 inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { re
turn equalIgnoringCase(a.impl(), b.impl()); } | |
212 inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return eq
ualIgnoringCase(a.impl(), b); } | |
213 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equ
alIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); } | |
214 inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return e
qualIgnoringCase(a.impl(), b.impl()); } | |
215 inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return eq
ualIgnoringCase(a, b.impl()); } | |
216 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equ
alIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); } | |
217 inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return e
qualIgnoringCase(a.impl(), b.impl()); } | |
218 | |
219 // Define external global variables for the commonly used atomic strings. | |
220 // These are only usable from the main thread. | |
221 #ifndef ATOMICSTRING_HIDE_GLOBALS | |
222 extern const WTF_EXPORTDATA AtomicString nullAtom; | |
223 extern const WTF_EXPORTDATA AtomicString emptyAtom; | |
224 extern const WTF_EXPORTDATA AtomicString textAtom; | |
225 extern const WTF_EXPORTDATA AtomicString commentAtom; | |
226 extern const WTF_EXPORTDATA AtomicString starAtom; | |
227 extern const WTF_EXPORTDATA AtomicString xmlAtom; | |
228 extern const WTF_EXPORTDATA AtomicString xmlnsAtom; | |
229 extern const WTF_EXPORTDATA AtomicString xlinkAtom; | |
230 | |
231 inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length
) | |
232 { | |
233 if (!characters) | |
234 return nullAtom; | |
235 if (!length) | |
236 return emptyAtom; | |
237 return fromUTF8Internal(characters, characters + length); | |
238 } | |
239 | |
240 inline AtomicString AtomicString::fromUTF8(const char* characters) | |
241 { | |
242 if (!characters) | |
243 return nullAtom; | |
244 if (!*characters) | |
245 return emptyAtom; | |
246 return fromUTF8Internal(characters, 0); | |
247 } | |
248 #endif | |
249 | |
250 // AtomicStringHash is the default hash for AtomicString | |
251 template<typename T> struct DefaultHash; | |
252 template<> struct DefaultHash<AtomicString> { | |
253 typedef AtomicStringHash Hash; | |
254 }; | |
255 | |
256 } // namespace WTF | |
257 | |
258 #ifndef ATOMICSTRING_HIDE_GLOBALS | |
259 using WTF::AtomicString; | |
260 using WTF::nullAtom; | |
261 using WTF::emptyAtom; | |
262 using WTF::textAtom; | |
263 using WTF::commentAtom; | |
264 using WTF::starAtom; | |
265 using WTF::xmlAtom; | |
266 using WTF::xmlnsAtom; | |
267 using WTF::xlinkAtom; | |
268 #endif | |
269 | |
270 #include <wtf/text/StringConcatenate.h> | |
271 #endif // AtomicString_h | |
OLD | NEW |