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