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

Side by Side Diff: Source/wtf/text/StringImpl.h

Issue 21262003: Remove String::adopt(Vector<UChar>) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix typo Created 7 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « Source/wtf/text/StringBuffer.h ('k') | Source/wtf/text/StringImpl.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Google Inc. All rights reserved. 4 * Copyright (C) 2009 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 NEW_DELETE_SAME_AS_MALLOC_FREE; 107 NEW_DELETE_SAME_AS_MALLOC_FREE;
108 friend struct WTF::CStringTranslator; 108 friend struct WTF::CStringTranslator;
109 template<typename CharacterType> friend struct WTF::HashAndCharactersTransla tor; 109 template<typename CharacterType> friend struct WTF::HashAndCharactersTransla tor;
110 friend struct WTF::HashAndUTF8CharactersTranslator; 110 friend struct WTF::HashAndUTF8CharactersTranslator;
111 friend struct WTF::CharBufferFromLiteralDataTranslator; 111 friend struct WTF::CharBufferFromLiteralDataTranslator;
112 friend struct WTF::LCharBufferTranslator; 112 friend struct WTF::LCharBufferTranslator;
113 friend struct WTF::SubstringTranslator; 113 friend struct WTF::SubstringTranslator;
114 friend struct WTF::UCharBufferTranslator; 114 friend struct WTF::UCharBufferTranslator;
115 115
116 private: 116 private:
117 enum BufferOwnership {
118 BufferInternal,
119 BufferOwned,
120 // NOTE: Adding more ownership types needs to extend m_hashAndFlags as w e're at capacity
121 };
122
123 // Used to construct static strings, which have an special refCount that can never hit zero. 117 // Used to construct static strings, which have an special refCount that can never hit zero.
124 // This means that the static string will never be destroyed, which is impor tant because 118 // This means that the static string will never be destroyed, which is impor tant because
125 // static strings will be shared across threads & ref-counted in a non-threa dsafe manner. 119 // static strings will be shared across threads & ref-counted in a non-threa dsafe manner.
126 enum ConstructStaticStringTag { ConstructStaticString }; 120 enum ConstructStaticStringTag { ConstructStaticString };
127 StringImpl(const UChar* characters, unsigned length, ConstructStaticStringTa g)
128 : m_data16(characters)
129 , m_refCount(s_refCountFlagIsStaticString)
130 , m_length(length)
131 , m_hashAndFlags(BufferOwned)
132 {
133 // Ensure that the hash is computed so that AtomicStringHash can call ex istingHash()
134 // with impunity. The empty string is special because it is never entere d into
135 // AtomicString's HashKey, but still needs to compare correctly.
136 STRING_STATS_ADD_16BIT_STRING(m_length);
137
138 hash();
139 }
140
141 // Used to construct static strings, which have an special refCount that can never hit zero.
142 // This means that the static string will never be destroyed, which is impor tant because
143 // static strings will be shared across threads & ref-counted in a non-threa dsafe manner.
144 StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTa g) 121 StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTa g)
145 : m_data8(characters) 122 : m_data8(characters)
146 , m_refCount(s_refCountFlagIsStaticString) 123 , m_refCount(s_refCountFlagIsStaticString)
147 , m_length(length) 124 , m_length(length)
148 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned) 125 , m_hashAndFlags(s_hashFlag8BitBuffer)
149 { 126 {
150 // Ensure that the hash is computed so that AtomicStringHash can call ex istingHash() 127 // Ensure that the hash is computed so that AtomicStringHash can call ex istingHash()
151 // with impunity. The empty string is special because it is never entere d into 128 // with impunity. The empty string is special because it is never entere d into
152 // AtomicString's HashKey, but still needs to compare correctly. 129 // AtomicString's HashKey, but still needs to compare correctly.
153 STRING_STATS_ADD_8BIT_STRING(m_length); 130 STRING_STATS_ADD_8BIT_STRING(m_length);
154 131
155 hash(); 132 hash();
156 } 133 }
157 134
158 // FIXME: there has to be a less hacky way to do this. 135 // FIXME: there has to be a less hacky way to do this.
159 enum Force8Bit { Force8BitConstructor }; 136 enum Force8Bit { Force8BitConstructor };
160 // Create a normal 8-bit string with internal storage (BufferInternal)
161 StringImpl(unsigned length, Force8Bit) 137 StringImpl(unsigned length, Force8Bit)
162 : m_data8(reinterpret_cast<const LChar*>(this + 1)) 138 : m_data8(reinterpret_cast<const LChar*>(this + 1))
163 , m_refCount(s_refCountIncrement) 139 , m_refCount(s_refCountIncrement)
164 , m_length(length) 140 , m_length(length)
165 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) 141 , m_hashAndFlags(s_hashFlag8BitBuffer)
166 { 142 {
167 ASSERT(m_data8); 143 ASSERT(m_data8);
168 ASSERT(m_length); 144 ASSERT(m_length);
169 145
170 STRING_STATS_ADD_8BIT_STRING(m_length); 146 STRING_STATS_ADD_8BIT_STRING(m_length);
171 } 147 }
172 148
173 // Create a normal 16-bit string with internal storage (BufferInternal)
174 StringImpl(unsigned length) 149 StringImpl(unsigned length)
175 : m_data16(reinterpret_cast<const UChar*>(this + 1)) 150 : m_data16(reinterpret_cast<const UChar*>(this + 1))
176 , m_refCount(s_refCountIncrement) 151 , m_refCount(s_refCountIncrement)
177 , m_length(length) 152 , m_length(length)
178 , m_hashAndFlags(BufferInternal) 153 , m_hashAndFlags(0)
179 { 154 {
180 ASSERT(m_data16); 155 ASSERT(m_data16);
181 ASSERT(m_length); 156 ASSERT(m_length);
182 157
183 STRING_STATS_ADD_16BIT_STRING(m_length); 158 STRING_STATS_ADD_16BIT_STRING(m_length);
184 } 159 }
185 160
186 // Create a StringImpl adopting ownership of the provided buffer (BufferOwne d)
187 StringImpl(const LChar* characters, unsigned length)
188 : m_data8(characters)
189 , m_refCount(s_refCountIncrement)
190 , m_length(length)
191 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned)
192 {
193 ASSERT(m_data8);
194 ASSERT(m_length);
195
196 STRING_STATS_ADD_8BIT_STRING(m_length);
197 }
198
199 enum ConstructFromLiteralTag { ConstructFromLiteral }; 161 enum ConstructFromLiteralTag { ConstructFromLiteral };
200 StringImpl(const char* characters, unsigned length, ConstructFromLiteralTag) 162 StringImpl(const char* characters, unsigned length, ConstructFromLiteralTag)
201 : m_data8(reinterpret_cast<const LChar*>(characters)) 163 : m_data8(reinterpret_cast<const LChar*>(characters))
202 , m_refCount(s_refCountIncrement) 164 , m_refCount(s_refCountIncrement)
203 , m_length(length) 165 , m_length(length)
204 , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) 166 , m_hashAndFlags(s_hashFlag8BitBuffer)
205 { 167 {
206 ASSERT(m_data8); 168 ASSERT(m_data8);
207 ASSERT(m_length); 169 ASSERT(m_length);
208 ASSERT(!characters[length]); 170 ASSERT(!characters[length]);
209 171
210 STRING_STATS_ADD_8BIT_STRING(0); 172 STRING_STATS_ADD_8BIT_STRING(0);
211 } 173 }
212 174
213 // Create a StringImpl adopting ownership of the provided buffer (BufferOwne d)
214 StringImpl(const UChar* characters, unsigned length)
215 : m_data16(characters)
216 , m_refCount(s_refCountIncrement)
217 , m_length(length)
218 , m_hashAndFlags(BufferOwned)
219 {
220 ASSERT(m_data16);
221 ASSERT(m_length);
222
223 STRING_STATS_ADD_16BIT_STRING(m_length);
224 }
225
226 enum CreateEmptyUnique_T { CreateEmptyUnique };
227 StringImpl(CreateEmptyUnique_T)
228 : m_data16(reinterpret_cast<const UChar*>(1))
229 , m_refCount(s_refCountIncrement)
230 , m_length(0)
231 {
232 ASSERT(m_data16);
233 // Set the hash early, so that all empty unique StringImpls have a hash,
234 // and don't use the normal hashing algorithm - the unique nature of the se
235 // keys means that we don't need them to match any other string (in fact ,
236 // that's exactly the oposite of what we want!), and teh normal hash wou ld
237 // lead to lots of conflicts.
238 unsigned hash = reinterpret_cast<uintptr_t>(this);
239 hash <<= s_flagCount;
240 if (!hash)
241 hash = 1 << s_flagCount;
242 m_hashAndFlags = hash | BufferInternal;
243
244 STRING_STATS_ADD_16BIT_STRING(m_length);
245 }
246 public: 175 public:
247 ~StringImpl(); 176 ~StringImpl();
248 177
249 static PassRefPtr<StringImpl> create(const UChar*, unsigned length); 178 static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
250 static PassRefPtr<StringImpl> create(const LChar*, unsigned length); 179 static PassRefPtr<StringImpl> create(const LChar*, unsigned length);
251 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le ngth); 180 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le ngth);
252 template<size_t inlineCapacity> 181 template<size_t inlineCapacity>
253 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin eCapacity>& vector) 182 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin eCapacity>& vector)
254 { 183 {
255 return create8BitIfPossible(vector.data(), vector.size()); 184 return create8BitIfPossible(vector.data(), vector.size());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 return 0; 218 return 0;
290 } 219 }
291 output = reinterpret_cast<T*>(resultImpl + 1); 220 output = reinterpret_cast<T*>(resultImpl + 1);
292 221
293 if (sizeof(T) == sizeof(char)) 222 if (sizeof(T) == sizeof(char))
294 return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8B itConstructor)); 223 return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8B itConstructor));
295 224
296 return adoptRef(new (NotNull, resultImpl) StringImpl(length)); 225 return adoptRef(new (NotNull, resultImpl) StringImpl(length));
297 } 226 }
298 227
299 static PassRefPtr<StringImpl> createEmptyUnique() 228 // Reallocate the StringImpl. The originalString must be only owned by the P assRefPtr.
300 { 229 // Just like the input pointer of realloc(), the originalString can't be use d after this function.
301 return adoptRef(new StringImpl(CreateEmptyUnique));
302 }
303
304 // Reallocate the StringImpl. The originalString must be only owned by the P assRefPtr,
305 // and the buffer ownership must be BufferInternal. Just like the input poin ter of realloc(),
306 // the originalString can't be used after this function.
307 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri ng, unsigned length, LChar*& data); 230 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri ng, unsigned length, LChar*& data);
308 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri ng, unsigned length, UChar*& data); 231 static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalStri ng, unsigned length, UChar*& data);
309 232
310 // If this StringImpl has only one reference, we can truncate the string by updating 233 // If this StringImpl has only one reference, we can truncate the string by updating
311 // its m_length property without actually re-allocating its buffer. 234 // its m_length property without actually re-allocating its buffer.
312 void truncateAssumingIsolated(unsigned length) 235 void truncateAssumingIsolated(unsigned length)
313 { 236 {
314 ASSERT(hasOneRef()); 237 ASSERT(hasOneRef());
238 ASSERT(!isASCIILiteral());
315 ASSERT(length <= m_length); 239 ASSERT(length <= m_length);
316 ASSERT(bufferOwnership() == BufferInternal);
317 m_length = length; 240 m_length = length;
318 } 241 }
319 242
320 static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAnd Flags); }
321 static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; }
322 static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
323
324 template<typename CharType, size_t inlineCapacity>
325 static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity>& vector )
326 {
327 if (size_t size = vector.size()) {
328 ASSERT(vector.data());
329 RELEASE_ASSERT(size <= std::numeric_limits<unsigned>::max());
330 return adoptRef(new StringImpl(vector.releaseBuffer(), size));
331 }
332 return empty();
333 }
334
335 unsigned length() const { return m_length; } 243 unsigned length() const { return m_length; }
336 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } 244 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; }
337 bool hasInternalBuffer() const { return bufferOwnership() == BufferInternal; }
338 bool hasOwnedBuffer() const { return bufferOwnership() == BufferOwned; }
339 245
340 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_ data8; } 246 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_ data8; }
341 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; } 247 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; }
342 248
343 template <typename CharType> 249 template <typename CharType>
344 ALWAYS_INLINE const CharType * getCharacters() const; 250 ALWAYS_INLINE const CharType * getCharacters() const;
345 251
346 size_t cost() 252 size_t cost()
347 { 253 {
348 if (m_hashAndFlags & s_hashFlagDidReportCost) 254 if (m_hashAndFlags & s_hashFlagDidReportCost)
349 return 0; 255 return 0;
350 256
351 m_hashAndFlags |= s_hashFlagDidReportCost; 257 m_hashAndFlags |= s_hashFlagDidReportCost;
352 return m_length; 258 return m_length;
353 } 259 }
354 260
355 size_t sizeInBytes() const; 261 size_t sizeInBytes() const;
356 262
357 bool isEmptyUnique() const
358 {
359 return !length() && !isStatic();
360 }
361
362 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } 263 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; }
363 void setIsAtomic(bool isAtomic) 264 void setIsAtomic(bool isAtomic)
364 { 265 {
365 if (isAtomic) 266 if (isAtomic)
366 m_hashAndFlags |= s_hashFlagIsAtomic; 267 m_hashAndFlags |= s_hashFlagIsAtomic;
367 else 268 else
368 m_hashAndFlags &= ~s_hashFlagIsAtomic; 269 m_hashAndFlags &= ~s_hashFlagIsAtomic;
369 } 270 }
370 271
371 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } 272 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 #endif 469 #endif
569 #ifdef __OBJC__ 470 #ifdef __OBJC__
570 operator NSString*(); 471 operator NSString*();
571 #endif 472 #endif
572 473
573 #ifdef STRING_STATS 474 #ifdef STRING_STATS
574 ALWAYS_INLINE static StringStats& stringStats() { return m_stringStats; } 475 ALWAYS_INLINE static StringStats& stringStats() { return m_stringStats; }
575 #endif 476 #endif
576 477
577 private: 478 private:
578
579 bool isASCIILiteral() const 479 bool isASCIILiteral() const
580 { 480 {
581 return is8Bit() && hasInternalBuffer() && reinterpret_cast<const void*>( m_data8) != reinterpret_cast<const void*>(this + 1); 481 return is8Bit() && length() && reinterpret_cast<const void*>(m_data8) != reinterpret_cast<const void*>(this + 1);
582 } 482 }
583 483
584 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 484 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
585 static const unsigned s_copyCharsInlineCutOff = 20; 485 static const unsigned s_copyCharsInlineCutOff = 20;
586 486
587 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership >(m_hashAndFlags & s_hashMaskBufferOwnership); }
588 template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacter s(UCharPredicate); 487 template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacter s(UCharPredicate);
589 template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> si mplifyMatchedCharactersToSpace(UCharPredicate); 488 template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> si mplifyMatchedCharactersToSpace(UCharPredicate);
590 NEVER_INLINE unsigned hashSlowCase() const; 489 NEVER_INLINE unsigned hashSlowCase() const;
591 490
592 // The bottom bit in the ref count indicates a static (immortal) string. 491 // The bottom bit in the ref count indicates a static (immortal) string.
593 static const unsigned s_refCountFlagIsStaticString = 0x1; 492 static const unsigned s_refCountFlagIsStaticString = 0x1;
594 static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag. 493 static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag.
595 494
596 // The bottom 8 bits in the hash are flags, of which only 4 are currently in use. 495 // The bottom 8 bits in the hash are flags, of which only 3 are currently in use.
597 static const unsigned s_flagCount = 8; 496 static const unsigned s_flagCount = 8;
598 static const unsigned s_flagMask = (1u << s_flagCount) - 1; 497 static const unsigned s_flagMask = (1u << s_flagCount) - 1;
599 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves _enough_bits_for_StringImpl_flags); 498 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves _enough_bits_for_StringImpl_flags);
600 499
601 static const unsigned s_hashFlagDidReportCost = 1u << 3; 500 static const unsigned s_hashFlagDidReportCost = 1u << 2;
602 static const unsigned s_hashFlagIsAtomic = 1u << 2; 501 static const unsigned s_hashFlagIsAtomic = 1u << 1;
603 static const unsigned s_hashFlag8BitBuffer = 1u << 1; 502 static const unsigned s_hashFlag8BitBuffer = 1u << 0;
604 static const unsigned s_hashMaskBufferOwnership = 1u;
605 503
606 #ifdef STRING_STATS 504 #ifdef STRING_STATS
607 static StringStats m_stringStats; 505 static StringStats m_stringStats;
608 #endif 506 #endif
609 507
610 public: 508 public:
611 struct StaticASCIILiteral { 509 struct StaticASCIILiteral {
612 // These member variables must match the layout of StringImpl. 510 // These member variables must match the layout of StringImpl.
613 const LChar* m_data8; 511 const LChar* m_data8;
614 unsigned m_refCount; 512 unsigned m_refCount;
615 unsigned m_length; 513 unsigned m_length;
616 unsigned m_hashAndFlags; 514 unsigned m_hashAndFlags;
617 515
618 static const unsigned s_initialRefCount = s_refCountFlagIsStaticString; 516 static const unsigned s_initialRefCount = s_refCountFlagIsStaticString;
619 static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInte rnal; 517 static const unsigned s_initialFlags = s_hashFlag8BitBuffer;
620 static const unsigned s_hashShift = s_flagCount; 518 static const unsigned s_hashShift = s_flagCount;
621 }; 519 };
622 520
623 #ifndef NDEBUG 521 #ifndef NDEBUG
624 void assertHashIsCorrect() 522 void assertHashIsCorrect()
625 { 523 {
626 ASSERT(hasHash()); 524 ASSERT(hasHash());
627 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac ters8(), length())); 525 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac ters8(), length()));
628 } 526 }
629 #endif 527 #endif
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 } 828 }
931 829
932 using WTF::StringImpl; 830 using WTF::StringImpl;
933 using WTF::equal; 831 using WTF::equal;
934 using WTF::equalNonNull; 832 using WTF::equalNonNull;
935 using WTF::TextCaseSensitivity; 833 using WTF::TextCaseSensitivity;
936 using WTF::TextCaseSensitive; 834 using WTF::TextCaseSensitive;
937 using WTF::TextCaseInsensitive; 835 using WTF::TextCaseInsensitive;
938 836
939 #endif 837 #endif
OLDNEW
« no previous file with comments | « Source/wtf/text/StringBuffer.h ('k') | Source/wtf/text/StringImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698