Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: compiled/String.h

Issue 29333474: Issue 4125 - [emscripten] Convert filter classes to C++ (Closed)
Left Patch Set: Split up String class into two, cleaned up RegExpFilter methods Created Feb. 4, 2016, 7:20 p.m.
Right Patch Set: Addressed comments from Patch Set 28 Created March 21, 2017, 10:04 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/RegExpFilter.cpp ('k') | compiled/StringMap.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #ifndef ADBLOCK_PLUS_STRING_H 1 #pragma once
2 #define ADBLOCK_PLUS_STRING_H
3 2
4 #include <cstddef> 3 #include <cstddef>
5 #include <cstring> 4 #include <cstring>
6 #include <algorithm> 5 #include <algorithm>
6
7 #include <emscripten.h>
7 8
8 #include "debug.h" 9 #include "debug.h"
9 10
10 inline void String_assert_readonly(bool readOnly); 11 inline void String_assert_readonly(bool readOnly);
11 12
12 class String 13 class String
13 { 14 {
14 friend class DependentString; 15 friend class DependentString;
15 friend class OwnedString; 16 friend class OwnedString;
16 17
17 public: 18 public:
18 typedef char16_t value_type; 19 typedef char16_t value_type;
19 typedef size_t size_type; 20 typedef size_t size_type;
20 21
21 // Type flags, stored in the top 2 bits of the mLen member 22 // Type flags, stored in the top 2 bits of the mLen member
22 static constexpr size_type INVALID = 0xC0000000; 23 static constexpr size_type INVALID = 0xC0000000;
23 static constexpr size_type DELETED = 0x80000000; 24 static constexpr size_type DELETED = 0x80000000;
24 static constexpr size_type READ_ONLY = 0x40000000; 25 static constexpr size_type READ_ONLY = 0x40000000;
25 static constexpr size_type READ_WRITE = 0x00000000; 26 static constexpr size_type READ_WRITE = 0x00000000;
26 27
27 static constexpr size_type FLAGS_MASK = 0xC0000000; 28 static constexpr size_type FLAGS_MASK = 0xC0000000;
28 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; 29 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF;
29 30
30 static constexpr size_type npos = -1; 31 static constexpr size_type npos = -1;
31 32
32 protected: 33 protected:
33 value_type* mBuf; 34 value_type* mBuf;
34 size_type mLen; 35 size_type mLen;
35 36
36 String(value_type* buf, size_type len, size_type flags) 37 explicit String(value_type* buf, size_type len, size_type flags)
37 : mBuf(buf), mLen((len & LENGTH_MASK) | flags) 38 : mBuf(buf), mLen((len & LENGTH_MASK) | flags)
39 {
40 }
41
42 ~String()
38 { 43 {
39 } 44 }
40 45
41 void reset(value_type* buf, size_type len, size_type flags) 46 void reset(value_type* buf, size_type len, size_type flags)
42 { 47 {
43 mBuf = buf; 48 mBuf = buf;
44 mLen = (len & LENGTH_MASK) | flags; 49 mLen = (len & LENGTH_MASK) | flags;
45 } 50 }
46 51
47 public: 52 public:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 bool is_readOnly() const 85 bool is_readOnly() const
81 { 86 {
82 return (mLen & FLAGS_MASK) != READ_WRITE; 87 return (mLen & FLAGS_MASK) != READ_WRITE;
83 } 88 }
84 89
85 bool equals(const String& other) const 90 bool equals(const String& other) const
86 { 91 {
87 if (length() != other.length()) 92 if (length() != other.length())
88 return false; 93 return false;
89 94
90 return memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0; 95 return std::memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0;
91 } 96 }
92 97
93 size_type find(value_type c, size_type pos = 0) const 98 size_type find(value_type c, size_type pos = 0) const
94 { 99 {
95 for (size_type i = pos; i < length(); ++i) 100 for (size_type i = pos; i < length(); ++i)
96 if (mBuf[i] == c) 101 if (mBuf[i] == c)
97 return i; 102 return i;
98 return npos; 103 return npos;
99 } 104 }
100 105
101 size_type find(const String& str, size_type pos = 0) const 106 size_type find(const String& str, size_type pos = 0) const
102 { 107 {
108 if (pos > LENGTH_MASK || pos + str.length() > length())
109 return npos;
110
103 if (!str.length()) 111 if (!str.length())
104 return pos; 112 return pos;
105 113
106 if (length() - pos < str.length()) 114 for (; pos + str.length() <= length(); ++pos)
107 return npos;
108
109 for (; pos < length() - str.length(); ++pos)
110 { 115 {
111 if (mBuf[pos] == str[0] && 116 if (mBuf[pos] == str[0] &&
112 memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) == 0) 117 std::memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) = = 0)
113 { 118 {
114 return pos; 119 return pos;
115 } 120 }
116 } 121 }
117 122
118 return npos; 123 return npos;
119 } 124 }
120 125
121 size_type rfind(value_type c, size_type pos = npos) const 126 size_type rfind(value_type c, size_type pos = npos) const
122 { 127 {
123 if (length() == 0) 128 if (length() == 0)
124 return npos; 129 return npos;
125 130
126 if (pos == npos) 131 if (pos >= length())
127 pos = length() - 1; 132 pos = length() - 1;
128 133
129 for (int i = pos; i >= 0; --i) 134 for (int i = pos; i >= 0; --i)
130 if (mBuf[i] == c) 135 if (mBuf[i] == c)
131 return i; 136 return i;
132 return npos; 137 return npos;
133 } 138 }
139
140 bool is_invalid() const
141 {
142 return (mLen & FLAGS_MASK) == INVALID;
143 }
144
145 bool is_deleted() const
146 {
147 return (mLen & FLAGS_MASK) == DELETED;
148 }
149
150 void toLower()
151 {
152 size_type len = length();
153 for (size_type i = 0; i < len; ++i)
154 {
155 value_type currChar = mBuf[i];
156
157 // This should be more efficient with a lookup table but I couldn't measur e
158 // any performance difference.
159 if (currChar >= u'A' && currChar <= u'Z')
160 mBuf[i] = currChar + u'a' - u'A';
161 else if (currChar >= 128)
162 {
163 // It seems that calling JS is the easiest solution for lowercasing
164 // Unicode characters.
165 mBuf[i] = EM_ASM_INT({
166 return String.fromCharCode($0).toLowerCase().charCodeAt(0);
167 }, currChar);
168 }
169 }
170 }
134 }; 171 };
135 172
136 class DependentString : public String 173 class DependentString : public String
137 { 174 {
138 public: 175 public:
139 DependentString() 176 explicit DependentString()
140 : String(nullptr, 0, INVALID) 177 : String(nullptr, 0, INVALID)
141 { 178 {
142 } 179 }
143 180
144 DependentString(value_type* buf, size_type len) 181 explicit DependentString(value_type* buf, size_type len)
145 : String(buf, len, READ_WRITE) 182 : String(buf, len, READ_WRITE)
146 { 183 {
147 } 184 }
148 185
149 DependentString(const value_type* buf, size_type len) 186 explicit DependentString(const value_type* buf, size_type len)
150 : String(const_cast<value_type*>(buf), len, READ_ONLY) 187 : String(const_cast<value_type*>(buf), len, READ_ONLY)
151 { 188 {
152 } 189 }
153 190
154 DependentString(String& str, size_type pos = 0, size_type len = npos) 191 explicit DependentString(String& str, size_type pos = 0, size_type len = npos)
155 : String( 192 : String(
156 str.mBuf + std::min(pos, str.length()), 193 str.mBuf + std::min(pos, str.length()),
157 std::min(len, str.length() - std::min(pos, str.length())), 194 std::min(len, str.length() - std::min(pos, str.length())),
158 READ_WRITE 195 str.is_readOnly() ? READ_ONLY : READ_WRITE
159 ) 196 )
160 { 197 {
161 } 198 }
162 199
163 DependentString(const String& str, size_type pos = 0, size_type len = npos) 200 explicit DependentString(const String& str, size_type pos = 0,
201 size_type len = npos)
164 : String( 202 : String(
165 str.mBuf + std::min(pos, str.length()), 203 str.mBuf + std::min(pos, str.length()),
166 std::min(len, str.length() - std::min(pos, str.length())), 204 std::min(len, str.length() - std::min(pos, str.length())),
167 READ_ONLY 205 READ_ONLY
168 ) 206 )
169 { 207 {
170 } 208 }
171 209
172 void reset(value_type* buf, size_type len) 210 void reset(value_type* buf, size_type len)
173 { 211 {
174 *this = DependentString(buf, len); 212 *this = DependentString(buf, len);
175 } 213 }
176 214
177 void reset(const value_type* buf, size_type len) 215 void reset(const value_type* buf, size_type len)
178 { 216 {
179 *this = DependentString(buf, len); 217 *this = DependentString(buf, len);
180 } 218 }
181 219
182 void reset(String& str, size_type pos = 0, size_type len = npos) 220 void reset(String& str, size_type pos = 0, size_type len = npos)
183 { 221 {
184 *this = DependentString(str, pos, len); 222 *this = DependentString(str, pos, len);
185 } 223 }
186 224
187 void reset(const String& str, size_type pos = 0, size_type len = npos) 225 void reset(const String& str, size_type pos = 0, size_type len = npos)
188 { 226 {
189 *this = DependentString(str, pos, len); 227 *this = DependentString(str, pos, len);
190 } 228 }
191 229
192 bool is_invalid() const 230 void erase()
193 { 231 {
194 return (mLen & FLAGS_MASK) == INVALID; 232 *this = DependentString();
195 } 233 mLen = DELETED;
196
197 bool is_deleted() const
198 {
199 return (mLen & FLAGS_MASK) == DELETED;
200 } 234 }
201 }; 235 };
202 236
237 inline DependentString operator "" _str(const String::value_type* str,
238 String::size_type len)
239 {
240 return DependentString(str, len);
241 }
242
243 inline void String_assert_readonly(bool readOnly)
244 {
245 assert(!readOnly, u"Writing access to a read-only string"_str);
246 }
247
203 class OwnedString : public String 248 class OwnedString : public String
204 { 249 {
205 private: 250 private:
206 value_type* allocate(size_type len) 251 void grow(size_type additionalSize)
252 {
253 OwnedString newValue(length() + additionalSize);
254 if (length() > 0)
255 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length());
256 *this = std::move(newValue);
257 }
258
259 public:
260 explicit OwnedString(size_type len = 0)
261 : String(nullptr, len, READ_WRITE)
207 { 262 {
208 if (len) 263 if (len)
209 return new value_type[len]; 264 {
265 mBuf = new value_type[length()];
266 annotate_address(mBuf, "String");
267 }
210 else 268 else
211 return nullptr; 269 mBuf = nullptr;
212 } 270 }
213 271
214 void resize(size_type newLength, bool copy) 272 explicit OwnedString(const String& str)
215 {
216 size_type oldLength = length();
217 value_type* oldBuffer = mBuf;
218
219 reset(nullptr, newLength, READ_WRITE);
220 newLength = length();
221 mBuf = allocate(newLength);
222 annotate_address(mBuf, "String");
223
224 if (copy && oldLength)
225 memcpy(mBuf, oldBuffer, sizeof(value_type) * std::min(oldLength, newLength ));
226 if (oldBuffer)
227 delete[] oldBuffer;
228 }
229
230 public:
231 OwnedString(size_type len = 0)
232 : String(nullptr, len, READ_WRITE)
233 {
234 mBuf = allocate(length());
235 annotate_address(mBuf, "String");
236 }
237
238 OwnedString(const String& str)
239 : OwnedString(str.length()) 273 : OwnedString(str.length())
240 { 274 {
241 memcpy(mBuf, str.mBuf, sizeof(value_type) * length()); 275 if (length())
276 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length());
242 } 277 }
243 278
244 OwnedString(const OwnedString& str) 279 OwnedString(const OwnedString& str)
245 : OwnedString(static_cast<const String&>(str)) 280 : OwnedString(static_cast<const String&>(str))
246 { 281 {
247 } 282 }
248 283
249 OwnedString(const value_type* str, size_type len) 284 explicit OwnedString(const value_type* str, size_type len)
250 : OwnedString(DependentString(str, len)) 285 : OwnedString(DependentString(str, len))
251 { 286 {
252 } 287 }
253 288
254 OwnedString(OwnedString&& str) 289 explicit OwnedString(OwnedString&& str)
255 : OwnedString(str.length()) 290 : OwnedString(0)
256 {
257 mBuf = str.mBuf;
258 str.mBuf = nullptr;
259 str.mLen = READ_WRITE | 0;
260 }
261
262 OwnedString(const char* source, size_type len)
263 : OwnedString(len)
264 {
265 for (size_type i = 0; i < len; i++)
266 mBuf[i] = source[i];
267 }
268
269 ~OwnedString()
270 {
271 if (mBuf)
272 delete[] mBuf;
273 }
274
275 OwnedString& operator=(const String& str)
276 {
277 *this = std::move(OwnedString(str));
278 return *this;
279 }
280
281 OwnedString& operator=(const OwnedString& str)
282 {
283 *this = std::move(OwnedString(str));
284 return *this;
285 }
286
287 OwnedString& operator=(OwnedString&& str)
288 { 291 {
289 mBuf = str.mBuf; 292 mBuf = str.mBuf;
290 mLen = str.mLen; 293 mLen = str.mLen;
291 str.mBuf = nullptr; 294 str.mBuf = nullptr;
292 str.mLen = READ_WRITE | 0; 295 str.mLen = READ_WRITE | 0;
296 }
297
298 ~OwnedString()
299 {
300 if (mBuf)
301 delete[] mBuf;
302 }
303
304 OwnedString& operator=(const String& str)
305 {
306 *this = std::move(OwnedString(str));
307 return *this;
308 }
309
310 OwnedString& operator=(const OwnedString& str)
311 {
312 *this = std::move(OwnedString(str));
313 return *this;
314 }
315
316 OwnedString& operator=(OwnedString&& str)
317 {
318 std::swap(mBuf, str.mBuf);
319 std::swap(mLen, str.mLen);
293 return *this; 320 return *this;
294 } 321 }
295 322
296 void append(const value_type* source, size_type sourceLen) 323 void append(const value_type* source, size_type sourceLen)
297 { 324 {
298 if (!sourceLen) 325 if (!sourceLen)
299 return; 326 return;
300 327
328 assert(source, u"Null buffer passed to OwnedString.append()"_str);
301 size_t oldLength = length(); 329 size_t oldLength = length();
302 resize(oldLength + sourceLen, true); 330 grow(sourceLen);
303 memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); 331 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen);
304 } 332 }
305 333
306 void append(const String& str) 334 void append(const String& str)
307 { 335 {
308 append(str.mBuf, str.length()); 336 append(str.mBuf, str.length());
309 } 337 }
310 338
311 void append(value_type c) 339 void append(value_type c)
312 { 340 {
313 append(&c, 1); 341 append(&c, 1);
314 } 342 }
315 }; 343 };
316
317 inline DependentString operator "" _str(const String::value_type* str,
318 String::size_type len)
319 {
320 return DependentString(str, len);
321 }
322
323 inline void String_assert_readonly(bool readOnly)
324 {
325 assert(!readOnly, u"Writing access to a read-only string"_str);
326 }
327
328 #endif
LEFTRIGHT

Powered by Google App Engine
This is Rietveld