diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/JSStringJoiner.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSStringJoiner.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSStringJoiner.cpp | 141 |
1 files changed, 76 insertions, 65 deletions
diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp index 6f1959388..b6461c750 100644 --- a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp +++ b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 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,94 +26,105 @@ #include "config.h" #include "JSStringJoiner.h" -#include "JSCInlines.h" +#include "ExceptionHelpers.h" +#include "JSScope.h" +#include "JSString.h" +#include "Operations.h" +#include <wtf/text/StringImpl.h> namespace JSC { -template<typename CharacterType> -static inline void appendStringToData(CharacterType*& data, StringView string) +// The destination is 16bits, at least one string is 16 bits. +static inline void appendStringToData(UChar*& data, const String& string) { - string.getCharactersWithUpconvert(data); - data += string.length(); -} + if (string.isNull()) + return; -template<typename CharacterType> -static inline String joinStrings(const Vector<StringViewWithUnderlyingString>& strings, StringView separator, unsigned joinedLength) -{ - ASSERT(joinedLength); + unsigned length = string.length(); + const StringImpl* stringImpl = string.impl(); - 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); + if (stringImpl->is8Bit()) { + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters8()[i]; + ++data; } - break; - } - default: - for (unsigned i = 1; i < size; ++i) { - appendStringToData(data, separator); - appendStringToData(data, strings[i].view); + } else { + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters16()[i]; + ++data; } } - ASSERT(data == result.characters<CharacterType>() + joinedLength); - - return result; } -inline unsigned JSStringJoiner::joinedLength(ExecState& state) const +// If the destination is 8bits, we know every string has to be 8bit. +static inline void appendStringToData(LChar*& data, const String& string) { - unsigned numberOfStrings = m_strings.size(); - if (!numberOfStrings) - return 0; + if (string.isNull()) + return; + ASSERT(string.is8Bit()); - Checked<unsigned, RecordOverflow> separatorLength = m_separator.length(); - Checked<unsigned, RecordOverflow> totalSeparatorsLength = separatorLength * (numberOfStrings - 1); - Checked<unsigned, RecordOverflow> totalLength = totalSeparatorsLength + m_accumulatedStringsLength; + unsigned length = string.length(); + const StringImpl* stringImpl = string.impl(); - unsigned result; - if (totalLength.safeGet(result) == CheckedState::DidOverflow) { - throwOutOfMemoryError(&state); - return 0; + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters8()[i]; + ++data; } - return result; } -JSValue JSStringJoiner::join(ExecState& state) +template<typename CharacterType> +static inline PassRefPtr<StringImpl> joinStrings(const Vector<String>& strings, const String& separator, unsigned outputLength) { - ASSERT(m_strings.size() <= m_strings.capacity()); + ASSERT(outputLength); - unsigned length = joinedLength(state); - if (state.hadException()) - return jsUndefined(); + CharacterType* data; + RefPtr<StringImpl> outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data); + if (!outputStringImpl) + return PassRefPtr<StringImpl>(); + + const String firstString = strings.first(); + appendStringToData(data, firstString); - if (!length) - return jsEmptyString(&state); + 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(); +} - String result; - if (m_isAll8Bit) - result = joinStrings<LChar>(m_strings, m_separator, length); +JSValue JSStringJoiner::join(ExecState* exec) +{ + if (!m_isValid) + return throwOutOfMemoryError(exec); + + if (!m_strings.size()) + return jsEmptyString(exec); + + Checked<unsigned, RecordOverflow> separatorLength = m_separator.length(); + // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1). + ASSERT(m_strings.size() > 0); + Checked<unsigned, RecordOverflow> totalSeparactorsLength = separatorLength * (m_strings.size() - 1); + Checked<unsigned, RecordOverflow> outputStringSize = totalSeparactorsLength + m_accumulatedStringsLength; + + unsigned 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); else - result = joinStrings<UChar>(m_strings, m_separator, length); + outputStringImpl = joinStrings<UChar>(m_strings, m_separator, finalSize); - if (result.isNull()) - return throwOutOfMemoryError(&state); + if (!outputStringImpl) + return throwOutOfMemoryError(exec); - return jsString(&state, WTF::move(result)); + return JSString::create(exec->vm(), outputStringImpl.release()); } } |