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: Rebased, addressed comments, changed StringMap::find() return value Created Feb. 18, 2016, 4:02 p.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 "debug.h"
8
9 inline void String_assert_readonly(bool readOnly);
10
11 class String
12 {
13 friend class DependentString;
14 friend class OwnedString;
15
16 public:
17 typedef char16_t value_type;
18 typedef size_t size_type;
19
20 // Type flags, stored in the top 2 bits of the mLen member
21 static constexpr size_type INVALID = 0xC0000000;
22 static constexpr size_type DELETED = 0x80000000;
23 static constexpr size_type READ_ONLY = 0x40000000;
24 static constexpr size_type READ_WRITE = 0x00000000;
25
26 static constexpr size_type FLAGS_MASK = 0xC0000000;
27 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF;
28
29 static constexpr size_type npos = -1;
30
31 protected:
32 value_type* mBuf;
33 size_type mLen;
34
35 String(value_type* buf, size_type len, size_type flags)
36 : mBuf(buf), mLen((len & LENGTH_MASK) | flags)
37 {
38 }
sergei 2016/02/22 12:46:01 What about assert(mLen > 0 || mBuf == nullptr)?
Wladimir Palant 2016/02/23 12:37:32 Somewhat problematic since asserts take string lit
39
40 ~String()
41 {
42 }
43
44 void reset(value_type* buf, size_type len, size_type flags)
45 {
46 mBuf = buf;
47 mLen = (len & LENGTH_MASK) | flags;
48 }
49
50 public:
51 size_type length() const
52 {
53 return mLen & LENGTH_MASK;
54 }
55
56 bool empty() const
57 {
58 return !(mLen & LENGTH_MASK);
59 }
60
61 const value_type* data() const
62 {
63 return mBuf;
64 }
65
66 value_type* data()
67 {
68 String_assert_readonly(is_readOnly());
69 return mBuf;
70 }
71
72 const value_type& operator[](size_type pos) const
73 {
74 return mBuf[pos];
75 }
76
77 value_type& operator[](size_type pos)
78 {
79 String_assert_readonly(is_readOnly());
80 return mBuf[pos];
81 }
82
83 bool is_readOnly() const
84 {
85 return (mLen & FLAGS_MASK) != READ_WRITE;
86 }
87
88 bool equals(const String& other) const
89 {
90 if (length() != other.length())
91 return false;
92
93 return std::memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0;
94 }
95
96 size_type find(value_type c, size_type pos = 0) const
97 {
98 for (size_type i = pos; i < length(); ++i)
99 if (mBuf[i] == c)
100 return i;
101 return npos;
102 }
103
104 size_type find(const String& str, size_type pos = 0) const
105 {
106 if (pos + str.length() > length())
107 return npos;
108
109 if (!str.length())
110 return pos;
111
112 for (; pos + str.length() <= length(); ++pos)
113 {
114 if (mBuf[pos] == str[0] &&
115 std::memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) = = 0)
116 {
117 return pos;
118 }
119 }
120
121 return npos;
122 }
123
124 size_type rfind(value_type c, size_type pos = npos) const
125 {
126 if (length() == 0)
127 return npos;
128
129 if (pos >= length())
130 pos = length() - 1;
131
132 for (int i = pos; i >= 0; --i)
133 if (mBuf[i] == c)
134 return i;
135 return npos;
136 }
137 };
138
139 class DependentString : public String
140 {
141 public:
142 DependentString()
143 : String(nullptr, 0, INVALID)
144 {
145 }
146
147 DependentString(value_type* buf, size_type len)
148 : String(buf, len, READ_WRITE)
149 {
150 }
151
152 DependentString(const value_type* buf, size_type len)
153 : String(const_cast<value_type*>(buf), len, READ_ONLY)
154 {
155 }
156
157 DependentString(String& str, size_type pos = 0, size_type len = npos)
158 : String(
159 str.mBuf + std::min(pos, str.length()),
160 std::min(len, str.length() - std::min(pos, str.length())),
161 READ_WRITE
sergei 2016/02/22 12:45:58 BTW, `READ_WRITE` here should be str.is_readOnly(
162 )
163 {
164 }
165
166 DependentString(const String& str, size_type pos = 0, size_type len = npos)
167 : String(
168 str.mBuf + std::min(pos, str.length()),
169 std::min(len, str.length() - std::min(pos, str.length())),
170 READ_ONLY
171 )
172 {
173 }
174
175 void reset(value_type* buf, size_type len)
176 {
177 *this = DependentString(buf, len);
178 }
179
180 void reset(const value_type* buf, size_type len)
181 {
182 *this = DependentString(buf, len);
183 }
184
185 void reset(String& str, size_type pos = 0, size_type len = npos)
186 {
187 *this = DependentString(str, pos, len);
188 }
189
190 void reset(const String& str, size_type pos = 0, size_type len = npos)
191 {
192 *this = DependentString(str, pos, len);
193 }
194
195 bool is_invalid() const
196 {
197 return (mLen & FLAGS_MASK) == INVALID;
198 }
199
200 bool is_deleted() const
201 {
202 return (mLen & FLAGS_MASK) == DELETED;
203 }
204 };
205
206 inline DependentString operator "" _str(const String::value_type* str,
207 String::size_type len)
208 {
209 return DependentString(str, len);
210 }
211
212 inline void String_assert_readonly(bool readOnly)
213 {
214 assert(!readOnly, u"Writing access to a read-only string"_str);
215 }
216
217 class OwnedString : public String
218 {
219 private:
220 value_type* allocate(size_type len)
221 {
222 if (len)
223 return new value_type[len];
224 else
225 return nullptr;
226 }
227
228 void grow(size_type additionalSize)
229 {
230 size_type oldLength = length();
231 size_type newLength = oldLength + additionalSize;
232 value_type* oldBuffer = mBuf;
233
234 reset(nullptr, newLength, READ_WRITE);
235 newLength = length();
236 mBuf = allocate(newLength);
237 annotate_address(mBuf, "String");
238
239 if (oldLength)
240 std::memcpy(mBuf, oldBuffer, sizeof(value_type) * oldLength);
241 if (oldBuffer)
242 delete[] oldBuffer;
243 }
244
245 public:
246 OwnedString(size_type len = 0)
247 : String(nullptr, len, READ_WRITE)
248 {
249 mBuf = allocate(length());
250 annotate_address(mBuf, "String");
251 }
252
253 OwnedString(const String& str)
254 : OwnedString(str.length())
255 {
256 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length());
257 }
258
259 OwnedString(const OwnedString& str)
260 : OwnedString(static_cast<const String&>(str))
261 {
262 }
263
264 OwnedString(const value_type* str, size_type len)
265 : OwnedString(DependentString(str, len))
266 {
267 }
268
269 OwnedString(OwnedString&& str)
270 : OwnedString(str.length())
271 {
272 mBuf = str.mBuf;
273 str.mBuf = nullptr;
274 str.mLen = READ_WRITE | 0;
275 }
sergei 2016/02/22 12:45:59 I think here is a memory leak. `OwnedString(str.le
Wladimir Palant 2016/02/23 12:37:33 Done.
276
277 OwnedString(const char* source, size_type len)
sergei 2016/02/22 12:46:00 I'm not sure whether we need this method because i
Wladimir Palant 2016/02/23 12:37:30 Yes, it's somewhat of a hack - removed.
278 : OwnedString(len)
279 {
280 for (size_type i = 0; i < len; i++)
281 mBuf[i] = source[i];
282 }
283
284 ~OwnedString()
285 {
286 if (mBuf)
287 delete[] mBuf;
288 }
289
290 OwnedString& operator=(const String& str)
291 {
292 *this = std::move(OwnedString(str));
293 return *this;
294 }
295
296 OwnedString& operator=(const OwnedString& str)
297 {
298 *this = std::move(OwnedString(str));
299 return *this;
300 }
301
302 OwnedString& operator=(OwnedString&& str)
303 {
304 mBuf = str.mBuf;
305 mLen = str.mLen;
306 str.mBuf = nullptr;
307 str.mLen = READ_WRITE | 0;
308 return *this;
309 }
310
311 void append(const value_type* source, size_type sourceLen)
312 {
313 if (!sourceLen)
314 return;
315
316 assert(source, u"Null buffer passed to OwnedString.append()"_str);
317 size_t oldLength = length();
318 grow(sourceLen);
319 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen);
320 }
321
322 void append(const String& str)
323 {
324 append(str.mBuf, str.length());
325 }
326
327 void append(value_type c)
328 {
329 append(&c, 1);
330 }
331 };
OLDNEW

Powered by Google App Engine
This is Rietveld