OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "platform/text/CompressibleString.h" | |
7 | |
8 // TODO: This seems illegal: Fix checkdeps? | |
9 #include "components/compression/compression_utils.h" | |
10 #include "wtf/Assertions.h" | |
11 #include "wtf/Partitions.h" | |
12 #include "wtf/WTFThreadData.h" | |
13 #include "wtf/text/WTFString.h" | |
14 | |
15 namespace blink { | |
16 | |
17 class CompressibleStringTable { | |
18 WTF_MAKE_NONCOPYABLE(CompressibleStringTable); | |
19 public: | |
20 static CompressibleStringTable* create(WTFThreadData& data) | |
21 { | |
22 data.m_compressibleStringTable = new CompressibleStringTable; | |
23 data.m_compressibleStringTableDestructor = CompressibleStringTable::dest roy; | |
24 return data.m_compressibleStringTable; | |
25 } | |
26 | |
27 CompressibleStringImpl* add(CompressibleStringImpl* string) | |
28 { | |
29 string->ref(); | |
30 return *m_table.add(string).storedValue; | |
31 } | |
32 | |
33 HashSet<CompressibleStringImpl*>& table() | |
34 { | |
35 return m_table; | |
36 } | |
37 | |
38 void compressAll() | |
39 { | |
40 HashSet<CompressibleStringImpl*>::iterator end = m_table.end(); | |
41 for (HashSet<CompressibleStringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) { | |
42 CompressibleStringImpl* string = *iter; | |
43 if (!string->isCompressed()) | |
44 string->compress(); | |
45 } | |
46 } | |
47 | |
48 private: | |
49 CompressibleStringTable() { } | |
50 | |
51 static void destroy(CompressibleStringTable* table) | |
52 { | |
53 HashSet<CompressibleStringImpl*>::iterator end = table->m_table.end(); | |
54 for (HashSet<CompressibleStringImpl*>::iterator iter = table->m_table.be gin(); iter != end; ++iter) | |
55 (*iter)->deref(); | |
56 delete table; | |
57 } | |
58 | |
59 HashSet<CompressibleStringImpl*> m_table; | |
60 }; | |
61 | |
62 static inline CompressibleStringTable& compressibleStringTable() | |
63 { | |
64 // Once possible we should make this non-lazy (constructed in WTFThreadData' s constructor). | |
65 WTFThreadData& data = wtfThreadData(); | |
66 CompressibleStringTable* table = data.compressibleStringTable(); | |
67 if (UNLIKELY(!table)) | |
68 table = CompressibleStringTable::create(data); | |
69 return *table; | |
70 } | |
71 | |
72 void CompressibleStringImpl::purgeMemory() | |
73 { | |
74 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.
| |
75 } | |
76 | |
77 CompressibleStringImpl::CompressibleStringImpl(PassRefPtr<StringImpl> impl) | |
78 : m_impl(impl) | |
79 , m_compressedData(nullptr) | |
80 , m_originalLength(m_impl->length()) | |
81 , 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.
| |
82 { | |
83 } | |
84 | |
85 unsigned CompressibleStringImpl::contentSizeInBytes() const | |
86 { | |
87 if (is8Bit()) | |
88 return m_originalLength; | |
89 return m_originalLength * 2; | |
90 } | |
91 | |
92 String CompressibleStringImpl::toString() | |
93 { | |
94 if (UNLIKELY(isCompressed())) | |
95 uncompress(); | |
96 return m_impl.get(); | |
97 } | |
98 | |
99 const LChar* CompressibleStringImpl::characters8() | |
100 { | |
101 return toString().characters8(); | |
102 } | |
103 | |
104 const UChar* CompressibleStringImpl::characters16() | |
105 { | |
106 return toString().characters16(); | |
107 } | |
108 | |
109 void CompressibleStringImpl::compress() | |
110 { | |
111 ASSERT(m_impl); | |
112 ASSERT(!isCompressed()); | |
113 | |
114 // TODO(hajimehoshi): Now components offers funcitons accepting only | |
115 // std::strings. This is not efficient. We should offer char* version. | |
116 std::string in, out; | |
117 if (m_is8Bit) | |
118 in = std::string(reinterpret_cast<const char*>(m_impl->characters8()), c ontentSizeInBytes()); | |
119 else | |
120 in = std::string(reinterpret_cast<const char*>(m_impl->characters16()), contentSizeInBytes()); | |
121 compression::GzipCompress(in, &out); | |
122 | |
123 m_impl = nullptr; | |
124 m_compressedData = SharedBuffer::create(out.c_str(), out.size()); | |
125 } | |
126 | |
127 void CompressibleStringImpl::uncompress() | |
128 { | |
129 ASSERT(m_compressedData); | |
130 ASSERT(!m_impl); | |
131 | |
132 std::string in(m_compressedData->data(), m_compressedData->size()); | |
133 std::string out; | |
134 compression::GzipUncompress(in, &out); | |
135 | |
136 if (m_is8Bit) { | |
137 LChar* data = nullptr; | |
138 m_impl = StringImpl::createUninitialized(out.size() / sizeof(LChar), dat a); | |
139 memcpy(data, out.c_str(), out.size()); | |
140 } else { | |
141 UChar* data = nullptr; | |
142 m_impl = StringImpl::createUninitialized(out.size() / sizeof(UChar), dat a); | |
143 memcpy(data, out.c_str(), out.size()); | |
144 } | |
145 | |
146 m_compressedData = nullptr; | |
147 ASSERT(m_is8Bit == m_impl->is8Bit()); | |
148 ASSERT(m_originalLength == m_impl->length()); | |
149 } | |
150 | |
151 CompressibleString::CompressibleString() | |
152 : m_impl(nullptr) | |
153 { | |
154 } | |
155 | |
156 CompressibleString::CompressibleString(const CompressibleString& rhs) | |
157 : m_impl(rhs.m_impl) | |
158 { | |
159 } | |
160 | |
161 CompressibleString::CompressibleString(PassRefPtr<StringImpl> impl) | |
162 : m_impl(impl ? adoptRef(new CompressibleStringImpl(impl)) : nullptr) | |
163 { | |
164 if (m_impl && contentSizeInBytes() > 100000) | |
165 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
| |
166 } | |
167 | |
168 void CompressibleString::compress() const | |
169 { | |
170 m_impl->compress(); | |
171 } | |
172 | |
173 void CompressibleString::uncompress() const | |
174 { | |
175 m_impl->uncompress(); | |
176 } | |
177 | |
178 } // namespace blink | |
OLD | NEW |