| OLD | NEW |
| 1 /* | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 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 | 4 |
| 21 #ifndef AtomicString_h | 5 #include "platform/wtf/text/AtomicString.h" |
| 22 #define AtomicString_h | |
| 23 | 6 |
| 24 #include "wtf/Allocator.h" | 7 // The contents of this header was moved to platform/wtf as part of |
| 25 #include "wtf/HashTableDeletedValueType.h" | 8 // WTF migration project. See the following post for details: |
| 26 #include "wtf/WTFExport.h" | 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY
CAAJ |
| 27 #include "wtf/text/CString.h" | |
| 28 #include "wtf/text/StringView.h" | |
| 29 #include "wtf/text/WTFString.h" | |
| 30 #include <cstring> | |
| 31 #include <iosfwd> | |
| 32 | |
| 33 namespace WTF { | |
| 34 | |
| 35 struct AtomicStringHash; | |
| 36 | |
| 37 // An AtomicString instance represents a string, and multiple AtomicString | |
| 38 // instances can share their string storage if the strings are | |
| 39 // identical. Comparing two AtomicString instances is much faster than comparing | |
| 40 // two String instances because we just check string storage identity. | |
| 41 // | |
| 42 // AtomicString instances are not thread-safe. An AtomicString instance created | |
| 43 // in a thread must be used only in the creator thread. If multiple threads | |
| 44 // access a single AtomicString instance, we have race condition of a reference | |
| 45 // count in StringImpl, and would hit a runtime CHECK in | |
| 46 // AtomicStringTable::remove(). | |
| 47 // | |
| 48 // Exception: nullAtom and emptyAtom, are shared in multiple threads, and are | |
| 49 // never stored in AtomicStringTable. | |
| 50 class WTF_EXPORT AtomicString { | |
| 51 USING_FAST_MALLOC(AtomicString); | |
| 52 | |
| 53 public: | |
| 54 // The function is defined in StringStatics.cpp. | |
| 55 static void init(); | |
| 56 | |
| 57 AtomicString() {} | |
| 58 AtomicString(const LChar* chars) | |
| 59 : AtomicString(chars, | |
| 60 chars ? strlen(reinterpret_cast<const char*>(chars)) : 0) { | |
| 61 } | |
| 62 AtomicString(const char* chars) | |
| 63 : AtomicString(reinterpret_cast<const LChar*>(chars)) {} | |
| 64 AtomicString(const LChar* chars, unsigned length); | |
| 65 AtomicString(const UChar* chars, unsigned length); | |
| 66 AtomicString(const UChar* chars); | |
| 67 AtomicString(const char16_t* chars) | |
| 68 : AtomicString(reinterpret_cast<const UChar*>(chars)) {} | |
| 69 | |
| 70 template <size_t inlineCapacity> | |
| 71 explicit AtomicString(const Vector<UChar, inlineCapacity>& vector) | |
| 72 : AtomicString(vector.data(), vector.size()) {} | |
| 73 | |
| 74 // Constructing an AtomicString from a String / StringImpl can be expensive if | |
| 75 // the StringImpl is not already atomic. | |
| 76 explicit AtomicString(StringImpl* impl) : m_string(add(impl)) {} | |
| 77 explicit AtomicString(const String& s) : m_string(add(s.impl())) {} | |
| 78 | |
| 79 // Hash table deleted values, which are only constructed and never copied or | |
| 80 // destroyed. | |
| 81 AtomicString(WTF::HashTableDeletedValueType) | |
| 82 : m_string(WTF::HashTableDeletedValue) {} | |
| 83 bool isHashTableDeletedValue() const { | |
| 84 return m_string.isHashTableDeletedValue(); | |
| 85 } | |
| 86 | |
| 87 explicit operator bool() const { return !isNull(); } | |
| 88 operator const String&() const { return m_string; } | |
| 89 const String& getString() const { return m_string; } | |
| 90 | |
| 91 StringImpl* impl() const { return m_string.impl(); } | |
| 92 | |
| 93 bool is8Bit() const { return m_string.is8Bit(); } | |
| 94 const LChar* characters8() const { return m_string.characters8(); } | |
| 95 const UChar* characters16() const { return m_string.characters16(); } | |
| 96 unsigned length() const { return m_string.length(); } | |
| 97 | |
| 98 UChar operator[](unsigned i) const { return m_string[i]; } | |
| 99 | |
| 100 // Find characters. | |
| 101 size_t find(UChar c, unsigned start = 0) const { | |
| 102 return m_string.find(c, start); | |
| 103 } | |
| 104 size_t find(LChar c, unsigned start = 0) const { | |
| 105 return m_string.find(c, start); | |
| 106 } | |
| 107 size_t find(char c, unsigned start = 0) const { | |
| 108 return find(static_cast<LChar>(c), start); | |
| 109 } | |
| 110 size_t find(CharacterMatchFunctionPtr matchFunction, | |
| 111 unsigned start = 0) const { | |
| 112 return m_string.find(matchFunction, start); | |
| 113 } | |
| 114 | |
| 115 // Find substrings. | |
| 116 size_t find(const StringView& value, | |
| 117 unsigned start = 0, | |
| 118 TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { | |
| 119 return m_string.find(value, start, caseSensitivity); | |
| 120 } | |
| 121 | |
| 122 // Unicode aware case insensitive string matching. Non-ASCII characters might | |
| 123 // match to ASCII characters. This function is rarely used to implement web | |
| 124 // platform features. | |
| 125 size_t findIgnoringCase(const StringView& value, unsigned start = 0) const { | |
| 126 return m_string.findIgnoringCase(value, start); | |
| 127 } | |
| 128 | |
| 129 // ASCII case insensitive string matching. | |
| 130 size_t findIgnoringASCIICase(const StringView& value, | |
| 131 unsigned start = 0) const { | |
| 132 return m_string.findIgnoringASCIICase(value, start); | |
| 133 } | |
| 134 | |
| 135 bool contains(char c) const { return find(c) != kNotFound; } | |
| 136 bool contains(const StringView& value, | |
| 137 TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { | |
| 138 return find(value, 0, caseSensitivity) != kNotFound; | |
| 139 } | |
| 140 | |
| 141 // Find the last instance of a single character or string. | |
| 142 size_t reverseFind(UChar c, unsigned start = UINT_MAX) const { | |
| 143 return m_string.reverseFind(c, start); | |
| 144 } | |
| 145 size_t reverseFind(const StringView& value, unsigned start = UINT_MAX) const { | |
| 146 return m_string.reverseFind(value, start); | |
| 147 } | |
| 148 | |
| 149 bool startsWith( | |
| 150 const StringView& prefix, | |
| 151 TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { | |
| 152 return m_string.startsWith(prefix, caseSensitivity); | |
| 153 } | |
| 154 bool startsWith(UChar character) const { | |
| 155 return m_string.startsWith(character); | |
| 156 } | |
| 157 | |
| 158 bool endsWith(const StringView& suffix, | |
| 159 TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { | |
| 160 return m_string.endsWith(suffix, caseSensitivity); | |
| 161 } | |
| 162 bool endsWith(UChar character) const { return m_string.endsWith(character); } | |
| 163 | |
| 164 // Returns a lowercase version of the string. This function might | |
| 165 // convert non-ASCII characters to ASCII characters. For example, | |
| 166 // lower() for U+212A is 'k'. | |
| 167 // This function is rarely used to implement web platform features. | |
| 168 AtomicString lower() const; | |
| 169 | |
| 170 // Returns a lowercase/uppercase version of the string. | |
| 171 // These functions convert ASCII characters only. | |
| 172 AtomicString lowerASCII() const; | |
| 173 AtomicString upperASCII() const; | |
| 174 | |
| 175 int toInt(bool* ok = 0) const { return m_string.toInt(ok); } | |
| 176 double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); } | |
| 177 float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); } | |
| 178 | |
| 179 static AtomicString number(int); | |
| 180 static AtomicString number(unsigned); | |
| 181 static AtomicString number(long); | |
| 182 static AtomicString number(unsigned long); | |
| 183 static AtomicString number(long long); | |
| 184 static AtomicString number(unsigned long long); | |
| 185 | |
| 186 static AtomicString number(double, unsigned precision = 6); | |
| 187 | |
| 188 bool isNull() const { return m_string.isNull(); } | |
| 189 bool isEmpty() const { return m_string.isEmpty(); } | |
| 190 | |
| 191 #ifdef __OBJC__ | |
| 192 AtomicString(NSString* s) : m_string(add((CFStringRef)s)) {} | |
| 193 operator NSString*() const { return m_string; } | |
| 194 #endif | |
| 195 // AtomicString::fromUTF8 will return a null string if | |
| 196 // the input data contains invalid UTF-8 sequences. | |
| 197 // NOTE: Passing a zero size means use the whole string. | |
| 198 static AtomicString fromUTF8(const char*, size_t length); | |
| 199 static AtomicString fromUTF8(const char*); | |
| 200 | |
| 201 CString ascii() const { return m_string.ascii(); } | |
| 202 CString latin1() const { return m_string.latin1(); } | |
| 203 CString utf8(UTF8ConversionMode mode = LenientUTF8Conversion) const { | |
| 204 return m_string.utf8(mode); | |
| 205 } | |
| 206 | |
| 207 size_t charactersSizeInBytes() const { | |
| 208 return m_string.charactersSizeInBytes(); | |
| 209 } | |
| 210 | |
| 211 bool isSafeToSendToAnotherThread() const { | |
| 212 return m_string.isSafeToSendToAnotherThread(); | |
| 213 } | |
| 214 | |
| 215 #ifndef NDEBUG | |
| 216 void show() const; | |
| 217 #endif | |
| 218 | |
| 219 private: | |
| 220 String m_string; | |
| 221 | |
| 222 ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r) { | |
| 223 if (!r || r->isAtomic()) | |
| 224 return r; | |
| 225 return addSlowCase(r); | |
| 226 } | |
| 227 static PassRefPtr<StringImpl> addSlowCase(StringImpl*); | |
| 228 #if OS(MACOSX) | |
| 229 static PassRefPtr<StringImpl> add(CFStringRef); | |
| 230 #endif | |
| 231 }; | |
| 232 | |
| 233 inline bool operator==(const AtomicString& a, const AtomicString& b) { | |
| 234 return a.impl() == b.impl(); | |
| 235 } | |
| 236 inline bool operator==(const AtomicString& a, const String& b) { | |
| 237 // We don't use equalStringView so we get the isAtomic() optimization inside | |
| 238 // WTF::equal. | |
| 239 return equal(a.impl(), b.impl()); | |
| 240 } | |
| 241 inline bool operator==(const String& a, const AtomicString& b) { | |
| 242 return b == a; | |
| 243 } | |
| 244 inline bool operator==(const AtomicString& a, const char* b) { | |
| 245 return equalStringView(a, b); | |
| 246 } | |
| 247 inline bool operator==(const char* a, const AtomicString& b) { | |
| 248 return b == a; | |
| 249 } | |
| 250 | |
| 251 inline bool operator!=(const AtomicString& a, const AtomicString& b) { | |
| 252 return a.impl() != b.impl(); | |
| 253 } | |
| 254 inline bool operator!=(const AtomicString& a, const String& b) { | |
| 255 return !(a == b); | |
| 256 } | |
| 257 inline bool operator!=(const String& a, const AtomicString& b) { | |
| 258 return !(a == b); | |
| 259 } | |
| 260 inline bool operator!=(const AtomicString& a, const char* b) { | |
| 261 return !(a == b); | |
| 262 } | |
| 263 inline bool operator!=(const char* a, const AtomicString& b) { | |
| 264 return !(a == b); | |
| 265 } | |
| 266 | |
| 267 // Define external global variables for the commonly used atomic strings. | |
| 268 // These are only usable from the main thread. | |
| 269 WTF_EXPORT extern const AtomicString& nullAtom; | |
| 270 WTF_EXPORT extern const AtomicString& emptyAtom; | |
| 271 WTF_EXPORT extern const AtomicString& starAtom; | |
| 272 WTF_EXPORT extern const AtomicString& xmlAtom; | |
| 273 WTF_EXPORT extern const AtomicString& xmlnsAtom; | |
| 274 WTF_EXPORT extern const AtomicString& xlinkAtom; | |
| 275 WTF_EXPORT extern const AtomicString& httpAtom; | |
| 276 WTF_EXPORT extern const AtomicString& httpsAtom; | |
| 277 | |
| 278 // AtomicStringHash is the default hash for AtomicString | |
| 279 template <typename T> | |
| 280 struct DefaultHash; | |
| 281 template <> | |
| 282 struct DefaultHash<AtomicString> { | |
| 283 typedef AtomicStringHash Hash; | |
| 284 }; | |
| 285 | |
| 286 // Pretty printer for gtest and base/logging.*. It prepends and appends | |
| 287 // double-quotes, and escapes chracters other than ASCII printables. | |
| 288 WTF_EXPORT std::ostream& operator<<(std::ostream&, const AtomicString&); | |
| 289 | |
| 290 inline StringView::StringView(const AtomicString& string, | |
| 291 unsigned offset, | |
| 292 unsigned length) | |
| 293 : StringView(string.impl(), offset, length) {} | |
| 294 inline StringView::StringView(const AtomicString& string, unsigned offset) | |
| 295 : StringView(string.impl(), offset) {} | |
| 296 inline StringView::StringView(const AtomicString& string) | |
| 297 : StringView(string.impl()) {} | |
| 298 | |
| 299 } // namespace WTF | |
| 300 | |
| 301 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(AtomicString); | |
| 302 | |
| 303 using WTF::AtomicString; | |
| 304 using WTF::nullAtom; | |
| 305 using WTF::emptyAtom; | |
| 306 using WTF::starAtom; | |
| 307 using WTF::xmlAtom; | |
| 308 using WTF::xmlnsAtom; | |
| 309 using WTF::xlinkAtom; | |
| 310 | |
| 311 #include "wtf/text/StringConcatenate.h" | |
| 312 #endif // AtomicString_h | |
| OLD | NEW |