natalie_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +22 -0
  3. data/Dockerfile +26 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +21 -0
  6. data/README.md +55 -0
  7. data/Rakefile +242 -0
  8. data/ext/natalie_parser/extconf.rb +9 -0
  9. data/ext/natalie_parser/mri_creator.hpp +139 -0
  10. data/ext/natalie_parser/natalie_parser.cpp +144 -0
  11. data/include/natalie_parser/creator/debug_creator.hpp +113 -0
  12. data/include/natalie_parser/creator.hpp +108 -0
  13. data/include/natalie_parser/lexer/interpolated_string_lexer.hpp +64 -0
  14. data/include/natalie_parser/lexer/regexp_lexer.hpp +37 -0
  15. data/include/natalie_parser/lexer/word_array_lexer.hpp +57 -0
  16. data/include/natalie_parser/lexer.hpp +135 -0
  17. data/include/natalie_parser/node/alias_node.hpp +35 -0
  18. data/include/natalie_parser/node/arg_node.hpp +74 -0
  19. data/include/natalie_parser/node/array_node.hpp +34 -0
  20. data/include/natalie_parser/node/array_pattern_node.hpp +28 -0
  21. data/include/natalie_parser/node/assignment_node.hpp +34 -0
  22. data/include/natalie_parser/node/back_ref_node.hpp +28 -0
  23. data/include/natalie_parser/node/begin_block_node.hpp +25 -0
  24. data/include/natalie_parser/node/begin_node.hpp +52 -0
  25. data/include/natalie_parser/node/begin_rescue_node.hpp +47 -0
  26. data/include/natalie_parser/node/bignum_node.hpp +37 -0
  27. data/include/natalie_parser/node/block_node.hpp +55 -0
  28. data/include/natalie_parser/node/block_pass_node.hpp +33 -0
  29. data/include/natalie_parser/node/break_node.hpp +32 -0
  30. data/include/natalie_parser/node/call_node.hpp +85 -0
  31. data/include/natalie_parser/node/case_in_node.hpp +40 -0
  32. data/include/natalie_parser/node/case_node.hpp +52 -0
  33. data/include/natalie_parser/node/case_when_node.hpp +43 -0
  34. data/include/natalie_parser/node/class_node.hpp +39 -0
  35. data/include/natalie_parser/node/colon2_node.hpp +44 -0
  36. data/include/natalie_parser/node/colon3_node.hpp +34 -0
  37. data/include/natalie_parser/node/constant_node.hpp +26 -0
  38. data/include/natalie_parser/node/def_node.hpp +55 -0
  39. data/include/natalie_parser/node/defined_node.hpp +33 -0
  40. data/include/natalie_parser/node/encoding_node.hpp +26 -0
  41. data/include/natalie_parser/node/end_block_node.hpp +25 -0
  42. data/include/natalie_parser/node/evaluate_to_string_node.hpp +37 -0
  43. data/include/natalie_parser/node/false_node.hpp +23 -0
  44. data/include/natalie_parser/node/fixnum_node.hpp +36 -0
  45. data/include/natalie_parser/node/float_node.hpp +36 -0
  46. data/include/natalie_parser/node/hash_node.hpp +34 -0
  47. data/include/natalie_parser/node/hash_pattern_node.hpp +27 -0
  48. data/include/natalie_parser/node/identifier_node.hpp +123 -0
  49. data/include/natalie_parser/node/if_node.hpp +43 -0
  50. data/include/natalie_parser/node/infix_op_node.hpp +46 -0
  51. data/include/natalie_parser/node/interpolated_node.hpp +33 -0
  52. data/include/natalie_parser/node/interpolated_regexp_node.hpp +28 -0
  53. data/include/natalie_parser/node/interpolated_shell_node.hpp +22 -0
  54. data/include/natalie_parser/node/interpolated_string_node.hpp +31 -0
  55. data/include/natalie_parser/node/interpolated_symbol_key_node.hpp +18 -0
  56. data/include/natalie_parser/node/interpolated_symbol_node.hpp +28 -0
  57. data/include/natalie_parser/node/iter_node.hpp +45 -0
  58. data/include/natalie_parser/node/keyword_arg_node.hpp +25 -0
  59. data/include/natalie_parser/node/keyword_splat_node.hpp +38 -0
  60. data/include/natalie_parser/node/logical_and_node.hpp +40 -0
  61. data/include/natalie_parser/node/logical_or_node.hpp +40 -0
  62. data/include/natalie_parser/node/match_node.hpp +38 -0
  63. data/include/natalie_parser/node/module_node.hpp +32 -0
  64. data/include/natalie_parser/node/multiple_assignment_arg_node.hpp +32 -0
  65. data/include/natalie_parser/node/multiple_assignment_node.hpp +37 -0
  66. data/include/natalie_parser/node/next_node.hpp +37 -0
  67. data/include/natalie_parser/node/nil_node.hpp +23 -0
  68. data/include/natalie_parser/node/nil_sexp_node.hpp +23 -0
  69. data/include/natalie_parser/node/node.hpp +155 -0
  70. data/include/natalie_parser/node/node_with_args.hpp +47 -0
  71. data/include/natalie_parser/node/not_match_node.hpp +35 -0
  72. data/include/natalie_parser/node/not_node.hpp +37 -0
  73. data/include/natalie_parser/node/nth_ref_node.hpp +27 -0
  74. data/include/natalie_parser/node/op_assign_accessor_node.hpp +74 -0
  75. data/include/natalie_parser/node/op_assign_and_node.hpp +34 -0
  76. data/include/natalie_parser/node/op_assign_node.hpp +47 -0
  77. data/include/natalie_parser/node/op_assign_or_node.hpp +34 -0
  78. data/include/natalie_parser/node/pin_node.hpp +33 -0
  79. data/include/natalie_parser/node/range_node.hpp +52 -0
  80. data/include/natalie_parser/node/redo_node.hpp +20 -0
  81. data/include/natalie_parser/node/regexp_node.hpp +36 -0
  82. data/include/natalie_parser/node/retry_node.hpp +20 -0
  83. data/include/natalie_parser/node/return_node.hpp +34 -0
  84. data/include/natalie_parser/node/safe_call_node.hpp +31 -0
  85. data/include/natalie_parser/node/sclass_node.hpp +37 -0
  86. data/include/natalie_parser/node/self_node.hpp +23 -0
  87. data/include/natalie_parser/node/shadow_arg_node.hpp +40 -0
  88. data/include/natalie_parser/node/shell_node.hpp +32 -0
  89. data/include/natalie_parser/node/splat_node.hpp +39 -0
  90. data/include/natalie_parser/node/splat_value_node.hpp +32 -0
  91. data/include/natalie_parser/node/stabby_proc_node.hpp +29 -0
  92. data/include/natalie_parser/node/string_node.hpp +42 -0
  93. data/include/natalie_parser/node/super_node.hpp +44 -0
  94. data/include/natalie_parser/node/symbol_key_node.hpp +19 -0
  95. data/include/natalie_parser/node/symbol_node.hpp +30 -0
  96. data/include/natalie_parser/node/to_array_node.hpp +33 -0
  97. data/include/natalie_parser/node/true_node.hpp +23 -0
  98. data/include/natalie_parser/node/unary_op_node.hpp +41 -0
  99. data/include/natalie_parser/node/undef_node.hpp +31 -0
  100. data/include/natalie_parser/node/until_node.hpp +21 -0
  101. data/include/natalie_parser/node/while_node.hpp +52 -0
  102. data/include/natalie_parser/node/yield_node.hpp +29 -0
  103. data/include/natalie_parser/node.hpp +89 -0
  104. data/include/natalie_parser/parser.hpp +218 -0
  105. data/include/natalie_parser/token.hpp +842 -0
  106. data/include/tm/defer.hpp +34 -0
  107. data/include/tm/hashmap.hpp +826 -0
  108. data/include/tm/macros.hpp +16 -0
  109. data/include/tm/optional.hpp +223 -0
  110. data/include/tm/owned_ptr.hpp +186 -0
  111. data/include/tm/recursion_guard.hpp +156 -0
  112. data/include/tm/shared_ptr.hpp +259 -0
  113. data/include/tm/string.hpp +1447 -0
  114. data/include/tm/tests.hpp +78 -0
  115. data/include/tm/vector.hpp +796 -0
  116. data/lib/natalie_parser/sexp.rb +36 -0
  117. data/lib/natalie_parser/version.rb +5 -0
  118. data/lib/natalie_parser.rb +3 -0
  119. data/natalie_parser.gemspec +23 -0
  120. data/src/lexer/interpolated_string_lexer.cpp +88 -0
  121. data/src/lexer/regexp_lexer.cpp +95 -0
  122. data/src/lexer/word_array_lexer.cpp +134 -0
  123. data/src/lexer.cpp +1703 -0
  124. data/src/node/alias_node.cpp +11 -0
  125. data/src/node/assignment_node.cpp +33 -0
  126. data/src/node/begin_node.cpp +29 -0
  127. data/src/node/begin_rescue_node.cpp +33 -0
  128. data/src/node/class_node.cpp +22 -0
  129. data/src/node/interpolated_regexp_node.cpp +19 -0
  130. data/src/node/interpolated_shell_node.cpp +25 -0
  131. data/src/node/interpolated_string_node.cpp +111 -0
  132. data/src/node/interpolated_symbol_node.cpp +25 -0
  133. data/src/node/match_node.cpp +14 -0
  134. data/src/node/module_node.cpp +21 -0
  135. data/src/node/multiple_assignment_node.cpp +37 -0
  136. data/src/node/node.cpp +10 -0
  137. data/src/node/node_with_args.cpp +35 -0
  138. data/src/node/op_assign_node.cpp +36 -0
  139. data/src/node/string_node.cpp +33 -0
  140. data/src/parser.cpp +2972 -0
  141. data/src/token.cpp +27 -0
  142. metadata +186 -0
@@ -0,0 +1,796 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <assert.h>
5
+ #include <initializer_list>
6
+ #include <stddef.h>
7
+ #include <string.h>
8
+ #include <type_traits>
9
+
10
+ namespace TM {
11
+
12
+ const int VECTOR_GROW_FACTOR = 2;
13
+ const int VECTOR_MIN_CAPACITY = 10;
14
+
15
+ template <typename T>
16
+ class Vector {
17
+ public:
18
+ /**
19
+ * Constructs an empty vector with the default capacity.
20
+ *
21
+ * ```
22
+ * auto vec = Vector<char> {};
23
+ * assert_eq(0, vec.size());
24
+ * assert_eq(10, vec.capacity());
25
+ * ```
26
+ */
27
+ Vector()
28
+ : m_capacity { VECTOR_MIN_CAPACITY }
29
+ , m_data { array_of_size(VECTOR_MIN_CAPACITY) } { }
30
+
31
+ /**
32
+ * Constructs an empty vector with the given capacity.
33
+ *
34
+ * ```
35
+ * auto vec = Vector<char>(1);
36
+ * assert_eq(0, vec.size());
37
+ * assert_eq(1, vec.capacity());
38
+ * ```
39
+ */
40
+ Vector(size_t initial_capacity)
41
+ : m_capacity { initial_capacity }
42
+ , m_data { array_of_size(initial_capacity) } { }
43
+
44
+ /**
45
+ * Constructs a vector with the given size
46
+ * and every slot filled with the given filler object.
47
+ *
48
+ * ```
49
+ * auto vec = Vector<char>(10, 'a');
50
+ * assert_eq(10, vec.size());
51
+ * assert_eq('a', vec[0]);
52
+ * assert_eq('a', vec[9]);
53
+ * ```
54
+ */
55
+ Vector(size_t size, T filler)
56
+ : m_size { size }
57
+ , m_capacity { size }
58
+ , m_data { array_of_size(size) } {
59
+ fill(0, size, filler);
60
+ }
61
+
62
+ /**
63
+ * Constructs a vector with the given list of items.
64
+ *
65
+ * ```
66
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
67
+ * assert_eq(3, vec.size());
68
+ * ```
69
+ */
70
+ Vector(std::initializer_list<T> list)
71
+ : m_capacity { list.size() }
72
+ , m_data { array_of_size(list.size()) } {
73
+ for (auto v : list) {
74
+ push(v);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Constructs a vector by copying data from another vector.
80
+ *
81
+ * ```
82
+ * auto vec1 = Vector<char> { 'a', 'b', 'c' };
83
+ * auto vec2 = Vector<char>(vec1);
84
+ * assert_eq(3, vec2.size());
85
+ * ```
86
+ */
87
+ Vector(const Vector &other)
88
+ : m_size { other.m_size }
89
+ , m_capacity { other.m_size }
90
+ , m_data { array_of_size(other.m_size) } {
91
+ copy_data(m_data, other.m_data, other.m_size);
92
+ }
93
+
94
+ ~Vector() {
95
+ delete_memory();
96
+ }
97
+
98
+ /**
99
+ * Deletes all the items in the vector.
100
+ *
101
+ * ```
102
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
103
+ * vec.clear();
104
+ * assert_eq(0, vec.size());
105
+ * ```
106
+ */
107
+ void clear() { m_size = 0; }
108
+
109
+ /**
110
+ * Returns a new vector from the given offset and count.
111
+ *
112
+ * ```
113
+ * auto vec1 = Vector<char> { 'a', 'b', 'c', 'd', 'e' };
114
+ * auto vec2 = vec1.slice(2, 2);
115
+ * assert_eq(2, vec2.size());
116
+ * assert_eq('c', vec2[0]);
117
+ * assert_eq('d', vec2[1]);
118
+ * ```
119
+ *
120
+ * If `count` is not specified, then the returned vector
121
+ * will include all items from the index to the end.
122
+ *
123
+ * ```
124
+ * auto vec1 = Vector<char> { 'a', 'b', 'c', 'd', 'e' };
125
+ * auto vec2 = vec1.slice(2);
126
+ * assert_eq(3, vec2.size());
127
+ * assert_eq('c', vec2[0]);
128
+ * assert_eq('d', vec2[1]);
129
+ * assert_eq('e', vec2[2]);
130
+ * ```
131
+ */
132
+ Vector slice(size_t offset, size_t count = 0) {
133
+ if (count == 0 || offset + count > m_size) {
134
+ count = m_size - offset;
135
+ }
136
+ if (offset >= m_size || count == 0) {
137
+ return {};
138
+ }
139
+ T *data = array_of_size(count);
140
+ copy_data(data, m_data + offset, count);
141
+ return { count, count, data };
142
+ }
143
+
144
+ /**
145
+ * Overwrites the vector data with that of another vector.
146
+ *
147
+ * ```
148
+ * auto vec1 = Vector<char> { 'a', 'b', 'c' };
149
+ * auto vec2 = Vector<char> { 'x', 'y', 'z' };
150
+ * vec1 = vec2;
151
+ * assert_eq('y', vec1[1]);
152
+ * ```
153
+ *
154
+ * This method handles non-trivially-copyable types as well:
155
+ *
156
+ * ```
157
+ * auto t1 = Thing(1);
158
+ * auto t2 = Thing(2);
159
+ * auto t3 = Thing(3);
160
+ * auto vec1 = Vector<Thing> { t1, t2, t3 };
161
+ * auto vec2 = Vector<Thing> { t3, t2, t1 };
162
+ * vec1 = vec2;
163
+ * assert_eq(3, vec1.size());
164
+ * assert_eq(t3, vec1[0]);
165
+ * assert_eq(t2, vec1[1]);
166
+ * assert_eq(t1, vec1[2]);
167
+ * ```
168
+ */
169
+ Vector &operator=(Vector &other) {
170
+ clear();
171
+ grow_at_least(other.m_size);
172
+ copy_data(m_data, other.m_data, other.m_size);
173
+ m_size = other.m_size;
174
+ return *this;
175
+ }
176
+
177
+ /**
178
+ * Moves another vector's data into this one.
179
+ * The other vector is left empty.
180
+ *
181
+ * ```
182
+ * auto vec1 = Vector<char> { 'a', 'b', 'c' };
183
+ * auto vec2 = Vector<char> { 'x', 'y', 'z' };
184
+ * vec1 = std::move(vec2);
185
+ * assert_eq('y', vec1[1]);
186
+ * assert_eq(0, vec2.size());
187
+ * ```
188
+ */
189
+ Vector &operator=(Vector &&other) {
190
+ delete_memory();
191
+ m_size = other.m_size;
192
+ m_capacity = other.m_capacity;
193
+ m_data = other.m_data;
194
+ other.m_data = nullptr;
195
+ other.m_size = 0;
196
+ other.m_capacity = 0;
197
+ return *this;
198
+ }
199
+
200
+ /**
201
+ * Returns a reference to the value at the given index.
202
+ *
203
+ * ```
204
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
205
+ * assert_eq('b', vec[1]);
206
+ * ```
207
+ *
208
+ * WARNING: This method does *not* check that the given
209
+ * index is within the bounds of the vector!
210
+ */
211
+ T &operator[](size_t index) const {
212
+ return m_data[index];
213
+ }
214
+
215
+ /**
216
+ * Returns a reference to the value at the given index.
217
+ *
218
+ * ```
219
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
220
+ * assert_eq('b', vec.at(1));
221
+ * ```
222
+ *
223
+ * If the vector is empty, then this method aborts.
224
+ *
225
+ * ```should_abort
226
+ * auto vec = Vector<char> {};
227
+ * vec.at(0);
228
+ * ```
229
+ */
230
+ T &at(size_t index) const {
231
+ assert(index < m_size);
232
+ return m_data[index];
233
+ }
234
+
235
+ /**
236
+ * Returns the value at the front (index 0).
237
+ *
238
+ * ```
239
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
240
+ * assert_eq('a', vec.first());
241
+ * ```
242
+ *
243
+ * If the vector is empty, then this method aborts.
244
+ *
245
+ * ```should_abort
246
+ * auto vec = Vector<char> {};
247
+ * vec.first();
248
+ * ```
249
+ */
250
+ T &first() const {
251
+ assert(m_size != 0);
252
+ return m_data[0];
253
+ }
254
+
255
+ /**
256
+ * Returns the value at the end (at index size() - 1).
257
+ *
258
+ * ```
259
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
260
+ * assert_eq('c', vec.last());
261
+ * ```
262
+ *
263
+ * If the vector is empty, then this method aborts.
264
+ *
265
+ * ```should_abort
266
+ * auto vec = Vector<char> {};
267
+ * vec.last();
268
+ * ```
269
+ */
270
+ T &last() const {
271
+ assert(m_size != 0);
272
+ return m_data[m_size - 1];
273
+ }
274
+
275
+ /**
276
+ * Removes and returns the value at the end (at index size() - 1).
277
+ *
278
+ * ```
279
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
280
+ * assert_eq('c', vec.pop());
281
+ * ```
282
+ *
283
+ * If the vector is empty, then this method aborts.
284
+ *
285
+ * ```should_abort
286
+ * auto vec = Vector<char> {};
287
+ * vec.pop();
288
+ * ```
289
+ */
290
+ T pop() {
291
+ assert(m_size != 0);
292
+ return m_data[--m_size];
293
+ }
294
+
295
+ /**
296
+ * Pushes (appends) a value at the end (at index size()).
297
+ *
298
+ * ```
299
+ * auto vec = Vector<char> { 'a' };
300
+ * vec.push('b');
301
+ * assert_eq('a', vec[0]);
302
+ * assert_eq('b', vec[1]);
303
+ * ```
304
+ */
305
+ void push(T val) {
306
+ size_t len = m_size;
307
+ if (m_size >= m_capacity) {
308
+ grow_at_least(m_size + 1);
309
+ }
310
+ m_size++;
311
+ m_data[len] = val;
312
+ }
313
+
314
+ /**
315
+ * Pushes (inserts) a value at the front (index 0).
316
+ *
317
+ * ```
318
+ * auto vec = Vector<char> { 'b' };
319
+ * vec.push_front('a');
320
+ * assert_eq('a', vec[0]);
321
+ * ```
322
+ */
323
+ void push_front(T val) {
324
+ insert(0, val);
325
+ }
326
+
327
+ /**
328
+ * Inserts a value at the given index.
329
+ * Index must be <= the size of the vector,
330
+ * i.e. you can only increase the vector size by one.
331
+ *
332
+ * ```
333
+ * auto vec = Vector<char>(0);
334
+ * vec.insert(0, 'a');
335
+ * vec.insert(1, 'b');
336
+ * vec.insert(0, 'c');
337
+ * assert_eq(3, vec.size());
338
+ * assert_eq('c', vec[0]);
339
+ * assert_eq('a', vec[1]);
340
+ * assert_eq('b', vec[2]);
341
+ * ```
342
+ *
343
+ * This method aborts if the given index is more than 1
344
+ * past the end.
345
+ *
346
+ * ```should_abort
347
+ * auto vec = Vector<char> { 0 };
348
+ * vec.insert(25, 'z'); // beyond the end
349
+ * ```
350
+ *
351
+ * This method handles non-trivially-copyable types as well:
352
+ *
353
+ * ```
354
+ * auto t1 = Thing(1);
355
+ * auto t2 = Thing(2);
356
+ * auto t3 = Thing(3);
357
+ * auto vec = Vector<Thing> { t1, t2 };
358
+ * vec.insert(0, t3);
359
+ * assert_eq(3, vec.size());
360
+ * assert_eq(t3, vec[0]);
361
+ * assert_eq(t1, vec[1]);
362
+ * assert_eq(t2, vec[2]);
363
+ * ```
364
+ */
365
+ void insert(size_t index, T val) {
366
+ assert(index <= m_size);
367
+ grow_at_least(m_size + 1);
368
+
369
+ if (index == m_size) {
370
+ m_size++;
371
+ m_data[index] = val;
372
+ return;
373
+ }
374
+
375
+ if constexpr (std::is_trivially_copyable<T>::value) {
376
+ memmove(m_data + index + 1, m_data + index, (m_size - index) * sizeof(T));
377
+ } else {
378
+ for (size_t i = m_size - 1; i > index; --i)
379
+ m_data[i + 1] = m_data[i];
380
+ m_data[index + 1] = m_data[index];
381
+ }
382
+
383
+ m_data[index] = val;
384
+ m_size++;
385
+ }
386
+
387
+ /**
388
+ * Removes the item from the front (index 0)
389
+ * and shifts all remaining items over.
390
+ *
391
+ * ```
392
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
393
+ * assert_eq('a', vec.pop_front());
394
+ * ```
395
+ *
396
+ * This method aborts if the vector is empty.
397
+ *
398
+ * ```should_abort
399
+ * auto vec = Vector<char> {};
400
+ * vec.pop_front();
401
+ * ```
402
+ */
403
+ T pop_front() {
404
+ T val = m_data[0];
405
+ remove(0);
406
+ return val;
407
+ }
408
+
409
+ /**
410
+ * Removes an item from the vector at the given index;
411
+ *
412
+ * ```
413
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
414
+ * vec.remove(1);
415
+ * assert_eq('c', vec[1]);
416
+ * ```
417
+ *
418
+ * This method aborts if the index is past the end.
419
+ *
420
+ * ```should_abort
421
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
422
+ * vec.remove(3);
423
+ * ```
424
+ *
425
+ * This method handles non-trivially-copyable types as well:
426
+ *
427
+ * ```
428
+ * auto t1 = Thing(1);
429
+ * auto t2 = Thing(2);
430
+ * auto vec = Vector<Thing> { t1, t2 };
431
+ * vec.remove(0);
432
+ * assert_eq(1, vec.size());
433
+ * assert_eq(t2, vec[0]);
434
+ * ```
435
+ */
436
+ void remove(size_t index) {
437
+ assert(m_size > index);
438
+
439
+ --m_size;
440
+
441
+ if (index == m_size)
442
+ return;
443
+
444
+ if constexpr (std::is_trivially_copyable<T>::value) {
445
+ memmove(m_data + index, m_data + index + 1, (m_size - index) * sizeof(T));
446
+ } else {
447
+ for (size_t i = index; i < m_size; ++i)
448
+ m_data[i] = m_data[i + 1];
449
+ }
450
+ }
451
+
452
+ /**
453
+ * Returns true if the vector has no items.
454
+ *
455
+ * ```
456
+ * auto vec1 = Vector<char> { 'a', 'b', 'c' };
457
+ * assert_eq(false, vec1.is_empty());
458
+ *
459
+ * auto vec2 = Vector<char> {};
460
+ * assert_eq(true, vec2.is_empty());
461
+ * ```
462
+ */
463
+ bool is_empty() const { return m_size == 0; }
464
+
465
+ /**
466
+ * Returns the number of items stored in the vector.
467
+ *
468
+ * ```
469
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
470
+ * assert_eq(3, vec.size());
471
+ * ```
472
+ */
473
+ size_t size() const { return m_size; }
474
+
475
+ /**
476
+ * Returns the size of the currently allocated storage array.
477
+ *
478
+ * ```
479
+ * auto vec = Vector<char>(10);
480
+ * assert_eq(10, vec.capacity());
481
+ * ```
482
+ */
483
+ size_t capacity() const { return m_capacity; }
484
+
485
+ /**
486
+ * Return a pointer to the underlying storage array.
487
+ *
488
+ * ```
489
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
490
+ * char *ary = vec.data();
491
+ * assert_eq('b', ary[1]);
492
+ * ```
493
+ */
494
+ T *data() { return m_data; }
495
+
496
+ /**
497
+ * Fill the given range with a filler value.
498
+ *
499
+ * The 'to' index is exclusive.
500
+ *
501
+ * ```
502
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
503
+ * vec.fill(1, 3, 'z');
504
+ * assert_eq('a', vec[0]);
505
+ * assert_eq('z', vec[1]);
506
+ * assert_eq('z', vec[2]);
507
+ * ```
508
+ *
509
+ * This method aborts if the 'to' index is past the end.
510
+ *
511
+ * ```should_abort
512
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
513
+ * vec.fill(0, 10, 'z');
514
+ * ```
515
+ */
516
+ void fill(size_t from, size_t to_exclusive, T filler) {
517
+ assert(to_exclusive <= m_size);
518
+ for (size_t i = from; i < to_exclusive; i++) {
519
+ m_data[i] = filler;
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Shrink the vector.
525
+ *
526
+ * ```
527
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
528
+ * vec.set_size(2);
529
+ * assert_eq(2, vec.size());
530
+ * assert_eq('a', vec[0]);
531
+ * assert_eq('b', vec[1]);
532
+ * ```
533
+ *
534
+ * This method aborts if the new size is larger.
535
+ *
536
+ * ```should_abort
537
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
538
+ * vec.set_size(10);
539
+ * ```
540
+ */
541
+ void set_size(size_t new_size) {
542
+ assert(new_size <= m_size);
543
+ grow(new_size);
544
+ m_size = new_size;
545
+ }
546
+
547
+ /**
548
+ * Grow or shrink the vector.
549
+ * New slots will be filled with the param `filler`.
550
+ *
551
+ * ```
552
+ * auto vec = Vector<char> { 'a', 'b', 'c' };
553
+ * vec.set_size(10, 'z'); // grow
554
+ * assert_eq('z', vec[9]);
555
+ *
556
+ * vec.set_size(2, 'x'); // shrink
557
+ * assert_eq(2, vec.size());
558
+ * assert_eq('a', vec[0]);
559
+ * assert_eq('b', vec[1]);
560
+ * ```
561
+ */
562
+ void set_size(size_t new_size, T filler) {
563
+ grow(new_size);
564
+ size_t old_size = m_size;
565
+ m_size = new_size;
566
+ fill(old_size, new_size, filler);
567
+ }
568
+
569
+ /**
570
+ * Grow the capacity (allocated memory) of the vector.
571
+ *
572
+ * ```
573
+ * auto vec = Vector<char> {};
574
+ * vec.set_capacity(100);
575
+ * assert_eq(100, vec.capacity());
576
+ * ```
577
+ */
578
+ void set_capacity(size_t new_size) {
579
+ grow_at_least(new_size);
580
+ }
581
+
582
+ class iterator {
583
+ public:
584
+ iterator(const Vector<T> *vector, size_t index)
585
+ : m_vector { vector }
586
+ , m_index { index } { }
587
+
588
+ iterator operator++() {
589
+ m_index++;
590
+ return *this;
591
+ }
592
+
593
+ iterator operator++(int) {
594
+ iterator i = *this;
595
+ m_index++;
596
+ return i;
597
+ }
598
+
599
+ T &operator*() { return m_vector->m_data[m_index]; }
600
+ T *operator->() { return m_vector->m_data[m_index]; }
601
+
602
+ friend bool operator==(const iterator &i1, const iterator &i2) {
603
+ return i1.m_vector == i2.m_vector && i1.m_index == i2.m_index;
604
+ }
605
+
606
+ friend bool operator!=(const iterator &i1, const iterator &i2) {
607
+ return i1.m_vector != i2.m_vector || i1.m_index != i2.m_index;
608
+ }
609
+
610
+ private:
611
+ const Vector<T> *m_vector;
612
+ size_t m_index { 0 };
613
+ };
614
+
615
+ /**
616
+ * Returns an iterator over the vector.
617
+ *
618
+ * ```
619
+ * auto vec1 = Vector<char> { 'a', 'b', 'c' };
620
+ * auto vec2 = Vector<char> {};
621
+ * for (auto c : vec1) {
622
+ * vec2.push(c);
623
+ * }
624
+ * assert_eq('a', vec2[0]);
625
+ * assert_eq('b', vec2[1]);
626
+ * assert_eq('c', vec2[2]);
627
+ * ```
628
+ */
629
+ iterator begin() {
630
+ return iterator { this, 0 };
631
+ }
632
+
633
+ iterator begin() const {
634
+ return iterator { this, 0 };
635
+ }
636
+
637
+ iterator end() {
638
+ return iterator { this, m_size };
639
+ }
640
+
641
+ iterator end() const {
642
+ return iterator { this, m_size };
643
+ }
644
+
645
+ /**
646
+ * Sorts the vector using the given lambda or callable type.
647
+ *
648
+ * ```
649
+ * auto vec = Vector<char> { 'b', 'c', 'a' };
650
+ * vec.sort([](char a, char b) { return a - b < 0; });
651
+ * assert_eq('a', vec[0]);
652
+ * assert_eq('b', vec[1]);
653
+ * assert_eq('c', vec[2]);
654
+ * ```
655
+ */
656
+ template <typename F>
657
+ void sort(F cmp) {
658
+ quicksort(0, m_size - 1, cmp);
659
+ }
660
+
661
+ protected:
662
+ Vector(size_t size, size_t capacity, T *data)
663
+ : m_size(size)
664
+ , m_capacity(capacity)
665
+ , m_data(data) { }
666
+
667
+ static T *array_of_size(size_t size) {
668
+ if constexpr (std::is_trivially_copyable<T>::value)
669
+ return reinterpret_cast<T *>(malloc(size * sizeof(T)));
670
+ else
671
+ return new T[size] {};
672
+ }
673
+
674
+ void grow(size_t capacity) {
675
+ if (m_capacity >= capacity)
676
+ return;
677
+ if constexpr (std::is_trivially_copyable<T>::value) {
678
+ m_data = static_cast<T *>(realloc(m_data, capacity * sizeof(T)));
679
+ } else {
680
+ auto old_data = m_data;
681
+ m_data = new T[capacity] {};
682
+ for (size_t i = 0; i < m_size; ++i)
683
+ m_data[i] = old_data[i];
684
+ delete[] old_data;
685
+ }
686
+ m_capacity = capacity;
687
+ }
688
+
689
+ void grow_at_least(size_t min_capacity) {
690
+ if (m_capacity >= min_capacity) {
691
+ return;
692
+ }
693
+ if (m_capacity > 0 && min_capacity <= m_capacity * VECTOR_GROW_FACTOR) {
694
+ grow(m_capacity * VECTOR_GROW_FACTOR);
695
+ } else {
696
+ grow(min_capacity);
697
+ }
698
+ }
699
+
700
+ template <typename F>
701
+ void quicksort(int start, int end, F cmp) {
702
+ if (start >= end) return;
703
+ int p_index = quicksort_partition(start, end, cmp);
704
+ quicksort(start, p_index - 1, cmp);
705
+ quicksort(p_index + 1, end, cmp);
706
+ }
707
+
708
+ template <typename F>
709
+ int quicksort_partition(int start, int end, F cmp) {
710
+ T pivot = m_data[end];
711
+ int p_index = start;
712
+ T temp;
713
+
714
+ for (int i = start; i < end; i++) {
715
+ if (cmp(m_data[i], pivot)) {
716
+ temp = m_data[i];
717
+ m_data[i] = m_data[p_index];
718
+ m_data[p_index] = temp;
719
+ p_index++;
720
+ }
721
+ }
722
+ temp = m_data[end];
723
+ m_data[end] = m_data[p_index];
724
+ m_data[p_index] = temp;
725
+ return p_index;
726
+ }
727
+
728
+ void copy_data(T *dest, T *src, size_t size) {
729
+ if constexpr (std::is_trivially_copyable<T>::value) {
730
+ memcpy(dest, src, sizeof(T) * size);
731
+ } else {
732
+ for (size_t i = 0; i < size; ++i)
733
+ dest[i] = src[i];
734
+ }
735
+ }
736
+
737
+ void delete_memory() {
738
+ if constexpr (std::is_trivially_copyable<T>::value)
739
+ free(m_data);
740
+ else
741
+ delete[] m_data;
742
+ }
743
+
744
+ size_t m_size { 0 };
745
+ size_t m_capacity { 0 };
746
+ T *m_data { nullptr };
747
+ };
748
+
749
+ template <typename T>
750
+ class OwnedVector : public Vector<T> {
751
+ public:
752
+ /**
753
+ * Constructs an empty OwnedVector with the default capacity.
754
+ *
755
+ * ```
756
+ * {
757
+ * auto vec = OwnedVector<Thing*> {};
758
+ * vec.push(new Thing(1));
759
+ * }
760
+ * // Thing was deleted
761
+ * ```
762
+ */
763
+ ~OwnedVector() {
764
+ if (!m_released) {
765
+ for (auto item : *this) {
766
+ delete item;
767
+ }
768
+ }
769
+ }
770
+
771
+ /**
772
+ * Releases the objects being stored in the vector so they
773
+ * are not destroyed when this OwnedVector is deleted.
774
+ * Calling this effectively turns this OwnedVector into a
775
+ * plain Vector<T>.
776
+ *
777
+ * ```
778
+ * auto thing = new Thing(1);
779
+ * {
780
+ * auto vec = OwnedVector<Thing*> {};
781
+ * vec.push(thing);
782
+ * vec.relese();
783
+ * }
784
+ * assert_eq(1, thing.value());
785
+ * ```
786
+ */
787
+ Vector<T> *release() {
788
+ m_released = true;
789
+ return static_cast<Vector<T> *>(this);
790
+ }
791
+
792
+ private:
793
+ bool m_released { false };
794
+ };
795
+
796
+ }