summaryrefslogtreecommitdiff
path: root/Source/WTF
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WTF')
-rw-r--r--Source/WTF/wtf/text/StringImpl.cpp38
-rw-r--r--Source/WTF/wtf/text/StringImpl.h42
-rw-r--r--Source/WTF/wtf/text/WTFString.cpp10
-rw-r--r--Source/WTF/wtf/text/WTFString.h1
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.