Chromium Code Reviews| Index: third_party/WebKit/Source/platform/text/CompressibleString.cpp |
| diff --git a/third_party/WebKit/Source/platform/text/CompressibleString.cpp b/third_party/WebKit/Source/platform/text/CompressibleString.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..52765cc3abc87b284c29487ba85fdad108f0e4d5 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/platform/text/CompressibleString.cpp |
| @@ -0,0 +1,178 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "platform/text/CompressibleString.h" |
| + |
| +// TODO: This seems illegal: Fix checkdeps? |
| +#include "components/compression/compression_utils.h" |
| +#include "wtf/Assertions.h" |
| +#include "wtf/Partitions.h" |
| +#include "wtf/WTFThreadData.h" |
| +#include "wtf/text/WTFString.h" |
| + |
| +namespace blink { |
| + |
| +class CompressibleStringTable { |
| + WTF_MAKE_NONCOPYABLE(CompressibleStringTable); |
| +public: |
| + static CompressibleStringTable* create(WTFThreadData& data) |
| + { |
| + data.m_compressibleStringTable = new CompressibleStringTable; |
| + data.m_compressibleStringTableDestructor = CompressibleStringTable::destroy; |
| + return data.m_compressibleStringTable; |
| + } |
| + |
| + CompressibleStringImpl* add(CompressibleStringImpl* string) |
| + { |
| + string->ref(); |
| + return *m_table.add(string).storedValue; |
| + } |
| + |
| + HashSet<CompressibleStringImpl*>& table() |
| + { |
| + return m_table; |
| + } |
| + |
| + void compressAll() |
| + { |
| + HashSet<CompressibleStringImpl*>::iterator end = m_table.end(); |
| + for (HashSet<CompressibleStringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) { |
| + CompressibleStringImpl* string = *iter; |
| + if (!string->isCompressed()) |
| + string->compress(); |
| + } |
| + } |
| + |
| +private: |
| + CompressibleStringTable() { } |
| + |
| + static void destroy(CompressibleStringTable* table) |
| + { |
| + HashSet<CompressibleStringImpl*>::iterator end = table->m_table.end(); |
| + for (HashSet<CompressibleStringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) |
| + (*iter)->deref(); |
| + delete table; |
| + } |
| + |
| + HashSet<CompressibleStringImpl*> m_table; |
| +}; |
| + |
| +static inline CompressibleStringTable& compressibleStringTable() |
| +{ |
| + // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor). |
| + WTFThreadData& data = wtfThreadData(); |
| + CompressibleStringTable* table = data.compressibleStringTable(); |
| + if (UNLIKELY(!table)) |
| + table = CompressibleStringTable::create(data); |
| + return *table; |
| +} |
| + |
| +void CompressibleStringImpl::purgeMemory() |
| +{ |
| + compressibleStringTable().compressAll(); |
|
haraken
2015/11/26 11:50:03
For now this is okay, but compressing the table of
hajimehoshi
2015/11/27 11:03:58
Commented.
|
| +} |
| + |
| +CompressibleStringImpl::CompressibleStringImpl(PassRefPtr<StringImpl> impl) |
| + : m_impl(impl) |
| + , m_compressedData(nullptr) |
| + , m_originalLength(m_impl->length()) |
| + , m_is8Bit(m_impl->is8Bit()) |
|
haraken
2015/11/26 11:50:03
You need to check !m_impl. If it's guaranteed to b
hajimehoshi
2015/11/27 11:03:58
Done.
|
| +{ |
| +} |
| + |
| +unsigned CompressibleStringImpl::contentSizeInBytes() const |
| +{ |
| + if (is8Bit()) |
| + return m_originalLength; |
| + return m_originalLength * 2; |
| +} |
| + |
| +String CompressibleStringImpl::toString() |
| +{ |
| + if (UNLIKELY(isCompressed())) |
| + uncompress(); |
| + return m_impl.get(); |
| +} |
| + |
| +const LChar* CompressibleStringImpl::characters8() |
| +{ |
| + return toString().characters8(); |
| +} |
| + |
| +const UChar* CompressibleStringImpl::characters16() |
| +{ |
| + return toString().characters16(); |
| +} |
| + |
| +void CompressibleStringImpl::compress() |
| +{ |
| + ASSERT(m_impl); |
| + ASSERT(!isCompressed()); |
| + |
| + // TODO(hajimehoshi): Now components offers funcitons accepting only |
| + // std::strings. This is not efficient. We should offer char* version. |
| + std::string in, out; |
| + if (m_is8Bit) |
| + in = std::string(reinterpret_cast<const char*>(m_impl->characters8()), contentSizeInBytes()); |
| + else |
| + in = std::string(reinterpret_cast<const char*>(m_impl->characters16()), contentSizeInBytes()); |
| + compression::GzipCompress(in, &out); |
| + |
| + m_impl = nullptr; |
| + m_compressedData = SharedBuffer::create(out.c_str(), out.size()); |
| +} |
| + |
| +void CompressibleStringImpl::uncompress() |
| +{ |
| + ASSERT(m_compressedData); |
| + ASSERT(!m_impl); |
| + |
| + std::string in(m_compressedData->data(), m_compressedData->size()); |
| + std::string out; |
| + compression::GzipUncompress(in, &out); |
| + |
| + if (m_is8Bit) { |
| + LChar* data = nullptr; |
| + m_impl = StringImpl::createUninitialized(out.size() / sizeof(LChar), data); |
| + memcpy(data, out.c_str(), out.size()); |
| + } else { |
| + UChar* data = nullptr; |
| + m_impl = StringImpl::createUninitialized(out.size() / sizeof(UChar), data); |
| + memcpy(data, out.c_str(), out.size()); |
| + } |
| + |
| + m_compressedData = nullptr; |
| + ASSERT(m_is8Bit == m_impl->is8Bit()); |
| + ASSERT(m_originalLength == m_impl->length()); |
| +} |
| + |
| +CompressibleString::CompressibleString() |
| + : m_impl(nullptr) |
| +{ |
| +} |
| + |
| +CompressibleString::CompressibleString(const CompressibleString& rhs) |
| + : m_impl(rhs.m_impl) |
| +{ |
| +} |
| + |
| +CompressibleString::CompressibleString(PassRefPtr<StringImpl> impl) |
| + : m_impl(impl ? adoptRef(new CompressibleStringImpl(impl)) : nullptr) |
| +{ |
| + if (m_impl && contentSizeInBytes() > 100000) |
| + compressibleStringTable().add(m_impl.get()); |
|
haraken
2015/11/26 11:50:03
Who removes the compressible string from the table
hajimehoshi
2015/11/27 11:03:58
Done. (Skipped checking leaking as we talked offli
|
| +} |
| + |
| +void CompressibleString::compress() const |
| +{ |
| + m_impl->compress(); |
| +} |
| + |
| +void CompressibleString::uncompress() const |
| +{ |
| + m_impl->uncompress(); |
| +} |
| + |
| +} // namespace blink |