1 use crate::api::{yaml_free, yaml_malloc};
2 use crate::externs::{memset, strcmp};
3 use crate::fmt::WriteToPtr;
4 use crate::ops::ForceMul as _;
5 use crate::success::{Success, FAIL, OK};
6 use 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 };
13 use crate::{libc, yaml_document_delete, yaml_emitter_emit, PointerExt};
14 use core::mem::{size_of, MaybeUninit};
15 use 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.
yaml_emitter_open(emitter: *mut yaml_emitter_t) -> Success20 pub 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.
yaml_emitter_close(emitter: *mut yaml_emitter_t) -> Success49 pub 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 documen 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.
yaml_emitter_dump( emitter: *mut yaml_emitter_t, document: *mut yaml_document_t, ) -> Success83 pub 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 
yaml_emitter_delete_document_and_anchors(emitter: *mut yaml_emitter_t)169 unsafe 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 
yaml_emitter_anchor_node_sub(emitter: *mut yaml_emitter_t, index: libc::c_int)211 unsafe 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 
yaml_emitter_anchor_node(emitter: *mut yaml_emitter_t, index: libc::c_int)219 unsafe 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 
yaml_emitter_generate_anchor( _emitter: *mut yaml_emitter_t, anchor_id: libc::c_int, ) -> *mut yaml_char_t256 unsafe 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 
yaml_emitter_dump_node(emitter: *mut yaml_emitter_t, index: libc::c_int) -> Success265 unsafe 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 
yaml_emitter_dump_alias( emitter: *mut yaml_emitter_t, anchor: *mut yaml_char_t, ) -> Success288 unsafe 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 
yaml_emitter_dump_scalar( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success311 unsafe 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 
yaml_emitter_dump_sequence( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success349 unsafe 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 
yaml_emitter_dump_mapping( emitter: *mut yaml_emitter_t, node: *mut yaml_node_t, anchor: *mut yaml_char_t, ) -> Success399 unsafe 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 }
451