]>
Commit | Line | Data |
---|---|---|
e27a3c88 KS |
1 | #include <yaml.h> |
2 | ||
3 | #include <stdlib.h> | |
4 | #include <stdio.h> | |
e27a3c88 KS |
5 | #include <string.h> |
6 | ||
01224901 KS |
7 | #ifdef NDEBUG |
8 | #undef NDEBUG | |
9 | #endif | |
10 | #include <assert.h> | |
11 | ||
e27a3c88 KS |
12 | #define BUFFER_SIZE 65536 |
13 | #define MAX_DOCUMENTS 16 | |
14 | ||
15 | int copy_document(yaml_document_t *document_to, yaml_document_t *document_from) | |
16 | { | |
17 | yaml_node_t *node; | |
18 | yaml_node_item_t *item; | |
19 | yaml_node_pair_t *pair; | |
20 | ||
21 | if (!yaml_document_initialize(document_to, document_from->version_directive, | |
22 | document_from->tag_directives.start, | |
23 | document_from->tag_directives.end, | |
24 | document_from->start_implicit, document_from->end_implicit)) | |
25 | return 0; | |
26 | ||
27 | for (node = document_from->nodes.start; | |
28 | node < document_from->nodes.top; node ++) { | |
29 | switch (node->type) { | |
30 | case YAML_SCALAR_NODE: | |
31 | if (!yaml_document_add_scalar(document_to, node->tag, | |
32 | node->data.scalar.value, node->data.scalar.length, | |
33 | node->data.scalar.style)) goto error; | |
34 | break; | |
35 | case YAML_SEQUENCE_NODE: | |
36 | if (!yaml_document_add_sequence(document_to, node->tag, | |
37 | node->data.sequence.style)) goto error; | |
38 | break; | |
39 | case YAML_MAPPING_NODE: | |
40 | if (!yaml_document_add_mapping(document_to, node->tag, | |
41 | node->data.mapping.style)) goto error; | |
42 | break; | |
43 | default: | |
44 | assert(0); | |
45 | break; | |
46 | } | |
47 | } | |
48 | ||
49 | for (node = document_from->nodes.start; | |
50 | node < document_from->nodes.top; node ++) { | |
51 | switch (node->type) { | |
52 | case YAML_SEQUENCE_NODE: | |
53 | for (item = node->data.sequence.items.start; | |
54 | item < node->data.sequence.items.top; item ++) { | |
55 | if (!yaml_document_append_sequence_item(document_to, | |
56 | node - document_from->nodes.start + 1, | |
57 | *item)) goto error; | |
58 | } | |
59 | break; | |
60 | case YAML_MAPPING_NODE: | |
61 | for (pair = node->data.mapping.pairs.start; | |
62 | pair < node->data.mapping.pairs.top; pair ++) { | |
63 | if (!yaml_document_append_mapping_pair(document_to, | |
64 | node - document_from->nodes.start + 1, | |
65 | pair->key, pair->value)) goto error; | |
66 | } | |
67 | break; | |
68 | default: | |
69 | break; | |
70 | } | |
71 | } | |
72 | return 1; | |
73 | ||
74 | error: | |
75 | yaml_document_delete(document_to); | |
76 | return 0; | |
77 | } | |
78 | ||
79 | int compare_nodes(yaml_document_t *document1, int index1, | |
80 | yaml_document_t *document2, int index2) | |
81 | { | |
82 | yaml_node_t *node1 = yaml_document_get_node(document1, index1); | |
83 | yaml_node_t *node2 = yaml_document_get_node(document2, index2); | |
84 | int k; | |
85 | ||
86 | assert(node1); | |
87 | assert(node2); | |
88 | ||
89 | if (node1->type != node2->type) | |
90 | return 0; | |
91 | ||
92 | if (strcmp((char *)node1->tag, (char *)node2->tag) != 0) return 0; | |
93 | ||
94 | switch (node1->type) { | |
95 | case YAML_SCALAR_NODE: | |
96 | if (node1->data.scalar.length != node2->data.scalar.length) | |
97 | return 0; | |
98 | if (strncmp((char *)node1->data.scalar.value, (char *)node2->data.scalar.value, | |
99 | node1->data.scalar.length) != 0) return 0; | |
100 | break; | |
101 | case YAML_SEQUENCE_NODE: | |
102 | if ((node1->data.sequence.items.top - node1->data.sequence.items.start) != | |
103 | (node2->data.sequence.items.top - node2->data.sequence.items.start)) | |
104 | return 0; | |
105 | for (k = 0; k < (node1->data.sequence.items.top - node1->data.sequence.items.start); k ++) { | |
106 | if (!compare_nodes(document1, node1->data.sequence.items.start[k], | |
107 | document2, node2->data.sequence.items.start[k])) return 0; | |
108 | } | |
109 | break; | |
110 | case YAML_MAPPING_NODE: | |
111 | if ((node1->data.mapping.pairs.top - node1->data.mapping.pairs.start) != | |
112 | (node2->data.mapping.pairs.top - node2->data.mapping.pairs.start)) | |
113 | return 0; | |
114 | for (k = 0; k < (node1->data.mapping.pairs.top - node1->data.mapping.pairs.start); k ++) { | |
115 | if (!compare_nodes(document1, node1->data.mapping.pairs.start[k].key, | |
116 | document2, node2->data.mapping.pairs.start[k].key)) return 0; | |
117 | if (!compare_nodes(document1, node1->data.mapping.pairs.start[k].value, | |
118 | document2, node2->data.mapping.pairs.start[k].value)) return 0; | |
119 | } | |
120 | break; | |
01224901 KS |
121 | default: |
122 | assert(0); | |
123 | break; | |
e27a3c88 KS |
124 | } |
125 | return 1; | |
126 | } | |
127 | ||
128 | int compare_documents(yaml_document_t *document1, yaml_document_t *document2) | |
129 | { | |
130 | int k; | |
131 | ||
132 | if ((document1->version_directive && !document2->version_directive) | |
133 | || (!document1->version_directive && document2->version_directive) | |
134 | || (document1->version_directive && document2->version_directive | |
135 | && (document1->version_directive->major != document2->version_directive->major | |
136 | || document1->version_directive->minor != document2->version_directive->minor))) | |
137 | return 0; | |
138 | ||
139 | if ((document1->tag_directives.end - document1->tag_directives.start) != | |
140 | (document2->tag_directives.end - document2->tag_directives.start)) | |
141 | return 0; | |
142 | for (k = 0; k < (document1->tag_directives.end - document1->tag_directives.start); k ++) { | |
143 | if ((strcmp((char *)document1->tag_directives.start[k].handle, | |
144 | (char *)document2->tag_directives.start[k].handle) != 0) | |
145 | || (strcmp((char *)document1->tag_directives.start[k].prefix, | |
146 | (char *)document2->tag_directives.start[k].prefix) != 0)) | |
147 | return 0; | |
148 | } | |
149 | ||
150 | if ((document1->nodes.top - document1->nodes.start) != | |
151 | (document2->nodes.top - document2->nodes.start)) | |
152 | return 0; | |
153 | ||
154 | if (document1->nodes.top != document1->nodes.start) { | |
155 | if (!compare_nodes(document1, 1, document2, 1)) | |
156 | return 0; | |
157 | } | |
158 | ||
159 | return 1; | |
160 | } | |
161 | ||
162 | int print_output(char *name, unsigned char *buffer, size_t size, int count) | |
163 | { | |
164 | FILE *file; | |
165 | char data[BUFFER_SIZE]; | |
166 | size_t data_size = 1; | |
167 | size_t total_size = 0; | |
168 | if (count >= 0) { | |
169 | printf("FAILED (at the document #%d)\nSOURCE:\n", count+1); | |
170 | } | |
171 | file = fopen(name, "rb"); | |
172 | assert(file); | |
173 | while (data_size > 0) { | |
174 | data_size = fread(data, 1, BUFFER_SIZE, file); | |
175 | assert(!ferror(file)); | |
176 | if (!data_size) break; | |
177 | assert(fwrite(data, 1, data_size, stdout) == data_size); | |
178 | total_size += data_size; | |
179 | if (feof(file)) break; | |
180 | } | |
181 | fclose(file); | |
182 | printf("#### (length: %d)\n", total_size); | |
183 | printf("OUTPUT:\n%s#### (length: %d)\n", buffer, size); | |
184 | return 0; | |
185 | } | |
186 | ||
187 | int | |
188 | main(int argc, char *argv[]) | |
189 | { | |
190 | int number; | |
191 | int canonical = 0; | |
192 | int unicode = 0; | |
193 | ||
194 | number = 1; | |
195 | while (number < argc) { | |
196 | if (strcmp(argv[number], "-c") == 0) { | |
197 | canonical = 1; | |
198 | } | |
199 | else if (strcmp(argv[number], "-u") == 0) { | |
200 | unicode = 1; | |
201 | } | |
202 | else if (argv[number][0] == '-') { | |
203 | printf("Unknown option: '%s'\n", argv[number]); | |
204 | return 0; | |
205 | } | |
206 | if (argv[number][0] == '-') { | |
207 | if (number < argc-1) { | |
208 | memmove(argv+number, argv+number+1, (argc-number-1)*sizeof(char *)); | |
209 | } | |
210 | argc --; | |
211 | } | |
212 | else { | |
213 | number ++; | |
214 | } | |
215 | } | |
216 | ||
217 | if (argc < 2) { | |
218 | printf("Usage: %s [-c] [-u] file1.yaml ...\n", argv[0]); | |
219 | return 0; | |
220 | } | |
221 | ||
222 | for (number = 1; number < argc; number ++) | |
223 | { | |
224 | FILE *file; | |
225 | yaml_parser_t parser; | |
226 | yaml_emitter_t emitter; | |
227 | ||
228 | yaml_document_t document; | |
229 | unsigned char buffer[BUFFER_SIZE]; | |
230 | size_t written = 0; | |
231 | yaml_document_t documents[MAX_DOCUMENTS]; | |
232 | size_t document_number = 0; | |
233 | int done = 0; | |
234 | int count = 0; | |
235 | int error = 0; | |
236 | int k; | |
237 | memset(buffer, 0, BUFFER_SIZE); | |
238 | memset(documents, 0, MAX_DOCUMENTS*sizeof(yaml_document_t)); | |
239 | ||
240 | printf("[%d] Loading, dumping, and loading again '%s': ", number, argv[number]); | |
241 | fflush(stdout); | |
242 | ||
243 | file = fopen(argv[number], "rb"); | |
244 | assert(file); | |
245 | ||
246 | assert(yaml_parser_initialize(&parser)); | |
247 | yaml_parser_set_input_file(&parser, file); | |
248 | assert(yaml_emitter_initialize(&emitter)); | |
249 | if (canonical) { | |
250 | yaml_emitter_set_canonical(&emitter, 1); | |
251 | } | |
252 | if (unicode) { | |
253 | yaml_emitter_set_unicode(&emitter, 1); | |
254 | } | |
255 | yaml_emitter_set_output_string(&emitter, buffer, BUFFER_SIZE, &written); | |
256 | yaml_emitter_open(&emitter); | |
257 | ||
258 | while (!done) | |
259 | { | |
260 | if (!yaml_parser_load(&parser, &document)) { | |
261 | error = 1; | |
262 | break; | |
263 | } | |
264 | ||
265 | done = (!yaml_document_get_root_node(&document)); | |
266 | if (!done) { | |
267 | assert(document_number < MAX_DOCUMENTS); | |
268 | assert(copy_document(&(documents[document_number++]), &document)); | |
269 | assert(yaml_emitter_dump(&emitter, &document) || | |
270 | (yaml_emitter_flush(&emitter) && print_output(argv[number], buffer, written, count))); | |
271 | count ++; | |
272 | } | |
273 | else { | |
274 | yaml_document_delete(&document); | |
275 | } | |
276 | } | |
277 | ||
278 | yaml_parser_delete(&parser); | |
279 | assert(!fclose(file)); | |
280 | yaml_emitter_close(&emitter); | |
281 | yaml_emitter_delete(&emitter); | |
282 | ||
283 | if (!error) | |
284 | { | |
285 | count = done = 0; | |
286 | assert(yaml_parser_initialize(&parser)); | |
287 | yaml_parser_set_input_string(&parser, buffer, written); | |
288 | ||
289 | while (!done) | |
290 | { | |
291 | assert(yaml_parser_load(&parser, &document) || print_output(argv[number], buffer, written, count)); | |
292 | done = (!yaml_document_get_root_node(&document)); | |
293 | if (!done) { | |
294 | assert(compare_documents(documents+count, &document) || print_output(argv[number], buffer, written, count)); | |
295 | count ++; | |
296 | } | |
297 | yaml_document_delete(&document); | |
298 | } | |
299 | yaml_parser_delete(&parser); | |
300 | } | |
301 | ||
302 | for (k = 0; k < document_number; k ++) { | |
303 | yaml_document_delete(documents+k); | |
304 | } | |
305 | ||
306 | printf("PASSED (length: %d)\n", written); | |
307 | print_output(argv[number], buffer, written, -1); | |
308 | } | |
309 | ||
310 | return 0; | |
311 | } |