Skip to content

Commit 12fb2e3

Browse files
authored
Merge pull request #17 from asdf-format/issue-15
Implement lazy YAML parsing
2 parents 945c596 + f02f20e commit 12fb2e3

22 files changed

+1156
-166
lines changed

Makefile.am

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
AM_CFLAGS = # CFLAGS applicable to all executables (products)
1+
AM_CFLAGS = -fvisibility=hidden
22
AM_CPPFLAGS = -I$(top_srcdir)/src # so that tests also find header files
33
ACLOCAL_AMFLAGS = -Im4
44

5-
src_files = src/block.c src/event.c src/info.c src/parse.c src/yaml.c
6-
src_headers = src/block.h src/event.h src/info.h src/parse.h src/yaml.h
5+
src_files = src/block.c src/event.c src/info.c src/parse.c src/parse_util.c src/yaml.c
6+
src_headers = src/block.h src/event.h src/info.h src/parse.h src/parse_util.h src/yaml.h
77

88
noinst_HEADERS = $(src_headers)
99

@@ -37,8 +37,7 @@ tidy:
3737

3838
CODE_COVERAGE_IGNORE_PATTERN = \
3939
$(abs_top_srcdir)/tests/* \
40-
$(abs_top_srcdir)/tests/munit/* \
41-
/usr/include/x86_64-linux-gnu/bits/*
40+
$(abs_top_srcdir)/tests/munit/*
4241

4342
# For rules generated by AX_AM_MACROS_STATIC; e.g. code coverage rules
4443
include $(top_srcdir)/aminclude_static.am

src/event.c

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ asdf_event_type_t asdf_event_type(asdf_event_t *event) {
2323
}
2424

2525

26+
const char *asdf_event_comment(const asdf_event_t *event) {
27+
if (!(event && event->type == ASDF_COMMENT_EVENT))
28+
return NULL;
29+
30+
return event->payload.comment;
31+
}
32+
33+
34+
const asdf_tree_info_t *asdf_event_tree_info(const asdf_event_t *event) {
35+
if (!(event && (event->type == ASDF_TREE_START_EVENT || event->type == ASDF_TREE_END_EVENT)))
36+
return NULL;
37+
38+
return event->payload.tree;
39+
}
40+
41+
2642
const asdf_block_info_t *asdf_event_block_info(const asdf_event_t *event) {
2743
if (!(event && event->type == ASDF_BLOCK_EVENT))
2844
return NULL;
@@ -67,6 +83,11 @@ void asdf_event_print(const asdf_event_t *event, FILE *file, bool verbose) {
6783
fprintf(file, " Standard Version: %s\n", event->payload.version->version);
6884
break;
6985

86+
87+
case ASDF_COMMENT_EVENT:
88+
fprintf(file, " Comment: %s\n", event->payload.comment);
89+
break;
90+
7091
case ASDF_YAML_EVENT: {
7192
fprintf(file, " Type: %s\n", asdf_yaml_event_type_text(event));
7293

@@ -85,14 +106,29 @@ void asdf_event_print(const asdf_event_t *event, FILE *file, bool verbose) {
85106
break;
86107
}
87108

109+
case ASDF_TREE_START_EVENT:
110+
fprintf(file, " Tree start position: %zu (0x%zx)\n", event->payload.tree->start,
111+
event->payload.tree->start);
112+
break;
113+
114+
case ASDF_TREE_END_EVENT:
115+
fprintf(file, " Tree end position: %zu (0x%zx)\n", event->payload.tree->end,
116+
event->payload.tree->end);
117+
break;
118+
88119
case ASDF_BLOCK_EVENT: {
89120
const asdf_block_info_t *block = event->payload.block;
90121
const asdf_block_header_t header = block->header;
91-
fprintf(file, " Header position: %" PRId64 "\n", (int64_t)block->header_pos);
92-
fprintf(file, " Data position: %" PRId64 "\n", (int64_t)block->data_pos);
93-
fprintf(file, " Allocated size: %" PRIu64 "\n", header.allocated_size);
94-
fprintf(file, " Used size: %" PRIu64 "\n", header.used_size);
95-
fprintf(file, " Data size: %" PRIu64 "\n", header.data_size);
122+
fprintf(file, " Header position: %" PRId64 " (0x%" PRIx64 ")\n",
123+
(int64_t)block->header_pos, (int64_t)block->header_pos);
124+
fprintf(file, " Data position: %" PRId64 " (0x%" PRIx64 ")\n",
125+
(int64_t)block->data_pos, (int64_t)block->data_pos);
126+
fprintf(file, " Allocated size: %" PRIu64 " (0x%" PRIx64 ")\n",
127+
header.allocated_size, header.allocated_size);
128+
fprintf(file, " Used size: %" PRIu64 " (0x%" PRIx64 ")\n", header.used_size,
129+
header.used_size);
130+
fprintf(file, " Data size: %" PRIu64 " (0x%" PRIx64 ")\n", header.data_size,
131+
header.data_size);
96132

97133
if (header.compression[0] != '\0')
98134
fprintf(file, " Compression: %.4s\n", header.compression);
@@ -114,6 +150,13 @@ void asdf_event_print(const asdf_event_t *event, FILE *file, bool verbose) {
114150
void asdf_event_destroy(asdf_parser_t *parser, asdf_event_t *event) {
115151
assert(event);
116152
switch (event->type) {
153+
case ASDF_TREE_START_EVENT:
154+
case ASDF_TREE_END_EVENT:
155+
if (event->payload.tree)
156+
free(event->payload.tree->buf);
157+
158+
free(event->payload.tree);
159+
break;
117160
case ASDF_YAML_EVENT:
118161
fy_parser_event_free(parser->yaml_parser, event->payload.yaml);
119162
break;
@@ -127,6 +170,9 @@ void asdf_event_destroy(asdf_parser_t *parser, asdf_event_t *event) {
127170
case ASDF_BLOCK_EVENT:
128171
free(event->payload.block);
129172
break;
173+
case ASDF_COMMENT_EVENT:
174+
free(event->payload.comment);
175+
break;
130176
default:
131177
break;
132178
}

src/event.h

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99

1010
#include "block.h"
1111
#include "parse.h"
12+
#include "util.h"
1213
#include "yaml.h"
1314

1415

1516
#define ASDF_EVENT_TYPES(X) \
1617
X(ASDF_NONE_EVENT) \
1718
X(ASDF_BEGIN_EVENT) \
18-
X(ASDF_COMMENT_EVENT) \
1919
X(ASDF_ASDF_VERSION_EVENT) \
2020
X(ASDF_STANDARD_VERSION_EVENT) \
21-
X(ASDF_YAML_VERSION_EVENT) \
21+
X(ASDF_COMMENT_EVENT) \
22+
X(ASDF_TREE_START_EVENT) \
2223
X(ASDF_YAML_EVENT) \
24+
X(ASDF_TREE_END_EVENT) \
2325
X(ASDF_BLOCK_EVENT) \
2426
X(ASDF_PADDING_EVENT) \
2527
X(ASDF_BLOCK_INDEX_EVENT) \
@@ -47,20 +49,36 @@ typedef struct {
4749
} asdf_version_t;
4850

4951

52+
typedef struct {
53+
size_t start;
54+
size_t end;
55+
char *buf;
56+
} asdf_tree_info_t;
57+
58+
5059
typedef struct asdf_event {
5160
asdf_event_type_t type;
5261
union {
53-
asdf_block_info_t *block;
54-
asdf_yaml_event_t *yaml;
62+
// Only if ASDF_*_VERSION_EVENT
5563
asdf_version_t *version;
64+
// Only if ASDF_COMMENT_EVENT
65+
char *comment;
66+
// Only if ASDF_TREE_*_EVENT
67+
asdf_tree_info_t *tree;
68+
// Only if ASDF_YAML_EVENT
69+
asdf_yaml_event_t *yaml;
70+
// Only if ASDF_BLOCK_EVENT
71+
asdf_block_info_t *block;
5672
} payload;
5773
} asdf_event_t;
5874

5975

6076
/* Public API functions */
61-
asdf_event_type_t asdf_event_type(asdf_event_t *event);
62-
const asdf_block_info_t *asdf_event_block_info(const asdf_event_t *event);
63-
int asdf_event_iterate(asdf_parser_t *parser, asdf_event_t *event);
64-
const char *asdf_event_type_name(asdf_event_type_t event_type);
65-
void asdf_event_print(const asdf_event_t *event, FILE *file, bool verbose);
66-
void asdf_event_destroy(asdf_parser_t *parser, asdf_event_t *event);
77+
ASDF_EXPORT asdf_event_type_t asdf_event_type(asdf_event_t *event);
78+
ASDF_EXPORT const char *asdf_event_comment(const asdf_event_t *event);
79+
ASDF_EXPORT const asdf_tree_info_t *asdf_event_tree_info(const asdf_event_t *event);
80+
ASDF_EXPORT const asdf_block_info_t *asdf_event_block_info(const asdf_event_t *event);
81+
ASDF_EXPORT int asdf_event_iterate(asdf_parser_t *parser, asdf_event_t *event);
82+
ASDF_EXPORT const char *asdf_event_type_name(asdf_event_type_t event_type);
83+
ASDF_EXPORT void asdf_event_print(const asdf_event_t *event, FILE *file, bool verbose);
84+
ASDF_EXPORT void asdf_event_destroy(asdf_parser_t *parser, asdf_event_t *event);

src/info.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,12 @@ int asdf_info(FILE *in_file, FILE *out_file, const asdf_info_cfg_t *cfg) {
459459
if (!cfg)
460460
cfg = &ASDF_INFO_DEFAULT_CFG;
461461

462-
if (asdf_parser_init(&parser) != 0)
462+
// Current implementation needs YAML events unless no-tree
463+
asdf_parser_cfg_t parser_cfg = {
464+
.flags = cfg->print_tree ? ASDF_PARSER_OPT_EMIT_YAML_EVENTS : 0
465+
};
466+
467+
if (asdf_parser_init(&parser, &parser_cfg) != 0)
463468
return 1;
464469

465470
if (asdf_parser_set_input_file(&parser, in_file, cfg->filename) != 0) {

src/info.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <stdio.h>
88

9+
#include "util.h"
10+
911

1012
/**
1113
* Optional configuration options for the `asdf_info` function
@@ -17,4 +19,4 @@ typedef struct {
1719
} asdf_info_cfg_t;
1820

1921

20-
int asdf_info(FILE *in_file, FILE *out_file, const asdf_info_cfg_t *cfg);
22+
ASDF_EXPORT int asdf_info(FILE *in_file, FILE *out_file, const asdf_info_cfg_t *cfg);

src/main.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,18 @@ static char events_doc[] = "Print event stream from ASDF parser (for debugging)"
151151
static char events_args_doc[] = "FILENAME";
152152

153153

154+
#define EVENTS_OPT_NO_YAML_KEY 0x100
155+
156+
154157
static struct argp_option events_options[] = {
155-
{"verbose", 'v', 0, 0, "Show extra information about each event", 0}, {0}};
158+
{"verbose", 'v', 0, 0, "Show extra information about each event", 0},
159+
{"no-yaml", EVENTS_OPT_NO_YAML_KEY, 0, 0, "Do not produce YAML stream events", 0}, {0}};
156160

157161

158162
struct events_args {
159163
const char *filename;
160164
bool verbose;
165+
bool no_yaml;
161166
};
162167

163168

@@ -166,6 +171,9 @@ static error_t parse_events_opt(int key, char *arg, struct argp_state *state) {
166171
struct events_args *args = state->input;
167172

168173
switch (key) {
174+
case EVENTS_OPT_NO_YAML_KEY:
175+
args->no_yaml = true;
176+
break;
169177
case 'v':
170178
args->verbose = true;
171179
break;
@@ -190,7 +198,7 @@ static error_t parse_events_opt(int key, char *arg, struct argp_state *state) {
190198
static struct argp events_argp = {events_options, parse_events_opt, events_args_doc, events_doc};
191199

192200

193-
int events_main(const char *filename, bool verbose) {
201+
int events_main(const char *filename, bool verbose, bool no_yaml) {
194202
FILE *file = fopen(filename, "r");
195203

196204
if (!file) {
@@ -199,8 +207,11 @@ int events_main(const char *filename, bool verbose) {
199207
}
200208

201209
asdf_parser_t parser;
210+
// Current implementation always outputs YAML events, so this is needed; later update
211+
// to allow an option to skip YAML events (useful for testing)
212+
asdf_parser_cfg_t parser_cfg = {.flags = no_yaml ? 0 : ASDF_PARSER_OPT_EMIT_YAML_EVENTS};
202213

203-
if (asdf_parser_init(&parser)) {
214+
if (asdf_parser_init(&parser, &parser_cfg)) {
204215
fprintf(stderr, "error: %s\n", asdf_parser_get_error(&parser));
205216
fclose(file);
206217
return EXIT_FAILURE;
@@ -253,7 +264,7 @@ int main(int argc, char *argv[]) {
253264
argp_parse(
254265
&events_argp, global_args.subcmd_argc, global_args.subcmd_argv, 0, NULL, &events_args);
255266

256-
return events_main(events_args.filename, events_args.verbose);
267+
return events_main(events_args.filename, events_args.verbose, events_args.no_yaml);
257268
}
258269
case ASDF_SUBCMD_NONE:
259270
break;

0 commit comments

Comments
 (0)