diff options
author | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2017-05-30 12:48:17 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2017-05-30 12:48:17 +0200 |
commit | 881da28418d380042aa95a97f0cbd42560a64f7c (patch) | |
tree | a794dff3274695e99c651902dde93d934ea7a5af /Source/JavaScriptCore/runtime/JSStringJoiner.cpp | |
parent | 7e104c57a70fdf551bb3d22a5d637cdcbc69dbea (diff) | |
parent | 0fcedcd17cc00d3dd44c718b3cb36c1033319671 (diff) | |
download | qtwebkit-881da28418d380042aa95a97f0cbd42560a64f7c.tar.gz |
Merge 'wip/next' into dev
Change-Id: Iff9ee5e23bb326c4371ec8ed81d56f2f05d680e9
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)); } } |