summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/JSStringJoiner.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSStringJoiner.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/JSStringJoiner.cpp145
1 files changed, 67 insertions, 78 deletions
diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
index 7e20d2195..57ffdd929 100644
--- a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
+++ b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,105 +26,94 @@
#include "config.h"
#include "JSStringJoiner.h"
-#include "ExceptionHelpers.h"
-#include "JSScope.h"
-#include "JSString.h"
-#include "Operations.h"
-#include <wtf/text/StringImpl.h>
+#include "JSCInlines.h"
namespace JSC {
-// The destination is 16bits, at least one string is 16 bits.
-static inline void appendStringToData(UChar*& data, const String& string)
+template<typename CharacterType>
+static inline void appendStringToData(CharacterType*& data, StringView string)
{
- if (string.isNull())
- return;
+ string.getCharactersWithUpconvert(data);
+ data += string.length();
+}
- unsigned length = string.length();
- const StringImpl* stringImpl = string.impl();
+template<typename CharacterType>
+static inline String joinStrings(const Vector<StringViewWithUnderlyingString>& strings, StringView separator, unsigned joinedLength)
+{
+ ASSERT(joinedLength);
- if (stringImpl->is8Bit()) {
- for (unsigned i = 0; i < length; ++i) {
- *data = stringImpl->characters8()[i];
- ++data;
+ CharacterType* data;
+ String result = StringImpl::tryCreateUninitialized(joinedLength, data);
+ if (result.isNull())
+ return result;
+
+ appendStringToData(data, strings[0].view);
+
+ unsigned size = strings.size();
+
+ switch (separator.length()) {
+ case 0:
+ for (unsigned i = 1; i < size; ++i)
+ appendStringToData(data, strings[i].view);
+ break;
+ case 1: {
+ CharacterType separatorCharacter = separator[0];
+ for (unsigned i = 1; i < size; ++i) {
+ *data++ = separatorCharacter;
+ appendStringToData(data, strings[i].view);
}
- } else {
- for (unsigned i = 0; i < length; ++i) {
- *data = stringImpl->characters16()[i];
- ++data;
+ break;
+ }
+ default:
+ for (unsigned i = 1; i < size; ++i) {
+ appendStringToData(data, separator);
+ appendStringToData(data, strings[i].view);
}
}
+ ASSERT(data == result.characters<CharacterType>() + joinedLength);
+
+ return result;
}
-// If the destination is 8bits, we know every string has to be 8bit.
-static inline void appendStringToData(LChar*& data, const String& string)
+inline unsigned JSStringJoiner::joinedLength(ExecState& state) const
{
- if (string.isNull())
- return;
- ASSERT(string.is8Bit());
-
- unsigned length = string.length();
- const StringImpl* stringImpl = string.impl();
-
- for (unsigned i = 0; i < length; ++i) {
- *data = stringImpl->characters8()[i];
- ++data;
+ unsigned numberOfStrings = m_strings.size();
+ if (!numberOfStrings)
+ return 0;
+
+ Checked<unsigned, RecordOverflow> separatorLength = m_separator.length();
+ Checked<unsigned, RecordOverflow> totalSeparatorsLength = separatorLength * (numberOfStrings - 1);
+ Checked<unsigned, RecordOverflow> totalLength = totalSeparatorsLength + m_accumulatedStringsLength;
+
+ unsigned result;
+ if (totalLength.safeGet(result) == CheckedState::DidOverflow) {
+ throwOutOfMemoryError(&state);
+ return 0;
}
+ return result;
}
-template<typename CharacterType>
-static inline PassRefPtr<StringImpl> joinStrings(const Vector<String>& strings, const String& separator, unsigned outputLength)
+JSValue JSStringJoiner::join(ExecState& state)
{
- ASSERT(outputLength);
-
- CharacterType* data;
- RefPtr<StringImpl> outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data);
- if (!outputStringImpl)
- return PassRefPtr<StringImpl>();
+ ASSERT(m_strings.size() <= m_strings.capacity());
- const String firstString = strings.first();
- appendStringToData(data, firstString);
+ unsigned length = joinedLength(state);
+ if (state.hadException())
+ return jsUndefined();
- for (size_t i = 1; i < strings.size(); ++i) {
- appendStringToData(data, separator);
- appendStringToData(data, strings[i]);
- }
-
- ASSERT(data == (outputStringImpl->getCharacters<CharacterType>() + outputStringImpl->length()));
- return outputStringImpl.release();
-}
+ if (!length)
+ return jsEmptyString(&state);
-JSValue JSStringJoiner::join(ExecState* exec)
-{
- if (!m_isValid)
- return throwOutOfMemoryError(exec);
-
- if (!m_strings.size())
- return jsEmptyString(exec);
-
- Checked<size_t, RecordOverflow> separatorLength = m_separator.length();
- // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1).
- ASSERT(m_strings.size() > 0);
- Checked<size_t, RecordOverflow> totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
- Checked<size_t, RecordOverflow> outputStringSize = totalSeparactorsLength + m_accumulatedStringsLength;
-
- size_t finalSize;
- if (outputStringSize.safeGet(finalSize) == CheckedState::DidOverflow)
- return throwOutOfMemoryError(exec);
-
- if (!outputStringSize)
- return jsEmptyString(exec);
-
- RefPtr<StringImpl> outputStringImpl;
- if (m_is8Bits)
- outputStringImpl = joinStrings<LChar>(m_strings, m_separator, finalSize);
+ String result;
+ if (m_isAll8Bit)
+ result = joinStrings<LChar>(m_strings, m_separator, length);
else
- outputStringImpl = joinStrings<UChar>(m_strings, m_separator, finalSize);
+ result = joinStrings<UChar>(m_strings, m_separator, length);
- if (!outputStringImpl)
- return throwOutOfMemoryError(exec);
+ if (result.isNull())
+ return throwOutOfMemoryError(&state);
- return JSString::create(exec->vm(), outputStringImpl.release());
+ return jsString(&state, WTFMove(result));
}
}