xref: /petsc/src/sys/yaml/src/api.c (revision 834855d6effb0d027771461c8e947ee1ce5a1e17)
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