diff options
Diffstat (limited to 'Source/WTF')
| -rw-r--r-- | Source/WTF/wtf/text/StringImpl.cpp | 38 | ||||
| -rw-r--r-- | Source/WTF/wtf/text/StringImpl.h | 42 | ||||
| -rw-r--r-- | Source/WTF/wtf/text/WTFString.cpp | 10 | ||||
| -rw-r--r-- | Source/WTF/wtf/text/WTFString.h | 1 |
4 files changed, 71 insertions, 20 deletions
diff --git a/Source/WTF/wtf/text/StringImpl.cpp b/Source/WTF/wtf/text/StringImpl.cpp index d1a3b56e8..5e6533e64 100644 --- a/Source/WTF/wtf/text/StringImpl.cpp +++ b/Source/WTF/wtf/text/StringImpl.cpp @@ -158,7 +158,7 @@ PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters, uns { ASSERT_WITH_MESSAGE(length, "Use StringImpl::empty() to create an empty string"); ASSERT(charactersAreAllASCII<LChar>(reinterpret_cast<const LChar*>(characters), length)); - return adoptRef(new StringImpl(reinterpret_cast<const LChar*>(characters), length, ConstructWithoutCopying)); + return adoptRef(new StringImpl(reinterpret_cast<const LChar*>(characters), length, DoesHaveTerminatingNullCharacter, ConstructWithoutCopying)); } PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters) @@ -166,20 +166,20 @@ PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters) return createFromLiteral(characters, strlen(characters)); } -PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length) +PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter) { if (!length) return empty(); - return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying)); + return adoptRef(new StringImpl(characters, length, hasTerminatingNullCharacter, ConstructWithoutCopying)); } -PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const LChar* characters, unsigned length) +PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const LChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter) { if (!length) return empty(); - return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying)); + return adoptRef(new StringImpl(characters, length, hasTerminatingNullCharacter, ConstructWithoutCopying)); } template <typename CharType> @@ -315,6 +315,8 @@ const UChar* StringImpl::getData16SlowCase() const STRING_STATS_ADD_UPCONVERTED_STRING(m_length); unsigned len = length(); + if (hasTerminatingNullCharacter()) + ++len; m_copyData16 = static_cast<UChar*>(fastMalloc(len * sizeof(UChar))); @@ -1935,6 +1937,30 @@ PassRefPtr<StringImpl> StringImpl::adopt(QStringData* qStringData) } #endif +PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string) +{ + // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer + // get allocated in a single memory block. + unsigned length = string.m_length; + if (length >= numeric_limits<unsigned>::max()) + CRASH(); + RefPtr<StringImpl> terminatedString; + if (string.is8Bit()) { + LChar* data; + terminatedString = createUninitialized(length + 1, data); + memcpy(data, string.m_data8, length * sizeof(LChar)); + data[length] = 0; + } else { + UChar* data; + terminatedString = createUninitialized(length + 1, data); + memcpy(data, string.m_data16, length * sizeof(UChar)); + data[length] = 0; + } + --(terminatedString->m_length); + terminatedString->m_hashAndFlags = (string.m_hashAndFlags & (~s_flagMask | s_hashFlag8BitBuffer)) | s_hashFlagHasTerminatingNullCharacter; + return terminatedString.release(); +} + size_t StringImpl::sizeInBytes() const { // FIXME: support substrings @@ -1942,6 +1968,8 @@ size_t StringImpl::sizeInBytes() const if (is8Bit()) { if (has16BitShadow()) { size += 2 * size; + if (hasTerminatingNullCharacter()) + size += 2; } } else size *= 2; diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h index 0d6c358a4..a0dd3021c 100644 --- a/Source/WTF/wtf/text/StringImpl.h +++ b/Source/WTF/wtf/text/StringImpl.h @@ -73,6 +73,12 @@ enum TextCaseSensitivity { TextCaseInsensitive }; +enum HasTerminatingNullCharacter { + DoesNotHaveTerminatingNullCharacter, + DoesHaveTerminatingNullCharacter, +}; + + typedef bool (*CharacterMatchFunctionPtr)(UChar); typedef bool (*IsWhiteSpaceFunctionPtr)(UChar); @@ -243,28 +249,30 @@ private: } enum ConstructWithoutCopyingTag { ConstructWithoutCopying }; - StringImpl(const UChar* characters, unsigned length, ConstructWithoutCopyingTag) + StringImpl(const UChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter, ConstructWithoutCopyingTag) : m_refCount(s_refCountIncrement) , m_length(length) , m_data16(characters) , m_buffer(0) - , m_hashAndFlags(BufferInternal) + , m_hashAndFlags(BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0)) { ASSERT(m_data16); ASSERT(m_length); + ASSERT(!(m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter) || !characters[length]); STRING_STATS_ADD_16BIT_STRING(0); } - StringImpl(const LChar* characters, unsigned length, ConstructWithoutCopyingTag) + StringImpl(const LChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter, ConstructWithoutCopyingTag) : m_refCount(s_refCountIncrement) , m_length(length) , m_data8(characters) , m_buffer(0) - , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) + , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0)) { ASSERT(m_data8); ASSERT(m_length); + ASSERT(!(m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter) || !characters[length]); STRING_STATS_ADD_8BIT_STRING(0); } @@ -413,15 +421,15 @@ public: COMPILE_ASSERT(charactersCount > 1, StringImplFromLiteralNotEmpty); COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), StringImplFromLiteralCannotOverflow); - return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1); + return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1, DoesHaveTerminatingNullCharacter); } // FIXME: Transition off of these functions to createWithoutCopying instead. WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters, unsigned length); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters); - WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const UChar* characters, unsigned length); - WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const LChar* characters, unsigned length); + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const UChar* characters, unsigned length, HasTerminatingNullCharacter); + WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const LChar* characters, unsigned length, HasTerminatingNullCharacter); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data); WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data); @@ -460,6 +468,7 @@ public: static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); } static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; } static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); } + static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); template<typename CharType, size_t inlineCapacity, typename OverflowHandler> static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity, OverflowHandler>& vector) @@ -529,6 +538,8 @@ public: return !length() && !isStatic(); } + bool hasTerminatingNullCharacter() const { return m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter; } + bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } void setIsAtomic(bool isAtomic) { @@ -778,13 +789,14 @@ private: static const unsigned s_refCountFlagIsStaticString = 0x1; static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag. - // The bottom 7 bits in the hash are flags. - static const unsigned s_flagCount = 7; + // The bottom 8 bits in the hash are flags. + static const unsigned s_flagCount = 8; static const unsigned s_flagMask = (1u << s_flagCount) - 1; - COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); + COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); - static const unsigned s_hashFlagHas16BitShadow = 1u << 6; - static const unsigned s_hashFlag8BitBuffer = 1u << 5; + static const unsigned s_hashFlagHas16BitShadow = 1u << 7; + static const unsigned s_hashFlag8BitBuffer = 1u << 6; + static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5; static const unsigned s_hashFlagIsAtomic = 1u << 4; static const unsigned s_hashFlagDidReportCost = 1u << 3; static const unsigned s_hashFlagIsIdentifier = 1u << 2; @@ -805,7 +817,7 @@ public: // These values mimic ConstructFromLiteral. static const unsigned s_initialRefCount = s_refCountIncrement; - static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInternal; + static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInternal | s_hashFlagHasTerminatingNullCharacter; static const unsigned s_hashShift = s_flagCount; }; @@ -1330,8 +1342,8 @@ inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const { if (!requiresCopy()) { if (is8Bit()) - return StringImpl::createWithoutCopying(m_data8, m_length); - return StringImpl::createWithoutCopying(m_data16, m_length); + return StringImpl::createWithoutCopying(m_data8, m_length, hasTerminatingNullCharacter() ? DoesHaveTerminatingNullCharacter : DoesNotHaveTerminatingNullCharacter); + return StringImpl::createWithoutCopying(m_data16, m_length, hasTerminatingNullCharacter() ? DoesHaveTerminatingNullCharacter : DoesNotHaveTerminatingNullCharacter); } if (is8Bit()) diff --git a/Source/WTF/wtf/text/WTFString.cpp b/Source/WTF/wtf/text/WTFString.cpp index 29c13c10d..a61fe103f 100644 --- a/Source/WTF/wtf/text/WTFString.cpp +++ b/Source/WTF/wtf/text/WTFString.cpp @@ -409,6 +409,16 @@ Vector<UChar> String::charactersWithNullTermination() const return result; } +const UChar* String::deprecatedCharactersWithNullTermination() +{ + if (!m_impl) + return 0; + if (m_impl->hasTerminatingNullCharacter()) + return m_impl->characters(); + m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl); + return m_impl->characters(); +} + String String::format(const char *format, ...) { #if PLATFORM(QT) diff --git a/Source/WTF/wtf/text/WTFString.h b/Source/WTF/wtf/text/WTFString.h index 1c8e9097e..63feb0fa1 100644 --- a/Source/WTF/wtf/text/WTFString.h +++ b/Source/WTF/wtf/text/WTFString.h @@ -282,6 +282,7 @@ public: { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); } WTF_EXPORT_STRING_API Vector<UChar> charactersWithNullTermination() const; + WTF_EXPORT_STRING_API const UChar* deprecatedCharactersWithNullTermination(); WTF_EXPORT_STRING_API UChar32 characterStartingAt(unsigned) const; // Ditto. |
