14
14
cmark_node_type CMARK_NODE_TABLE , CMARK_NODE_TABLE_ROW ,
15
15
CMARK_NODE_TABLE_CELL ;
16
16
17
+ typedef struct {
18
+ cmark_strbuf * buf ;
19
+ int start_offset , end_offset , internal_offset ;
20
+ } node_cell ;
21
+
17
22
typedef struct {
18
23
uint16_t n_columns ;
19
24
int paragraph_offset ;
20
- cmark_llist * cells ;
25
+ node_cell * cells ;
21
26
} table_row ;
22
27
23
28
typedef struct {
@@ -29,24 +34,24 @@ typedef struct {
29
34
bool is_header ;
30
35
} node_table_row ;
31
36
32
- typedef struct {
33
- cmark_strbuf * buf ;
34
- int start_offset , end_offset , internal_offset ;
35
- } node_cell ;
36
-
37
- static void free_table_cell (cmark_mem * mem , void * data ) {
38
- node_cell * cell = (node_cell * )data ;
37
+ static void free_table_cell (cmark_mem * mem , node_cell * cell ) {
39
38
cmark_strbuf_free ((cmark_strbuf * )cell -> buf );
40
39
mem -> free (cell -> buf );
41
- mem -> free (cell );
40
+ }
41
+
42
+ static void free_row_cells (cmark_mem * mem , table_row * row ) {
43
+ while (row -> n_columns > 0 ) {
44
+ free_table_cell (mem , & row -> cells [-- row -> n_columns ]);
45
+ }
46
+ mem -> free (row -> cells );
47
+ row -> cells = NULL ;
42
48
}
43
49
44
50
static void free_table_row (cmark_mem * mem , table_row * row ) {
45
51
if (!row )
46
52
return ;
47
53
48
- cmark_llist_free_full (mem , row -> cells , (cmark_free_func )free_table_cell );
49
-
54
+ free_row_cells (mem , row );
50
55
mem -> free (row );
51
56
}
52
57
@@ -152,24 +157,29 @@ static table_row *row_from_string(cmark_syntax_extension *self,
152
157
cell_matched );
153
158
cmark_strbuf_trim (cell_buf );
154
159
155
- node_cell * cell = (node_cell * )parser -> mem -> calloc (1 , sizeof (* cell ));
160
+ const uint32_t n_columns = row -> n_columns + 1 ;
161
+ // realloc when n_columns is a power of 2
162
+ if ((n_columns & (n_columns - 1 )) == 0 ) {
163
+ // make sure we never wrap row->n_columns
164
+ // offset will != len and our exit will clean up as intended
165
+ if (n_columns > UINT16_MAX ) {
166
+ int_overflow_abort = 1 ;
167
+ break ;
168
+ }
169
+ // Use realloc to double the size of the buffer.
170
+ row -> cells = (node_cell * )parser -> mem -> realloc (row -> cells , (2 * n_columns - 1 ) * sizeof (node_cell ));
171
+ }
172
+ row -> n_columns = n_columns ;
173
+ node_cell * cell = & row -> cells [n_columns - 1 ];
156
174
cell -> buf = cell_buf ;
157
175
cell -> start_offset = offset ;
158
176
cell -> end_offset = offset + cell_matched - 1 ;
177
+ cell -> internal_offset = 0 ;
159
178
160
179
while (cell -> start_offset > 0 && string [cell -> start_offset - 1 ] != '|' ) {
161
180
-- cell -> start_offset ;
162
181
++ cell -> internal_offset ;
163
182
}
164
-
165
- // make sure we never wrap row->n_columns
166
- // offset will != len and our exit will clean up as intended
167
- if (row -> n_columns == UINT16_MAX ) {
168
- int_overflow_abort = 1 ;
169
- break ;
170
- }
171
- row -> n_columns += 1 ;
172
- row -> cells = cmark_llist_append (parser -> mem , row -> cells , cell );
173
183
}
174
184
175
185
offset += cell_matched + pipe_matched ;
@@ -187,9 +197,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
187
197
if (row_end_offset && offset != len ) {
188
198
row -> paragraph_offset = offset ;
189
199
190
- cmark_llist_free_full (parser -> mem , row -> cells , (cmark_free_func )free_table_cell );
191
- row -> cells = NULL ;
192
- row -> n_columns = 0 ;
200
+ free_row_cells (parser -> mem , row );
193
201
194
202
// Scan past the (optional) leading pipe.
195
203
offset += scan_table_cell_end (string , len , offset );
@@ -303,9 +311,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
303
311
// since we populate the alignments array based on marker_row->cells
304
312
uint8_t * alignments =
305
313
(uint8_t * )parser -> mem -> calloc (marker_row -> n_columns , sizeof (uint8_t ));
306
- cmark_llist * it = marker_row -> cells ;
307
- for (i = 0 ; it ; it = it -> next , ++ i ) {
308
- node_cell * node = (node_cell * )it -> data ;
314
+ for (i = 0 ; i < marker_row -> n_columns ; ++ i ) {
315
+ node_cell * node = & marker_row -> cells [i ];
309
316
bool left = node -> buf -> ptr [0 ] == ':' , right = node -> buf -> ptr [node -> buf -> size - 1 ] == ':' ;
310
317
311
318
if (left && right )
@@ -328,10 +335,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
328
335
ntr -> is_header = true;
329
336
330
337
{
331
- cmark_llist * tmp ;
332
-
333
- for (tmp = header_row -> cells ; tmp ; tmp = tmp -> next ) {
334
- node_cell * cell = (node_cell * ) tmp -> data ;
338
+ for (i = 0 ; i < header_row -> n_columns ; ++ i ) {
339
+ node_cell * cell = & header_row -> cells [i ];
335
340
cmark_node * header_cell = cmark_parser_add_child (parser , table_header ,
336
341
CMARK_NODE_TABLE_CELL , parent_container -> start_column + cell -> start_offset );
337
342
header_cell -> start_line = header_cell -> end_line = parent_container -> start_line ;
@@ -378,11 +383,10 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
378
383
}
379
384
380
385
{
381
- cmark_llist * tmp ;
382
386
int i , table_columns = get_n_table_columns (parent_container );
383
387
384
- for (tmp = row -> cells , i = 0 ; tmp && i < table_columns ; tmp = tmp -> next , ++ i ) {
385
- node_cell * cell = ( node_cell * ) tmp -> data ;
388
+ for (i = 0 ; i < row -> n_columns && i < table_columns ; ++ i ) {
389
+ node_cell * cell = & row -> cells [ i ] ;
386
390
cmark_node * node = cmark_parser_add_child (parser , table_row_block ,
387
391
CMARK_NODE_TABLE_CELL , parent_container -> start_column + cell -> start_offset );
388
392
node -> internal_offset = cell -> internal_offset ;
0 commit comments