summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/wtf/text
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/wtf/text')
-rw-r--r--JavaScriptCore/wtf/text/CString.cpp4
-rw-r--r--JavaScriptCore/wtf/text/CString.h10
-rw-r--r--JavaScriptCore/wtf/text/StringBuffer.h17
-rw-r--r--JavaScriptCore/wtf/text/StringBuilder.cpp172
-rw-r--r--JavaScriptCore/wtf/text/StringBuilder.h139
-rw-r--r--JavaScriptCore/wtf/text/StringConcatenate.h467
-rw-r--r--JavaScriptCore/wtf/text/StringHash.h95
-rw-r--r--JavaScriptCore/wtf/text/StringImpl.cpp2
-rw-r--r--JavaScriptCore/wtf/text/StringImpl.h6
-rw-r--r--JavaScriptCore/wtf/text/WTFString.cpp12
10 files changed, 824 insertions, 100 deletions
diff --git a/JavaScriptCore/wtf/text/CString.cpp b/JavaScriptCore/wtf/text/CString.cpp
index 7d09f12..c048a1b 100644
--- a/JavaScriptCore/wtf/text/CString.cpp
+++ b/JavaScriptCore/wtf/text/CString.cpp
@@ -36,12 +36,12 @@ CString::CString(const char* str)
init(str, strlen(str));
}
-CString::CString(const char* str, unsigned length)
+CString::CString(const char* str, size_t length)
{
init(str, length);
}
-void CString::init(const char* str, unsigned length)
+void CString::init(const char* str, size_t length)
{
if (!str)
return;
diff --git a/JavaScriptCore/wtf/text/CString.h b/JavaScriptCore/wtf/text/CString.h
index d8250c5..343a7a5 100644
--- a/JavaScriptCore/wtf/text/CString.h
+++ b/JavaScriptCore/wtf/text/CString.h
@@ -40,8 +40,8 @@ public:
private:
friend class CString;
- static PassRefPtr<CStringBuffer> create(unsigned length) { return adoptRef(new CStringBuffer(length)); }
- CStringBuffer(unsigned length) : m_vector(length) { }
+ static PassRefPtr<CStringBuffer> create(size_t length) { return adoptRef(new CStringBuffer(length)); }
+ CStringBuffer(size_t length) : m_vector(length) { }
char* mutableData() { return m_vector.data(); }
Vector<char> m_vector;
@@ -53,7 +53,7 @@ class CString {
public:
CString() { }
CString(const char*);
- CString(const char*, unsigned length);
+ CString(const char*, size_t length);
CString(CStringBuffer* buffer) : m_buffer(buffer) { }
static CString newUninitialized(size_t length, char*& characterBuffer);
@@ -62,7 +62,7 @@ public:
return m_buffer ? m_buffer->data() : 0;
}
char* mutableData();
- unsigned length() const
+ size_t length() const
{
return m_buffer ? m_buffer->length() - 1 : 0;
}
@@ -73,7 +73,7 @@ public:
private:
void copyBufferIfNeeded();
- void init(const char*, unsigned length);
+ void init(const char*, size_t length);
RefPtr<CStringBuffer> m_buffer;
};
diff --git a/JavaScriptCore/wtf/text/StringBuffer.h b/JavaScriptCore/wtf/text/StringBuffer.h
index c29dd79..a546bf3 100644
--- a/JavaScriptCore/wtf/text/StringBuffer.h
+++ b/JavaScriptCore/wtf/text/StringBuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +32,7 @@
#include <wtf/Assertions.h>
#include <wtf/Noncopyable.h>
#include <wtf/unicode/Unicode.h>
+#include <limits>
namespace WTF {
@@ -39,9 +40,12 @@ class StringBuffer : public Noncopyable {
public:
explicit StringBuffer(unsigned length)
: m_length(length)
- , m_data(static_cast<UChar*>(fastMalloc(length * sizeof(UChar))))
{
+ if (m_length > std::numeric_limits<unsigned>::max() / sizeof(UChar))
+ CRASH();
+ m_data = static_cast<UChar*>(fastMalloc(m_length * sizeof(UChar)));
}
+
~StringBuffer()
{
fastFree(m_data);
@@ -55,8 +59,11 @@ public:
void resize(unsigned newLength)
{
- if (newLength > m_length)
+ if (newLength > m_length) {
+ if (newLength > std::numeric_limits<unsigned>::max() / sizeof(UChar))
+ CRASH();
m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar)));
+ }
m_length = newLength;
}
@@ -72,8 +79,8 @@ private:
UChar* m_data;
};
-}
+} // namespace WTF
using WTF::StringBuffer;
-#endif
+#endif // StringBuffer_h
diff --git a/JavaScriptCore/wtf/text/StringBuilder.cpp b/JavaScriptCore/wtf/text/StringBuilder.cpp
new file mode 100644
index 0000000..dfc9ff3
--- /dev/null
+++ b/JavaScriptCore/wtf/text/StringBuilder.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StringBuilder.h"
+
+#include "WTFString.h"
+
+namespace WTF {
+
+void StringBuilder::reifyString()
+{
+ // Check if the string already exists.
+ if (!m_string.isNull()) {
+ ASSERT(m_string.length() == m_length);
+ return;
+ }
+
+ // Check for empty.
+ if (!m_length) {
+ m_string = StringImpl::empty();
+ return;
+ }
+
+ // Must be valid in the buffer, take a substring (unless string fills the buffer).
+ ASSERT(m_buffer && m_length <= m_buffer->length());
+ m_string = (m_length == m_buffer->length())
+ ? m_buffer.get()
+ : StringImpl::create(m_buffer, 0, m_length);
+}
+
+void StringBuilder::resize(unsigned newSize)
+{
+ // Check newSize < m_length, hence m_length > 0.
+ ASSERT(newSize <= m_length);
+ if (newSize == m_length)
+ return;
+ ASSERT(m_length);
+
+ // If there is a buffer, we only need to duplicate it if it has more than one ref.
+ if (m_buffer) {
+ if (!m_buffer->hasOneRef())
+ allocateBuffer(m_buffer->characters(), m_buffer->length());
+ m_length = newSize;
+ m_string = String();
+ return;
+ }
+
+ // Since m_length && !m_buffer, the string must be valid in m_string, and m_string.length() > 0.
+ ASSERT(!m_string.isEmpty());
+ ASSERT(m_length == m_string.length());
+ ASSERT(newSize < m_string.length());
+ m_length = newSize;
+ m_string = StringImpl::create(m_string.impl(), 0, newSize);
+}
+
+void StringBuilder::reserveCapacity(unsigned newCapacity)
+{
+ if (m_buffer) {
+ // If there is already a buffer, then grow if necessary.
+ if (newCapacity > m_buffer->length())
+ allocateBuffer(m_buffer->characters(), newCapacity);
+ } else {
+ // Grow the string, if necessary.
+ if (newCapacity > m_length)
+ allocateBuffer(m_string.characters(), newCapacity);
+ }
+}
+
+// Allocate a new buffer, copying in currentCharacters (these may come from either m_string
+// or m_buffer, neither will be reassigned until the copy has completed).
+void StringBuilder::allocateBuffer(const UChar* currentCharacters, unsigned requiredLength)
+{
+ // Copy the existing data into a new buffer, set result to point to the end of the existing data.
+ RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters);
+ memcpy(m_bufferCharacters, currentCharacters, static_cast<size_t>(m_length) * sizeof(UChar)); // This can't overflow.
+
+ // Update the builder state.
+ m_buffer = buffer.release();
+ m_string = String();
+}
+
+// Make 'length' additional capacity be available in m_buffer, update m_string & m_length,
+// return a pointer to the newly allocated storage.
+UChar* StringBuilder::appendUninitialized(unsigned length)
+{
+ ASSERT(length);
+
+ // Calcuate the new size of the builder after appending.
+ unsigned requiredLength = length + m_length;
+ if (requiredLength < length)
+ CRASH();
+
+ if (m_buffer) {
+ // If the buffer is valid it must be at least as long as the current builder contents!
+ ASSERT(m_buffer->length() >= m_length);
+
+ // Check if the buffer already has sufficient capacity.
+ if (requiredLength <= m_buffer->length()) {
+ unsigned currentLength = m_length;
+ m_string = String();
+ m_length = requiredLength;
+ return m_bufferCharacters + currentLength;
+ }
+
+ // We need to realloc the buffer.
+ allocateBuffer(m_buffer->characters(), std::max(requiredLength, m_buffer->length() * 2));
+ } else {
+ ASSERT(m_string.length() == m_length);
+ allocateBuffer(m_string.characters(), std::max(requiredLength, requiredLength * 2));
+ }
+
+ UChar* result = m_bufferCharacters + m_length;
+ m_length = requiredLength;
+ return result;
+}
+
+void StringBuilder::append(const UChar* characters, unsigned length)
+{
+ if (!length)
+ return;
+ ASSERT(characters);
+
+ memcpy(appendUninitialized(length), characters, static_cast<size_t>(length) * 2);
+}
+
+void StringBuilder::append(const char* characters, unsigned length)
+{
+ if (!length)
+ return;
+ ASSERT(characters);
+
+ UChar* dest = appendUninitialized(length);
+ const char* end = characters + length;
+ while (characters < end)
+ *(dest++) = *(const unsigned char*)(characters++);
+}
+
+void StringBuilder::shrinkToFit()
+{
+ // If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic!
+ if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) {
+ UChar* result;
+ m_string = StringImpl::createUninitialized(m_length, result);
+ memcpy(result, m_buffer->characters(), static_cast<size_t>(m_length) * 2); // This can't overflow.
+ m_buffer = 0;
+ }
+}
+
+} // namespace WTF
diff --git a/JavaScriptCore/wtf/text/StringBuilder.h b/JavaScriptCore/wtf/text/StringBuilder.h
new file mode 100644
index 0000000..f10af64
--- /dev/null
+++ b/JavaScriptCore/wtf/text/StringBuilder.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StringBuilder_h
+#define StringBuilder_h
+
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+class StringBuilder {
+public:
+ StringBuilder()
+ : m_length(0)
+ {
+ }
+
+ void append(const UChar*, unsigned);
+ void append(const char*, unsigned);
+
+ void append(const String& string)
+ {
+ // If we're appending to an empty string, and there is not buffer
+ // (in case reserveCapacity has been called) then just retain the
+ // string.
+ if (!m_length && !m_buffer) {
+ m_string = string;
+ m_length = string.length();
+ return;
+ }
+ append(string.characters(), string.length());
+ }
+
+ void append(const char* characters)
+ {
+ if (characters)
+ append(characters, strlen(characters));
+ }
+
+ void append(UChar c)
+ {
+ if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
+ m_bufferCharacters[m_length++] = c;
+ else
+ append(&c, 1);
+ }
+
+ void append(char c)
+ {
+ if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
+ m_bufferCharacters[m_length++] = (unsigned char)c;
+ else
+ append(&c, 1);
+ }
+
+ String toString()
+ {
+ if (m_string.isNull()) {
+ shrinkToFit();
+ reifyString();
+ }
+ return m_string;
+ }
+
+ String toStringPreserveCapacity()
+ {
+ if (m_string.isNull())
+ reifyString();
+ return m_string;
+ }
+
+ unsigned length() const
+ {
+ return m_length;
+ }
+
+ bool isEmpty() const { return !length(); }
+
+ void reserveCapacity(unsigned newCapacity);
+
+ void resize(unsigned newSize);
+
+ void shrinkToFit();
+
+ UChar operator[](unsigned i) const
+ {
+ ASSERT(i < m_length);
+ if (!m_string.isNull())
+ return m_string[i];
+ ASSERT(m_buffer);
+ return m_buffer->characters()[i];
+ }
+
+ void clear()
+ {
+ m_length = 0;
+ m_string = String();
+ m_buffer = 0;
+ }
+
+private:
+ void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
+ UChar* appendUninitialized(unsigned length);
+ void reifyString();
+
+ unsigned m_length;
+ String m_string;
+ RefPtr<StringImpl> m_buffer;
+ UChar* m_bufferCharacters;
+};
+
+} // namespace WTF
+
+using WTF::StringBuilder;
+
+#endif // StringBuilder_h
diff --git a/JavaScriptCore/wtf/text/StringConcatenate.h b/JavaScriptCore/wtf/text/StringConcatenate.h
new file mode 100644
index 0000000..b54a108
--- /dev/null
+++ b/JavaScriptCore/wtf/text/StringConcatenate.h
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StringConcatenate_h
+#define StringConcatenate_h
+
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+template<typename StringType>
+class StringTypeAdapter {
+};
+
+template<>
+class StringTypeAdapter<char> {
+public:
+ StringTypeAdapter<char>(char buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+ unsigned length() { return 1; }
+ void writeTo(UChar* destination) { *destination = m_buffer; }
+
+private:
+ unsigned char m_buffer;
+};
+
+template<>
+class StringTypeAdapter<UChar> {
+public:
+ StringTypeAdapter<UChar>(UChar buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+ unsigned length() { return 1; }
+ void writeTo(UChar* destination) { *destination = m_buffer; }
+
+private:
+ UChar m_buffer;
+};
+
+template<>
+class StringTypeAdapter<char*> {
+public:
+ StringTypeAdapter<char*>(char* buffer)
+ : m_buffer((unsigned char*)buffer)
+ , m_length(strlen(buffer))
+ {
+ }
+
+ unsigned length() { return m_length; }
+
+ void writeTo(UChar* destination)
+ {
+ for (unsigned i = 0; i < m_length; ++i)
+ destination[i] = m_buffer[i];
+ }
+
+private:
+ const unsigned char* m_buffer;
+ unsigned m_length;
+};
+
+template<>
+class StringTypeAdapter<const char*> {
+public:
+ StringTypeAdapter<const char*>(const char* buffer)
+ : m_buffer((unsigned char*)buffer)
+ , m_length(strlen(buffer))
+ {
+ }
+
+ unsigned length() { return m_length; }
+
+ void writeTo(UChar* destination)
+ {
+ for (unsigned i = 0; i < m_length; ++i)
+ destination[i] = m_buffer[i];
+ }
+
+private:
+ const unsigned char* m_buffer;
+ unsigned m_length;
+};
+
+template<>
+class StringTypeAdapter<String> {
+public:
+ StringTypeAdapter<String>(String& string)
+ : m_data(string.characters())
+ , m_length(string.length())
+ {
+ }
+
+ unsigned length() { return m_length; }
+
+ void writeTo(UChar* destination)
+ {
+ for (unsigned i = 0; i < m_length; ++i)
+ destination[i] = m_data[i];
+ }
+
+private:
+ const UChar* m_data;
+ unsigned m_length;
+};
+
+inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
+{
+ unsigned oldTotal = total;
+ total = oldTotal + addend;
+ if (total < oldTotal)
+ overflow = true;
+}
+
+template<typename StringType1, typename StringType2>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+
+ UChar* buffer = 0;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+ StringTypeAdapter<StringType4> adapter4(string4);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ sumWithOverflow(length, adapter4.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+ result += adapter3.length();
+ adapter4.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+ StringTypeAdapter<StringType4> adapter4(string4);
+ StringTypeAdapter<StringType5> adapter5(string5);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ sumWithOverflow(length, adapter4.length(), overflow);
+ sumWithOverflow(length, adapter5.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+ result += adapter3.length();
+ adapter4.writeTo(result);
+ result += adapter4.length();
+ adapter5.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+ StringTypeAdapter<StringType4> adapter4(string4);
+ StringTypeAdapter<StringType5> adapter5(string5);
+ StringTypeAdapter<StringType6> adapter6(string6);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ sumWithOverflow(length, adapter4.length(), overflow);
+ sumWithOverflow(length, adapter5.length(), overflow);
+ sumWithOverflow(length, adapter6.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+ result += adapter3.length();
+ adapter4.writeTo(result);
+ result += adapter4.length();
+ adapter5.writeTo(result);
+ result += adapter5.length();
+ adapter6.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+ StringTypeAdapter<StringType4> adapter4(string4);
+ StringTypeAdapter<StringType5> adapter5(string5);
+ StringTypeAdapter<StringType6> adapter6(string6);
+ StringTypeAdapter<StringType7> adapter7(string7);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ sumWithOverflow(length, adapter4.length(), overflow);
+ sumWithOverflow(length, adapter5.length(), overflow);
+ sumWithOverflow(length, adapter6.length(), overflow);
+ sumWithOverflow(length, adapter7.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+ result += adapter3.length();
+ adapter4.writeTo(result);
+ result += adapter4.length();
+ adapter5.writeTo(result);
+ result += adapter5.length();
+ adapter6.writeTo(result);
+ result += adapter6.length();
+ adapter7.writeTo(result);
+
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+{
+ StringTypeAdapter<StringType1> adapter1(string1);
+ StringTypeAdapter<StringType2> adapter2(string2);
+ StringTypeAdapter<StringType3> adapter3(string3);
+ StringTypeAdapter<StringType4> adapter4(string4);
+ StringTypeAdapter<StringType5> adapter5(string5);
+ StringTypeAdapter<StringType6> adapter6(string6);
+ StringTypeAdapter<StringType7> adapter7(string7);
+ StringTypeAdapter<StringType8> adapter8(string8);
+
+ UChar* buffer;
+ bool overflow = false;
+ unsigned length = adapter1.length();
+ sumWithOverflow(length, adapter2.length(), overflow);
+ sumWithOverflow(length, adapter3.length(), overflow);
+ sumWithOverflow(length, adapter4.length(), overflow);
+ sumWithOverflow(length, adapter5.length(), overflow);
+ sumWithOverflow(length, adapter6.length(), overflow);
+ sumWithOverflow(length, adapter7.length(), overflow);
+ sumWithOverflow(length, adapter8.length(), overflow);
+ if (overflow)
+ return 0;
+ PassRefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+ if (!resultImpl)
+ return 0;
+
+ UChar* result = buffer;
+ adapter1.writeTo(result);
+ result += adapter1.length();
+ adapter2.writeTo(result);
+ result += adapter2.length();
+ adapter3.writeTo(result);
+ result += adapter3.length();
+ adapter4.writeTo(result);
+ result += adapter4.length();
+ adapter5.writeTo(result);
+ result += adapter5.length();
+ adapter6.writeTo(result);
+ result += adapter6.length();
+ adapter7.writeTo(result);
+ result += adapter7.length();
+ adapter8.writeTo(result);
+
+ return resultImpl;
+}
+
+// Convenience only.
+template<typename StringType1>
+String makeString(StringType1 string1)
+{
+ return String(string1);
+}
+
+template<typename StringType1, typename StringType2>
+String makeString(StringType1 string1, StringType2 string2)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+{
+ PassRefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
+ if (!resultImpl)
+ CRASH();
+ return resultImpl;
+}
+
+} // namespace WTF
+
+using WTF::makeString;
+
+#endif
diff --git a/JavaScriptCore/wtf/text/StringHash.h b/JavaScriptCore/wtf/text/StringHash.h
index bfd05eb..d7aabdb 100644
--- a/JavaScriptCore/wtf/text/StringHash.h
+++ b/JavaScriptCore/wtf/text/StringHash.h
@@ -26,7 +26,7 @@
#include "WTFString.h"
#include <wtf/Forward.h>
#include <wtf/HashTraits.h>
-#include <wtf/StringHashFunctions.h>
+#include <wtf/StringHasher.h>
#include <wtf/unicode/Unicode.h>
namespace WTF {
@@ -97,99 +97,26 @@ namespace WTF {
class CaseFoldingHash {
public:
- // Paul Hsieh's SuperFastHash
- // http://www.azillionmonkeys.com/qed/hash.html
+ template<typename T> static inline UChar foldCase(T ch)
+ {
+ return WTF::Unicode::foldCase(ch);
+ }
+
static unsigned hash(const UChar* data, unsigned length)
{
- unsigned l = length;
- const UChar* s = data;
- uint32_t hash = WTF::stringHashingStartValue;
- uint32_t tmp;
-
- int rem = l & 1;
- l >>= 1;
-
- // Main loop.
- for (; l > 0; l--) {
- hash += WTF::Unicode::foldCase(s[0]);
- tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case.
- if (rem) {
- hash += WTF::Unicode::foldCase(s[0]);
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits.
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // This avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked.
- hash |= !hash << 31;
-
- return hash;
+ return StringHasher::createHash<UChar, foldCase<UChar> >(data, length);
}
static unsigned hash(StringImpl* str)
{
return hash(str->characters(), str->length());
}
-
- static unsigned hash(const char* str, unsigned length)
- {
- // This hash is designed to work on 16-bit chunks at a time. But since the normal case
- // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
- // were 16-bit chunks, which will give matching results.
- unsigned l = length;
- const char* s = str;
- uint32_t hash = WTF::stringHashingStartValue;
- uint32_t tmp;
-
- int rem = l & 1;
- l >>= 1;
-
- // Main loop
- for (; l > 0; l--) {
- hash += WTF::Unicode::foldCase(s[0]);
- tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Handle end case
- if (rem) {
- hash += WTF::Unicode::foldCase(s[0]);
- hash ^= hash << 11;
- hash += hash >> 17;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- hash |= !hash << 31;
-
- return hash;
+ static unsigned hash(const char* data, unsigned length)
+ {
+ return StringHasher::createHash<char, foldCase<char> >(data, length);
}
-
+
static bool equal(const StringImpl* a, const StringImpl* b)
{
if (a == b)
diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp
index 7822c00..e1e08ee 100644
--- a/JavaScriptCore/wtf/text/StringImpl.cpp
+++ b/JavaScriptCore/wtf/text/StringImpl.cpp
@@ -81,7 +81,7 @@ PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*&
// Allocate a single buffer large enough to contain the StringImpl
// struct as well as the data which it contains. This removes one
// heap allocation from this call.
- if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar)))
+ if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)))
CRASH();
size_t size = sizeof(StringImpl) + length * sizeof(UChar);
StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h
index 7025d9f..897751d 100644
--- a/JavaScriptCore/wtf/text/StringImpl.h
+++ b/JavaScriptCore/wtf/text/StringImpl.h
@@ -29,7 +29,7 @@
#include <wtf/Forward.h>
#include <wtf/OwnFastMallocPtr.h>
#include <wtf/StdLibExtras.h>
-#include <wtf/StringHashFunctions.h>
+#include <wtf/StringHasher.h>
#include <wtf/Vector.h>
#include <wtf/text/StringImplBase.h>
#include <wtf/unicode/Unicode.h>
@@ -165,7 +165,7 @@ public:
return empty();
}
- if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar))) {
+ if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) {
output = 0;
return 0;
}
@@ -187,6 +187,8 @@ public:
{
if (size_t size = vector.size()) {
ASSERT(vector.data());
+ if (size > std::numeric_limits<unsigned>::max())
+ CRASH();
return adoptRef(new StringImpl(vector.releaseBuffer(), size));
}
return empty();
diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp
index 9b53e81..5161477 100644
--- a/JavaScriptCore/wtf/text/WTFString.cpp
+++ b/JavaScriptCore/wtf/text/WTFString.cpp
@@ -48,9 +48,12 @@ String::String(const UChar* str)
if (!str)
return;
- int len = 0;
+ size_t len = 0;
while (str[len] != UChar(0))
len++;
+
+ if (len > std::numeric_limits<unsigned>::max())
+ CRASH();
m_impl = StringImpl::create(str, len);
}
@@ -175,6 +178,8 @@ void String::append(const UChar* charactersToAppend, unsigned lengthToAppend)
ASSERT(charactersToAppend);
UChar* data;
+ if (lengthToAppend > std::numeric_limits<unsigned>::max() - length())
+ CRASH();
RefPtr<StringImpl> newImpl =
StringImpl::createUninitialized(length() + lengthToAppend, data);
memcpy(data, characters(), length() * sizeof(UChar));
@@ -196,6 +201,8 @@ void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, un
ASSERT(charactersToInsert);
UChar* data;
+ if (lengthToInsert > std::numeric_limits<unsigned>::max() - length())
+ CRASH();
RefPtr<StringImpl> newImpl =
StringImpl::createUninitialized(length() + lengthToInsert, data);
memcpy(data, characters(), position * sizeof(UChar));
@@ -718,6 +725,9 @@ CString String::utf8(bool strict) const
String String::fromUTF8(const char* stringStart, size_t length)
{
+ if (length > std::numeric_limits<unsigned>::max())
+ CRASH();
+
if (!stringStart)
return String();