2 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
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.
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.
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.
21 #ifndef AtomicString_h
22 #define AtomicString_h
24 #include <wtf/text/AtomicStringImpl.h>
25 #include <wtf/text/WTFString.h>
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
32 #define ATOMICSTRING_CONVERSION
37 struct AtomicStringHash;
41 WTF_EXPORT_PRIVATE static void init();
44 AtomicString(const LChar* s) : m_string(add(s)) { }
45 AtomicString(const char* s) : m_string(add(s)) { }
46 AtomicString(const LChar* s, unsigned length) : m_string(add(s, length)) { }
47 AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { }
48 AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { }
49 AtomicString(const UChar* s) : m_string(add(s)) { }
50 ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
51 AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
52 ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
53 AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { }
55 enum ConstructFromLiteralTag { ConstructFromLiteral };
56 AtomicString(const char* characters, unsigned length, ConstructFromLiteralTag)
57 : m_string(addFromLiteralData(characters, length))
60 template<unsigned charactersCount>
61 ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], ConstructFromLiteralTag)
62 : m_string(addFromLiteralData(characters, charactersCount - 1))
64 COMPILE_ASSERT(charactersCount > 1, AtomicStringFromLiteralNotEmpty);
65 COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow);
68 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
69 // We have to declare the copy constructor and copy assignment operator as well, otherwise
70 // they'll be implicitly deleted by adding the move constructor and move assignment operator.
71 // FIXME: Instead of explicitly casting to String&& here, we should use std::move, but that requires us to
72 // have a standard library that supports move semantics.
73 AtomicString(const AtomicString& other) : m_string(other.m_string) { }
74 AtomicString(AtomicString&& other) : m_string(static_cast<String&&>(other.m_string)) { }
75 AtomicString& operator=(const AtomicString& other) { m_string = other.m_string; return *this; }
76 AtomicString& operator=(AtomicString&& other) { m_string = static_cast<String&&>(other.m_string); return *this; }
79 // Hash table deleted values, which are only constructed and never copied or destroyed.
80 AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
81 bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
83 WTF_EXPORT_STRING_API static AtomicStringImpl* find(const StringImpl*);
85 operator const String&() const { return m_string; }
86 const String& string() const { return m_string; };
88 AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
90 const UChar* characters() const { return m_string.characters(); }
91 unsigned length() const { return m_string.length(); }
93 UChar operator[](unsigned int i) const { return m_string[i]; }
95 bool contains(UChar c) const { return m_string.contains(c); }
96 bool contains(const LChar* s, bool caseSensitive = true) const
97 { return m_string.contains(s, caseSensitive); }
98 bool contains(const String& s, bool caseSensitive = true) const
99 { return m_string.contains(s, caseSensitive); }
101 size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); }
102 size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) const
103 { return m_string.find(s, start, caseSentitive); }
104 size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const
105 { return m_string.find(s, start, caseSentitive); }
107 bool startsWith(const String& s, bool caseSensitive = true) const
108 { return m_string.startsWith(s, caseSensitive); }
109 bool startsWith(UChar character) const
110 { return m_string.startsWith(character); }
111 template<unsigned matchLength>
112 bool startsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
113 { return m_string.startsWith<matchLength>(prefix, caseSensitive); }
115 bool endsWith(const String& s, bool caseSensitive = true) const
116 { return m_string.endsWith(s, caseSensitive); }
117 bool endsWith(UChar character) const
118 { return m_string.endsWith(character); }
119 template<unsigned matchLength>
120 bool endsWith(const char (&prefix)[matchLength], bool caseSensitive = true) const
121 { return m_string.endsWith<matchLength>(prefix, caseSensitive); }
123 WTF_EXPORT_STRING_API AtomicString lower() const;
124 AtomicString upper() const { return AtomicString(impl()->upper()); }
126 int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
127 double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
128 float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
129 bool percentage(int& p) const { return m_string.percentage(p); }
131 bool isNull() const { return m_string.isNull(); }
132 bool isEmpty() const { return m_string.isEmpty(); }
134 static void remove(StringImpl*);
137 AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { }
138 CFStringRef createCFString() const { return m_string.createCFString(); }
141 AtomicString(NSString* s) : m_string(add(String(s).impl())) { }
142 operator NSString*() const { return m_string; }
145 AtomicString(const QString& s) : m_string(add(String(s).impl())) { }
146 operator QString() const { return m_string; }
149 // AtomicString::fromUTF8 will return a null string if
150 // the input data contains invalid UTF-8 sequences.
151 static AtomicString fromUTF8(const char*, size_t);
152 static AtomicString fromUTF8(const char*);
160 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const LChar*);
161 ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s) { return add(reinterpret_cast<const LChar*>(s)); };
162 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const LChar*, unsigned length);
163 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
164 ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const char*>(s), length); };
165 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
166 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(const UChar*);
167 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length);
168 ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r)
170 if (!r || r->isAtomic())
172 return addSlowCase(r);
174 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addFromLiteralData(const char* characters, unsigned length);
175 WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
176 WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, const char*);
179 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
180 bool operator==(const AtomicString&, const LChar*);
181 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
182 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }
183 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
184 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
185 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
186 inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
188 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
189 inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); }
190 inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b); }
191 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
192 inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
193 inline bool operator!=(const LChar* a, const AtomicString& b) { return !(b == a); }
194 inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
195 inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
197 inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
198 inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); }
199 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); }
200 inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
201 inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
202 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
203 inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
205 // Define external global variables for the commonly used atomic strings.
206 // These are only usable from the main thread.
207 #ifndef ATOMICSTRING_HIDE_GLOBALS
208 extern const WTF_EXPORTDATA AtomicString nullAtom;
209 extern const WTF_EXPORTDATA AtomicString emptyAtom;
210 extern const WTF_EXPORTDATA AtomicString textAtom;
211 extern const WTF_EXPORTDATA AtomicString commentAtom;
212 extern const WTF_EXPORTDATA AtomicString starAtom;
213 extern const WTF_EXPORTDATA AtomicString xmlAtom;
214 extern const WTF_EXPORTDATA AtomicString xmlnsAtom;
215 extern const WTF_EXPORTDATA AtomicString xlinkAtom;
217 inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length)
223 return fromUTF8Internal(characters, characters + length);
226 inline AtomicString AtomicString::fromUTF8(const char* characters)
232 return fromUTF8Internal(characters, 0);
236 // AtomicStringHash is the default hash for AtomicString
237 template<typename T> struct DefaultHash;
238 template<> struct DefaultHash<AtomicString> {
239 typedef AtomicStringHash Hash;
244 #ifndef ATOMICSTRING_HIDE_GLOBALS
245 using WTF::AtomicString;
247 using WTF::emptyAtom;
249 using WTF::commentAtom;
252 using WTF::xmlnsAtom;
253 using WTF::xlinkAtom;
256 #include <wtf/text/StringConcatenate.h>
257 #endif // AtomicString_h