#
unsafe_libyaml/
dumper.rs

    1use crate::api::{yaml_free, yaml_malloc};
    2use crate::externs::{memset, strcmp};
    3use crate::fmt::WriteToPtr;
    4use crate::ops::ForceMul as _;
    5use crate::success::{Success, FAIL, OK};
    6use crate::yaml::{
    7    yaml_anchors_t, yaml_char_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_mark_t,
    8    yaml_node_item_t, yaml_node_pair_t, yaml_node_t, YAML_ALIAS_EVENT, YAML_ANY_ENCODING,
    9    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE,
    10    YAML_MAPPING_START_EVENT, YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT,
    11    YAML_SEQUENCE_NODE, YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
    12};
    13use crate::{libc, yaml_document_delete, yaml_emitter_emit, PointerExt};
    14use core::mem::{size_of, MaybeUninit};
    15use core::ptr::{self, addr_of_mut};
    16
    17/// Start a YAML stream.
    18///
    19/// This function should be used before yaml_emitter_dump() is called.
    20pub unsafe fn yaml_emitter_open(emitter: *mut yaml_emitter_t) -> Success {
    21    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    22    let event = event.as_mut_ptr();
    23    let mark = yaml_mark_t {
    24        index: 0_u64,
    25        line: 0_u64,
    26        column: 0_u64,
    27    };
    28    __assert!(!emitter.is_null());
    29    __assert!(!(*emitter).opened);
    30    memset(
    31        event as *mut libc::c_void,
    32        0,
    33        size_of::<yaml_event_t>() as libc::c_ulong,
    34    );
    35    (*event).type_ = YAML_STREAM_START_EVENT;
    36    (*event).start_mark = mark;
    37    (*event).end_mark = mark;
    38    (*event).data.stream_start.encoding = YAML_ANY_ENCODING;
    39    if yaml_emitter_emit(emitter, event).fail {
    40        return FAIL;
    41    }
    42    (*emitter).opened = true;
    43    OK
    44}
    45
    46/// Finish a YAML stream.
    47///
    48/// This function should be used after yaml_emitter_dump() is called.
    49pub unsafe fn yaml_emitter_close(emitter: *mut yaml_emitter_t) -> Success {
    50    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    51    let event = event.as_mut_ptr();
    52    let mark = yaml_mark_t {
    53        index: 0_u64,
    54        line: 0_u64,
    55        column: 0_u64,
    56    };
    57    __assert!(!emitter.is_null());
    58    __assert!((*emitter).opened);
    59    if (*emitter).closed {
    60        return OK;
    61    }
    62    memset(
    63        event as *mut libc::c_void,
    64        0,
    65        size_of::<yaml_event_t>() as libc::c_ulong,
    66    );
    67    (*event).type_ = YAML_STREAM_END_EVENT;
    68    (*event).start_mark = mark;
    69    (*event).end_mark = mark;
    70    if yaml_emitter_emit(emitter, event).fail {
    71        return FAIL;
    72    }
    73    (*emitter).closed = true;
    74    OK
    75}
    76
    77/// Emit a YAML document.
    78///
    79/// The document object may be generated using the yaml_parser_load() function or
    80/// the yaml_document_initialize() function. The emitter takes the
    81/// responsibility for the document object and destroys its content after it is
    82/// emitted. The document object is destroyed even if the function fails.
    83pub unsafe fn yaml_emitter_dump(
    84    emitter: *mut yaml_emitter_t,
    85    document: *mut yaml_document_t,
    86) -> Success {
    87    let current_block: u64;
    88    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    89    let event = event.as_mut_ptr();
    90    let mark = yaml_mark_t {
    91        index: 0_u64,
    92        line: 0_u64,
    93        column: 0_u64,
    94    };
    95    __assert!(!emitter.is_null());
    96    __assert!(!document.is_null());
    97    let fresh0 = addr_of_mut!((*emitter).document);
    98    *fresh0 = document;
    99    if !(*emitter).opened {
    100        if yaml_emitter_open(emitter).fail {
    101            current_block = 5018439318894558507;
    102        } else {
    103            current_block = 15619007995458559411;
    104        }
    105    } else {
    106        current_block = 15619007995458559411;
    107    }
    108    match current_block {
    109        15619007995458559411 => {
    110            if STACK_EMPTY!((*document).nodes) {
    111                if yaml_emitter_close(emitter).ok {
    112                    yaml_emitter_delete_document_and_anchors(emitter);
    113                    return OK;
    114                }
    115            } else {
    116                __assert!((*emitter).opened);
    117                let fresh1 = addr_of_mut!((*emitter).anchors);
    118                *fresh1 = yaml_malloc(
    119                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
    120                        .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
    121                            as libc::c_ulong),
    122                ) as *mut yaml_anchors_t;
    123                memset(
    124                    (*emitter).anchors as *mut libc::c_void,
    125                    0,
    126                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
    127                        .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
    128                            as libc::c_ulong),
    129                );
    130                memset(
    131                    event as *mut libc::c_void,
    132                    0,
    133                    size_of::<yaml_event_t>() as libc::c_ulong,
    134                );
    135                (*event).type_ = YAML_DOCUMENT_START_EVENT;
    136                (*event).start_mark = mark;
    137                (*event).end_mark = mark;
    138                (*event).data.document_start.version_directive = (*document).version_directive;
    139                (*event).data.document_start.tag_directives.start =
    140                    (*document).tag_directives.start;
    141                (*event).data.document_start.tag_directives.end = (*document).tag_directives.end;
    142                (*event).data.document_start.implicit = (*document).start_implicit;
    143                if yaml_emitter_emit(emitter, event).ok {
    144                    yaml_emitter_anchor_node(emitter, 1);
    145                    if yaml_emitter_dump_node(emitter, 1).ok {
    146                        memset(
    147                            event as *mut libc::c_void,
    148                            0,
    149                            size_of::<yaml_event_t>() as libc::c_ulong,
    150                        );
    151                        (*event).type_ = YAML_DOCUMENT_END_EVENT;
    152                        (*event).start_mark = mark;
    153                        (*event).end_mark = mark;
    154                        (*event).data.document_end.implicit = (*document).end_implicit;
    155                        if yaml_emitter_emit(emitter, event).ok {
    156                            yaml_emitter_delete_document_and_anchors(emitter);
    157                            return OK;
    158                        }
    159                    }
    160                }
    161            }
    162        }
    163        _ => {}
    164    }
    165    yaml_emitter_delete_document_and_anchors(emitter);
    166    FAIL
    167}
    168
    169unsafe fn yaml_emitter_delete_document_and_anchors(emitter: *mut yaml_emitter_t) {
    170    let mut index: libc::c_int;
    171    if (*emitter).anchors.is_null() {
    172        yaml_document_delete((*emitter).document);
    173        let fresh2 = addr_of_mut!((*emitter).document);
    174        *fresh2 = ptr::null_mut::<yaml_document_t>();
    175        return;
    176    }
    177    index = 0;
    178    while (*(*emitter).document)
    179        .nodes
    180        .start
    181        .wrapping_offset(index as isize)
    182        < (*(*emitter).document).nodes.top
    183    {
    184        let mut node: yaml_node_t = *(*(*emitter).document)
    185            .nodes
    186            .start
    187            .wrapping_offset(index as isize);
    188        if !(*(*emitter).anchors.wrapping_offset(index as isize)).serialized {
    189            yaml_free(node.tag as *mut libc::c_void);
    190            if node.type_ == YAML_SCALAR_NODE {
    191                yaml_free(node.data.scalar.value as *mut libc::c_void);
    192            }
    193        }
    194        if node.type_ == YAML_SEQUENCE_NODE {
    195            STACK_DEL!(node.data.sequence.items);
    196        }
    197        if node.type_ == YAML_MAPPING_NODE {
    198            STACK_DEL!(node.data.mapping.pairs);
    199        }
    200        index += 1;
    201    }
    202    STACK_DEL!((*(*emitter).document).nodes);
    203    yaml_free((*emitter).anchors as *mut libc::c_void);
    204    let fresh6 = addr_of_mut!((*emitter).anchors);
    205    *fresh6 = ptr::null_mut::<yaml_anchors_t>();
    206    (*emitter).last_anchor_id = 0;
    207    let fresh7 = addr_of_mut!((*emitter).document);
    208    *fresh7 = ptr::null_mut::<yaml_document_t>();
    209}
    210
    211unsafe fn yaml_emitter_anchor_node_sub(emitter: *mut yaml_emitter_t, index: libc::c_int) {
    212    (*((*emitter).anchors).offset((index - 1) as isize)).references += 1;
    213    if (*(*emitter).anchors.offset((index - 1) as isize)).references == 2 {
    214        (*emitter).last_anchor_id += 1;
    215        (*(*emitter).anchors.offset((index - 1) as isize)).anchor = (*emitter).last_anchor_id;
    216    }
    217}
    218
    219unsafe fn yaml_emitter_anchor_node(emitter: *mut yaml_emitter_t, index: libc::c_int) {
    220    let node: *mut yaml_node_t = (*(*emitter).document)
    221        .nodes
    222        .start
    223        .wrapping_offset(index as isize)
    224        .wrapping_offset(-1_isize);
    225    let mut item: *mut yaml_node_item_t;
    226    let mut pair: *mut yaml_node_pair_t;
    227    let fresh8 =
    228        addr_of_mut!((*((*emitter).anchors).wrapping_offset((index - 1) as isize)).references);
    229    *fresh8 += 1;
    230    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 1 {
    231        match (*node).type_ {
    232            YAML_SEQUENCE_NODE => {
    233                item = (*node).data.sequence.items.start;
    234                while item < (*node).data.sequence.items.top {
    235                    yaml_emitter_anchor_node_sub(emitter, *item);
    236                    item = item.wrapping_offset(1);
    237                }
    238            }
    239            YAML_MAPPING_NODE => {
    240                pair = (*node).data.mapping.pairs.start;
    241                while pair < (*node).data.mapping.pairs.top {
    242                    yaml_emitter_anchor_node_sub(emitter, (*pair).key);
    243                    yaml_emitter_anchor_node_sub(emitter, (*pair).value);
    244                    pair = pair.wrapping_offset(1);
    245                }
    246            }
    247            _ => {}
    248        }
    249    } else if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 2 {
    250        let fresh9 = addr_of_mut!((*emitter).last_anchor_id);
    251        *fresh9 += 1;
    252        (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor = *fresh9;
    253    }
    254}
    255
    256unsafe fn yaml_emitter_generate_anchor(
    257    _emitter: *mut yaml_emitter_t,
    258    anchor_id: libc::c_int,
    259) -> *mut yaml_char_t {
    260    let anchor: *mut yaml_char_t = yaml_malloc(16_u64) as *mut yaml_char_t;
    261    write!(WriteToPtr::new(anchor), "id{:03}\0", anchor_id);
    262    anchor
    263}
    264
    265unsafe fn yaml_emitter_dump_node(emitter: *mut yaml_emitter_t, index: libc::c_int) -> Success {
    266    let node: *mut yaml_node_t = (*(*emitter).document)
    267        .nodes
    268        .start
    269        .wrapping_offset(index as isize)
    270        .wrapping_offset(-1_isize);
    271    let anchor_id: libc::c_int = (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor;
    272    let mut anchor: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
    273    if anchor_id != 0 {
    274        anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
    275    }
    276    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized {
    277        return yaml_emitter_dump_alias(emitter, anchor);
    278    }
    279    (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized = true;
    280    match (*node).type_ {
    281        YAML_SCALAR_NODE => yaml_emitter_dump_scalar(emitter, node, anchor),
    282        YAML_SEQUENCE_NODE => yaml_emitter_dump_sequence(emitter, node, anchor),
    283        YAML_MAPPING_NODE => yaml_emitter_dump_mapping(emitter, node, anchor),
    284        _ => __assert!(false),
    285    }
    286}
    287
    288unsafe fn yaml_emitter_dump_alias(
    289    emitter: *mut yaml_emitter_t,
    290    anchor: *mut yaml_char_t,
    291) -> Success {
    292    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    293    let event = event.as_mut_ptr();
    294    let mark = yaml_mark_t {
    295        index: 0_u64,
    296        line: 0_u64,
    297        column: 0_u64,
    298    };
    299    memset(
    300        event as *mut libc::c_void,
    301        0,
    302        size_of::<yaml_event_t>() as libc::c_ulong,
    303    );
    304    (*event).type_ = YAML_ALIAS_EVENT;
    305    (*event).start_mark = mark;
    306    (*event).end_mark = mark;
    307    (*event).data.alias.anchor = anchor;
    308    yaml_emitter_emit(emitter, event)
    309}
    310
    311unsafe fn yaml_emitter_dump_scalar(
    312    emitter: *mut yaml_emitter_t,
    313    node: *mut yaml_node_t,
    314    anchor: *mut yaml_char_t,
    315) -> Success {
    316    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    317    let event = event.as_mut_ptr();
    318    let mark = yaml_mark_t {
    319        index: 0_u64,
    320        line: 0_u64,
    321        column: 0_u64,
    322    };
    323    let plain_implicit = strcmp(
    324        (*node).tag as *mut libc::c_char,
    325        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
    326    ) == 0;
    327    let quoted_implicit = strcmp(
    328        (*node).tag as *mut libc::c_char,
    329        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
    330    ) == 0;
    331    memset(
    332        event as *mut libc::c_void,
    333        0,
    334        size_of::<yaml_event_t>() as libc::c_ulong,
    335    );
    336    (*event).type_ = YAML_SCALAR_EVENT;
    337    (*event).start_mark = mark;
    338    (*event).end_mark = mark;
    339    (*event).data.scalar.anchor = anchor;
    340    (*event).data.scalar.tag = (*node).tag;
    341    (*event).data.scalar.value = (*node).data.scalar.value;
    342    (*event).data.scalar.length = (*node).data.scalar.length;
    343    (*event).data.scalar.plain_implicit = plain_implicit;
    344    (*event).data.scalar.quoted_implicit = quoted_implicit;
    345    (*event).data.scalar.style = (*node).data.scalar.style;
    346    yaml_emitter_emit(emitter, event)
    347}
    348
    349unsafe fn yaml_emitter_dump_sequence(
    350    emitter: *mut yaml_emitter_t,
    351    node: *mut yaml_node_t,
    352    anchor: *mut yaml_char_t,
    353) -> Success {
    354    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    355    let event = event.as_mut_ptr();
    356    let mark = yaml_mark_t {
    357        index: 0_u64,
    358        line: 0_u64,
    359        column: 0_u64,
    360    };
    361    let implicit = strcmp(
    362        (*node).tag as *mut libc::c_char,
    363        b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char,
    364    ) == 0;
    365    let mut item: *mut yaml_node_item_t;
    366    memset(
    367        event as *mut libc::c_void,
    368        0,
    369        size_of::<yaml_event_t>() as libc::c_ulong,
    370    );
    371    (*event).type_ = YAML_SEQUENCE_START_EVENT;
    372    (*event).start_mark = mark;
    373    (*event).end_mark = mark;
    374    (*event).data.sequence_start.anchor = anchor;
    375    (*event).data.sequence_start.tag = (*node).tag;
    376    (*event).data.sequence_start.implicit = implicit;
    377    (*event).data.sequence_start.style = (*node).data.sequence.style;
    378    if yaml_emitter_emit(emitter, event).fail {
    379        return FAIL;
    380    }
    381    item = (*node).data.sequence.items.start;
    382    while item < (*node).data.sequence.items.top {
    383        if yaml_emitter_dump_node(emitter, *item).fail {
    384            return FAIL;
    385        }
    386        item = item.wrapping_offset(1);
    387    }
    388    memset(
    389        event as *mut libc::c_void,
    390        0,
    391        size_of::<yaml_event_t>() as libc::c_ulong,
    392    );
    393    (*event).type_ = YAML_SEQUENCE_END_EVENT;
    394    (*event).start_mark = mark;
    395    (*event).end_mark = mark;
    396    yaml_emitter_emit(emitter, event)
    397}
    398
    399unsafe fn yaml_emitter_dump_mapping(
    400    emitter: *mut yaml_emitter_t,
    401    node: *mut yaml_node_t,
    402    anchor: *mut yaml_char_t,
    403) -> Success {
    404    let mut event = MaybeUninit::<yaml_event_t>::uninit();
    405    let event = event.as_mut_ptr();
    406    let mark = yaml_mark_t {
    407        index: 0_u64,
    408        line: 0_u64,
    409        column: 0_u64,
    410    };
    411    let implicit = strcmp(
    412        (*node).tag as *mut libc::c_char,
    413        b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char,
    414    ) == 0;
    415    let mut pair: *mut yaml_node_pair_t;
    416    memset(
    417        event as *mut libc::c_void,
    418        0,
    419        size_of::<yaml_event_t>() as libc::c_ulong,
    420    );
    421    (*event).type_ = YAML_MAPPING_START_EVENT;
    422    (*event).start_mark = mark;
    423    (*event).end_mark = mark;
    424    (*event).data.mapping_start.anchor = anchor;
    425    (*event).data.mapping_start.tag = (*node).tag;
    426    (*event).data.mapping_start.implicit = implicit;
    427    (*event).data.mapping_start.style = (*node).data.mapping.style;
    428    if yaml_emitter_emit(emitter, event).fail {
    429        return FAIL;
    430    }
    431    pair = (*node).data.mapping.pairs.start;
    432    while pair < (*node).data.mapping.pairs.top {
    433        if yaml_emitter_dump_node(emitter, (*pair).key).fail {
    434            return FAIL;
    435        }
    436        if yaml_emitter_dump_node(emitter, (*pair).value).fail {
    437            return FAIL;
    438        }
    439        pair = pair.wrapping_offset(1);
    440    }
    441    memset(
    442        event as *mut libc::c_void,
    443        0,
    444        size_of::<yaml_event_t>() as libc::c_ulong,
    445    );
    446    (*event).type_ = YAML_MAPPING_END_EVENT;
    447    (*event).start_mark = mark;
    448    (*event).end_mark = mark;
    449    yaml_emitter_emit(emitter, event)
    450}