From 6882a04fb36642862b11efe514251d32070c3d65 Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Thu, 25 Aug 2016 19:20:41 +0300 Subject: Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443) Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev --- Source/JavaScriptCore/runtime/JSStringJoiner.cpp | 145 +++++++++++------------ 1 file changed, 67 insertions(+), 78 deletions(-) (limited to 'Source/JavaScriptCore/runtime/JSStringJoiner.cpp') 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 +#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 +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 +static inline String joinStrings(const Vector& 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() + 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 separatorLength = m_separator.length(); + Checked totalSeparatorsLength = separatorLength * (numberOfStrings - 1); + Checked totalLength = totalSeparatorsLength + m_accumulatedStringsLength; + + unsigned result; + if (totalLength.safeGet(result) == CheckedState::DidOverflow) { + throwOutOfMemoryError(&state); + return 0; } + return result; } -template -static inline PassRefPtr joinStrings(const Vector& strings, const String& separator, unsigned outputLength) +JSValue JSStringJoiner::join(ExecState& state) { - ASSERT(outputLength); - - CharacterType* data; - RefPtr outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data); - if (!outputStringImpl) - return PassRefPtr(); + 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() + 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 separatorLength = m_separator.length(); - // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1). - ASSERT(m_strings.size() > 0); - Checked totalSeparactorsLength = separatorLength * (m_strings.size() - 1); - Checked outputStringSize = totalSeparactorsLength + m_accumulatedStringsLength; - - size_t finalSize; - if (outputStringSize.safeGet(finalSize) == CheckedState::DidOverflow) - return throwOutOfMemoryError(exec); - - if (!outputStringSize) - return jsEmptyString(exec); - - RefPtr outputStringImpl; - if (m_is8Bits) - outputStringImpl = joinStrings(m_strings, m_separator, finalSize); + String result; + if (m_isAll8Bit) + result = joinStrings(m_strings, m_separator, length); else - outputStringImpl = joinStrings(m_strings, m_separator, finalSize); + result = joinStrings(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)); } } -- cgit v1.2.1