@@ -17,10 +17,15 @@ static cmark_node__internal_flags CMARK_NODE__TABLE_VISITED;
17
17
cmark_node_type CMARK_NODE_TABLE , CMARK_NODE_TABLE_ROW ,
18
18
CMARK_NODE_TABLE_CELL ;
19
19
20
+ typedef struct {
21
+ cmark_strbuf * buf ;
22
+ int start_offset , end_offset , internal_offset ;
23
+ } node_cell ;
24
+
20
25
typedef struct {
21
26
uint16_t n_columns ;
22
27
int paragraph_offset ;
23
- cmark_llist * cells ;
28
+ node_cell * cells ;
24
29
} table_row ;
25
30
26
31
typedef struct {
@@ -32,24 +37,24 @@ typedef struct {
32
37
bool is_header ;
33
38
} node_table_row ;
34
39
35
- typedef struct {
36
- cmark_strbuf * buf ;
37
- int start_offset , end_offset , internal_offset ;
38
- } node_cell ;
39
-
40
- static void free_table_cell (cmark_mem * mem , void * data ) {
41
- node_cell * cell = (node_cell * )data ;
40
+ static void free_table_cell (cmark_mem * mem , node_cell * cell ) {
42
41
cmark_strbuf_free ((cmark_strbuf * )cell -> buf );
43
42
mem -> free (cell -> buf );
44
- mem -> free (cell );
43
+ }
44
+
45
+ static void free_row_cells (cmark_mem * mem , table_row * row ) {
46
+ while (row -> n_columns > 0 ) {
47
+ free_table_cell (mem , & row -> cells [-- row -> n_columns ]);
48
+ }
49
+ mem -> free (row -> cells );
50
+ row -> cells = NULL ;
45
51
}
46
52
47
53
static void free_table_row (cmark_mem * mem , table_row * row ) {
48
54
if (!row )
49
55
return ;
50
56
51
- cmark_llist_free_full (mem , row -> cells , (cmark_free_func )free_table_cell );
52
-
57
+ free_row_cells (mem , row );
53
58
mem -> free (row );
54
59
}
55
60
@@ -114,6 +119,24 @@ static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsi
114
119
return res ;
115
120
}
116
121
122
+ // Adds a new cell to the end of the row. A pointer to the new cell is returned
123
+ // for the caller to initialize.
124
+ static node_cell * append_row_cell (cmark_mem * mem , table_row * row ) {
125
+ const uint32_t n_columns = row -> n_columns + 1 ;
126
+ // realloc when n_columns is a power of 2
127
+ if ((n_columns & (n_columns - 1 )) == 0 ) {
128
+ // make sure we never wrap row->n_columns
129
+ // offset will != len and our exit will clean up as intended
130
+ if (n_columns > UINT16_MAX ) {
131
+ return NULL ;
132
+ }
133
+ // Use realloc to double the size of the buffer.
134
+ row -> cells = (node_cell * )mem -> realloc (row -> cells , (2 * n_columns - 1 ) * sizeof (node_cell ));
135
+ }
136
+ row -> n_columns = n_columns ;
137
+ return & row -> cells [n_columns - 1 ];
138
+ }
139
+
117
140
static table_row * row_from_string (cmark_syntax_extension * self ,
118
141
cmark_parser * parser , unsigned char * string ,
119
142
int len ) {
@@ -155,24 +178,22 @@ static table_row *row_from_string(cmark_syntax_extension *self,
155
178
cell_matched );
156
179
cmark_strbuf_trim (cell_buf );
157
180
158
- node_cell * cell = (node_cell * )parser -> mem -> calloc (1 , sizeof (* cell ));
181
+ node_cell * cell = append_row_cell (parser -> mem , row );
182
+ if (!cell ) {
183
+ int_overflow_abort = 1 ;
184
+ cmark_strbuf_free (cell_buf );
185
+ parser -> mem -> free (cell_buf );
186
+ break ;
187
+ }
159
188
cell -> buf = cell_buf ;
160
189
cell -> start_offset = offset ;
161
190
cell -> end_offset = offset + cell_matched - 1 ;
191
+ cell -> internal_offset = 0 ;
162
192
163
193
while (cell -> start_offset > 0 && string [cell -> start_offset - 1 ] != '|' ) {
164
194
-- cell -> start_offset ;
165
195
++ cell -> internal_offset ;
166
196
}
167
-
168
- // make sure we never wrap row->n_columns
169
- // offset will != len and our exit will clean up as intended
170
- if (row -> n_columns == UINT16_MAX ) {
171
- int_overflow_abort = 1 ;
172
- break ;
173
- }
174
- row -> n_columns += 1 ;
175
- row -> cells = cmark_llist_append (parser -> mem , row -> cells , cell );
176
197
}
177
198
178
199
offset += cell_matched + pipe_matched ;
@@ -190,9 +211,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
190
211
if (row_end_offset && offset != len ) {
191
212
row -> paragraph_offset = offset ;
192
213
193
- cmark_llist_free_full (parser -> mem , row -> cells , (cmark_free_func )free_table_cell );
194
- row -> cells = NULL ;
195
- row -> n_columns = 0 ;
214
+ free_row_cells (parser -> mem , row );
196
215
197
216
// Scan past the (optional) leading pipe.
198
217
offset += scan_table_cell_end (string , len , offset );
@@ -311,9 +330,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
311
330
// since we populate the alignments array based on marker_row->cells
312
331
uint8_t * alignments =
313
332
(uint8_t * )parser -> mem -> calloc (marker_row -> n_columns , sizeof (uint8_t ));
314
- cmark_llist * it = marker_row -> cells ;
315
- for (i = 0 ; it ; it = it -> next , ++ i ) {
316
- node_cell * node = (node_cell * )it -> data ;
333
+ for (i = 0 ; i < marker_row -> n_columns ; ++ i ) {
334
+ node_cell * node = & marker_row -> cells [i ];
317
335
bool left = node -> buf -> ptr [0 ] == ':' , right = node -> buf -> ptr [node -> buf -> size - 1 ] == ':' ;
318
336
319
337
if (left && right )
@@ -336,10 +354,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
336
354
ntr -> is_header = true;
337
355
338
356
{
339
- cmark_llist * tmp ;
340
-
341
- for (tmp = header_row -> cells ; tmp ; tmp = tmp -> next ) {
342
- node_cell * cell = (node_cell * ) tmp -> data ;
357
+ for (i = 0 ; i < header_row -> n_columns ; ++ i ) {
358
+ node_cell * cell = & header_row -> cells [i ];
343
359
cmark_node * header_cell = cmark_parser_add_child (parser , table_header ,
344
360
CMARK_NODE_TABLE_CELL , parent_container -> start_column + cell -> start_offset );
345
361
header_cell -> start_line = header_cell -> end_line = parent_container -> start_line ;
@@ -386,11 +402,10 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
386
402
}
387
403
388
404
{
389
- cmark_llist * tmp ;
390
405
int i , table_columns = get_n_table_columns (parent_container );
391
406
392
- for (tmp = row -> cells , i = 0 ; tmp && i < table_columns ; tmp = tmp -> next , ++ i ) {
393
- node_cell * cell = ( node_cell * ) tmp -> data ;
407
+ for (i = 0 ; i < row -> n_columns && i < table_columns ; ++ i ) {
408
+ node_cell * cell = & row -> cells [ i ] ;
394
409
cmark_node * node = cmark_parser_add_child (parser , table_row_block ,
395
410
CMARK_NODE_TABLE_CELL , parent_container -> start_column + cell -> start_offset );
396
411
node -> internal_offset = cell -> internal_offset ;
0 commit comments