@@ -52,67 +52,96 @@ extern "C" {
5252
5353// / Reserve `new_capacity` elements of space in the array. If `new_capacity` is
5454// / less than the array's current capacity, this function has no effect.
55- #define array_reserve (self, new_capacity ) \
56- _array__reserve ((Array *)(self), array_elem_size(self), new_capacity)
55+ #define array_reserve (self, new_capacity ) \
56+ ((self)->contents = _array__reserve( \
57+ (void *)(self)->contents, &(self)->capacity, \
58+ array_elem_size (self), new_capacity) \
59+ )
5760
5861// / Free any memory allocated for this array. Note that this does not free any
5962// / memory allocated for the array's contents.
60- #define array_delete (self ) _array__delete((Array *)(self))
63+ #define array_delete (self ) \
64+ do { \
65+ if ((self)->contents ) ts_free ((self)->contents ); \
66+ (self)->contents = NULL ; \
67+ (self)->size = 0 ; \
68+ (self)->capacity = 0 ; \
69+ } while (0 )
6170
6271// / Push a new `element` onto the end of the array.
63- #define array_push (self, element ) \
64- (_array__grow((Array *)(self), 1 , array_elem_size(self)), \
65- (self)->contents[(self)->size++] = (element))
72+ #define array_push (self, element ) \
73+ do { \
74+ (self)->contents = _array__grow ( \
75+ (void *)(self)->contents , (self)->size , &(self)->capacity , \
76+ 1 , array_elem_size (self) \
77+ ); \
78+ (self)->contents [(self)->size ++] = (element); \
79+ } while (0 )
6680
6781// / Increase the array's size by `count` elements.
6882// / New elements are zero-initialized.
69- #define array_grow_by (self, count ) \
70- do { \
71- if ((count) == 0 ) break ; \
72- _array__grow ((Array *)(self), count, array_elem_size (self)); \
83+ #define array_grow_by (self, count ) \
84+ do { \
85+ if ((count) == 0 ) break ; \
86+ (self)->contents = _array__grow ( \
87+ (self)->contents , (self)->size , &(self)->capacity , \
88+ count, array_elem_size (self) \
89+ ); \
7390 memset ((self)->contents + (self)->size , 0 , (count) * array_elem_size (self)); \
74- (self)->size += (count); \
91+ (self)->size += (count); \
7592 } while (0 )
7693
7794// / Append all elements from one array to the end of another.
78- #define array_push_all (self, other ) \
95+ #define array_push_all (self, other ) \
7996 array_extend ((self), (other)->size, (other)->contents)
8097
8198// / Append `count` elements to the end of the array, reading their values from the
8299// / `contents` pointer.
83- #define array_extend (self, count, contents ) \
84- _array__splice ( \
85- (Array *)(self), array_elem_size (self), (self)->size, \
86- 0, count, contents \
100+ #define array_extend (self, count, other_contents ) \
101+ (self)->contents = _array__splice( \
102+ (void *)(self)->contents, & (self)->size, & (self)->capacity, \
103+ array_elem_size (self), (self)->size, 0, count, other_contents \
87104 )
88105
89106// / Remove `old_count` elements from the array starting at the given `index`. At
90107// / the same index, insert `new_count` new elements, reading their values from the
91108// / `new_contents` pointer.
92- #define array_splice (self, _index, old_count, new_count, new_contents ) \
93- _array__splice ( \
94- (Array *)(self), array_elem_size (self), _index, \
95- old_count, new_count, new_contents \
109+ #define array_splice (self, _index, old_count, new_count, new_contents ) \
110+ (self)->contents = _array__splice( \
111+ (void *)(self)->contents, & (self)->size, &(self)->capacity, \
112+ array_elem_size (self), _index, old_count, new_count, new_contents \
96113 )
97114
98115// / Insert one `element` into the array at the given `index`.
99- #define array_insert (self, _index, element ) \
100- _array__splice ((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
116+ #define array_insert (self, _index, element ) \
117+ (self)->contents = _array__splice( \
118+ (void *)(self)->contents, &(self)->size, &(self)->capacity, \
119+ array_elem_size (self), _index, 0, 1, &(element) \
120+ )
101121
102122// / Remove one element from the array at the given `index`.
103123#define array_erase (self, _index ) \
104- _array__erase ((Array *)(self), array_elem_size(self), _index)
124+ _array__erase ((void *)(self)->contents, &(self)->size , array_elem_size(self), _index)
105125
106126// / Pop the last element off the array, returning the element by value.
107127#define array_pop (self ) ((self)->contents[--(self)->size])
108128
109129// / Assign the contents of one array to another, reallocating if necessary.
110- #define array_assign (self, other ) \
111- _array__assign ((Array *)(self), (const Array *)(other), array_elem_size(self))
130+ #define array_assign (self, other ) \
131+ (self)->contents = _array__assign( \
132+ (void *)(self)->contents, &(self)->size, &(self)->capacity, \
133+ (const void *)(other)->contents, (other)->size, array_elem_size(self) \
134+ )
112135
113136// / Swap one array with another
114- #define array_swap (self, other ) \
115- _array__swap ((Array *)(self), (Array *)(other))
137+ #define array_swap (self, other ) \
138+ do { \
139+ void *_array_swap_tmp = (void *)(self)->contents ; \
140+ (self)->contents = (other)->contents ; \
141+ (other)->contents = _array_swap_tmp; \
142+ _array__swap (&(self)->size , &(self)->capacity , \
143+ &(other)->size , &(other)->capacity ); \
144+ } while (0 )
116145
117146// / Get the size of the array contents
118147#define array_elem_size (self ) (sizeof *(self)->contents)
@@ -157,82 +186,90 @@ extern "C" {
157186
158187// Private
159188
160- typedef Array (void ) Array;
161-
162- // / This is not what you're looking for, see `array_delete`.
163- static inline void _array__delete (Array *self) {
164- if (self->contents ) {
165- ts_free (self->contents );
166- self->contents = NULL ;
167- self->size = 0 ;
168- self->capacity = 0 ;
169- }
170- }
189+ // Pointers to individual `Array` fields (rather than the entire `Array` itself)
190+ // are passed to the various `_array__*` functions below to address strict aliasing
191+ // violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`.
192+ //
193+ // The `Array` type itself was not altered as a solution in order to avoid breakage
194+ // with existing consumers (in particular, parsers with external scanners).
171195
172196// / This is not what you're looking for, see `array_erase`.
173- static inline void _array__erase (Array *self, size_t element_size ,
174- uint32_t index) {
175- assert (index < self-> size );
176- char *contents = (char *)self-> contents ;
197+ static inline void _array__erase (void * self_contents, uint32_t *size ,
198+ size_t element_size, uint32_t index) {
199+ assert (index < * size);
200+ char *contents = (char *)self_contents ;
177201 memmove (contents + index * element_size, contents + (index + 1 ) * element_size,
178- (self-> size - index - 1 ) * element_size);
179- self-> size --;
202+ (* size - index - 1 ) * element_size);
203+ (* size) --;
180204}
181205
182206// / This is not what you're looking for, see `array_reserve`.
183- static inline void _array__reserve (Array *self, size_t element_size, uint32_t new_capacity) {
184- if (new_capacity > self->capacity ) {
185- if (self->contents ) {
186- self->contents = ts_realloc (self->contents , new_capacity * element_size);
207+ static inline void *_array__reserve (void *contents, uint32_t *capacity,
208+ size_t element_size, uint32_t new_capacity) {
209+ void *new_contents = contents;
210+ if (new_capacity > *capacity) {
211+ if (contents) {
212+ new_contents = ts_realloc (contents, new_capacity * element_size);
187213 } else {
188- self-> contents = ts_malloc (new_capacity * element_size);
214+ new_contents = ts_malloc (new_capacity * element_size);
189215 }
190- self-> capacity = new_capacity;
216+ * capacity = new_capacity;
191217 }
218+ return new_contents;
192219}
193220
194221// / This is not what you're looking for, see `array_assign`.
195- static inline void _array__assign (Array *self, const Array *other, size_t element_size) {
196- _array__reserve (self, element_size, other->size );
197- self->size = other->size ;
198- memcpy (self->contents , other->contents , self->size * element_size);
222+ static inline void *_array__assign (void * self_contents, uint32_t *self_size, uint32_t *self_capacity,
223+ const void *other_contents, uint32_t other_size, size_t element_size) {
224+ void *new_contents = _array__reserve (self_contents, self_capacity, element_size, other_size);
225+ *self_size = other_size;
226+ memcpy (new_contents, other_contents, *self_size * element_size);
227+ return new_contents;
199228}
200229
201230// / This is not what you're looking for, see `array_swap`.
202- static inline void _array__swap (Array *self, Array *other) {
203- Array swap = *other;
204- *other = *self;
205- *self = swap;
231+ static inline void _array__swap (uint32_t *self_size, uint32_t *self_capacity,
232+ uint32_t *other_size, uint32_t *other_capacity) {
233+ uint32_t tmp_size = *self_size;
234+ uint32_t tmp_capacity = *self_capacity;
235+ *self_size = *other_size;
236+ *self_capacity = *other_capacity;
237+ *other_size = tmp_size;
238+ *other_capacity = tmp_capacity;
206239}
207240
208241// / This is not what you're looking for, see `array_push` or `array_grow_by`.
209- static inline void _array__grow (Array *self, uint32_t count, size_t element_size) {
210- uint32_t new_size = self->size + count;
211- if (new_size > self->capacity ) {
212- uint32_t new_capacity = self->capacity * 2 ;
242+ static inline void *_array__grow (void *contents, uint32_t size, uint32_t *capacity,
243+ uint32_t count, size_t element_size) {
244+ void *new_contents = contents;
245+ uint32_t new_size = size + count;
246+ if (new_size > *capacity) {
247+ uint32_t new_capacity = *capacity * 2 ;
213248 if (new_capacity < 8 ) new_capacity = 8 ;
214249 if (new_capacity < new_size) new_capacity = new_size;
215- _array__reserve (self , element_size, new_capacity);
250+ new_contents = _array__reserve (contents, capacity , element_size, new_capacity);
216251 }
252+ return new_contents;
217253}
218254
219255// / This is not what you're looking for, see `array_splice`.
220- static inline void _array__splice (Array *self, size_t element_size,
256+ static inline void *_array__splice (void *self_contents, uint32_t *size, uint32_t *capacity,
257+ size_t element_size,
221258 uint32_t index, uint32_t old_count,
222259 uint32_t new_count, const void *elements) {
223- uint32_t new_size = self-> size + new_count - old_count;
260+ uint32_t new_size = * size + new_count - old_count;
224261 uint32_t old_end = index + old_count;
225262 uint32_t new_end = index + new_count;
226- assert (old_end <= self-> size );
263+ assert (old_end <= * size);
227264
228- _array__reserve (self , element_size, new_size);
265+ void *new_contents = _array__reserve (self_contents, capacity , element_size, new_size);
229266
230- char *contents = (char *)self-> contents ;
231- if (self-> size > old_end) {
267+ char *contents = (char *)new_contents ;
268+ if (* size > old_end) {
232269 memmove (
233270 contents + new_end * element_size,
234271 contents + old_end * element_size,
235- (self-> size - old_end) * element_size
272+ (* size - old_end) * element_size
236273 );
237274 }
238275 if (new_count > 0 ) {
@@ -250,7 +287,9 @@ static inline void _array__splice(Array *self, size_t element_size,
250287 );
251288 }
252289 }
253- self->size += new_count - old_count;
290+ *size += new_count - old_count;
291+
292+ return new_contents;
254293}
255294
256295// / A binary search routine, based on Rust's `std::slice::binary_search_by`.
0 commit comments