use crate::api::{yaml_free, yaml_malloc}; use crate::externs::{memset, strcmp}; use crate::fmt::WriteToPtr; use crate::ops::ForceMul as _; use crate::success::{Success, FAIL, OK}; use crate::yaml::{ yaml_anchors_t, yaml_char_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_mark_t, yaml_node_item_t, yaml_node_pair_t, yaml_node_t, YAML_ALIAS_EVENT, YAML_ANY_ENCODING, YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE, YAML_MAPPING_START_EVENT, YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT, YAML_SEQUENCE_NODE, YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT, }; use crate::{libc, yaml_document_delete, yaml_emitter_emit, PointerExt}; use core::mem::{size_of, MaybeUninit}; use core::ptr::{self, addr_of_mut}; /// Start a YAML stream. /// /// This function should be used before yaml_emitter_dump() is called. pub unsafe fn yaml_emitter_open(emitter: *mut yaml_emitter_t) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; __assert!(!emitter.is_null()); __assert!(!(*emitter).opened); memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_STREAM_START_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.stream_start.encoding = YAML_ANY_ENCODING; if yaml_emitter_emit(emitter, event).fail { return FAIL; } (*emitter).opened = true; OK } /// Finish a YAML stream. /// /// This function should be used after yaml_emitter_dump() is called. pub unsafe fn yaml_emitter_close(emitter: *mut yaml_emitter_t) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; __assert!(!emitter.is_null()); __assert!((*emitter).opened); if (*emitter).closed { return OK; } memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_STREAM_END_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; if yaml_emitter_emit(emitter, event).fail { return FAIL; } (*emitter).closed = true; OK } /// Emit a YAML document. /// /// The documen object may be generated using the yaml_parser_load() function or /// the yaml_document_initialize() function. The emitter takes the /// responsibility for the document object and destroys its content after it is /// emitted. The document object is destroyed even if the function fails. pub unsafe fn yaml_emitter_dump( emitter: *mut yaml_emitter_t, document: *mut yaml_document_t, ) -> Success { let current_block: u64; let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; __assert!(!emitter.is_null()); __assert!(!document.is_null()); let fresh0 = addr_of_mut!((*emitter).document); *fresh0 = document; if !(*emitter).opened { if yaml_emitter_open(emitter).fail { current_block = 5018439318894558507; } else { current_block = 15619007995458559411; } } else { current_block = 15619007995458559411; } match current_block { 15619007995458559411 => { if STACK_EMPTY!((*document).nodes) { if yaml_emitter_close(emitter).ok { yaml_emitter_delete_document_and_anchors(emitter); return OK; } } else { __assert!((*emitter).opened); let fresh1 = addr_of_mut!((*emitter).anchors); *fresh1 = yaml_malloc( (size_of::() as libc::c_ulong) .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start) as libc::c_ulong), ) as *mut yaml_anchors_t; memset( (*emitter).anchors as *mut libc::c_void, 0, (size_of::() as libc::c_ulong) .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start) as libc::c_ulong), ); memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_DOCUMENT_START_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.document_start.version_directive = (*document).version_directive; (*event).data.document_start.tag_directives.start = (*document).tag_directives.start; (*event).data.document_start.tag_directives.end = (*document).tag_directives.end; (*event).data.document_start.implicit = (*document).start_implicit; if yaml_emitter_emit(emitter, event).ok { yaml_emitter_anchor_node(emitter, 1); if yaml_emitter_dump_node(emitter, 1).ok { memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_DOCUMENT_END_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.document_end.implicit = (*document).end_implicit; if yaml_emitter_emit(emitter, event).ok { yaml_emitter_delete_document_and_anchors(emitter); return OK; } } } } } _ => {} } yaml_emitter_delete_document_and_anchors(emitter); FAIL } unsafe fn yaml_emitter_delete_document_and_anchors(emitter: *mut yaml_emitter_t) { let mut index: libc::c_int; if (*emitter).anchors.is_null() { yaml_document_delete((*emitter).document); let fresh2 = addr_of_mut!((*emitter).document); *fresh2 = ptr::null_mut::(); return; } index = 0; while (*(*emitter).document) .nodes .start .wrapping_offset(index as isize) < (*(*emitter).document).nodes.top { let mut node: yaml_node_t = *(*(*emitter).document) .nodes .start .wrapping_offset(index as isize); if !(*(*emitter).anchors.wrapping_offset(index as isize)).serialized { yaml_free(node.tag as *mut libc::c_void); if node.type_ == YAML_SCALAR_NODE { yaml_free(node.data.scalar.value as *mut libc::c_void); } } if node.type_ == YAML_SEQUENCE_NODE { STACK_DEL!(node.data.sequence.items); } if node.type_ == YAML_MAPPING_NODE { STACK_DEL!(node.data.mapping.pairs); } index += 1; } STACK_DEL!((*(*emitter).document).nodes); yaml_free((*emitter).anchors as *mut libc::c_void); let fresh6 = addr_of_mut!((*emitter).anchors); *fresh6 = ptr::null_mut::(); (*emitter).last_anchor_id = 0; let fresh7 = addr_of_mut!((*emitter).document); *fresh7 = ptr::null_mut::(); } unsafe fn yaml_emitter_anchor_node_sub(emitter: *mut yaml_emitter_t, index: libc::c_int) { (*((*emitter).anchors).offset((index - 1) as isize)).references += 1; if (*(*emitter).anchors.offset((index - 1) as isize)).references == 2 { (*emitter).last_anchor_id += 1; (*(*emitter).anchors.offset((index - 1) as isize)).anchor = (*emitter).last_anchor_id; } } unsafe fn yaml_emitter_anchor_node(emitter: *mut yaml_emitter_t, index: libc::c_int) { let node: *mut yaml_node_t = (*(*emitter).document) .nodes .start .wrapping_offset(index as isize) .wrapping_offset(-1_isize); let mut item: *mut yaml_node_item_t; let mut pair: *mut yaml_node_pair_t; let fresh8 = addr_of_mut!((*((*emitter).anchors).wrapping_offset((index - 1) as isize)).references); *fresh8 += 1; if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 1 { match (*node).type_ { YAML_SEQUENCE_NODE => { item = (*node).data.sequence.items.start; while item < (*node).data.sequence.items.top { yaml_emitter_anchor_node_sub(emitter, *item); item = item.wrapping_offset(1); } } YAML_MAPPING_NODE => { pair = (*node).data.mapping.pairs.start; while pair < (*node).data.mapping.pairs.top { yaml_emitter_anchor_node_sub(emitter, (*pair).key); yaml_emitter_anchor_node_sub(emitter, (*pair).value); pair = pair.wrapping_offset(1); } } _ => {} } } else if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 2 { let fresh9 = addr_of_mut!((*emitter).last_anchor_id); *fresh9 += 1; (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor = *fresh9; } } unsafe fn yaml_emitter_generate_anchor( _emitter: *mut yaml_emitter_t, anchor_id: libc::c_int, ) -> *mut yaml_char_t { let anchor: *mut yaml_char_t = yaml_malloc(16_u64) as *mut yaml_char_t; write!(WriteToPtr::new(anchor), "id{:03}\0", anchor_id); anchor } unsafe fn yaml_emitter_dump_node(emitter: *mut yaml_emitter_t, index: libc::c_int) -> Success { let node: *mut yaml_node_t = (*(*emitter).document) .nodes .start .wrapping_offset(index as isize) .wrapping_offset(-1_isize); let anchor_id: libc::c_int = (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor; let mut anchor: *mut yaml_char_t = ptr::null_mut::(); if anchor_id != 0 { anchor = yaml_emitter_generate_anchor(emitter, anchor_id); } if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized { return yaml_emitter_dump_alias(emitter, anchor); } (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized = true; match (*node).type_ { YAML_SCALAR_NODE => yaml_emitter_dump_scalar(emitter, node, anchor), YAML_SEQUENCE_NODE => yaml_emitter_dump_sequence(emitter, node, anchor), YAML_MAPPING_NODE => yaml_emitter_dump_mapping(emitter, node, anchor), _ => __assert!(false), } } unsafe fn yaml_emitter_dump_alias( emitter: *mut yaml_emitter_t, anchor: *mut yaml_char_t, ) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_ALIAS_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.alias.anchor = anchor; yaml_emitter_emit(emitter, event) } unsafe fn yaml_emitter_dump_scalar( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; let plain_implicit = strcmp( (*node).tag as *mut libc::c_char, b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char, ) == 0; let quoted_implicit = strcmp( (*node).tag as *mut libc::c_char, b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char, ) == 0; memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_SCALAR_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.scalar.anchor = anchor; (*event).data.scalar.tag = (*node).tag; (*event).data.scalar.value = (*node).data.scalar.value; (*event).data.scalar.length = (*node).data.scalar.length; (*event).data.scalar.plain_implicit = plain_implicit; (*event).data.scalar.quoted_implicit = quoted_implicit; (*event).data.scalar.style = (*node).data.scalar.style; yaml_emitter_emit(emitter, event) } unsafe fn yaml_emitter_dump_sequence( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; let implicit = strcmp( (*node).tag as *mut libc::c_char, b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char, ) == 0; let mut item: *mut yaml_node_item_t; memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_SEQUENCE_START_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.sequence_start.anchor = anchor; (*event).data.sequence_start.tag = (*node).tag; (*event).data.sequence_start.implicit = implicit; (*event).data.sequence_start.style = (*node).data.sequence.style; if yaml_emitter_emit(emitter, event).fail { return FAIL; } item = (*node).data.sequence.items.start; while item < (*node).data.sequence.items.top { if yaml_emitter_dump_node(emitter, *item).fail { return FAIL; } item = item.wrapping_offset(1); } memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_SEQUENCE_END_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; yaml_emitter_emit(emitter, event) } unsafe fn yaml_emitter_dump_mapping( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success { let mut event = MaybeUninit::::uninit(); let event = event.as_mut_ptr(); let mark = yaml_mark_t { index: 0_u64, line: 0_u64, column: 0_u64, }; let implicit = strcmp( (*node).tag as *mut libc::c_char, b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char, ) == 0; let mut pair: *mut yaml_node_pair_t; memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_MAPPING_START_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; (*event).data.mapping_start.anchor = anchor; (*event).data.mapping_start.tag = (*node).tag; (*event).data.mapping_start.implicit = implicit; (*event).data.mapping_start.style = (*node).data.mapping.style; if yaml_emitter_emit(emitter, event).fail { return FAIL; } pair = (*node).data.mapping.pairs.start; while pair < (*node).data.mapping.pairs.top { if yaml_emitter_dump_node(emitter, (*pair).key).fail { return FAIL; } if yaml_emitter_dump_node(emitter, (*pair).value).fail { return FAIL; } pair = pair.wrapping_offset(1); } memset( event as *mut libc::c_void, 0, size_of::() as libc::c_ulong, ); (*event).type_ = YAML_MAPPING_END_EVENT; (*event).start_mark = mark; (*event).end_mark = mark; yaml_emitter_emit(emitter, event) }