]>
Commit | Line | Data |
---|---|---|
b3043c48 KS |
1 | #include <yaml.h> |
2 | ||
3 | #include <stdlib.h> | |
4 | #include <stdio.h> | |
5 | #include <assert.h> | |
6 | #include <string.h> | |
7 | ||
8 | #define BUFFER_SIZE 65536 | |
9 | #define MAX_EVENTS 1024 | |
10 | ||
11 | int copy_event(yaml_event_t *event_to, yaml_event_t *event_from) | |
12 | { | |
13 | switch (event_from->type) | |
14 | { | |
15 | case YAML_STREAM_START_EVENT: | |
16 | return yaml_stream_start_event_initialize(event_to, | |
17 | event_from->data.stream_start.encoding); | |
18 | ||
19 | case YAML_STREAM_END_EVENT: | |
20 | return yaml_stream_end_event_initialize(event_to); | |
21 | ||
22 | case YAML_DOCUMENT_START_EVENT: | |
23 | return yaml_document_start_event_initialize(event_to, | |
24 | event_from->data.document_start.version_directive, | |
25 | event_from->data.document_start.tag_directives.start, | |
26 | event_from->data.document_start.tag_directives.end, | |
27 | event_from->data.document_start.implicit); | |
28 | ||
29 | case YAML_DOCUMENT_END_EVENT: | |
30 | return yaml_document_end_event_initialize(event_to, | |
31 | event_from->data.document_end.implicit); | |
32 | ||
33 | case YAML_ALIAS_EVENT: | |
34 | return yaml_alias_event_initialize(event_to, | |
35 | event_from->data.alias.anchor); | |
36 | ||
37 | case YAML_SCALAR_EVENT: | |
38 | return yaml_scalar_event_initialize(event_to, | |
39 | event_from->data.scalar.anchor, | |
40 | event_from->data.scalar.tag, | |
41 | event_from->data.scalar.value, | |
42 | event_from->data.scalar.length, | |
43 | event_from->data.scalar.plain_implicit, | |
44 | event_from->data.scalar.quoted_implicit, | |
45 | event_from->data.scalar.style); | |
46 | ||
47 | case YAML_SEQUENCE_START_EVENT: | |
48 | return yaml_sequence_start_event_initialize(event_to, | |
49 | event_from->data.sequence_start.anchor, | |
50 | event_from->data.sequence_start.tag, | |
51 | event_from->data.sequence_start.implicit, | |
52 | event_from->data.sequence_start.style); | |
53 | ||
54 | case YAML_SEQUENCE_END_EVENT: | |
55 | return yaml_sequence_end_event_initialize(event_to); | |
56 | ||
57 | case YAML_MAPPING_START_EVENT: | |
58 | return yaml_mapping_start_event_initialize(event_to, | |
59 | event_from->data.mapping_start.anchor, | |
60 | event_from->data.mapping_start.tag, | |
61 | event_from->data.mapping_start.implicit, | |
62 | event_from->data.mapping_start.style); | |
63 | ||
64 | case YAML_MAPPING_END_EVENT: | |
65 | return yaml_mapping_end_event_initialize(event_to); | |
66 | ||
67 | default: | |
68 | assert(1); | |
69 | } | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | int compare_events(yaml_event_t *event1, yaml_event_t *event2) | |
75 | { | |
76 | int k; | |
77 | ||
78 | if (event1->type != event2->type) | |
79 | return 0; | |
80 | ||
81 | switch (event1->type) | |
82 | { | |
83 | case YAML_STREAM_START_EVENT: | |
84 | return 1; | |
85 | /* return (event1->data.stream_start.encoding == | |
86 | event2->data.stream_start.encoding); */ | |
87 | ||
88 | case YAML_DOCUMENT_START_EVENT: | |
89 | if ((event1->data.document_start.version_directive && !event2->data.document_start.version_directive) | |
90 | || (!event1->data.document_start.version_directive && event2->data.document_start.version_directive) | |
91 | || (event1->data.document_start.version_directive && event2->data.document_start.version_directive | |
92 | && (event1->data.document_start.version_directive->major != event2->data.document_start.version_directive->major | |
93 | || event1->data.document_start.version_directive->minor != event2->data.document_start.version_directive->minor))) | |
94 | return 0; | |
95 | if ((event1->data.document_start.tag_directives.end - event1->data.document_start.tag_directives.start) != | |
96 | (event2->data.document_start.tag_directives.end - event2->data.document_start.tag_directives.start)) | |
97 | return 0; | |
98 | for (k = 0; k < (event1->data.document_start.tag_directives.end - event1->data.document_start.tag_directives.start); k ++) { | |
99 | if ((strcmp((char *)event1->data.document_start.tag_directives.start[k].handle, | |
100 | (char *)event2->data.document_start.tag_directives.start[k].handle) != 0) | |
101 | || (strcmp((char *)event1->data.document_start.tag_directives.start[k].prefix, | |
102 | (char *)event2->data.document_start.tag_directives.start[k].prefix) != 0)) | |
103 | return 0; | |
104 | } | |
105 | /* if (event1->data.document_start.implicit != event2->data.document_start.implicit) | |
106 | return 0; */ | |
107 | return 1; | |
108 | ||
109 | case YAML_DOCUMENT_END_EVENT: | |
110 | return 1; | |
111 | /* return (event1->data.document_end.implicit == | |
112 | event2->data.document_end.implicit); */ | |
113 | ||
114 | case YAML_ALIAS_EVENT: | |
115 | return (strcmp((char *)event1->data.alias.anchor, | |
116 | (char *)event2->data.alias.anchor) == 0); | |
117 | ||
118 | case YAML_SCALAR_EVENT: | |
119 | if ((event1->data.scalar.anchor && !event2->data.scalar.anchor) | |
120 | || (!event1->data.scalar.anchor && event2->data.scalar.anchor) | |
121 | || (event1->data.scalar.anchor && event2->data.scalar.anchor | |
122 | && strcmp((char *)event1->data.scalar.anchor, | |
123 | (char *)event2->data.scalar.anchor) != 0)) | |
124 | return 0; | |
125 | if ((event1->data.scalar.tag && !event2->data.scalar.tag | |
126 | && strcmp((char *)event1->data.scalar.tag, "!") != 0) | |
127 | || (!event1->data.scalar.tag && event2->data.scalar.tag | |
128 | && strcmp((char *)event2->data.scalar.tag, "!") != 0) | |
129 | || (event1->data.scalar.tag && event2->data.scalar.tag | |
130 | && strcmp((char *)event1->data.scalar.tag, | |
131 | (char *)event2->data.scalar.tag) != 0)) | |
132 | return 0; | |
133 | if ((event1->data.scalar.length != event2->data.scalar.length) | |
134 | || memcmp(event1->data.scalar.value, event2->data.scalar.value, | |
135 | event1->data.scalar.length) != 0) | |
136 | return 0; | |
137 | if ((event1->data.scalar.plain_implicit != event2->data.scalar.plain_implicit) | |
138 | || (event2->data.scalar.quoted_implicit != event2->data.scalar.quoted_implicit) | |
139 | /* || (event2->data.scalar.style != event2->data.scalar.style) */) | |
140 | return 0; | |
141 | return 1; | |
142 | ||
143 | case YAML_SEQUENCE_START_EVENT: | |
144 | if ((event1->data.sequence_start.anchor && !event2->data.sequence_start.anchor) | |
145 | || (!event1->data.sequence_start.anchor && event2->data.sequence_start.anchor) | |
146 | || (event1->data.sequence_start.anchor && event2->data.sequence_start.anchor | |
147 | && strcmp((char *)event1->data.sequence_start.anchor, | |
148 | (char *)event2->data.sequence_start.anchor) != 0)) | |
149 | return 0; | |
150 | if ((event1->data.sequence_start.tag && !event2->data.sequence_start.tag) | |
151 | || (!event1->data.sequence_start.tag && event2->data.sequence_start.tag) | |
152 | || (event1->data.sequence_start.tag && event2->data.sequence_start.tag | |
153 | && strcmp((char *)event1->data.sequence_start.tag, | |
154 | (char *)event2->data.sequence_start.tag) != 0)) | |
155 | return 0; | |
156 | if ((event1->data.sequence_start.implicit != event2->data.sequence_start.implicit) | |
157 | /* || (event2->data.sequence_start.style != event2->data.sequence_start.style) */) | |
158 | return 0; | |
159 | return 1; | |
160 | ||
161 | case YAML_MAPPING_START_EVENT: | |
162 | if ((event1->data.mapping_start.anchor && !event2->data.mapping_start.anchor) | |
163 | || (!event1->data.mapping_start.anchor && event2->data.mapping_start.anchor) | |
164 | || (event1->data.mapping_start.anchor && event2->data.mapping_start.anchor | |
165 | && strcmp((char *)event1->data.mapping_start.anchor, | |
166 | (char *)event2->data.mapping_start.anchor) != 0)) | |
167 | return 0; | |
168 | if ((event1->data.mapping_start.tag && !event2->data.mapping_start.tag) | |
169 | || (!event1->data.mapping_start.tag && event2->data.mapping_start.tag) | |
170 | || (event1->data.mapping_start.tag && event2->data.mapping_start.tag | |
171 | && strcmp((char *)event1->data.mapping_start.tag, | |
172 | (char *)event2->data.mapping_start.tag) != 0)) | |
173 | return 0; | |
174 | if ((event1->data.mapping_start.implicit != event2->data.mapping_start.implicit) | |
175 | /* || (event2->data.mapping_start.style != event2->data.mapping_start.style) */) | |
176 | return 0; | |
177 | return 1; | |
178 | ||
179 | default: | |
180 | return 1; | |
181 | } | |
182 | } | |
183 | ||
184 | int print_output(char *name, unsigned char *buffer, size_t size, int count) | |
185 | { | |
186 | FILE *file; | |
187 | char data[BUFFER_SIZE]; | |
188 | size_t data_size = 1; | |
189 | size_t total_size = 0; | |
190 | if (count >= 0) { | |
191 | printf("FAILED (at the event #%d)\nSOURCE:\n", count+1); | |
192 | } | |
193 | file = fopen(name, "rb"); | |
194 | assert(file); | |
195 | while (data_size > 0) { | |
196 | data_size = fread(data, 1, BUFFER_SIZE, file); | |
197 | assert(!ferror(file)); | |
198 | if (!data_size) break; | |
199 | assert(fwrite(data, 1, data_size, stdout) == data_size); | |
200 | total_size += data_size; | |
201 | if (feof(file)) break; | |
202 | } | |
203 | fclose(file); | |
204 | printf("#### (length: %d)\n", total_size); | |
205 | printf("OUTPUT:\n%s#### (length: %d)\n", buffer, size); | |
206 | return 0; | |
207 | } | |
208 | ||
209 | int | |
210 | main(int argc, char *argv[]) | |
211 | { | |
212 | int number; | |
213 | int canonical = 0; | |
214 | int unicode = 0; | |
215 | ||
216 | number = 1; | |
217 | while (number < argc) { | |
218 | if (strcmp(argv[number], "-c") == 0) { | |
219 | canonical = 1; | |
220 | } | |
221 | else if (strcmp(argv[number], "-u") == 0) { | |
222 | unicode = 1; | |
223 | } | |
224 | else if (argv[number][0] == '-') { | |
225 | printf("Unknown option: '%s'\n", argv[number]); | |
226 | return 0; | |
227 | } | |
228 | if (argv[number][0] == '-') { | |
229 | if (number < argc-1) { | |
230 | memmove(argv+number, argv+number+1, (argc-number-1)*sizeof(char *)); | |
231 | } | |
232 | argc --; | |
233 | } | |
234 | else { | |
235 | number ++; | |
236 | } | |
237 | } | |
238 | ||
239 | if (argc < 2) { | |
240 | printf("Usage: %s [-c] [-u] file1.yaml ...\n", argv[0]); | |
241 | return 0; | |
242 | } | |
243 | ||
244 | for (number = 1; number < argc; number ++) | |
245 | { | |
246 | FILE *file; | |
247 | yaml_parser_t parser; | |
248 | yaml_emitter_t emitter; | |
249 | yaml_event_t event; | |
250 | unsigned char buffer[BUFFER_SIZE]; | |
251 | size_t written = 0; | |
252 | yaml_event_t events[MAX_EVENTS]; | |
253 | size_t event_number = 0; | |
254 | int done = 0; | |
255 | int count = 0; | |
256 | int error = 0; | |
257 | int k; | |
258 | memset(buffer, 0, BUFFER_SIZE); | |
259 | memset(events, 0, MAX_EVENTS); | |
260 | ||
261 | printf("[%d] Parsing, emitting, and parsing again '%s': ", number, argv[number]); | |
262 | fflush(stdout); | |
263 | ||
264 | file = fopen(argv[number], "rb"); | |
265 | assert(file); | |
266 | ||
267 | assert(yaml_parser_initialize(&parser)); | |
268 | yaml_parser_set_input_file(&parser, file); | |
269 | assert(yaml_emitter_initialize(&emitter)); | |
270 | if (canonical) { | |
271 | yaml_emitter_set_canonical(&emitter, 1); | |
272 | } | |
273 | if (unicode) { | |
274 | yaml_emitter_set_unicode(&emitter, 1); | |
275 | } | |
276 | yaml_emitter_set_output_string(&emitter, buffer, BUFFER_SIZE, &written); | |
277 | ||
278 | while (!done) | |
279 | { | |
280 | if (!yaml_parser_parse(&parser, &event)) { | |
281 | error = 1; | |
282 | break; | |
283 | } | |
284 | ||
285 | done = (event.type == YAML_STREAM_END_EVENT); | |
286 | assert(event_number < MAX_EVENTS); | |
287 | assert(copy_event(&(events[event_number++]), &event)); | |
288 | assert(yaml_emitter_emit(&emitter, &event) || | |
289 | (yaml_emitter_flush(&emitter) && print_output(argv[number], buffer, written, count))); | |
290 | count ++; | |
291 | } | |
292 | ||
293 | yaml_parser_delete(&parser); | |
294 | assert(!fclose(file)); | |
295 | yaml_emitter_delete(&emitter); | |
296 | ||
297 | if (!error) | |
298 | { | |
299 | count = done = 0; | |
300 | assert(yaml_parser_initialize(&parser)); | |
301 | yaml_parser_set_input_string(&parser, buffer, written); | |
302 | ||
303 | while (!done) | |
304 | { | |
305 | assert(yaml_parser_parse(&parser, &event) || print_output(argv[number], buffer, written, count)); | |
306 | done = (event.type == YAML_STREAM_END_EVENT); | |
307 | assert(compare_events(events+count, &event) || print_output(argv[number], buffer, written, count)); | |
308 | yaml_event_delete(&event); | |
309 | count ++; | |
310 | } | |
311 | yaml_parser_delete(&parser); | |
312 | } | |
313 | ||
314 | for (k = 0; k < event_number; k ++) { | |
315 | yaml_event_delete(events+k); | |
316 | } | |
317 | ||
318 | printf("PASSED (length: %d)\n", written); | |
319 | print_output(argv[number], buffer, written, -1); | |
320 | } | |
321 | ||
322 | return 0; | |
323 | } |