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: Addressed Sergei`s comments again and added some asserts Created Feb. 23, 2016, 12:30 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 #pragma once 1 #pragma once
2 2
3 #include <cstddef> 3 #include <cstddef>
4 #include <cstring> 4 #include <cstring>
5 #include <algorithm> 5 #include <algorithm>
6
7 #include <emscripten.h>
6 8
7 #include "debug.h" 9 #include "debug.h"
8 10
9 inline void String_assert_readonly(bool readOnly); 11 inline void String_assert_readonly(bool readOnly);
10 12
11 class String 13 class String
12 { 14 {
13 friend class DependentString; 15 friend class DependentString;
14 friend class OwnedString; 16 friend class OwnedString;
15 17
16 public: 18 public:
17 typedef char16_t value_type; 19 typedef char16_t value_type;
18 typedef size_t size_type; 20 typedef size_t size_type;
19 21
20 // 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
21 static constexpr size_type INVALID = 0xC0000000; 23 static constexpr size_type INVALID = 0xC0000000;
22 static constexpr size_type DELETED = 0x80000000; 24 static constexpr size_type DELETED = 0x80000000;
23 static constexpr size_type READ_ONLY = 0x40000000; 25 static constexpr size_type READ_ONLY = 0x40000000;
24 static constexpr size_type READ_WRITE = 0x00000000; 26 static constexpr size_type READ_WRITE = 0x00000000;
25 27
26 static constexpr size_type FLAGS_MASK = 0xC0000000; 28 static constexpr size_type FLAGS_MASK = 0xC0000000;
27 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; 29 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF;
28 30
29 static constexpr size_type npos = -1; 31 static constexpr size_type npos = -1;
30 32
31 protected: 33 protected:
32 value_type* mBuf; 34 value_type* mBuf;
33 size_type mLen; 35 size_type mLen;
34 36
35 String(value_type* buf, size_type len, size_type flags) 37 explicit String(value_type* buf, size_type len, size_type flags)
36 : mBuf(buf), mLen((len & LENGTH_MASK) | flags) 38 : mBuf(buf), mLen((len & LENGTH_MASK) | flags)
37 { 39 {
38 } 40 }
39 41
40 ~String() 42 ~String()
41 { 43 {
42 } 44 }
43 45
44 void reset(value_type* buf, size_type len, size_type flags) 46 void reset(value_type* buf, size_type len, size_type flags)
45 { 47 {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 size_type find(value_type c, size_type pos = 0) const 98 size_type find(value_type c, size_type pos = 0) const
97 { 99 {
98 for (size_type i = pos; i < length(); ++i) 100 for (size_type i = pos; i < length(); ++i)
99 if (mBuf[i] == c) 101 if (mBuf[i] == c)
100 return i; 102 return i;
101 return npos; 103 return npos;
102 } 104 }
103 105
104 size_type find(const String& str, size_type pos = 0) const 106 size_type find(const String& str, size_type pos = 0) const
105 { 107 {
106 if (pos + str.length() > length()) 108 if (pos > LENGTH_MASK || pos + str.length() > length())
107 return npos; 109 return npos;
108 110
109 if (!str.length()) 111 if (!str.length())
110 return pos; 112 return pos;
111 113
112 for (; pos + str.length() <= length(); ++pos) 114 for (; pos + str.length() <= length(); ++pos)
113 { 115 {
114 if (mBuf[pos] == str[0] && 116 if (mBuf[pos] == str[0] &&
115 std::memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) = = 0) 117 std::memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) = = 0)
116 { 118 {
(...skipping 20 matching lines...) Expand all
137 139
138 bool is_invalid() const 140 bool is_invalid() const
139 { 141 {
140 return (mLen & FLAGS_MASK) == INVALID; 142 return (mLen & FLAGS_MASK) == INVALID;
141 } 143 }
142 144
143 bool is_deleted() const 145 bool is_deleted() const
144 { 146 {
145 return (mLen & FLAGS_MASK) == DELETED; 147 return (mLen & FLAGS_MASK) == DELETED;
146 } 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 }
147 }; 171 };
148 172
149 class DependentString : public String 173 class DependentString : public String
150 { 174 {
151 public: 175 public:
152 DependentString() 176 explicit DependentString()
153 : String(nullptr, 0, INVALID) 177 : String(nullptr, 0, INVALID)
154 { 178 {
155 } 179 }
156 180
157 DependentString(value_type* buf, size_type len) 181 explicit DependentString(value_type* buf, size_type len)
158 : String(buf, len, READ_WRITE) 182 : String(buf, len, READ_WRITE)
159 { 183 {
160 } 184 }
161 185
162 DependentString(const value_type* buf, size_type len) 186 explicit DependentString(const value_type* buf, size_type len)
163 : String(const_cast<value_type*>(buf), len, READ_ONLY) 187 : String(const_cast<value_type*>(buf), len, READ_ONLY)
164 { 188 {
165 } 189 }
166 190
167 DependentString(String& str, size_type pos = 0, size_type len = npos) 191 explicit DependentString(String& str, size_type pos = 0, size_type len = npos)
168 : String( 192 : String(
169 str.mBuf + std::min(pos, str.length()), 193 str.mBuf + std::min(pos, str.length()),
170 std::min(len, str.length() - std::min(pos, str.length())), 194 std::min(len, str.length() - std::min(pos, str.length())),
171 str.is_readOnly() ? READ_ONLY : READ_WRITE 195 str.is_readOnly() ? READ_ONLY : READ_WRITE
172 ) 196 )
173 { 197 {
174 } 198 }
175 199
176 DependentString(const String& str, size_type pos = 0, 200 explicit DependentString(const String& str, size_type pos = 0,
177 size_type len = npos) 201 size_type len = npos)
178 : String( 202 : String(
179 str.mBuf + std::min(pos, str.length()), 203 str.mBuf + std::min(pos, str.length()),
180 std::min(len, str.length() - std::min(pos, str.length())), 204 std::min(len, str.length() - std::min(pos, str.length())),
181 READ_ONLY 205 READ_ONLY
182 ) 206 )
183 { 207 {
184 } 208 }
185 209
186 void reset(value_type* buf, size_type len) 210 void reset(value_type* buf, size_type len)
187 { 211 {
188 *this = DependentString(buf, len); 212 *this = DependentString(buf, len);
189 } 213 }
190 214
191 void reset(const value_type* buf, size_type len) 215 void reset(const value_type* buf, size_type len)
192 { 216 {
193 *this = DependentString(buf, len); 217 *this = DependentString(buf, len);
194 } 218 }
195 219
196 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)
197 { 221 {
198 *this = DependentString(str, pos, len); 222 *this = DependentString(str, pos, len);
199 } 223 }
200 224
201 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)
202 { 226 {
203 *this = DependentString(str, pos, len); 227 *this = DependentString(str, pos, len);
204 } 228 }
229
230 void erase()
231 {
232 *this = DependentString();
233 mLen = DELETED;
234 }
205 }; 235 };
206 236
207 inline DependentString operator "" _str(const String::value_type* str, 237 inline DependentString operator "" _str(const String::value_type* str,
208 String::size_type len) 238 String::size_type len)
209 { 239 {
210 return DependentString(str, len); 240 return DependentString(str, len);
211 } 241 }
212 242
213 inline void String_assert_readonly(bool readOnly) 243 inline void String_assert_readonly(bool readOnly)
214 { 244 {
215 assert(!readOnly, u"Writing access to a read-only string"_str); 245 assert(!readOnly, u"Writing access to a read-only string"_str);
216 } 246 }
217 247
218 class OwnedString : public String 248 class OwnedString : public String
219 { 249 {
220 private: 250 private:
221 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)
222 { 262 {
223 if (len) 263 if (len)
224 return new value_type[len]; 264 {
265 mBuf = new value_type[length()];
266 annotate_address(mBuf, "String");
267 }
225 else 268 else
226 return nullptr; 269 mBuf = nullptr;
227 } 270 }
228 271
229 void grow(size_type additionalSize) 272 explicit OwnedString(const String& str)
230 {
231 size_type oldLength = length();
232 size_type newLength = oldLength + additionalSize;
233 value_type* oldBuffer = mBuf;
234
235 reset(nullptr, newLength, READ_WRITE);
236 newLength = length();
237 mBuf = allocate(newLength);
238 annotate_address(mBuf, "String");
239
240 if (oldLength)
241 std::memcpy(mBuf, oldBuffer, sizeof(value_type) * oldLength);
242 if (oldBuffer)
243 delete[] oldBuffer;
244 }
245
246 public:
247 OwnedString(size_type len = 0)
248 : String(nullptr, len, READ_WRITE)
249 {
250 mBuf = allocate(length());
251 annotate_address(mBuf, "String");
252 }
253
254 OwnedString(const String& str)
255 : OwnedString(str.length()) 273 : OwnedString(str.length())
256 { 274 {
257 if (length()) 275 if (length())
258 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length()); 276 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length());
259 } 277 }
260 278
261 OwnedString(const OwnedString& str) 279 OwnedString(const OwnedString& str)
262 : OwnedString(static_cast<const String&>(str)) 280 : OwnedString(static_cast<const String&>(str))
263 { 281 {
264 } 282 }
265 283
266 OwnedString(const value_type* str, size_type len) 284 explicit OwnedString(const value_type* str, size_type len)
267 : OwnedString(DependentString(str, len)) 285 : OwnedString(DependentString(str, len))
268 { 286 {
269 } 287 }
270 288
271 OwnedString(OwnedString&& str) 289 explicit OwnedString(OwnedString&& str)
272 : OwnedString(0) 290 : OwnedString(0)
273 { 291 {
274 mBuf = str.mBuf; 292 mBuf = str.mBuf;
275 mLen = str.mLen; 293 mLen = str.mLen;
276 str.mBuf = nullptr; 294 str.mBuf = nullptr;
277 str.mLen = READ_WRITE | 0; 295 str.mLen = READ_WRITE | 0;
sergei 2016/02/23 15:07:34 I would like to use `std::swap` here, but the curr
Wladimir Palant 2016/02/23 21:34:57 I don't see how that could be used in a meaningful
278 } 296 }
279 297
280 ~OwnedString() 298 ~OwnedString()
281 { 299 {
282 if (mBuf) 300 if (mBuf)
283 delete[] mBuf; 301 delete[] mBuf;
284 } 302 }
285 303
286 OwnedString& operator=(const String& str) 304 OwnedString& operator=(const String& str)
287 { 305 {
288 *this = std::move(OwnedString(str)); 306 *this = std::move(OwnedString(str));
289 return *this; 307 return *this;
290 } 308 }
291 309
292 OwnedString& operator=(const OwnedString& str) 310 OwnedString& operator=(const OwnedString& str)
293 { 311 {
294 *this = std::move(OwnedString(str)); 312 *this = std::move(OwnedString(str));
295 return *this; 313 return *this;
296 } 314 }
297 315
298 OwnedString& operator=(OwnedString&& str) 316 OwnedString& operator=(OwnedString&& str)
299 { 317 {
300 mBuf = str.mBuf; 318 std::swap(mBuf, str.mBuf);
301 mLen = str.mLen; 319 std::swap(mLen, str.mLen);
302 str.mBuf = nullptr;
303 str.mLen = READ_WRITE | 0;
304 return *this; 320 return *this;
305 } 321 }
306 322
307 void append(const value_type* source, size_type sourceLen) 323 void append(const value_type* source, size_type sourceLen)
308 { 324 {
309 if (!sourceLen) 325 if (!sourceLen)
310 return; 326 return;
311 327
312 assert(source, u"Null buffer passed to OwnedString.append()"_str); 328 assert(source, u"Null buffer passed to OwnedString.append()"_str);
313 size_t oldLength = length(); 329 size_t oldLength = length();
314 grow(sourceLen); 330 grow(sourceLen);
315 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); 331 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen);
316 } 332 }
317 333
318 void append(const String& str) 334 void append(const String& str)
319 { 335 {
320 append(str.mBuf, str.length()); 336 append(str.mBuf, str.length());
321 } 337 }
322 338
323 void append(value_type c) 339 void append(value_type c)
324 { 340 {
325 append(&c, 1); 341 append(&c, 1);
326 } 342 }
327 }; 343 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld