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

Side by Side Diff: compiled/String.h

Issue 29333474: Issue 4125 - [emscripten] Convert filter classes to C++ (Closed)
Patch Set: Addressed comments from Patch Set 24 Created Dec. 6, 2016, 10:43 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #pragma once
2
3 #include <cstddef>
4 #include <cstring>
5 #include <algorithm>
6
7 #include <emscripten.h>
8
9 #include "debug.h"
10
11 inline void String_assert_readonly(bool readOnly);
12
13 class String
14 {
15 friend class DependentString;
16 friend class OwnedString;
17
18 public:
19 typedef char16_t value_type;
20 typedef size_t size_type;
21
22 // Type flags, stored in the top 2 bits of the mLen member
23 static constexpr size_type INVALID = 0xC0000000;
24 static constexpr size_type DELETED = 0x80000000;
25 static constexpr size_type READ_ONLY = 0x40000000;
26 static constexpr size_type READ_WRITE = 0x00000000;
27
28 static constexpr size_type FLAGS_MASK = 0xC0000000;
29 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF;
30
31 static constexpr size_type npos = -1;
32
33 protected:
34 value_type* mBuf;
35 size_type mLen;
36
37 String(value_type* buf, size_type len, size_type flags)
38 : mBuf(buf), mLen((len & LENGTH_MASK) | flags)
39 {
40 }
41
42 ~String()
43 {
44 }
45
46 void reset(value_type* buf, size_type len, size_type flags)
47 {
48 mBuf = buf;
49 mLen = (len & LENGTH_MASK) | flags;
50 }
51
52 public:
53 size_type length() const
54 {
55 return mLen & LENGTH_MASK;
56 }
57
58 bool empty() const
59 {
60 return !(mLen & LENGTH_MASK);
61 }
62
63 const value_type* data() const
64 {
65 return mBuf;
66 }
67
68 value_type* data()
69 {
70 String_assert_readonly(is_readOnly());
71 return mBuf;
72 }
73
74 const value_type& operator[](size_type pos) const
75 {
76 return mBuf[pos];
77 }
78
79 value_type& operator[](size_type pos)
80 {
81 String_assert_readonly(is_readOnly());
82 return mBuf[pos];
83 }
84
85 bool is_readOnly() const
86 {
87 return (mLen & FLAGS_MASK) != READ_WRITE;
88 }
89
90 bool equals(const String& other) const
91 {
92 if (length() != other.length())
93 return false;
94
95 return std::memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0;
96 }
97
98 size_type find(value_type c, size_type pos = 0) const
99 {
100 for (size_type i = pos; i < length(); ++i)
101 if (mBuf[i] == c)
102 return i;
103 return npos;
104 }
105
106 size_type find(const String& str, size_type pos = 0) const
107 {
108 if (pos > LENGTH_MASK || pos + str.length() > length())
109 return npos;
110
111 if (!str.length())
112 return pos;
113
114 for (; pos + str.length() <= length(); ++pos)
115 {
116 if (mBuf[pos] == str[0] &&
117 std::memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) = = 0)
118 {
119 return pos;
120 }
121 }
122
123 return npos;
124 }
125
126 size_type rfind(value_type c, size_type pos = npos) const
127 {
128 if (length() == 0)
129 return npos;
130
131 if (pos >= length())
132 pos = length() - 1;
133
134 for (int i = pos; i >= 0; --i)
135 if (mBuf[i] == c)
136 return i;
137 return npos;
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()
sergei 2017/01/10 15:58:02 it seems to be consistent it should be to_lower or
Wladimir Palant 2017/03/13 17:42:15 Done.
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 it the easiest solution for lowercasing
sergei 2017/01/10 15:57:54 typo: it -> is
Wladimir Palant 2017/03/13 17:42:20 Done.
164 // Unicode characters.
165 mBuf[i] = EM_ASM_INT({
166 return String.fromCharCode($0).toLowerCase().charCodeAt(0);
167 }, currChar);
168 }
169 }
170 }
171 };
172
173 class DependentString : public String
174 {
175 public:
176 DependentString()
177 : String(nullptr, 0, INVALID)
178 {
179 }
180
181 DependentString(value_type* buf, size_type len)
182 : String(buf, len, READ_WRITE)
183 {
184 }
185
186 DependentString(const value_type* buf, size_type len)
187 : String(const_cast<value_type*>(buf), len, READ_ONLY)
188 {
189 }
190
191 explicit DependentString(String& str, size_type pos = 0, size_type len = npos)
192 : String(
193 str.mBuf + std::min(pos, str.length()),
194 std::min(len, str.length() - std::min(pos, str.length())),
195 str.is_readOnly() ? READ_ONLY : READ_WRITE
196 )
197 {
198 }
199
200 explicit DependentString(const String& str, size_type pos = 0,
201 size_type len = npos)
202 : String(
203 str.mBuf + std::min(pos, str.length()),
204 std::min(len, str.length() - std::min(pos, str.length())),
205 READ_ONLY
206 )
207 {
208 }
209
210 void reset(value_type* buf, size_type len)
211 {
212 *this = DependentString(buf, len);
213 }
214
215 void reset(const value_type* buf, size_type len)
216 {
217 *this = DependentString(buf, len);
218 }
219
220 void reset(String& str, size_type pos = 0, size_type len = npos)
221 {
222 *this = DependentString(str, pos, len);
223 }
224
225 void reset(const String& str, size_type pos = 0, size_type len = npos)
226 {
227 *this = DependentString(str, pos, len);
228 }
229
230 void erase()
231 {
232 *this = DependentString();
233 mLen = DELETED;
234 }
235 };
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
248 class OwnedString : public String
249 {
250 private:
251 value_type* allocate(size_type len)
252 {
253 if (len)
254 return new value_type[len];
255 else
256 return nullptr;
257 }
258
259 void grow(size_type additionalSize)
260 {
261 size_type oldLength = length();
sergei 2017/01/10 15:57:56 It seems it can be simplified to auto newValue =
Wladimir Palant 2017/03/13 17:42:18 Done.
262 size_type newLength = oldLength + additionalSize;
263 value_type* oldBuffer = mBuf;
264
265 reset(nullptr, newLength, READ_WRITE);
266 newLength = length();
267 mBuf = allocate(newLength);
268 annotate_address(mBuf, "String");
269
270 if (oldLength)
271 std::memcpy(mBuf, oldBuffer, sizeof(value_type) * oldLength);
272 if (oldBuffer)
273 delete[] oldBuffer;
274 }
275
276 public:
277 OwnedString(size_type len = 0)
278 : String(nullptr, len, READ_WRITE)
279 {
280 mBuf = allocate(length());
281 annotate_address(mBuf, "String");
282 }
283
284 OwnedString(const String& str)
285 : OwnedString(str.length())
286 {
287 if (length())
288 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length());
289 }
290
291 OwnedString(const OwnedString& str)
292 : OwnedString(static_cast<const String&>(str))
293 {
294 }
295
296 OwnedString(const value_type* str, size_type len)
297 : OwnedString(DependentString(str, len))
298 {
299 }
300
301 OwnedString(OwnedString&& str)
302 : OwnedString(0)
303 {
304 mBuf = str.mBuf;
305 mLen = str.mLen;
306 str.mBuf = nullptr;
307 str.mLen = READ_WRITE | 0;
308 }
309
310 ~OwnedString()
311 {
312 if (mBuf)
313 delete[] mBuf;
314 }
315
316 OwnedString& operator=(const String& str)
317 {
318 *this = std::move(OwnedString(str));
319 return *this;
320 }
321
322 OwnedString& operator=(const OwnedString& str)
323 {
324 *this = std::move(OwnedString(str));
325 return *this;
326 }
327
328 OwnedString& operator=(OwnedString&& str)
sergei 2017/01/10 15:57:52 I don't know how I missed it before but it's incor
Wladimir Palant 2017/03/13 17:42:13 Done.
329 {
330 mBuf = str.mBuf;
331 mLen = str.mLen;
332 str.mBuf = nullptr;
333 str.mLen = READ_WRITE | 0;
334 return *this;
335 }
336
337 void append(const value_type* source, size_type sourceLen)
338 {
339 if (!sourceLen)
340 return;
341
342 assert(source, u"Null buffer passed to OwnedString.append()"_str);
343 size_t oldLength = length();
344 grow(sourceLen);
345 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen);
346 }
347
348 void append(const String& str)
349 {
350 append(str.mBuf, str.length());
351 }
352
353 void append(value_type c)
354 {
355 append(&c, 1);
356 }
357 };
OLDNEW

Powered by Google App Engine
This is Rietveld