1247738Sbapt 2247738Sbapt#include "yaml_private.h" 3247738Sbapt 4247738Sbapt/* 5247738Sbapt * API functions. 6247738Sbapt */ 7247738Sbapt 8247738SbaptYAML_DECLARE(int) 9247738Sbaptyaml_emitter_open(yaml_emitter_t *emitter); 10247738Sbapt 11247738SbaptYAML_DECLARE(int) 12247738Sbaptyaml_emitter_close(yaml_emitter_t *emitter); 13247738Sbapt 14247738SbaptYAML_DECLARE(int) 15247738Sbaptyaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document); 16247738Sbapt 17247738Sbapt/* 18247738Sbapt * Clean up functions. 19247738Sbapt */ 20247738Sbapt 21247738Sbaptstatic void 22247738Sbaptyaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter); 23247738Sbapt 24247738Sbapt/* 25247738Sbapt * Anchor functions. 26247738Sbapt */ 27247738Sbapt 28247738Sbaptstatic void 29247738Sbaptyaml_emitter_anchor_node(yaml_emitter_t *emitter, int index); 30247738Sbapt 31247738Sbaptstatic yaml_char_t * 32247738Sbaptyaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id); 33247738Sbapt 34247738Sbapt 35247738Sbapt/* 36247738Sbapt * Serialize functions. 37247738Sbapt */ 38247738Sbapt 39247738Sbaptstatic int 40247738Sbaptyaml_emitter_dump_node(yaml_emitter_t *emitter, int index); 41247738Sbapt 42247738Sbaptstatic int 43247738Sbaptyaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor); 44247738Sbapt 45247738Sbaptstatic int 46247738Sbaptyaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, 47247738Sbapt yaml_char_t *anchor); 48247738Sbapt 49247738Sbaptstatic int 50247738Sbaptyaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, 51247738Sbapt yaml_char_t *anchor); 52247738Sbapt 53247738Sbaptstatic int 54247738Sbaptyaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, 55247738Sbapt yaml_char_t *anchor); 56247738Sbapt 57247738Sbapt/* 58247738Sbapt * Issue a STREAM-START event. 59247738Sbapt */ 60247738Sbapt 61247738SbaptYAML_DECLARE(int) 62247738Sbaptyaml_emitter_open(yaml_emitter_t *emitter) 63247738Sbapt{ 64247738Sbapt yaml_event_t event; 65247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 66247738Sbapt 67247738Sbapt assert(emitter); /* Non-NULL emitter object is required. */ 68247738Sbapt assert(!emitter->opened); /* Emitter should not be opened yet. */ 69247738Sbapt 70247738Sbapt STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark); 71247738Sbapt 72247738Sbapt if (!yaml_emitter_emit(emitter, &event)) { 73247738Sbapt return 0; 74247738Sbapt } 75247738Sbapt 76247738Sbapt emitter->opened = 1; 77247738Sbapt 78247738Sbapt return 1; 79247738Sbapt} 80247738Sbapt 81247738Sbapt/* 82247738Sbapt * Issue a STREAM-END event. 83247738Sbapt */ 84247738Sbapt 85247738SbaptYAML_DECLARE(int) 86247738Sbaptyaml_emitter_close(yaml_emitter_t *emitter) 87247738Sbapt{ 88247738Sbapt yaml_event_t event; 89247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 90247738Sbapt 91247738Sbapt assert(emitter); /* Non-NULL emitter object is required. */ 92247738Sbapt assert(emitter->opened); /* Emitter should be opened. */ 93247738Sbapt 94247738Sbapt if (emitter->closed) return 1; 95247738Sbapt 96247738Sbapt STREAM_END_EVENT_INIT(event, mark, mark); 97247738Sbapt 98247738Sbapt if (!yaml_emitter_emit(emitter, &event)) { 99247738Sbapt return 0; 100247738Sbapt } 101247738Sbapt 102247738Sbapt emitter->closed = 1; 103247738Sbapt 104247738Sbapt return 1; 105247738Sbapt} 106247738Sbapt 107247738Sbapt/* 108247738Sbapt * Dump a YAML document. 109247738Sbapt */ 110247738Sbapt 111247738SbaptYAML_DECLARE(int) 112247738Sbaptyaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document) 113247738Sbapt{ 114247738Sbapt yaml_event_t event; 115247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 116247738Sbapt 117247738Sbapt assert(emitter); /* Non-NULL emitter object is required. */ 118247738Sbapt assert(document); /* Non-NULL emitter object is expected. */ 119247738Sbapt 120247738Sbapt emitter->document = document; 121247738Sbapt 122247738Sbapt if (!emitter->opened) { 123247738Sbapt if (!yaml_emitter_open(emitter)) goto error; 124247738Sbapt } 125247738Sbapt 126247738Sbapt if (STACK_EMPTY(emitter, document->nodes)) { 127247738Sbapt if (!yaml_emitter_close(emitter)) goto error; 128247738Sbapt yaml_emitter_delete_document_and_anchors(emitter); 129247738Sbapt return 1; 130247738Sbapt } 131247738Sbapt 132247738Sbapt assert(emitter->opened); /* Emitter should be opened. */ 133247738Sbapt 134247738Sbapt emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors)) 135247738Sbapt * (document->nodes.top - document->nodes.start)); 136247738Sbapt if (!emitter->anchors) goto error; 137247738Sbapt memset(emitter->anchors, 0, sizeof(*(emitter->anchors)) 138247738Sbapt * (document->nodes.top - document->nodes.start)); 139247738Sbapt 140247738Sbapt DOCUMENT_START_EVENT_INIT(event, document->version_directive, 141247738Sbapt document->tag_directives.start, document->tag_directives.end, 142247738Sbapt document->start_implicit, mark, mark); 143247738Sbapt if (!yaml_emitter_emit(emitter, &event)) goto error; 144247738Sbapt 145247738Sbapt yaml_emitter_anchor_node(emitter, 1); 146247738Sbapt if (!yaml_emitter_dump_node(emitter, 1)) goto error; 147247738Sbapt 148247738Sbapt DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark); 149247738Sbapt if (!yaml_emitter_emit(emitter, &event)) goto error; 150247738Sbapt 151247738Sbapt yaml_emitter_delete_document_and_anchors(emitter); 152247738Sbapt 153247738Sbapt return 1; 154247738Sbapt 155247738Sbapterror: 156247738Sbapt 157247738Sbapt yaml_emitter_delete_document_and_anchors(emitter); 158247738Sbapt 159247738Sbapt return 0; 160247738Sbapt} 161247738Sbapt 162247738Sbapt/* 163247738Sbapt * Clean up the emitter object after a document is dumped. 164247738Sbapt */ 165247738Sbapt 166247738Sbaptstatic void 167247738Sbaptyaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter) 168247738Sbapt{ 169247738Sbapt int index; 170247738Sbapt 171247738Sbapt if (!emitter->anchors) { 172247738Sbapt yaml_document_delete(emitter->document); 173247738Sbapt emitter->document = NULL; 174247738Sbapt return; 175247738Sbapt } 176247738Sbapt 177247738Sbapt for (index = 0; emitter->document->nodes.start + index 178247738Sbapt < emitter->document->nodes.top; index ++) { 179247738Sbapt yaml_node_t node = emitter->document->nodes.start[index]; 180247738Sbapt if (!emitter->anchors[index].serialized) { 181247738Sbapt yaml_free(node.tag); 182247738Sbapt if (node.type == YAML_SCALAR_NODE) { 183247738Sbapt yaml_free(node.data.scalar.value); 184247738Sbapt } 185247738Sbapt } 186247738Sbapt if (node.type == YAML_SEQUENCE_NODE) { 187247738Sbapt STACK_DEL(emitter, node.data.sequence.items); 188247738Sbapt } 189247738Sbapt if (node.type == YAML_MAPPING_NODE) { 190247738Sbapt STACK_DEL(emitter, node.data.mapping.pairs); 191247738Sbapt } 192247738Sbapt } 193247738Sbapt 194247738Sbapt STACK_DEL(emitter, emitter->document->nodes); 195247738Sbapt yaml_free(emitter->anchors); 196247738Sbapt 197247738Sbapt emitter->anchors = NULL; 198247738Sbapt emitter->last_anchor_id = 0; 199247738Sbapt emitter->document = NULL; 200247738Sbapt} 201247738Sbapt 202247738Sbapt/* 203247738Sbapt * Check the references of a node and assign the anchor id if needed. 204247738Sbapt */ 205247738Sbapt 206247738Sbaptstatic void 207247738Sbaptyaml_emitter_anchor_node(yaml_emitter_t *emitter, int index) 208247738Sbapt{ 209247738Sbapt yaml_node_t *node = emitter->document->nodes.start + index - 1; 210247738Sbapt yaml_node_item_t *item; 211247738Sbapt yaml_node_pair_t *pair; 212247738Sbapt 213247738Sbapt emitter->anchors[index-1].references ++; 214247738Sbapt 215247738Sbapt if (emitter->anchors[index-1].references == 1) { 216247738Sbapt switch (node->type) { 217247738Sbapt case YAML_SEQUENCE_NODE: 218247738Sbapt for (item = node->data.sequence.items.start; 219247738Sbapt item < node->data.sequence.items.top; item ++) { 220247738Sbapt yaml_emitter_anchor_node(emitter, *item); 221247738Sbapt } 222247738Sbapt break; 223247738Sbapt case YAML_MAPPING_NODE: 224247738Sbapt for (pair = node->data.mapping.pairs.start; 225247738Sbapt pair < node->data.mapping.pairs.top; pair ++) { 226247738Sbapt yaml_emitter_anchor_node(emitter, pair->key); 227247738Sbapt yaml_emitter_anchor_node(emitter, pair->value); 228247738Sbapt } 229247738Sbapt break; 230247738Sbapt default: 231247738Sbapt break; 232247738Sbapt } 233247738Sbapt } 234247738Sbapt 235247738Sbapt else if (emitter->anchors[index-1].references == 2) { 236247738Sbapt emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id); 237247738Sbapt } 238247738Sbapt} 239247738Sbapt 240247738Sbapt/* 241247738Sbapt * Generate a textual representation for an anchor. 242247738Sbapt */ 243247738Sbapt 244247738Sbapt#define ANCHOR_TEMPLATE "id%03d" 245247738Sbapt#define ANCHOR_TEMPLATE_LENGTH 16 246247738Sbapt 247247738Sbaptstatic yaml_char_t * 248247738Sbaptyaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id) 249247738Sbapt{ 250247738Sbapt yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH); 251247738Sbapt 252247738Sbapt if (!anchor) return NULL; 253247738Sbapt 254247738Sbapt sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id); 255247738Sbapt 256247738Sbapt return anchor; 257247738Sbapt} 258247738Sbapt 259247738Sbapt/* 260247738Sbapt * Serialize a node. 261247738Sbapt */ 262247738Sbapt 263247738Sbaptstatic int 264247738Sbaptyaml_emitter_dump_node(yaml_emitter_t *emitter, int index) 265247738Sbapt{ 266247738Sbapt yaml_node_t *node = emitter->document->nodes.start + index - 1; 267247738Sbapt int anchor_id = emitter->anchors[index-1].anchor; 268247738Sbapt yaml_char_t *anchor = NULL; 269247738Sbapt 270247738Sbapt if (anchor_id) { 271247738Sbapt anchor = yaml_emitter_generate_anchor(emitter, anchor_id); 272247738Sbapt if (!anchor) return 0; 273247738Sbapt } 274247738Sbapt 275247738Sbapt if (emitter->anchors[index-1].serialized) { 276247738Sbapt return yaml_emitter_dump_alias(emitter, anchor); 277247738Sbapt } 278247738Sbapt 279247738Sbapt emitter->anchors[index-1].serialized = 1; 280247738Sbapt 281247738Sbapt switch (node->type) { 282247738Sbapt case YAML_SCALAR_NODE: 283247738Sbapt return yaml_emitter_dump_scalar(emitter, node, anchor); 284247738Sbapt case YAML_SEQUENCE_NODE: 285247738Sbapt return yaml_emitter_dump_sequence(emitter, node, anchor); 286247738Sbapt case YAML_MAPPING_NODE: 287247738Sbapt return yaml_emitter_dump_mapping(emitter, node, anchor); 288247738Sbapt default: 289247738Sbapt assert(0); /* Could not happen. */ 290247738Sbapt break; 291247738Sbapt } 292247738Sbapt 293247738Sbapt return 0; /* Could not happen. */ 294247738Sbapt} 295247738Sbapt 296247738Sbapt/* 297247738Sbapt * Serialize an alias. 298247738Sbapt */ 299247738Sbapt 300247738Sbaptstatic int 301247738Sbaptyaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor) 302247738Sbapt{ 303247738Sbapt yaml_event_t event; 304247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 305247738Sbapt 306247738Sbapt ALIAS_EVENT_INIT(event, anchor, mark, mark); 307247738Sbapt 308247738Sbapt return yaml_emitter_emit(emitter, &event); 309247738Sbapt} 310247738Sbapt 311247738Sbapt/* 312247738Sbapt * Serialize a scalar. 313247738Sbapt */ 314247738Sbapt 315247738Sbaptstatic int 316247738Sbaptyaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, 317247738Sbapt yaml_char_t *anchor) 318247738Sbapt{ 319247738Sbapt yaml_event_t event; 320247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 321247738Sbapt 322247738Sbapt int plain_implicit = (strcmp((char *)node->tag, 323247738Sbapt YAML_DEFAULT_SCALAR_TAG) == 0); 324247738Sbapt int quoted_implicit = (strcmp((char *)node->tag, 325247738Sbapt YAML_DEFAULT_SCALAR_TAG) == 0); 326247738Sbapt 327247738Sbapt SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value, 328247738Sbapt node->data.scalar.length, plain_implicit, quoted_implicit, 329247738Sbapt node->data.scalar.style, mark, mark); 330247738Sbapt 331247738Sbapt return yaml_emitter_emit(emitter, &event); 332247738Sbapt} 333247738Sbapt 334247738Sbapt/* 335247738Sbapt * Serialize a sequence. 336247738Sbapt */ 337247738Sbapt 338247738Sbaptstatic int 339247738Sbaptyaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, 340247738Sbapt yaml_char_t *anchor) 341247738Sbapt{ 342247738Sbapt yaml_event_t event; 343247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 344247738Sbapt 345247738Sbapt int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0); 346247738Sbapt 347247738Sbapt yaml_node_item_t *item; 348247738Sbapt 349247738Sbapt SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit, 350247738Sbapt node->data.sequence.style, mark, mark); 351247738Sbapt if (!yaml_emitter_emit(emitter, &event)) return 0; 352247738Sbapt 353247738Sbapt for (item = node->data.sequence.items.start; 354247738Sbapt item < node->data.sequence.items.top; item ++) { 355247738Sbapt if (!yaml_emitter_dump_node(emitter, *item)) return 0; 356247738Sbapt } 357247738Sbapt 358247738Sbapt SEQUENCE_END_EVENT_INIT(event, mark, mark); 359247738Sbapt if (!yaml_emitter_emit(emitter, &event)) return 0; 360247738Sbapt 361247738Sbapt return 1; 362247738Sbapt} 363247738Sbapt 364247738Sbapt/* 365247738Sbapt * Serialize a mapping. 366247738Sbapt */ 367247738Sbapt 368247738Sbaptstatic int 369247738Sbaptyaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, 370247738Sbapt yaml_char_t *anchor) 371247738Sbapt{ 372247738Sbapt yaml_event_t event; 373247738Sbapt yaml_mark_t mark = { 0, 0, 0 }; 374247738Sbapt 375247738Sbapt int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0); 376247738Sbapt 377247738Sbapt yaml_node_pair_t *pair; 378247738Sbapt 379247738Sbapt MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit, 380247738Sbapt node->data.mapping.style, mark, mark); 381247738Sbapt if (!yaml_emitter_emit(emitter, &event)) return 0; 382247738Sbapt 383247738Sbapt for (pair = node->data.mapping.pairs.start; 384247738Sbapt pair < node->data.mapping.pairs.top; pair ++) { 385247738Sbapt if (!yaml_emitter_dump_node(emitter, pair->key)) return 0; 386247738Sbapt if (!yaml_emitter_dump_node(emitter, pair->value)) return 0; 387247738Sbapt } 388247738Sbapt 389247738Sbapt MAPPING_END_EVENT_INIT(event, mark, mark); 390247738Sbapt if (!yaml_emitter_emit(emitter, &event)) return 0; 391247738Sbapt 392247738Sbapt return 1; 393247738Sbapt} 394247738Sbapt 395