Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(631)

Side by Side Diff: third_party/WebKit/Source/wtf/text/AtomicString.cpp

Issue 1611343002: wtf reformat test Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pydent Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> 3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4 * Copyright (C) 2012 Google Inc. All rights reserved. 4 * Copyright (C) 2012 Google Inc. All rights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
(...skipping 15 matching lines...) Expand all
26 #include "wtf/WTFThreadData.h" 26 #include "wtf/WTFThreadData.h"
27 #include "wtf/dtoa.h" 27 #include "wtf/dtoa.h"
28 #include "wtf/text/IntegerToStringConversion.h" 28 #include "wtf/text/IntegerToStringConversion.h"
29 #include "wtf/text/StringHash.h" 29 #include "wtf/text/StringHash.h"
30 #include "wtf/text/UTF8.h" 30 #include "wtf/text/UTF8.h"
31 31
32 namespace WTF { 32 namespace WTF {
33 33
34 using namespace Unicode; 34 using namespace Unicode;
35 35
36 static_assert(sizeof(AtomicString) == sizeof(String), "AtomicString and String m ust be same size"); 36 static_assert(sizeof(AtomicString) == sizeof(String),
37 "AtomicString and String must be same size");
37 38
38 class AtomicStringTable { 39 class AtomicStringTable {
39 USING_FAST_MALLOC(AtomicStringTable); 40 USING_FAST_MALLOC(AtomicStringTable);
40 WTF_MAKE_NONCOPYABLE(AtomicStringTable); 41 WTF_MAKE_NONCOPYABLE(AtomicStringTable);
41 public: 42
42 static AtomicStringTable* create(WTFThreadData& data) 43 public:
43 { 44 static AtomicStringTable* create(WTFThreadData& data) {
44 data.m_atomicStringTable = new AtomicStringTable; 45 data.m_atomicStringTable = new AtomicStringTable;
45 data.m_atomicStringTableDestructor = AtomicStringTable::destroy; 46 data.m_atomicStringTableDestructor = AtomicStringTable::destroy;
46 data.m_atomicStringTable->addStaticStrings(); 47 data.m_atomicStringTable->addStaticStrings();
47 return data.m_atomicStringTable; 48 return data.m_atomicStringTable;
49 }
50
51 StringImpl* addStringImpl(StringImpl* string) {
52 if (!string->length())
53 return StringImpl::empty();
54
55 StringImpl* result = *m_table.add(string).storedValue;
56
57 if (!result->isAtomic())
58 result->setIsAtomic(true);
59
60 ASSERT(!string->isStatic() || result->isStatic());
61 return result;
62 }
63
64 HashSet<StringImpl*>& table() { return m_table; }
65
66 private:
67 AtomicStringTable() {}
68
69 void addStaticStrings() {
70 const StaticStringsTable& staticStrings = StringImpl::allStaticStrings();
71
72 StaticStringsTable::const_iterator it = staticStrings.begin();
73 for (; it != staticStrings.end(); ++it) {
74 addStringImpl(it->value);
48 } 75 }
49 76 }
50 StringImpl* addStringImpl(StringImpl* string) 77
51 { 78 static void destroy(AtomicStringTable* table) {
52 if (!string->length()) 79 HashSet<StringImpl*>::iterator end = table->m_table.end();
53 return StringImpl::empty(); 80 for (HashSet<StringImpl*>::iterator iter = table->m_table.begin();
54 81 iter != end; ++iter) {
55 StringImpl* result = *m_table.add(string).storedValue; 82 StringImpl* string = *iter;
56 83 if (!string->isStatic()) {
57 if (!result->isAtomic()) 84 ASSERT(string->isAtomic());
58 result->setIsAtomic(true); 85 string->setIsAtomic(false);
59 86 }
60 ASSERT(!string->isStatic() || result->isStatic());
61 return result;
62 } 87 }
63 88 delete table;
64 HashSet<StringImpl*>& table() 89 }
65 { 90
66 return m_table; 91 HashSet<StringImpl*> m_table;
67 } 92 };
68 93
69 private: 94 static inline AtomicStringTable& atomicStringTable() {
70 AtomicStringTable() { } 95 // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor).
71 96 WTFThreadData& data = wtfThreadData();
72 void addStaticStrings() 97 AtomicStringTable* table = data.atomicStringTable();
73 { 98 if (UNLIKELY(!table))
74 const StaticStringsTable& staticStrings = StringImpl::allStaticStrings() ; 99 table = AtomicStringTable::create(data);
75 100 return *table;
76 StaticStringsTable::const_iterator it = staticStrings.begin(); 101 }
77 for (; it != staticStrings.end(); ++it) { 102
78 addStringImpl(it->value); 103 static inline HashSet<StringImpl*>& atomicStrings() {
79 } 104 return atomicStringTable().table();
80 } 105 }
81 106
82 static void destroy(AtomicStringTable* table) 107 void AtomicString::reserveTableCapacity(size_t size) {
83 { 108 atomicStringTable().table().reserveCapacityForSize(size);
84 HashSet<StringImpl*>::iterator end = table->m_table.end(); 109 }
85 for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) { 110
86 StringImpl* string = *iter; 111 template <typename T, typename HashTranslator>
87 if (!string->isStatic()) { 112 static inline PassRefPtr<StringImpl> addToStringTable(const T& value) {
88 ASSERT(string->isAtomic()); 113 HashSet<StringImpl*>::AddResult addResult =
89 string->setIsAtomic(false); 114 atomicStrings().add<HashTranslator>(value);
90 } 115
91 } 116 // If the string is newly-translated, then we need to adopt it.
92 delete table; 117 // The boolean in the pair tells us if that is so.
93 } 118 return addResult.isNewEntry ? adoptRef(*addResult.storedValue)
94 119 : *addResult.storedValue;
95 HashSet<StringImpl*> m_table; 120 }
96 }; 121
97 122 PassRefPtr<StringImpl> AtomicString::add(const LChar* c) {
98 static inline AtomicStringTable& atomicStringTable() 123 if (!c)
99 { 124 return nullptr;
100 // Once possible we should make this non-lazy (constructed in WTFThreadData' s constructor). 125 if (!*c)
101 WTFThreadData& data = wtfThreadData(); 126 return StringImpl::empty();
102 AtomicStringTable* table = data.atomicStringTable(); 127
103 if (UNLIKELY(!table)) 128 return add(c, strlen(reinterpret_cast<const char*>(c)));
104 table = AtomicStringTable::create(data); 129 }
105 return *table; 130
106 } 131 template <typename CharacterType>
107
108 static inline HashSet<StringImpl*>& atomicStrings()
109 {
110 return atomicStringTable().table();
111 }
112
113 void AtomicString::reserveTableCapacity(size_t size)
114 {
115 atomicStringTable().table().reserveCapacityForSize(size);
116 }
117
118 template<typename T, typename HashTranslator>
119 static inline PassRefPtr<StringImpl> addToStringTable(const T& value)
120 {
121 HashSet<StringImpl*>::AddResult addResult = atomicStrings().add<HashTranslat or>(value);
122
123 // If the string is newly-translated, then we need to adopt it.
124 // The boolean in the pair tells us if that is so.
125 return addResult.isNewEntry ? adoptRef(*addResult.storedValue) : *addResult. storedValue;
126 }
127
128 PassRefPtr<StringImpl> AtomicString::add(const LChar* c)
129 {
130 if (!c)
131 return nullptr;
132 if (!*c)
133 return StringImpl::empty();
134
135 return add(c, strlen(reinterpret_cast<const char*>(c)));
136 }
137
138 template<typename CharacterType>
139 struct HashTranslatorCharBuffer { 132 struct HashTranslatorCharBuffer {
140 const CharacterType* s; 133 const CharacterType* s;
141 unsigned length; 134 unsigned length;
142 }; 135 };
143 136
144 typedef HashTranslatorCharBuffer<UChar> UCharBuffer; 137 typedef HashTranslatorCharBuffer<UChar> UCharBuffer;
145 struct UCharBufferTranslator { 138 struct UCharBufferTranslator {
146 static unsigned hash(const UCharBuffer& buf) 139 static unsigned hash(const UCharBuffer& buf) {
147 { 140 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
148 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length); 141 }
142
143 static bool equal(StringImpl* const& str, const UCharBuffer& buf) {
144 return WTF::equal(str, buf.s, buf.length);
145 }
146
147 static void translate(StringImpl*& location,
148 const UCharBuffer& buf,
149 unsigned hash) {
150 location = StringImpl::create8BitIfPossible(buf.s, buf.length).leakRef();
151 location->setHash(hash);
152 location->setIsAtomic(true);
153 }
154 };
155
156 template <typename CharacterType>
157 struct HashAndCharacters {
158 unsigned hash;
159 const CharacterType* characters;
160 unsigned length;
161 };
162
163 template <typename CharacterType>
164 struct HashAndCharactersTranslator {
165 static unsigned hash(const HashAndCharacters<CharacterType>& buffer) {
166 ASSERT(buffer.hash == StringHasher::computeHashAndMaskTop8Bits(
167 buffer.characters, buffer.length));
168 return buffer.hash;
169 }
170
171 static bool equal(StringImpl* const& string,
172 const HashAndCharacters<CharacterType>& buffer) {
173 return WTF::equal(string, buffer.characters, buffer.length);
174 }
175
176 static void translate(StringImpl*& location,
177 const HashAndCharacters<CharacterType>& buffer,
178 unsigned hash) {
179 location = StringImpl::create(buffer.characters, buffer.length).leakRef();
180 location->setHash(hash);
181 location->setIsAtomic(true);
182 }
183 };
184
185 struct HashAndUTF8Characters {
186 unsigned hash;
187 const char* characters;
188 unsigned length;
189 unsigned utf16Length;
190 };
191
192 struct HashAndUTF8CharactersTranslator {
193 static unsigned hash(const HashAndUTF8Characters& buffer) {
194 return buffer.hash;
195 }
196
197 static bool equal(StringImpl* const& string,
198 const HashAndUTF8Characters& buffer) {
199 if (buffer.utf16Length != string->length())
200 return false;
201
202 // If buffer contains only ASCII characters UTF-8 and UTF16 length are the s ame.
203 if (buffer.utf16Length != buffer.length) {
204 if (string->is8Bit()) {
205 const LChar* characters8 = string->characters8();
206 return equalLatin1WithUTF8(characters8, characters8 + string->length(),
207 buffer.characters,
208 buffer.characters + buffer.length);
209 }
210 const UChar* characters16 = string->characters16();
211 return equalUTF16WithUTF8(characters16, characters16 + string->length(),
212 buffer.characters,
213 buffer.characters + buffer.length);
149 } 214 }
150 215
151 static bool equal(StringImpl* const& str, const UCharBuffer& buf) 216 if (string->is8Bit()) {
152 { 217 const LChar* stringCharacters = string->characters8();
153 return WTF::equal(str, buf.s, buf.length); 218
219 for (unsigned i = 0; i < buffer.length; ++i) {
220 ASSERT(isASCII(buffer.characters[i]));
221 if (stringCharacters[i] != buffer.characters[i])
222 return false;
223 }
224
225 return true;
154 } 226 }
155 227
156 static void translate(StringImpl*& location, const UCharBuffer& buf, unsigne d hash) 228 const UChar* stringCharacters = string->characters16();
157 { 229
158 location = StringImpl::create8BitIfPossible(buf.s, buf.length).leakRef() ; 230 for (unsigned i = 0; i < buffer.length; ++i) {
159 location->setHash(hash); 231 ASSERT(isASCII(buffer.characters[i]));
160 location->setIsAtomic(true); 232 if (stringCharacters[i] != buffer.characters[i])
233 return false;
161 } 234 }
162 }; 235
163 236 return true;
164 template<typename CharacterType> 237 }
165 struct HashAndCharacters { 238
166 unsigned hash; 239 static void translate(StringImpl*& location,
167 const CharacterType* characters; 240 const HashAndUTF8Characters& buffer,
168 unsigned length; 241 unsigned hash) {
169 }; 242 UChar* target;
170 243 RefPtr<StringImpl> newString =
171 template<typename CharacterType> 244 StringImpl::createUninitialized(buffer.utf16Length, target);
172 struct HashAndCharactersTranslator { 245
173 static unsigned hash(const HashAndCharacters<CharacterType>& buffer) 246 bool isAllASCII;
174 { 247 const char* source = buffer.characters;
175 ASSERT(buffer.hash == StringHasher::computeHashAndMaskTop8Bits(buffer.ch aracters, buffer.length)); 248 if (convertUTF8ToUTF16(&source, source + buffer.length, &target,
176 return buffer.hash; 249 target + buffer.utf16Length,
177 } 250 &isAllASCII) != conversionOK)
178 251 ASSERT_NOT_REACHED();
179 static bool equal(StringImpl* const& string, const HashAndCharacters<Charact erType>& buffer) 252
180 { 253 if (isAllASCII)
181 return WTF::equal(string, buffer.characters, buffer.length); 254 newString = StringImpl::create(buffer.characters, buffer.length);
182 } 255
183 256 location = newString.release().leakRef();
184 static void translate(StringImpl*& location, const HashAndCharacters<Charact erType>& buffer, unsigned hash) 257 location->setHash(hash);
185 { 258 location->setIsAtomic(true);
186 location = StringImpl::create(buffer.characters, buffer.length).leakRef( ); 259 }
187 location->setHash(hash); 260 };
188 location->setIsAtomic(true); 261
189 } 262 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length) {
190 }; 263 if (!s)
191 264 return nullptr;
192 struct HashAndUTF8Characters { 265
193 unsigned hash; 266 if (!length)
194 const char* characters; 267 return StringImpl::empty();
195 unsigned length; 268
196 unsigned utf16Length; 269 UCharBuffer buffer = {s, length};
197 }; 270 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
198 271 }
199 struct HashAndUTF8CharactersTranslator { 272
200 static unsigned hash(const HashAndUTF8Characters& buffer) 273 PassRefPtr<StringImpl> AtomicString::add(const UChar* s,
201 { 274 unsigned length,
202 return buffer.hash; 275 unsigned existingHash) {
203 } 276 ASSERT(s);
204 277 ASSERT(existingHash);
205 static bool equal(StringImpl* const& string, const HashAndUTF8Characters& bu ffer) 278
206 { 279 if (!length)
207 if (buffer.utf16Length != string->length()) 280 return StringImpl::empty();
208 return false; 281
209 282 HashAndCharacters<UChar> buffer = {existingHash, s, length};
210 // If buffer contains only ASCII characters UTF-8 and UTF16 length are t he same. 283 return addToStringTable<HashAndCharacters<UChar>,
211 if (buffer.utf16Length != buffer.length) { 284 HashAndCharactersTranslator<UChar>>(buffer);
212 if (string->is8Bit()) { 285 }
213 const LChar* characters8 = string->characters8(); 286
214 return equalLatin1WithUTF8(characters8, characters8 + string->le ngth(), buffer.characters, buffer.characters + buffer.length); 287 PassRefPtr<StringImpl> AtomicString::add(const UChar* s) {
215 } 288 if (!s)
216 const UChar* characters16 = string->characters16(); 289 return nullptr;
217 return equalUTF16WithUTF8(characters16, characters16 + string->lengt h(), buffer.characters, buffer.characters + buffer.length); 290
218 } 291 unsigned length = 0;
219 292 while (s[length] != UChar(0))
220 if (string->is8Bit()) { 293 ++length;
221 const LChar* stringCharacters = string->characters8(); 294
222 295 if (!length)
223 for (unsigned i = 0; i < buffer.length; ++i) { 296 return StringImpl::empty();
224 ASSERT(isASCII(buffer.characters[i])); 297
225 if (stringCharacters[i] != buffer.characters[i]) 298 UCharBuffer buffer = {s, length};
226 return false; 299 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
227 }
228
229 return true;
230 }
231
232 const UChar* stringCharacters = string->characters16();
233
234 for (unsigned i = 0; i < buffer.length; ++i) {
235 ASSERT(isASCII(buffer.characters[i]));
236 if (stringCharacters[i] != buffer.characters[i])
237 return false;
238 }
239
240 return true;
241 }
242
243 static void translate(StringImpl*& location, const HashAndUTF8Characters& bu ffer, unsigned hash)
244 {
245 UChar* target;
246 RefPtr<StringImpl> newString = StringImpl::createUninitialized(buffer.ut f16Length, target);
247
248 bool isAllASCII;
249 const char* source = buffer.characters;
250 if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII) != conversionOK)
251 ASSERT_NOT_REACHED();
252
253 if (isAllASCII)
254 newString = StringImpl::create(buffer.characters, buffer.length);
255
256 location = newString.release().leakRef();
257 location->setHash(hash);
258 location->setIsAtomic(true);
259 }
260 };
261
262 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
263 {
264 if (!s)
265 return nullptr;
266
267 if (!length)
268 return StringImpl::empty();
269
270 UCharBuffer buffer = { s, length };
271 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
272 }
273
274 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsign ed existingHash)
275 {
276 ASSERT(s);
277 ASSERT(existingHash);
278
279 if (!length)
280 return StringImpl::empty();
281
282 HashAndCharacters<UChar> buffer = { existingHash, s, length };
283 return addToStringTable<HashAndCharacters<UChar>, HashAndCharactersTranslato r<UChar>>(buffer);
284 }
285
286 PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
287 {
288 if (!s)
289 return nullptr;
290
291 unsigned length = 0;
292 while (s[length] != UChar(0))
293 ++length;
294
295 if (!length)
296 return StringImpl::empty();
297
298 UCharBuffer buffer = { s, length };
299 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
300 } 300 }
301 301
302 struct SubstringLocation { 302 struct SubstringLocation {
303 StringImpl* baseString; 303 StringImpl* baseString;
304 unsigned start; 304 unsigned start;
305 unsigned length; 305 unsigned length;
306 }; 306 };
307 307
308 struct SubstringTranslator { 308 struct SubstringTranslator {
309 static unsigned hash(const SubstringLocation& buffer) 309 static unsigned hash(const SubstringLocation& buffer) {
310 { 310 if (buffer.baseString->is8Bit())
311 if (buffer.baseString->is8Bit()) 311 return StringHasher::computeHashAndMaskTop8Bits(
312 return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->c haracters8() + buffer.start, buffer.length); 312 buffer.baseString->characters8() + buffer.start, buffer.length);
313 return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->chara cters16() + buffer.start, buffer.length); 313 return StringHasher::computeHashAndMaskTop8Bits(
314 } 314 buffer.baseString->characters16() + buffer.start, buffer.length);
315 315 }
316 static bool equal(StringImpl* const& string, const SubstringLocation& buffer ) 316
317 { 317 static bool equal(StringImpl* const& string,
318 if (buffer.baseString->is8Bit()) 318 const SubstringLocation& buffer) {
319 return WTF::equal(string, buffer.baseString->characters8() + buffer. start, buffer.length); 319 if (buffer.baseString->is8Bit())
320 return WTF::equal(string, buffer.baseString->characters16() + buffer.sta rt, buffer.length); 320 return WTF::equal(string, buffer.baseString->characters8() + buffer.start,
321 } 321 buffer.length);
322 322 return WTF::equal(string, buffer.baseString->characters16() + buffer.start,
323 static void translate(StringImpl*& location, const SubstringLocation& buffer , unsigned hash) 323 buffer.length);
324 { 324 }
325 location = buffer.baseString->substring(buffer.start, buffer.length).lea kRef(); 325
326 location->setHash(hash); 326 static void translate(StringImpl*& location,
327 location->setIsAtomic(true); 327 const SubstringLocation& buffer,
328 } 328 unsigned hash) {
329 }; 329 location =
330 330 buffer.baseString->substring(buffer.start, buffer.length).leakRef();
331 PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length) 331 location->setHash(hash);
332 { 332 location->setIsAtomic(true);
333 if (!baseString) 333 }
334 return nullptr; 334 };
335 335
336 if (!length || start >= baseString->length()) 336 PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString,
337 return StringImpl::empty(); 337 unsigned start,
338 338 unsigned length) {
339 unsigned maxLength = baseString->length() - start; 339 if (!baseString)
340 if (length >= maxLength) { 340 return nullptr;
341 if (!start) 341
342 return add(baseString); 342 if (!length || start >= baseString->length())
343 length = maxLength; 343 return StringImpl::empty();
344 } 344
345 345 unsigned maxLength = baseString->length() - start;
346 SubstringLocation buffer = { baseString, start, length }; 346 if (length >= maxLength) {
347 return addToStringTable<SubstringLocation, SubstringTranslator>(buffer); 347 if (!start)
348 return add(baseString);
349 length = maxLength;
350 }
351
352 SubstringLocation buffer = {baseString, start, length};
353 return addToStringTable<SubstringLocation, SubstringTranslator>(buffer);
348 } 354 }
349 355
350 typedef HashTranslatorCharBuffer<LChar> LCharBuffer; 356 typedef HashTranslatorCharBuffer<LChar> LCharBuffer;
351 struct LCharBufferTranslator { 357 struct LCharBufferTranslator {
352 static unsigned hash(const LCharBuffer& buf) 358 static unsigned hash(const LCharBuffer& buf) {
353 { 359 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
354 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length); 360 }
355 } 361
356 362 static bool equal(StringImpl* const& str, const LCharBuffer& buf) {
357 static bool equal(StringImpl* const& str, const LCharBuffer& buf) 363 return WTF::equal(str, buf.s, buf.length);
358 { 364 }
359 return WTF::equal(str, buf.s, buf.length); 365
360 } 366 static void translate(StringImpl*& location,
361 367 const LCharBuffer& buf,
362 static void translate(StringImpl*& location, const LCharBuffer& buf, unsigne d hash) 368 unsigned hash) {
363 { 369 location = StringImpl::create(buf.s, buf.length).leakRef();
364 location = StringImpl::create(buf.s, buf.length).leakRef(); 370 location->setHash(hash);
365 location->setHash(hash); 371 location->setIsAtomic(true);
366 location->setIsAtomic(true); 372 }
367 }
368 }; 373 };
369 374
370 typedef HashTranslatorCharBuffer<char> CharBuffer; 375 typedef HashTranslatorCharBuffer<char> CharBuffer;
371 struct CharBufferFromLiteralDataTranslator { 376 struct CharBufferFromLiteralDataTranslator {
372 static unsigned hash(const CharBuffer& buf) 377 static unsigned hash(const CharBuffer& buf) {
373 { 378 return StringHasher::computeHashAndMaskTop8Bits(
374 return StringHasher::computeHashAndMaskTop8Bits(reinterpret_cast<const L Char*>(buf.s), buf.length); 379 reinterpret_cast<const LChar*>(buf.s), buf.length);
375 } 380 }
376 381
377 static bool equal(StringImpl* const& str, const CharBuffer& buf) 382 static bool equal(StringImpl* const& str, const CharBuffer& buf) {
378 { 383 return WTF::equal(str, buf.s, buf.length);
379 return WTF::equal(str, buf.s, buf.length); 384 }
380 } 385
381 386 static void translate(StringImpl*& location,
382 static void translate(StringImpl*& location, const CharBuffer& buf, unsigned hash) 387 const CharBuffer& buf,
383 { 388 unsigned hash) {
384 location = StringImpl::create(buf.s, buf.length).leakRef(); 389 location = StringImpl::create(buf.s, buf.length).leakRef();
385 location->setHash(hash); 390 location->setHash(hash);
386 location->setIsAtomic(true); 391 location->setIsAtomic(true);
387 } 392 }
388 }; 393 };
389 394
390 PassRefPtr<StringImpl> AtomicString::add(const LChar* s, unsigned length) 395 PassRefPtr<StringImpl> AtomicString::add(const LChar* s, unsigned length) {
391 { 396 if (!s)
392 if (!s) 397 return nullptr;
393 return nullptr; 398
394 399 if (!length)
395 if (!length) 400 return StringImpl::empty();
396 return StringImpl::empty(); 401
397 402 LCharBuffer buffer = {s, length};
398 LCharBuffer buffer = { s, length }; 403 return addToStringTable<LCharBuffer, LCharBufferTranslator>(buffer);
399 return addToStringTable<LCharBuffer, LCharBufferTranslator>(buffer); 404 }
400 } 405
401 406 PassRefPtr<StringImpl> AtomicString::addFromLiteralData(const char* characters,
402 PassRefPtr<StringImpl> AtomicString::addFromLiteralData(const char* characters, unsigned length) 407 unsigned length) {
403 { 408 ASSERT(characters);
404 ASSERT(characters); 409 ASSERT(length);
405 ASSERT(length); 410
406 411 CharBuffer buffer = {characters, length};
407 CharBuffer buffer = { characters, length }; 412 return addToStringTable<CharBuffer, CharBufferFromLiteralDataTranslator>(
408 return addToStringTable<CharBuffer, CharBufferFromLiteralDataTranslator>(buf fer); 413 buffer);
409 } 414 }
410 415
411 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* string) 416 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* string) {
412 { 417 return atomicStringTable().addStringImpl(string);
413 return atomicStringTable().addStringImpl(string); 418 }
414 } 419
415 420 template <typename CharacterType>
416 template<typename CharacterType> 421 static inline HashSet<StringImpl*>::iterator findString(
417 static inline HashSet<StringImpl*>::iterator findString(const StringImpl* string Impl) 422 const StringImpl* stringImpl) {
418 { 423 HashAndCharacters<CharacterType> buffer = {
419 HashAndCharacters<CharacterType> buffer = { stringImpl->existingHash(), stri ngImpl->getCharacters<CharacterType>(), stringImpl->length() }; 424 stringImpl->existingHash(), stringImpl->getCharacters<CharacterType>(),
420 return atomicStrings().find<HashAndCharactersTranslator<CharacterType>>(buff er); 425 stringImpl->length()};
421 } 426 return atomicStrings().find<HashAndCharactersTranslator<CharacterType>>(
422 427 buffer);
423 StringImpl* AtomicString::find(const StringImpl* stringImpl) 428 }
424 { 429
425 ASSERT(stringImpl); 430 StringImpl* AtomicString::find(const StringImpl* stringImpl) {
426 ASSERT(stringImpl->existingHash()); 431 ASSERT(stringImpl);
427 432 ASSERT(stringImpl->existingHash());
428 if (!stringImpl->length()) 433
429 return StringImpl::empty(); 434 if (!stringImpl->length())
430 435 return StringImpl::empty();
431 HashSet<StringImpl*>::iterator iterator; 436
432 if (stringImpl->is8Bit()) 437 HashSet<StringImpl*>::iterator iterator;
433 iterator = findString<LChar>(stringImpl); 438 if (stringImpl->is8Bit())
434 else 439 iterator = findString<LChar>(stringImpl);
435 iterator = findString<UChar>(stringImpl); 440 else
436 if (iterator == atomicStrings().end()) 441 iterator = findString<UChar>(stringImpl);
437 return 0; 442 if (iterator == atomicStrings().end())
438 return *iterator; 443 return 0;
439 } 444 return *iterator;
440 445 }
441 void AtomicString::remove(StringImpl* r) 446
442 { 447 void AtomicString::remove(StringImpl* r) {
443 HashSet<StringImpl*>::iterator iterator; 448 HashSet<StringImpl*>::iterator iterator;
444 if (r->is8Bit()) 449 if (r->is8Bit())
445 iterator = findString<LChar>(r); 450 iterator = findString<LChar>(r);
446 else 451 else
447 iterator = findString<UChar>(r); 452 iterator = findString<UChar>(r);
448 RELEASE_ASSERT(iterator != atomicStrings().end()); 453 RELEASE_ASSERT(iterator != atomicStrings().end());
449 atomicStrings().remove(iterator); 454 atomicStrings().remove(iterator);
450 } 455 }
451 456
452 AtomicString AtomicString::lower() const 457 AtomicString AtomicString::lower() const {
453 { 458 // Note: This is a hot function in the Dromaeo benchmark.
454 // Note: This is a hot function in the Dromaeo benchmark. 459 StringImpl* impl = this->impl();
455 StringImpl* impl = this->impl(); 460 if (UNLIKELY(!impl))
456 if (UNLIKELY(!impl)) 461 return *this;
457 return *this; 462 RefPtr<StringImpl> newImpl = impl->lower();
458 RefPtr<StringImpl> newImpl = impl->lower(); 463 if (LIKELY(newImpl == impl))
459 if (LIKELY(newImpl == impl)) 464 return *this;
460 return *this; 465 return AtomicString(newImpl.release());
461 return AtomicString(newImpl.release()); 466 }
462 } 467
463 468 AtomicString AtomicString::lowerASCII() const {
464 AtomicString AtomicString::lowerASCII() const 469 StringImpl* impl = this->impl();
465 { 470 if (UNLIKELY(!impl))
466 StringImpl* impl = this->impl(); 471 return *this;
467 if (UNLIKELY(!impl)) 472 RefPtr<StringImpl> newImpl = impl->lowerASCII();
468 return *this; 473 if (LIKELY(newImpl == impl))
469 RefPtr<StringImpl> newImpl = impl->lowerASCII(); 474 return *this;
470 if (LIKELY(newImpl == impl)) 475 return AtomicString(newImpl.release());
471 return *this; 476 }
472 return AtomicString(newImpl.release()); 477
473 } 478 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart,
474 479 const char* charactersEnd) {
475 480 HashAndUTF8Characters buffer;
476 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const c har* charactersEnd) 481 buffer.characters = charactersStart;
477 { 482 buffer.hash = calculateStringHashAndLengthFromUTF8MaskingTop8Bits(
478 HashAndUTF8Characters buffer; 483 charactersStart, charactersEnd, buffer.length, buffer.utf16Length);
479 buffer.characters = charactersStart; 484
480 buffer.hash = calculateStringHashAndLengthFromUTF8MaskingTop8Bits(characters Start, charactersEnd, buffer.length, buffer.utf16Length); 485 if (!buffer.hash)
481 486 return nullAtom;
482 if (!buffer.hash) 487
483 return nullAtom; 488 AtomicString atomicString;
484 489 atomicString.m_string =
485 AtomicString atomicString; 490 addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(
486 atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8C haractersTranslator>(buffer); 491 buffer);
487 return atomicString; 492 return atomicString;
488 } 493 }
489 494
490 AtomicString AtomicString::number(int number) 495 AtomicString AtomicString::number(int number) {
491 { 496 return numberToStringSigned<AtomicString>(number);
492 return numberToStringSigned<AtomicString>(number); 497 }
493 } 498
494 499 AtomicString AtomicString::number(unsigned number) {
495 AtomicString AtomicString::number(unsigned number) 500 return numberToStringUnsigned<AtomicString>(number);
496 { 501 }
497 return numberToStringUnsigned<AtomicString>(number); 502
498 } 503 AtomicString AtomicString::number(long number) {
499 504 return numberToStringSigned<AtomicString>(number);
500 AtomicString AtomicString::number(long number) 505 }
501 { 506
502 return numberToStringSigned<AtomicString>(number); 507 AtomicString AtomicString::number(unsigned long number) {
503 } 508 return numberToStringUnsigned<AtomicString>(number);
504 509 }
505 AtomicString AtomicString::number(unsigned long number) 510
506 { 511 AtomicString AtomicString::number(long long number) {
507 return numberToStringUnsigned<AtomicString>(number); 512 return numberToStringSigned<AtomicString>(number);
508 } 513 }
509 514
510 AtomicString AtomicString::number(long long number) 515 AtomicString AtomicString::number(unsigned long long number) {
511 { 516 return numberToStringUnsigned<AtomicString>(number);
512 return numberToStringSigned<AtomicString>(number); 517 }
513 } 518
514 519 AtomicString AtomicString::number(
515 AtomicString AtomicString::number(unsigned long long number) 520 double number,
516 { 521 unsigned precision,
517 return numberToStringUnsigned<AtomicString>(number); 522 TrailingZerosTruncatingPolicy trailingZerosTruncatingPolicy) {
518 } 523 NumberToStringBuffer buffer;
519 524 return AtomicString(numberToFixedPrecisionString(
520 AtomicString AtomicString::number(double number, unsigned precision, TrailingZer osTruncatingPolicy trailingZerosTruncatingPolicy) 525 number, precision, buffer,
521 { 526 trailingZerosTruncatingPolicy == TruncateTrailingZeros));
522 NumberToStringBuffer buffer;
523 return AtomicString(numberToFixedPrecisionString(number, precision, buffer, trailingZerosTruncatingPolicy == TruncateTrailingZeros));
524 } 527 }
525 528
526 #ifndef NDEBUG 529 #ifndef NDEBUG
527 void AtomicString::show() const 530 void AtomicString::show() const {
528 { 531 m_string.show();
529 m_string.show();
530 } 532 }
531 #endif 533 #endif
532 534
533 } // namespace WTF 535 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/text/AtomicString.h ('k') | third_party/WebKit/Source/wtf/text/AtomicStringCF.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698