1
2 #include "yaml_private.h"
3
4 /*
5 * Allocate a dynamic memory block.
6 */
7
8 YAML_DECLARE(void *)
yaml_malloc(size_t size)9 yaml_malloc(size_t size)
10 {
11 return malloc(size ? size : 1);
12 }
13
14 /*
15 * Reallocate a dynamic memory block.
16 */
17
18 YAML_DECLARE(void *)
yaml_realloc(void * ptr,size_t size)19 yaml_realloc(void *ptr, size_t size)
20 {
21 return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1);
22 }
23
24 /*
25 * Free a dynamic memory block.
26 */
27
28 YAML_DECLARE(void)
yaml_free(void * ptr)29 yaml_free(void *ptr)
30 {
31 if (ptr) free(ptr);
32 }
33
34 /*
35 * Duplicate a string.
36 */
37
38 YAML_DECLARE(yaml_char_t *)
yaml_strdup(const yaml_char_t * str)39 yaml_strdup(const yaml_char_t *str)
40 {
41 if (!str)
42 return NULL;
43
44 return (yaml_char_t *)strdup((char *)str);
45 }
46
47 /*
48 * Extend a string.
49 */
50
51 YAML_DECLARE(int)
yaml_string_extend(yaml_char_t ** start,yaml_char_t ** pointer,yaml_char_t ** end)52 yaml_string_extend(yaml_char_t **start,
53 yaml_char_t **pointer, yaml_char_t **end)
54 {
55 yaml_char_t *new_start = (yaml_char_t *)yaml_realloc((void*)*start, (*end - *start)*2);
56
57 if (!new_start) return 0;
58
59 memset(new_start + (*end - *start), 0, *end - *start);
60
61 *pointer = new_start + (*pointer - *start);
62 *end = new_start + (*end - *start)*2;
63 *start = new_start;
64
65 return 1;
66 }
67
68 /*
69 * Append a string B to a string A.
70 */
71
72 YAML_DECLARE(int)
yaml_string_join(yaml_char_t ** a_start,yaml_char_t ** a_pointer,yaml_char_t ** a_end,yaml_char_t ** b_start,yaml_char_t ** b_pointer,SHIM (yaml_char_t ** b_end))73 yaml_string_join(
74 yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end,
75 yaml_char_t **b_start, yaml_char_t **b_pointer, SHIM(yaml_char_t **b_end))
76 {
77 UNUSED_PARAM(b_end)
78 if (*b_start == *b_pointer)
79 return 1;
80
81 while (*a_end - *a_pointer <= *b_pointer - *b_start) {
82 if (!yaml_string_extend(a_start, a_pointer, a_end))
83 return 0;
84 }
85
86 memcpy(*a_pointer, *b_start, *b_pointer - *b_start);
87 *a_pointer += *b_pointer - *b_start;
88
89 return 1;
90 }
91
92 /*
93 * Extend a stack.
94 */
95
96 YAML_DECLARE(int)
yaml_stack_extend(void ** start,void ** top,void ** end)97 yaml_stack_extend(void **start, void **top, void **end)
98 {
99 void *new_start;
100
101 if ((char *)*end - (char *)*start >= INT_MAX / 2)
102 return 0;
103
104 new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
105
106 if (!new_start) return 0;
107
108 *top = (char *)new_start + ((char *)*top - (char *)*start);
109 *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
110 *start = new_start;
111
112 return 1;
113 }
114
115 /*
116 * Extend or move a queue.
117 */
118
119 YAML_DECLARE(int)
yaml_queue_extend(void ** start,void ** head,void ** tail,void ** end)120 yaml_queue_extend(void **start, void **head, void **tail, void **end)
121 {
122 /* Check if we need to resize the queue. */
123
124 if (*start == *head && *tail == *end) {
125 void *new_start = yaml_realloc(*start,
126 ((char *)*end - (char *)*start)*2);
127
128 if (!new_start) return 0;
129
130 *head = (char *)new_start + ((char *)*head - (char *)*start);
131 *tail = (char *)new_start + ((char *)*tail - (char *)*start);
132 *end = (char *)new_start + ((char *)*end - (char *)*start)*2;
133 *start = new_start;
134 }
135
136 /* Check if we need to move the queue at the beginning of the buffer. */
137
138 if (*tail == *end) {
139 if (*head != *tail) memmove(*start, *head, (char *)*tail - (char *)*head);
140 *tail = (char *)*tail - (char *)*head + (char *)*start;
141 *head = *start;
142 }
143
144 return 1;
145 }
146
147
148 /*
149 * Create a new parser object.
150 */
151
152 YAML_DECLARE(int)
yaml_parser_initialize(yaml_parser_t * parser)153 yaml_parser_initialize(yaml_parser_t *parser)
154 {
155 assert(parser); /* Non-NULL parser object expected. */
156
157 memset(parser, 0, sizeof(yaml_parser_t));
158 if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE))
159 goto error;
160 if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE))
161 goto error;
162 if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE, yaml_token_t*))
163 goto error;
164 if (!STACK_INIT(parser, parser->indents, int*))
165 goto error;
166 if (!STACK_INIT(parser, parser->simple_keys, yaml_simple_key_t*))
167 goto error;
168 if (!STACK_INIT(parser, parser->states, yaml_parser_state_t*))
169 goto error;
170 if (!STACK_INIT(parser, parser->marks, yaml_mark_t*))
171 goto error;
172 if (!STACK_INIT(parser, parser->tag_directives, yaml_tag_directive_t*))
173 goto error;
174
175 return 1;
176
177 error:
178
179 BUFFER_DEL(parser, parser->raw_buffer);
180 BUFFER_DEL(parser, parser->buffer);
181 QUEUE_DEL(parser, parser->tokens);
182 STACK_DEL(parser, parser->indents);
183 STACK_DEL(parser, parser->simple_keys);
184 STACK_DEL(parser, parser->states);
185 STACK_DEL(parser, parser->marks);
186 STACK_DEL(parser, parser->tag_directives);
187
188 return 0;
189 }
190
191 /*
192 * Destroy a parser object.
193 */
194
195 YAML_DECLARE(void)
yaml_parser_delete(yaml_parser_t * parser)196 yaml_parser_delete(yaml_parser_t *parser)
197 {
198 assert(parser); /* Non-NULL parser object expected. */
199
200 BUFFER_DEL(parser, parser->raw_buffer);
201 BUFFER_DEL(parser, parser->buffer);
202 while (!QUEUE_EMPTY(parser, parser->tokens)) yaml_token_delete(&DEQUEUE(parser, parser->tokens));
203 QUEUE_DEL(parser, parser->tokens);
204 STACK_DEL(parser, parser->indents);
205 STACK_DEL(parser, parser->simple_keys);
206 STACK_DEL(parser, parser->states);
207 STACK_DEL(parser, parser->marks);
208 while (!STACK_EMPTY(parser, parser->tag_directives)) {
209 yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives);
210 yaml_free(tag_directive.handle);
211 yaml_free(tag_directive.prefix);
212 }
213 STACK_DEL(parser, parser->tag_directives);
214
215 memset(parser, 0, sizeof(yaml_parser_t));
216 }
217
218 /*
219 * String read handler.
220 */
221
222 static int
yaml_string_read_handler(void * data,unsigned char * buffer,size_t size,size_t * size_read)223 yaml_string_read_handler(void *data, unsigned char *buffer, size_t size,
224 size_t *size_read)
225 {
226 yaml_parser_t *parser = (yaml_parser_t *)data;
227
228 if (parser->input.string.current == parser->input.string.end) {
229 *size_read = 0;
230 return 1;
231 }
232
233 if (size > (size_t)(parser->input.string.end
234 - parser->input.string.current)) {
235 size = parser->input.string.end - parser->input.string.current;
236 }
237
238 memcpy(buffer, parser->input.string.current, size);
239 parser->input.string.current += size;
240 *size_read = size;
241 return 1;
242 }
243
244 /*
245 * File read handler.
246 */
247
248 static int
yaml_file_read_handler(void * data,unsigned char * buffer,size_t size,size_t * size_read)249 yaml_file_read_handler(void *data, unsigned char *buffer, size_t size,
250 size_t *size_read)
251 {
252 yaml_parser_t *parser = (yaml_parser_t *)data;
253
254 *size_read = fread(buffer, 1, size, parser->input.file);
255 return !ferror(parser->input.file);
256 }
257
258 /*
259 * Set a string input.
260 */
261
262 YAML_DECLARE(void)
yaml_parser_set_input_string(yaml_parser_t * parser,const unsigned char * input,size_t size)263 yaml_parser_set_input_string(yaml_parser_t *parser,
264 const unsigned char *input, size_t size)
265 {
266 assert(parser); /* Non-NULL parser object expected. */
267 assert(!parser->read_handler); /* You can set the source only once. */
268 assert(input); /* Non-NULL input string expected. */
269
270 parser->read_handler = yaml_string_read_handler;
271 parser->read_handler_data = parser;
272
273 parser->input.string.start = input;
274 parser->input.string.current = input;
275 parser->input.string.end = input+size;
276 }
277
278 /*
279 * Set a file input.
280 */
281
282 YAML_DECLARE(void)
yaml_parser_set_input_file(yaml_parser_t * parser,FILE * file)283 yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file)
284 {
285 assert(parser); /* Non-NULL parser object expected. */
286 assert(!parser->read_handler); /* You can set the source only once. */
287 assert(file); /* Non-NULL file object expected. */
288
289 parser->read_handler = yaml_file_read_handler;
290 parser->read_handler_data = parser;
291
292 parser->input.file = file;
293 }
294
295 /*
296 * Set a generic input.
297 */
298
299 YAML_DECLARE(void)
yaml_parser_set_input(yaml_parser_t * parser,yaml_read_handler_t * handler,void * data)300 yaml_parser_set_input(yaml_parser_t *parser,
301 yaml_read_handler_t *handler, void *data)
302 {
303 assert(parser); /* Non-NULL parser object expected. */
304 assert(!parser->read_handler); /* You can set the source only once. */
305 assert(handler); /* Non-NULL read handler expected. */
306
307 parser->read_handler = handler;
308 parser->read_handler_data = data;
309 }
310
311 /*
312 * Set the source encoding.
313 */
314
315 YAML_DECLARE(void)
yaml_parser_set_encoding(yaml_parser_t * parser,yaml_encoding_t encoding)316 yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding)
317 {
318 assert(parser); /* Non-NULL parser object expected. */
319 assert(!parser->encoding); /* Encoding is already set or detected. */
320
321 parser->encoding = encoding;
322 }
323
324 /*
325 * Destroy a token object.
326 */
327
328 YAML_DECLARE(void)
yaml_token_delete(yaml_token_t * token)329 yaml_token_delete(yaml_token_t *token)
330 {
331 assert(token); /* Non-NULL token object expected. */
332
333 switch (token->type)
334 {
335 case YAML_TAG_DIRECTIVE_TOKEN:
336 yaml_free(token->data.tag_directive.handle);
337 yaml_free(token->data.tag_directive.prefix);
338 break;
339
340 case YAML_ALIAS_TOKEN:
341 yaml_free(token->data.alias.value);
342 break;
343
344 case YAML_ANCHOR_TOKEN:
345 yaml_free(token->data.anchor.value);
346 break;
347
348 case YAML_TAG_TOKEN:
349 yaml_free(token->data.tag.handle);
350 yaml_free(token->data.tag.suffix);
351 break;
352
353 case YAML_SCALAR_TOKEN:
354 yaml_free(token->data.scalar.value);
355 break;
356
357 default:
358 break;
359 }
360
361 memset(token, 0, sizeof(yaml_token_t));
362 }
363
364 /*
365 * Destroy a document object.
366 */
367
368 YAML_DECLARE(void)
yaml_document_delete(yaml_document_t * document)369 yaml_document_delete(yaml_document_t *document)
370 {
371 yaml_tag_directive_t *tag_directive;
372
373 assert(document); /* Non-NULL document object is expected. */
374
375 while (!STACK_EMPTY(&context, document->nodes)) {
376 yaml_node_t node = POP(&context, document->nodes);
377 yaml_free(node.tag);
378 switch (node.type) {
379 case YAML_SCALAR_NODE:
380 yaml_free(node.data.scalar.value);
381 break;
382 case YAML_SEQUENCE_NODE:
383 STACK_DEL(&context, node.data.sequence.items);
384 break;
385 case YAML_MAPPING_NODE:
386 STACK_DEL(&context, node.data.mapping.pairs);
387 break;
388 default:
389 assert(0); /* Should not happen. */
390 }
391 }
392 STACK_DEL(&context, document->nodes);
393
394 yaml_free(document->version_directive);
395 for (tag_directive = document->tag_directives.start;
396 tag_directive != document->tag_directives.end;
397 tag_directive++) {
398 yaml_free(tag_directive->handle);
399 yaml_free(tag_directive->prefix);
400 }
401 yaml_free(document->tag_directives.start);
402
403 memset(document, 0, sizeof(yaml_document_t));
404 }
405
406 /**
407 * Get a document node.
408 */
409
410 YAML_DECLARE(yaml_node_t *)
yaml_document_get_node(yaml_document_t * document,int index)411 yaml_document_get_node(yaml_document_t *document, int index)
412 {
413 assert(document); /* Non-NULL document object is expected. */
414
415 if (index > 0 && document->nodes.start + index <= document->nodes.top) return document->nodes.start + index - 1;
416 return NULL;
417 }
418
419 /**
420 * Get the root object.
421 */
422
423 YAML_DECLARE(yaml_node_t *)
yaml_document_get_root_node(yaml_document_t * document)424 yaml_document_get_root_node(yaml_document_t *document)
425 {
426 assert(document); /* Non-NULL document object is expected. */
427
428 if (document->nodes.top != document->nodes.start) return document->nodes.start;
429 return NULL;
430 }
431