diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/JSStringJoiner.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-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.cpp | 145 |
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)); } } |