libyml-0.0.5/Cargo.lock 0000644 00000002311 00000000001 0010276 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "libyml"
version = "0.0.5"
dependencies = [
"anyhow",
"pretty_assertions",
"version_check",
]
[[package]]
name = "pretty_assertions"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
libyml-0.0.5/Cargo.toml 0000644 00000011425 00000000001 0010327 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.56.0"
name = "libyml"
version = "0.0.5"
authors = ["LibYML Contributors"]
build = false
exclude = [
"/.git/*",
"/.github/*",
"/.gitignore",
"/.vscode/*",
]
include = [
"/CONTRIBUTING.md",
"/LICENSE-MIT",
"/benches/**",
"/build.rs",
"/Cargo.toml",
"/examples/**",
"/README.md",
"/src/**",
"/tests/**",
]
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "A safe and efficient Rust library for parsing, emitting, and manipulating YAML data."
homepage = "https://libyml.com"
documentation = "https://docs.rs/libyml"
readme = "README.md"
keywords = [
"yaml",
"serde",
"serialization",
]
categories = [
"encoding",
"parser-implementations",
"no-std",
]
license = "MIT"
repository = "https://github.com/sebastienrousseau/libyml"
[package.metadata.clippy]
warn-lints = [
"clippy::all",
"clippy::pedantic",
"clippy::cargo",
"clippy::nursery",
]
[package.metadata.docs.rs]
rustdoc-args = ["--generate-link-to-definition"]
targets = ["x86_64-unknown-linux-gnu"]
[profile.dev]
opt-level = 0
lto = false
codegen-units = 256
debug = 2
debug-assertions = true
rpath = false
panic = "unwind"
overflow-checks = true
incremental = true
strip = false
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
debug = 0
debug-assertions = false
rpath = false
panic = "abort"
overflow-checks = false
incremental = false
strip = "symbols"
[profile.test]
opt-level = 0
lto = false
codegen-units = 256
debug = 2
debug-assertions = true
rpath = false
overflow-checks = true
incremental = true
strip = false
[lib]
name = "libyml"
crate-type = ["lib"]
path = "src/lib.rs"
doc-scrape-examples = false
[[bin]]
name = "run-emitter-test-suite"
path = "src/bin/run-emitter-test-suite.rs"
[[bin]]
name = "run-parser-test-suite"
path = "src/bin/run-parser-test-suite.rs"
[[example]]
name = "apis"
path = "examples/apis/main.rs"
[[example]]
name = "example"
path = "examples/example.rs"
[[test]]
name = "test_api"
path = "tests/test_api.rs"
[[test]]
name = "test_decode"
path = "tests/test_decode.rs"
[[test]]
name = "test_document"
path = "tests/test_document.rs"
[[test]]
name = "test_dumper"
path = "tests/test_dumper.rs"
[[test]]
name = "test_emitter"
path = "tests/test_emitter.rs"
[[test]]
name = "test_internal"
path = "tests/test_internal.rs"
[[test]]
name = "test_lib"
path = "tests/test_lib.rs"
[[test]]
name = "test_loader"
path = "tests/test_loader.rs"
[[test]]
name = "test_macros"
path = "tests/test_macros.rs"
[[test]]
name = "test_memory"
path = "tests/test_memory.rs"
[[test]]
name = "test_parser"
path = "tests/test_parser.rs"
[[test]]
name = "test_parser_error"
path = "tests/test_parser_error.rs"
[[test]]
name = "test_string"
path = "tests/test_string.rs"
[[test]]
name = "test_yaml"
path = "tests/test_yaml.rs"
[dependencies.anyhow]
version = "1.0.86"
[dev-dependencies.pretty_assertions]
version = "1.4.0"
[build-dependencies.version_check]
version = "0.9.5"
[features]
default = []
test-utils = []
[lints.rust]
bare_trait_objects = "allow"
box_pointers = "warn"
dead_code = "deny"
deprecated_in_future = "deny"
elided_lifetimes_in_paths = "allow"
ellipsis_inclusive_range_patterns = "deny"
explicit_outlives_requirements = "deny"
macro_use_extern_crate = "deny"
meta_variable_misuse = "deny"
missing_copy_implementations = "warn"
missing_debug_implementations = "forbid"
missing_docs = "warn"
missing_fragment_specifier = "deny"
non_ascii_idents = "forbid"
non_camel_case_types = "allow"
non_upper_case_globals = "allow"
noop_method_call = "deny"
single_use_lifetimes = "deny"
trivial_bounds = "allow"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
unreachable_pub = "forbid"
unsafe_code = "allow"
unstable_features = "warn"
unused_crate_dependencies = "allow"
unused_extern_crates = "warn"
unused_features = "deny"
unused_import_braces = "deny"
unused_labels = "deny"
unused_lifetimes = "deny"
unused_macro_rules = "deny"
unused_qualifications = "deny"
unused_results = "warn"
variant_size_differences = "deny"
[lints.rust.future_incompatible]
level = "deny"
priority = -1
[lints.rust.keyword_idents]
level = "deny"
priority = -1
[lints.rust.rust_2018_idioms]
level = "deny"
priority = -1
[lints.rust.rust_2021_compatibility]
level = "deny"
priority = -1
[lints.rust.unused]
level = "deny"
priority = -1
libyml-0.0.5/Cargo.toml.orig 0000644 0000000 0000000 00000012232 10461020230 0014005 0 ustar 0000000 0000000 [package]
# Metadata about the package
authors = ["LibYML Contributors"]
categories = ["encoding", "parser-implementations", "no-std"]
description = "A safe and efficient Rust library for parsing, emitting, and manipulating YAML data."
documentation = "https://docs.rs/libyml"
edition = "2021"
exclude = ["/.git/*", "/.github/*", "/.gitignore", "/.vscode/*"]
homepage = "https://libyml.com"
keywords = ["yaml", "serde", "serialization"]
license = "MIT"
name = "libyml"
readme = "README.md"
repository = "https://github.com/sebastienrousseau/libyml"
rust-version = "1.56.0"
version = "0.0.5"
# Specify which files to include in the package
include = [
"/CONTRIBUTING.md",
"/LICENSE-MIT",
"/benches/**",
"/build.rs",
"/Cargo.toml",
"/examples/**",
"/README.md",
"/src/**",
"/tests/**",
]
[dependencies]
# General dependencies for the package
anyhow = "1.0.86" # Rust library for reporting multiple error types through a single type.
[build-dependencies]
# Dependencies specifically for build scripts
version_check = "0.9.5" # Check the Rust version used to compile the package.
[dev-dependencies]
# Dependencies used during development and testing
pretty_assertions = "1.4.0" # Pretty assertions for tests.
libyml-test-suite = { path = "tests/data" } # Local dependency for test suite.
[features]
# Define optional features for the package
default = [] # No default features
test-utils = [] # Feature for test utilities
[lib]
# Library configuration options
crate-type = ["lib"]
name = "libyml"
path = "src/lib.rs"
doc-scrape-examples = false # Disable scraping of examples for documentation
[package.metadata.docs.rs]
# Metadata for generating documentation on docs.rs
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]
# Linting configuration
[lints.rust]
## Warn
box_pointers = "warn" # Warn on usage of heap-allocated pointers
missing_copy_implementations = "warn" # Warn if a `Copy` implementation is missing
missing_docs = "warn" # Warn if documentation is missing
unstable_features = "warn" # Warn on unstable features
unused_extern_crates = "warn" # Warn on unused external crates
unused_results = "warn" # Warn if the result of a function is unused
## Allow
bare_trait_objects = "allow" # Allow usage of bare trait objects
elided_lifetimes_in_paths = "allow" # Allow omitted lifetimes in paths
non_camel_case_types = "allow" # Allow types not in camel case
non_upper_case_globals = "allow" # Allow global variables not in upper case
trivial_bounds = "allow" # Allow trivial bounds in trait declarations
unused_crate_dependencies = "allow" # Allow unused crate dependencies
unsafe_code = "allow" # Allow usage of unsafe code
## Forbid
missing_debug_implementations = "forbid" # Forbid missing Debug implementations
non_ascii_idents = "forbid" # Forbid non-ASCII identifiers
unreachable_pub = "forbid" # Forbid unreachable public items
## Deny
dead_code = "deny" # Deny dead code
deprecated_in_future = "deny" # Deny features deprecated in future Rust versions
ellipsis_inclusive_range_patterns = "deny" # Deny ellipsis in inclusive range patterns
explicit_outlives_requirements = "deny" # Deny unnecessary lifetime bounds
future_incompatible = { level = "deny", priority = -1 } # Deny future-incompatible changes
keyword_idents = { level = "deny", priority = -1 } # Deny keywords used as identifiers
macro_use_extern_crate = "deny" # Deny `extern crate` with `macro_use`
meta_variable_misuse = "deny" # Deny misuse of macro variables
missing_fragment_specifier = "deny" # Deny missing fragment specifiers in macros
noop_method_call = "deny" # Deny no-op method calls
rust_2018_idioms = { level = "deny", priority = -1 } # Deny idioms from the 2018 edition
rust_2021_compatibility = { level = "deny", priority = -1 } # Deny issues with Rust 2021 edition
single_use_lifetimes = "deny" # Deny single-use lifetimes
trivial_casts = "deny" # Deny trivial casts
trivial_numeric_casts = "deny" # Deny trivial numeric casts
unused = { level = "deny", priority = -1 } # Deny unused code
unused_features = "deny" # Deny unused features
unused_import_braces = "deny" # Deny unused import braces
unused_labels = "deny" # Deny unused labels
unused_lifetimes = "deny" # Deny unused lifetimes
unused_macro_rules = "deny" # Deny unused macro rules
unused_qualifications = "deny" # Deny unused qualifications
variant_size_differences = "deny" # Deny variant size differences
[package.metadata.clippy]
# Clippy linting configuration
warn-lints = [
"clippy::all",
"clippy::pedantic",
"clippy::cargo",
"clippy::nursery",
]
[profile.dev]
# Profile settings for development builds
codegen-units = 256
debug = true
debug-assertions = true
incremental = true
lto = false
opt-level = 0
overflow-checks = true
panic = 'unwind'
rpath = false
strip = false
[profile.release]
# Profile settings for release builds
codegen-units = 1
debug = false
debug-assertions = false
incremental = false
lto = true
opt-level = "s"
overflow-checks = false
panic = "abort"
rpath = false
strip = "symbols"
[profile.test]
# Profile settings for test builds
codegen-units = 256
debug = true
debug-assertions = true
incremental = true
lto = false
opt-level = 0
overflow-checks = true
rpath = false
strip = false
libyml-0.0.5/LICENSE-MIT 0000644 0000000 0000000 00000001777 10461020230 0012566 0 ustar 0000000 0000000 Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
libyml-0.0.5/README.md 0000644 0000000 0000000 00000011452 10461020230 0012400 0 ustar 0000000 0000000
# LibYML (a fork of unsafe-libyaml)
[![Made With Love][made-with-rust]][10]
[![Crates.io][crates-badge]][06]
[![lib.rs][libs-badge]][11]
[![Docs.rs][docs-badge]][07]
[![Codecov][codecov-badge]][08]
[![Build Status][build-badge]][09]
[![GitHub][github-badge]][05]
LibYML is a Rust library for working with YAML data, forked from [unsafe-libyaml][01]. It offers a safe and efficient interface for parsing, emitting, and manipulating YAML data.
## Features
- **Serialization and Deserialization**: Easy-to-use APIs for serializing Rust structs and enums to YAML and vice versa.
- **Custom Struct and Enum Support**: Seamless serialization and deserialization of custom data types.
- **Comprehensive Error Handling**: Detailed error messages and recovery mechanisms.
- **Streaming Support**: Efficient processing of large YAML documents.
- **Alias and Anchor Support**: Handling of complex YAML structures with references.
- **Tag Handling**: Support for custom tags and type-specific serialization.
- **Configurable Emitter**: Customizable YAML output generation.
- **Extensive Documentation**: Detailed docs and examples for easy onboarding.
- **Safety and Efficiency**: Minimized unsafe code with an interface designed to prevent common pitfalls.
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
libyml = "0.0.5"
```
## Usage
Here's a quick example on how to use LibYML to parse a YAML string:
```rust
use core::mem::MaybeUninit;
use libyml::{
success::is_success,
yaml_parser_delete,
yaml_parser_initialize,
yaml_parser_parse,
yaml_parser_set_input_string,
YamlEventT,
YamlParserT,
};
fn main() {
unsafe {
let mut parser = MaybeUninit::::uninit();
if is_success(yaml_parser_initialize(parser.as_mut_ptr())) {
let mut parser = parser.assume_init();
let yaml = "{key1: value1, key2: [item1, item2]}";
yaml_parser_set_input_string(
&mut parser,
yaml.as_ptr(),
yaml.len() as u64,
);
let mut event = MaybeUninit::::uninit();
let result = yaml_parser_parse(&mut parser, event.as_mut_ptr());
if is_success(result) {
// Process the event here
} else {
// Failed to parse YAML
}
yaml_parser_delete(&mut parser);
} else {
// Failed to initialize parser
}
}
}
```
## Documentation
For full API documentation, please visit [https://doc.libyml.com/libyml/][03] or [https://docs.rs/libyml][07].
## Rust Version Compatibility
Compiler support: requires rustc 1.56.0+
## Contributing
Contributions are welcome! If you'd like to contribute, please feel free to submit a Pull Request on [GitHub][05].
## Credits and Acknowledgements
LibYML is a fork of the work done by [David Tolnay][04] and the maintainers of [unsafe-libyaml][01]. While it has evolved into a separate library, we express our sincere gratitude to them as well as the [libyaml][02] maintainers for their contributions to the Rust and C programming communities.
## License
[MIT license](LICENSE-MIT), same as libyaml.
[00]: https://libyml.com
[01]: https://github.com/dtolnay/unsafe-libyaml
[02]: https://github.com/yaml/libyaml/tree/2c891fc7a770e8ba2fec34fc6b545c672beb37e6
[03]: https://doc.libyml.com/libyml/
[04]: https://github.com/dtolnay
[05]: https://github.com/sebastienrousseau/libyml
[06]: https://crates.io/crates/libyml
[07]: https://docs.rs/libyml
[08]: https://codecov.io/gh/sebastienrousseau/libyml
[09]: https://github.com/sebastienrousseau/libyml/actions?query=branch%3Amaster
[10]: https://www.rust-lang.org/
[11]: https://lib.rs/crates/libyml
[build-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/libyml/release.yml?branch=master&style=for-the-badge&logo=github "Build Status"
[codecov-badge]: https://img.shields.io/codecov/c/github/sebastienrousseau/libyml?style=for-the-badge&logo=codecov&token=yc9s578xIk "Code Coverage"
[crates-badge]: https://img.shields.io/crates/v/libyml.svg?style=for-the-badge&color=fc8d62&logo=rust "View on Crates.io"
[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.5-orange.svg?style=for-the-badge "View on lib.rs"
[docs-badge]: https://img.shields.io/badge/docs.rs-libyml-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs "View Documentation"
[github-badge]: https://img.shields.io/badge/github-sebastienrousseau/libyml-8da0cb?style=for-the-badge&labelColor=555555&logo=github "View on GitHub"
[made-with-rust]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust'
libyml-0.0.5/examples/apis/main.rs 0000644 0000000 0000000 00000006376 10461020230 0015176 0 ustar 0000000 0000000 #![allow(missing_docs)]
use core::mem::MaybeUninit;
pub(crate) use core::primitive::u8 as yaml_char_t;
use core::ptr;
use libyml::api::yaml_parser_set_input_string;
use libyml::decode::{yaml_parser_delete, yaml_parser_initialize};
use libyml::memory::{
yaml_free, yaml_malloc, yaml_realloc, yaml_strdup,
};
use libyml::string::{yaml_string_extend, yaml_string_join};
pub(crate) fn main() {
// Print a message to indicate the file being executed.
println!("\n❯ Executing examples/apis/yaml_parser_delete.rs");
let mut parser = MaybeUninit::uninit();
let parser_ptr = parser.as_mut_ptr();
unsafe {
let _ = yaml_parser_initialize(parser_ptr);
println!(
"✅ Successfully initialized the YAML parser:\n{:#?}",
parser.assume_init()
);
let input = b"key: value\n";
yaml_parser_set_input_string(
parser_ptr,
input.as_ptr(),
input.len().try_into().unwrap(),
);
println!(
"✅ Successfully set the input string for the YAML parser"
);
// Example: yaml_malloc
let size = 1024;
let ptr = yaml_malloc(size);
// Use the allocated memory
yaml_free(ptr);
println!("✅ Successfully allocated and freed memory");
// Example: yaml_realloc
let size = 1024;
let ptr = yaml_malloc(size);
// Reallocate the memory
let new_size = 2048;
let new_ptr = yaml_realloc(ptr, new_size);
// Use the reallocated memory
yaml_free(new_ptr);
println!("✅ Successfully reallocated and freed memory");
// Example: yaml_strdup
let str = b"Hello, world!\0" as *const yaml_char_t;
let dup_str = yaml_strdup(str);
// Use the duplicated string
yaml_free(dup_str as *mut std::ffi::c_void);
println!("✅ Successfully duplicated and freed the string");
// Example: yaml_string_extend
let mut start = ptr::null_mut::();
let mut pointer = ptr::null_mut::();
let mut end = ptr::null_mut::();
yaml_string_extend(&mut start, &mut pointer, &mut end);
// Use the extended string buffer
yaml_free(start as *mut std::ffi::c_void);
println!(
"✅ Successfully extended and freed the string buffer"
);
// Example: yaml_string_join
let mut a_start = ptr::null_mut::();
let mut a_pointer = ptr::null_mut::();
let mut a_end = ptr::null_mut::();
let mut b_start = ptr::null_mut::();
let mut b_pointer = ptr::null_mut::();
let mut b_end = ptr::null_mut::();
yaml_string_join(
&mut a_start,
&mut a_pointer,
&mut a_end,
&mut b_start,
&mut b_pointer,
&mut b_end,
);
println!("✅ Successfully joined the string buffers");
// Use the joined string buffer
yaml_free(a_start as *mut std::ffi::c_void);
println!("✅ Successfully freed the joined string buffer");
yaml_parser_delete(parser_ptr);
println!("✅ Successfully deleted the YAML parser");
}
}
libyml-0.0.5/examples/apis/mod.rs 0000644 0000000 0000000 00000000110 10461020230 0015005 0 ustar 0000000 0000000 /// This module contains the apis `main` examples.
pub(crate) mod main;
libyml-0.0.5/examples/example.rs 0000644 0000000 0000000 00000000575 10461020230 0014744 0 ustar 0000000 0000000 #![allow(missing_docs)]
/// This module contains the `yaml_parser_initialize` example.
mod apis;
/// The main function that runs all the example modules.
///
/// This function is responsible for running all the example modules.
/// It does this by calling the `main` function of each example module.
///
fn main() {
// Run the example module `apis`.
apis::main::main();
}
libyml-0.0.5/src/api.rs 0000644 0000000 0000000 00000107522 10461020230 0013033 0 ustar 0000000 0000000 use crate::{
externs::{memcpy, memset, strlen},
internal::yaml_check_utf8,
libc,
memory::{yaml_free, yaml_malloc, yaml_strdup},
ops::ForceAdd as _,
success::{Success, FAIL, OK},
yaml::{size_t, yaml_char_t},
PointerExt, YamlAliasEvent, YamlAliasToken, YamlAnchorToken,
YamlAnyEncoding, YamlBreakT, YamlEmitterStateT, YamlEmitterT,
YamlEncodingT, YamlEventT,
YamlEventTypeT::{
YamlDocumentStartEvent, YamlScalarEvent, YamlStreamEndEvent,
},
YamlMappingEndEvent, YamlMappingStartEvent, YamlMappingStyleT,
YamlMarkT, YamlParserT, YamlReadHandlerT, YamlScalarStyleT,
YamlScalarToken, YamlSequenceEndEvent, YamlSequenceStartEvent,
YamlSequenceStyleT, YamlStreamStartEvent, YamlTagDirectiveT,
YamlTagDirectiveToken, YamlTagToken, YamlTokenT, YamlWriteHandlerT,
};
use core::{
mem::size_of,
ptr::{self, addr_of_mut},
};
const OUTPUT_BUFFER_SIZE: usize = 16384;
const OUTPUT_RAW_BUFFER_SIZE: usize = OUTPUT_BUFFER_SIZE * 2 + 2;
unsafe fn yaml_string_read_handler(
data: *mut libc::c_void,
buffer: *mut libc::c_uchar,
mut size: size_t,
size_read: *mut size_t,
) -> libc::c_int {
let parser: *mut YamlParserT = data as *mut YamlParserT;
if (*parser).input.string.current == (*parser).input.string.end {
*size_read = 0_u64;
return 1;
}
if size
> (*parser)
.input
.string
.end
.c_offset_from((*parser).input.string.current)
as size_t
{
size = (*parser)
.input
.string
.end
.c_offset_from((*parser).input.string.current)
as size_t;
}
let _ = memcpy(
buffer as *mut libc::c_void,
(*parser).input.string.current as *const libc::c_void,
size,
);
let fresh80 = addr_of_mut!((*parser).input.string.current);
*fresh80 = (*fresh80).wrapping_offset(size as isize);
*size_read = size;
1
}
/// Set a string input.
///
/// This function sets the input source for the parser to a string buffer.
/// Note that the `input` pointer must be valid while the `parser` object
/// exists. The application is responsible for destroying `input` after
/// destroying the `parser`.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - The `YamlParserT` struct must not have an input handler already set.
/// - `input` must be a valid, non-null pointer to a null-terminated string buffer.
/// - The `input` string buffer must remain valid and unmodified until the `parser` object is destroyed.
/// - The `YamlParserT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_parser_set_input_string(
parser: *mut YamlParserT,
input: *const libc::c_uchar,
size: size_t,
) {
assert!(!parser.is_null());
assert!((*parser).read_handler.is_none());
assert!(!input.is_null());
(*parser).read_handler = Some(yaml_string_read_handler);
(*parser).read_handler_data = parser as *mut libc::c_void;
(*parser).input.string.start = input;
(*parser).input.string.current = input;
(*parser).input.string.end = input.wrapping_offset(size as isize);
}
/// Set a generic input handler.
///
/// This function sets a custom input handler for the parser.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - The `YamlParserT` struct must not have an input handler already set.
/// - `handler` must be a valid function pointer that follows the signature of `YamlReadHandlerT`.
/// - `data` must be a valid pointer that will be passed to the `handler` function.
/// - The `YamlParserT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_parser_set_input(
parser: *mut YamlParserT,
handler: YamlReadHandlerT,
data: *mut libc::c_void,
) {
__assert!(!parser.is_null());
__assert!(((*parser).read_handler).is_none());
let fresh89 = addr_of_mut!((*parser).read_handler);
*fresh89 = Some(handler);
let fresh90 = addr_of_mut!((*parser).read_handler_data);
*fresh90 = data;
}
/// Set the source encoding.
///
/// This function sets the expected encoding of the input source for the parser.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - The `YamlParserT` struct must not have an encoding already set, or the encoding must be `YamlAnyEncoding`.
/// - The `YamlParserT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_parser_set_encoding(
parser: *mut YamlParserT,
encoding: YamlEncodingT,
) {
__assert!(!parser.is_null());
__assert!((*parser).encoding == YamlAnyEncoding);
(*parser).encoding = encoding;
}
/// Initialize an emitter.
///
/// This function creates a new emitter object. An application is responsible
/// for destroying the object using the yaml_emitter_delete() function.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to an uninitialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for properly destroying the emitter object using `yaml_emitter_delete`.
///
pub unsafe fn yaml_emitter_initialize(
emitter: *mut YamlEmitterT,
) -> Success {
__assert!(!emitter.is_null());
let _ = memset(
emitter as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
BUFFER_INIT!((*emitter).buffer, OUTPUT_BUFFER_SIZE);
BUFFER_INIT!((*emitter).raw_buffer, OUTPUT_RAW_BUFFER_SIZE);
STACK_INIT!((*emitter).states, YamlEmitterStateT);
QUEUE_INIT!((*emitter).events, YamlEventT);
STACK_INIT!((*emitter).indents, libc::c_int);
STACK_INIT!((*emitter).tag_directives, YamlTagDirectiveT);
OK
}
/// Destroy an emitter.
///
/// This function frees all memory associated with an emitter object, including
/// any dynamically allocated buffers, events, and other data structures.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must have been properly initialized and their memory allocated correctly.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
/// - After calling this function, the `emitter` pointer should be considered invalid and should not be used again.
///
pub unsafe fn yaml_emitter_delete(emitter: *mut YamlEmitterT) {
__assert!(!emitter.is_null());
BUFFER_DEL!((*emitter).buffer);
BUFFER_DEL!((*emitter).raw_buffer);
STACK_DEL!((*emitter).states);
while !QUEUE_EMPTY!((*emitter).events) {
yaml_event_delete(addr_of_mut!(DEQUEUE!((*emitter).events)));
}
QUEUE_DEL!((*emitter).events);
STACK_DEL!((*emitter).indents);
while !STACK_EMPTY!((*emitter).tag_directives) {
let tag_directive = POP!((*emitter).tag_directives);
yaml_free(tag_directive.handle as *mut libc::c_void);
yaml_free(tag_directive.prefix as *mut libc::c_void);
}
STACK_DEL!((*emitter).tag_directives);
yaml_free((*emitter).anchors as *mut libc::c_void);
let _ = memset(
emitter as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
}
unsafe fn yaml_string_write_handler(
data: *mut libc::c_void,
buffer: *mut libc::c_uchar,
size: size_t,
) -> libc::c_int {
let emitter: *mut YamlEmitterT = data as *mut YamlEmitterT;
if (*emitter)
.output
.string
.size
.wrapping_sub(*(*emitter).output.string.size_written)
< size
{
let _ =
memcpy(
(*emitter).output.string.buffer.wrapping_offset(
*(*emitter).output.string.size_written as isize,
) as *mut libc::c_void,
buffer as *const libc::c_void,
(*emitter).output.string.size.wrapping_sub(
*(*emitter).output.string.size_written,
),
);
*(*emitter).output.string.size_written =
(*emitter).output.string.size;
return 0;
}
let _ = memcpy(
(*emitter).output.string.buffer.wrapping_offset(
*(*emitter).output.string.size_written as isize,
) as *mut libc::c_void,
buffer as *const libc::c_void,
size,
);
let fresh153 =
addr_of_mut!((*(*emitter).output.string.size_written));
*fresh153 = (*fresh153).wrapping_add(size);
1
}
/// Set a string output.
///
/// This function sets the output destination for the emitter to a string buffer.
/// The emitter will write the output characters to the `output` buffer of the
/// specified `size`. The emitter will set `size_written` to the number of written
/// bytes. If the buffer is smaller than required, the emitter produces the
/// YAML_write_ERROR error.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must not have an output handler already set.
/// - `output` must be a valid, non-null pointer to a writeable buffer of size `size`.
/// - `size_written` must be a valid, non-null pointer to a `size_t` variable.
/// - The `output` buffer must remain valid and unmodified until the emitter is destroyed or the output is reset.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_output_string(
emitter: *mut YamlEmitterT,
output: *mut libc::c_uchar,
size: size_t,
size_written: *mut size_t,
) {
assert!(!emitter.is_null());
assert!((*emitter).write_handler.is_none());
assert!(!output.is_null());
(*emitter).write_handler = Some(yaml_string_write_handler);
(*emitter).write_handler_data = emitter as *mut libc::c_void;
(*emitter).output.string.buffer = output;
(*emitter).output.string.size = size;
*size_written = 0;
}
/// Set a generic output handler.
///
/// This function sets a custom output handler for the emitter.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must not have an output handler already set.
/// - `handler` must be a valid function pointer that follows the signature of `YamlWriteHandlerT`.
/// - `data` must be a valid pointer that will be passed to the `handler` function.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_output(
emitter: *mut YamlEmitterT,
handler: YamlWriteHandlerT,
data: *mut libc::c_void,
) {
__assert!(!emitter.is_null());
__assert!(((*emitter).write_handler).is_none());
let fresh161 = addr_of_mut!((*emitter).write_handler);
*fresh161 = Some(handler);
let fresh162 = addr_of_mut!((*emitter).write_handler_data);
*fresh162 = data;
}
/// Set the output encoding.
///
/// This function sets the encoding to be used for the output by the emitter.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must not have an encoding already set, or the encoding must be `YamlAnyEncoding`.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_encoding(
emitter: *mut YamlEmitterT,
encoding: YamlEncodingT,
) {
__assert!(!emitter.is_null());
__assert!((*emitter).encoding == YamlAnyEncoding);
(*emitter).encoding = encoding;
}
/// Set if the output should be in the "canonical" format as in the YAML
/// specification.
///
/// This function sets whether the emitter should produce output in the canonical
/// format, as defined by the YAML specification.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_canonical(
emitter: *mut YamlEmitterT,
canonical: bool,
) {
__assert!(!emitter.is_null());
(*emitter).canonical = canonical;
}
/// Set the indentation increment.
///
/// This function sets the indentation increment to be used by the emitter when
/// emitting indented content.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_indent(
emitter: *mut YamlEmitterT,
indent: libc::c_int,
) {
__assert!(!emitter.is_null());
(*emitter).best_indent =
if 1 < indent && indent < 10 { indent } else { 2 };
}
/// Set the preferred line width. -1 means unlimited.
///
/// This function sets the preferred line width for the emitter's output.
/// A value of -1 means that the line width is unlimited.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_width(
emitter: *mut YamlEmitterT,
width: libc::c_int,
) {
__assert!(!emitter.is_null());
(*emitter).best_width = if width >= 0 { width } else { -1 };
}
/// Set if unescaped non-ASCII characters are allowed.
///
/// This function sets whether the emitter should allow unescaped non-ASCII
/// characters in its output.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_unicode(
emitter: *mut YamlEmitterT,
unicode: bool,
) {
__assert!(!emitter.is_null());
(*emitter).unicode = unicode;
}
/// Set the preferred line break.
///
/// This function sets the preferred line break character to be used by the emitter.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct and its associated data structures must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_set_break(
emitter: *mut YamlEmitterT,
line_break: YamlBreakT,
) {
__assert!(!emitter.is_null());
(*emitter).line_break = line_break;
}
/// Free any memory allocated for a token object.
///
/// This function frees the dynamically allocated memory associated with a `YamlTokenT` struct,
/// such as strings for tag directives, aliases, anchors, tags, and scalar values.
///
/// # Safety
///
/// - `token` must be a valid, non-null pointer to a `YamlTokenT` struct.
/// - The `YamlTokenT` struct must have been properly initialized and its memory allocated correctly.
/// - The `YamlTokenT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_token_delete(token: *mut YamlTokenT) {
__assert!(!token.is_null());
match (*token).type_ {
YamlTagDirectiveToken => {
yaml_free(
(*token).data.tag_directive.handle as *mut libc::c_void,
);
yaml_free(
(*token).data.tag_directive.prefix as *mut libc::c_void,
);
}
YamlAliasToken => {
yaml_free((*token).data.alias.value as *mut libc::c_void);
}
YamlAnchorToken => {
yaml_free((*token).data.anchor.value as *mut libc::c_void);
}
YamlTagToken => {
yaml_free((*token).data.tag.handle as *mut libc::c_void);
yaml_free((*token).data.tag.suffix as *mut libc::c_void);
}
YamlScalarToken => {
yaml_free((*token).data.scalar.value as *mut libc::c_void);
}
_ => {}
}
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
}
/// Create the STREAM-START event.
///
/// This function initializes a `YamlEventT` struct with the type `YamlStreamStartEvent`.
/// It is used to signal the start of a YAML stream being emitted.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_stream_start_event_initialize(
event: *mut YamlEventT,
encoding: YamlEncodingT,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlStreamStartEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
(*event).data.stream_start.encoding = encoding;
OK
}
/// Create the STREAM-END event.
///
/// This function initializes a `YamlEventT` struct with the type `YamlStreamEndEvent`.
/// It is used to signal the end of a YAML stream being emitted.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_stream_end_event_initialize(
event: *mut YamlEventT,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlStreamEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
OK
}
/// Create an ALIAS event.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `anchor` must be a valid, non-null pointer to a null-terminated UTF-8 string.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
pub unsafe fn yaml_alias_event_initialize(
event: *mut YamlEventT,
anchor: *const yaml_char_t,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
__assert!(!anchor.is_null());
if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char)).fail
{
return FAIL;
}
let anchor_copy: *mut yaml_char_t = yaml_strdup(anchor);
if anchor_copy.is_null() {
return FAIL;
}
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlAliasEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh167 = addr_of_mut!((*event).data.alias.anchor);
*fresh167 = anchor_copy;
OK
}
/// Create a SCALAR event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or one of the `plain_implicit` and
/// `quoted_implicit` flags must be set.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `data.value` must be a valid, non-null pointer to a null-terminated UTF-8 string.
/// - `data.anchor`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - `data.tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct ScalarEventData<'a> {
/// Anchor name or null.
pub anchor: *const yaml_char_t,
/// Tag or null.
pub tag: *const yaml_char_t,
/// Value.
pub value: *const yaml_char_t,
/// Value length.
pub length: libc::c_int,
/// Is the tag optional for the plain style?
pub plain_implicit: bool,
/// Is the tag optional for any non-plain style?
pub quoted_implicit: bool,
/// Scalar style.
pub style: YamlScalarStyleT,
/// Lifetime marker.
pub _marker: core::marker::PhantomData<&'a ()>,
}
/// Create a SCALAR event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or one of the `plain_implicit` and
/// `quoted_implicit` flags must be set.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `value` must be a valid, non-null pointer to a null-terminated UTF-8 string.
/// - `anchor`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
pub unsafe fn yaml_scalar_event_initialize(
event: *mut YamlEventT,
mut data: ScalarEventData<'_>,
) -> Success {
let mut current_block: u64;
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut anchor_copy: *mut yaml_char_t =
ptr::null_mut::();
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
let mut value_copy: *mut yaml_char_t =
ptr::null_mut::();
__assert!(!event.is_null());
__assert!(!data.value.is_null());
if !data.anchor.is_null() {
if yaml_check_utf8(
data.anchor,
strlen(data.anchor as *mut libc::c_char),
)
.fail
{
current_block = 16285396129609901221;
} else {
anchor_copy = yaml_strdup(data.anchor);
if anchor_copy.is_null() {
current_block = 16285396129609901221;
} else {
current_block = 8515828400728868193;
}
}
} else {
current_block = 8515828400728868193;
}
if current_block == 8515828400728868193 {
if !data.tag.is_null() {
if yaml_check_utf8(
data.tag,
strlen(data.tag as *mut libc::c_char),
)
.fail
{
current_block = 16285396129609901221;
} else {
tag_copy = yaml_strdup(data.tag);
if tag_copy.is_null() {
current_block = 16285396129609901221;
} else {
current_block = 12800627514080957624;
}
}
} else {
current_block = 12800627514080957624;
}
if current_block != 16285396129609901221 {
if data.length < 0 {
data.length = strlen(data.value as *mut libc::c_char)
as libc::c_int;
}
if yaml_check_utf8(data.value, data.length as size_t).ok {
value_copy =
yaml_malloc(data.length.force_add(1) as size_t)
as *mut yaml_char_t;
let _ = memcpy(
value_copy as *mut libc::c_void,
data.value as *const libc::c_void,
data.length as libc::c_ulong,
);
*value_copy.wrapping_offset(data.length as isize) =
b'\0';
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlScalarEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh168 =
addr_of_mut!((*event).data.scalar.anchor);
*fresh168 = anchor_copy;
let fresh169 = addr_of_mut!((*event).data.scalar.tag);
*fresh169 = tag_copy;
let fresh170 = addr_of_mut!((*event).data.scalar.value);
*fresh170 = value_copy;
(*event).data.scalar.length = data.length as size_t;
(*event).data.scalar.plain_implicit =
data.plain_implicit;
(*event).data.scalar.quoted_implicit =
data.quoted_implicit;
(*event).data.scalar.style = data.style;
return OK;
}
}
}
yaml_free(anchor_copy as *mut libc::c_void);
yaml_free(tag_copy as *mut libc::c_void);
yaml_free(value_copy as *mut libc::c_void);
FAIL
}
/// Create a SEQUENCE-START event.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `anchor`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
pub unsafe fn yaml_sequence_start_event_initialize(
event: *mut YamlEventT,
anchor: *const yaml_char_t,
tag: *const yaml_char_t,
implicit: bool,
style: YamlSequenceStyleT,
) -> Success {
let mut current_block: u64;
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut anchor_copy: *mut yaml_char_t =
ptr::null_mut::();
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
__assert!(!event.is_null());
if !anchor.is_null() {
if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char))
.fail
{
current_block = 8817775685815971442;
} else {
anchor_copy = yaml_strdup(anchor);
if anchor_copy.is_null() {
current_block = 8817775685815971442;
} else {
current_block = 11006700562992250127;
}
}
} else {
current_block = 11006700562992250127;
}
if current_block == 11006700562992250127 {
if !tag.is_null() {
if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char))
.fail
{
current_block = 8817775685815971442;
} else {
tag_copy = yaml_strdup(tag);
if tag_copy.is_null() {
current_block = 8817775685815971442;
} else {
current_block = 7651349459974463963;
}
}
} else {
current_block = 7651349459974463963;
}
if current_block != 8817775685815971442 {
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceStartEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh171 =
addr_of_mut!((*event).data.sequence_start.anchor);
*fresh171 = anchor_copy;
let fresh172 =
addr_of_mut!((*event).data.sequence_start.tag);
*fresh172 = tag_copy;
(*event).data.sequence_start.implicit = implicit;
(*event).data.sequence_start.style = style;
return OK;
}
}
yaml_free(anchor_copy as *mut libc::c_void);
yaml_free(tag_copy as *mut libc::c_void);
FAIL
}
/// Create a SEQUENCE-END event.
///
/// This function initializes a `YamlEventT` struct with the type `YamlSequenceEndEvent`.
/// It is used to signal the end of a sequence in the YAML document being emitted.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_sequence_end_event_initialize(
event: *mut YamlEventT,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
OK
}
/// Create a MAPPING-START event.
///
/// This function initializes a `YamlEventT` struct with the type `YamlMappingStartEvent`.
/// It is used to signal the start of a mapping (key-value pairs) in the YAML document being emitted.
///
/// The `style` argument may be ignored by the emitter.
///
/// Either the `tag` attribute or the `implicit` flag must be set.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `anchor`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
pub unsafe fn yaml_mapping_start_event_initialize(
event: *mut YamlEventT,
anchor: *const yaml_char_t,
tag: *const yaml_char_t,
implicit: bool,
style: YamlMappingStyleT,
) -> Success {
let mut current_block: u64;
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut anchor_copy: *mut yaml_char_t =
ptr::null_mut::();
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
__assert!(!event.is_null());
if !anchor.is_null() {
if yaml_check_utf8(anchor, strlen(anchor as *mut libc::c_char))
.fail
{
current_block = 14748279734549812740;
} else {
anchor_copy = yaml_strdup(anchor);
if anchor_copy.is_null() {
current_block = 14748279734549812740;
} else {
current_block = 11006700562992250127;
}
}
} else {
current_block = 11006700562992250127;
}
if current_block == 11006700562992250127 {
if !tag.is_null() {
if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char))
.fail
{
current_block = 14748279734549812740;
} else {
tag_copy = yaml_strdup(tag);
if tag_copy.is_null() {
current_block = 14748279734549812740;
} else {
current_block = 7651349459974463963;
}
}
} else {
current_block = 7651349459974463963;
}
if current_block != 14748279734549812740 {
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingStartEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh173 =
addr_of_mut!((*event).data.mapping_start.anchor);
*fresh173 = anchor_copy;
let fresh174 =
addr_of_mut!((*event).data.mapping_start.tag);
*fresh174 = tag_copy;
(*event).data.mapping_start.implicit = implicit;
(*event).data.mapping_start.style = style;
return OK;
}
}
yaml_free(anchor_copy as *mut libc::c_void);
yaml_free(tag_copy as *mut libc::c_void);
FAIL
}
/// Create a MAPPING-END event.
///
/// This function initializes a `YamlEventT` struct with the type `YamlMappingEndEvent`.
/// It is used to signal the end of a mapping (key-value pairs) in the YAML document being emitted.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_mapping_end_event_initialize(
event: *mut YamlEventT,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
OK
}
/// Free any memory allocated for an event object.
///
/// This function frees the dynamically allocated memory associated with a `YamlEventT` struct,
/// such as strings for anchors, tags, and scalar values.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct.
/// - The `YamlEventT` struct must have been properly initialized and its memory allocated correctly.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_event_delete(event: *mut YamlEventT) {
let mut tag_directive: *mut YamlTagDirectiveT;
__assert!(!event.is_null());
match (*event).type_ {
YamlDocumentStartEvent => {
yaml_free(
(*event).data.document_start.version_directive
as *mut libc::c_void,
);
tag_directive =
(*event).data.document_start.tag_directives.start;
while tag_directive
!= (*event).data.document_start.tag_directives.end
{
yaml_free((*tag_directive).handle as *mut libc::c_void);
yaml_free((*tag_directive).prefix as *mut libc::c_void);
tag_directive = tag_directive.wrapping_offset(1);
}
yaml_free(
(*event).data.document_start.tag_directives.start
as *mut libc::c_void,
);
}
YamlAliasEvent => {
yaml_free((*event).data.alias.anchor as *mut libc::c_void);
}
YamlScalarEvent => {
yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
yaml_free((*event).data.scalar.tag as *mut libc::c_void);
yaml_free((*event).data.scalar.value as *mut libc::c_void);
}
YamlSequenceStartEvent => {
yaml_free(
(*event).data.sequence_start.anchor
as *mut libc::c_void,
);
yaml_free(
(*event).data.sequence_start.tag as *mut libc::c_void,
);
}
YamlMappingStartEvent => {
yaml_free(
(*event).data.mapping_start.anchor as *mut libc::c_void,
);
yaml_free(
(*event).data.mapping_start.tag as *mut libc::c_void,
);
}
_ => {}
}
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
}
libyml-0.0.5/src/bin/cstr/mod.rs 0000644 0000000 0000000 00000002651 10461020230 0014561 0 ustar 0000000 0000000 use std::fmt::{self, Display, Write as _};
use std::slice;
use std::str;
#[allow(non_camel_case_types)]
type c_char = i8;
pub(crate) struct CStr {
pub(crate) ptr: *const u8,
}
impl CStr {
pub(crate) unsafe fn from_ptr(ptr: *const c_char) -> Self {
CStr { ptr: ptr.cast() }
}
}
impl Display for CStr {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let len = unsafe { strlen(self.ptr) };
let mut bytes = unsafe { slice::from_raw_parts(self.ptr, len) };
loop {
match str::from_utf8(bytes) {
Ok(valid) => return formatter.write_str(valid),
Err(utf8_error) => {
let valid_up_to = utf8_error.valid_up_to();
let valid = unsafe {
str::from_utf8_unchecked(&bytes[..valid_up_to])
};
formatter.write_str(valid)?;
formatter
.write_char(char::REPLACEMENT_CHARACTER)?;
if let Some(error_len) = utf8_error.error_len() {
bytes = &bytes[valid_up_to + error_len..];
} else {
return Ok(());
}
}
}
}
}
}
unsafe fn strlen(s: *const u8) -> usize {
let mut end = s;
while *end != 0 {
end = end.add(1);
}
end.offset_from(s) as usize
}
libyml-0.0.5/src/bin/run-emitter-test-suite.rs 0000644 0000000 0000000 00000027745 10461020230 0017421 0 ustar 0000000 0000000 #![allow(missing_docs)]
#![warn(clippy::pedantic)]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::items_after_statements,
clippy::let_underscore_untyped,
clippy::missing_errors_doc,
clippy::missing_safety_doc,
clippy::ptr_as_ptr,
clippy::single_match_else,
clippy::too_many_lines,
clippy::uninlined_format_args,
clippy::unreadable_literal
)]
mod cstr;
use self::cstr::CStr;
use core::fmt;
pub(crate) use core::primitive::u8 as yaml_char_t;
use libyml::api::ScalarEventData;
use libyml::document::{
yaml_document_end_event_initialize,
yaml_document_start_event_initialize,
};
use libyml::{
yaml_alias_event_initialize, yaml_emitter_delete,
yaml_emitter_emit, yaml_emitter_initialize,
yaml_emitter_set_canonical, yaml_emitter_set_output,
yaml_emitter_set_unicode, yaml_mapping_end_event_initialize,
yaml_mapping_start_event_initialize, yaml_scalar_event_initialize,
yaml_sequence_end_event_initialize,
yaml_sequence_start_event_initialize,
yaml_stream_end_event_initialize,
yaml_stream_start_event_initialize, YamlAnyScalarStyle,
YamlBlockMappingStyle, YamlBlockSequenceStyle,
YamlDoubleQuotedScalarStyle, YamlEmitterError, YamlEmitterT,
YamlEventT, YamlFoldedScalarStyle, YamlLiteralScalarStyle,
YamlMemoryError, YamlPlainScalarStyle, YamlScalarStyleT,
YamlSingleQuotedScalarStyle, YamlTagDirectiveT, YamlUtf8Encoding,
YamlVersionDirectiveT, YamlWriterError,
};
use std::env;
use std::error::Error;
use std::ffi::c_void;
use std::fs::File;
use std::io::{self, Read, Write};
use std::mem::MaybeUninit;
use std::process::{self, ExitCode};
use std::ptr::{self, addr_of_mut};
#[derive(Debug)]
pub(crate) enum EmitterError {
InitializationError(String),
MemoryError(String),
UnknownEvent(String),
EmittingError(String),
InternalError,
}
impl fmt::Display for EmitterError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EmitterError::InitializationError(msg)
| EmitterError::MemoryError(msg)
| EmitterError::UnknownEvent(msg)
| EmitterError::EmittingError(msg) => {
write!(f, "{}", msg)
}
EmitterError::InternalError => write!(f, "Internal error"),
}
}
}
impl Error for EmitterError {}
pub(crate) unsafe fn unsafe_main(
stdin: &mut dyn Read,
mut stdout: &mut dyn Write,
) -> Result<(), EmitterError> {
let mut emitter = MaybeUninit::::uninit();
let emitter = emitter.as_mut_ptr();
if yaml_emitter_initialize(emitter).fail {
return Err(EmitterError::InitializationError(
"Could not initialize the emitter object".into(),
));
}
unsafe fn write_to_stdio(
data: *mut c_void,
buffer: *mut u8,
size: u64,
) -> i32 {
let stdout: *mut &mut dyn Write = data as _;
let bytes = std::slice::from_raw_parts(buffer, size as usize);
match (*stdout).write(bytes) {
Ok(n) => n as i32,
Err(_) => 0,
}
}
yaml_emitter_set_output(
emitter,
write_to_stdio,
addr_of_mut!(stdout).cast(),
);
yaml_emitter_set_canonical(emitter, false);
yaml_emitter_set_unicode(emitter, false);
let mut buf = ReadBuf::new();
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let result = loop {
let line = match buf.get_line(stdin) {
Some(line) => line,
None => break Ok(()),
};
let mut anchor = [0u8; 256];
let mut tag = [0u8; 256];
let result = if line.starts_with(b"+STR") {
yaml_stream_start_event_initialize(event, YamlUtf8Encoding)
} else if line.starts_with(b"-STR") {
yaml_stream_end_event_initialize(event)
} else if line.starts_with(b"+DOC") {
let implicit = !line[4..].starts_with(b" ---");
yaml_document_start_event_initialize(
event,
ptr::null_mut::(),
ptr::null_mut::(),
ptr::null_mut::(),
implicit,
)
} else if line.starts_with(b"-DOC") {
let implicit = !line[4..].starts_with(b" ...");
yaml_document_end_event_initialize(event, implicit)
} else if line.starts_with(b"+MAP") {
yaml_mapping_start_event_initialize(
event,
get_anchor(b'&', line, anchor.as_mut_ptr()),
get_tag(line, tag.as_mut_ptr()),
false,
YamlBlockMappingStyle,
)
} else if line.starts_with(b"-MAP") {
yaml_mapping_end_event_initialize(event)
} else if line.starts_with(b"+SEQ") {
yaml_sequence_start_event_initialize(
event,
get_anchor(b'&', line, anchor.as_mut_ptr()),
get_tag(line, tag.as_mut_ptr()),
false,
YamlBlockSequenceStyle,
)
} else if line.starts_with(b"-SEQ") {
yaml_sequence_end_event_initialize(event)
} else if line.starts_with(b"=VAL") {
let mut value = [0i8; 1024];
let mut style = YamlAnyScalarStyle;
get_value(line, value.as_mut_ptr(), &mut style);
let implicit = get_tag(line, tag.as_mut_ptr()).is_null();
let scalar_event_data = ScalarEventData {
anchor: get_anchor(b'&', line, anchor.as_mut_ptr()),
tag: get_tag(line, tag.as_mut_ptr()),
value: value.as_mut_ptr() as *const yaml_char_t,
length: -1,
plain_implicit: implicit,
quoted_implicit: implicit,
style,
_marker: core::marker::PhantomData,
};
yaml_scalar_event_initialize(event, scalar_event_data)
} else if line.starts_with(b"=ALI") {
yaml_alias_event_initialize(
event,
get_anchor(b'*', line, anchor.as_mut_ptr()),
)
} else {
let line = line.as_mut_ptr() as *mut i8;
break Err(EmitterError::UnknownEvent(format!(
"Unknown event: '{}'",
CStr::from_ptr(line)
)));
};
if result.fail {
break Err(EmitterError::MemoryError(
"Memory error: Not enough memory for creating an event"
.into(),
));
}
if yaml_emitter_emit(emitter, event).fail {
break Err(match (*emitter).error {
YamlMemoryError => EmitterError::MemoryError(
"Memory error: Not enough memory for emitting"
.into(),
),
YamlWriterError => {
EmitterError::EmittingError(format!(
"Writer error: {}",
CStr::from_ptr((*emitter).problem)
))
}
YamlEmitterError => {
EmitterError::EmittingError(format!(
"Emitter error: {}",
CStr::from_ptr((*emitter).problem)
))
}
_ => EmitterError::InternalError,
});
}
};
yaml_emitter_delete(emitter);
result.map_err(Into::into)
}
struct ReadBuf {
buf: [u8; 1024],
offset: usize,
filled: usize,
}
impl ReadBuf {
fn new() -> Self {
ReadBuf {
buf: [0; 1024],
offset: 0,
filled: 0,
}
}
fn get_line(&mut self, input: &mut dyn Read) -> Option<&mut [u8]> {
loop {
for i in self.offset..self.offset + self.filled {
if self.buf[i] == b'\n' {
self.buf[i] = b'\0';
let line = &mut self.buf[self.offset..=i];
self.offset = i + 1;
self.filled -= line.len();
return Some(line);
}
}
let mut remainder =
&mut self.buf[self.offset + self.filled..];
if remainder.is_empty() {
if self.offset == 0 {
let _ = writeln!(
io::stderr(),
"Line too long: '{}'",
String::from_utf8_lossy(&self.buf),
);
process::abort();
}
self.buf.copy_within(self.offset.., 0);
self.offset = 0;
remainder = &mut self.buf;
}
let n = input.read(remainder).ok()?;
self.filled += n;
if n == 0 {
return None;
}
}
}
}
unsafe fn get_anchor(
sigil: u8,
line: &[u8],
anchor: *mut u8,
) -> *mut u8 {
let start = match line.iter().position(|ch| *ch == sigil) {
Some(offset) => offset + 1,
None => return ptr::null_mut(),
};
let end = match line[start..].iter().position(|ch| *ch == b' ') {
Some(offset) => start + offset,
None => line.len(),
};
anchor.copy_from_nonoverlapping(
line[start..end].as_ptr(),
end - start,
);
*anchor.add(end - start) = b'\0';
anchor
}
unsafe fn get_tag(line: &[u8], tag: *mut u8) -> *mut u8 {
let start = match line.iter().position(|ch| *ch == b'<') {
Some(offset) => offset + 1,
None => return ptr::null_mut(),
};
let end = match line[start..].iter().position(|ch| *ch == b'>') {
Some(offset) => start + offset,
None => return ptr::null_mut(),
};
tag.copy_from_nonoverlapping(
line[start..end].as_ptr(),
end - start,
);
*tag.add(end - start) = b'\0';
tag
}
unsafe fn get_value(
line: &[u8],
value: *mut i8,
style: *mut YamlScalarStyleT,
) {
let line_len = line.len();
let line = line.as_ptr() as *mut i8;
let mut start = ptr::null_mut::();
let end = line.add(line_len);
let mut c = line.offset(4);
while c < end {
if *c as u8 == b' ' {
start = c.offset(1);
*style = match *start as u8 {
b':' => YamlPlainScalarStyle,
b'\'' => YamlSingleQuotedScalarStyle,
b'"' => YamlDoubleQuotedScalarStyle,
b'|' => YamlLiteralScalarStyle,
b'>' => YamlFoldedScalarStyle,
_ => {
start = ptr::null_mut::();
c = c.offset(1);
continue;
}
};
start = start.offset(1);
break;
}
c = c.offset(1);
}
if start.is_null() {
process::abort();
}
let mut i = 0;
c = start;
while c < end {
*value.offset(i) = if *c as u8 == b'\\' {
c = c.offset(1);
match *c as u8 {
b'\\' => b'\\' as i8,
b'0' => b'\0' as i8,
b'b' => b'\x08' as i8,
b'n' => b'\n' as i8,
b'r' => b'\r' as i8,
b't' => b'\t' as i8,
_ => process::abort(),
}
} else {
*c
};
i += 1;
c = c.offset(1);
}
*value.offset(i) = b'\0' as i8;
}
fn main() -> ExitCode {
let args = env::args_os().skip(1);
if args.len() == 0 {
let _ = writeln!(
io::stderr(),
"Usage: run-emitter-test-suite ...",
);
return ExitCode::FAILURE;
}
for arg in args {
let mut stdin = File::open(arg).unwrap();
let mut stdout = io::stdout();
let result = unsafe { unsafe_main(&mut stdin, &mut stdout) };
if let Err(err) = result {
let _ = writeln!(io::stderr(), "{}", err);
return ExitCode::FAILURE;
}
}
ExitCode::SUCCESS
}
libyml-0.0.5/src/bin/run-parser-test-suite.rs 0000644 0000000 0000000 00000031011 10461020230 0017221 0 ustar 0000000 0000000 //! A YAML parser and formatter using the libyml library.
//!
//! This program reads YAML files, parses them using the libyml library,
//! and outputs a formatted representation of the YAML structure.
#![allow(missing_docs)]
#![warn(clippy::pedantic)]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::items_after_statements,
clippy::let_underscore_untyped,
clippy::missing_errors_doc,
clippy::missing_safety_doc,
clippy::too_many_lines,
clippy::uninlined_format_args
)]
mod cstr;
use self::cstr::CStr;
use anyhow::{bail, Error, Result};
use libyml::{
yaml_event_delete, yaml_parser_delete, yaml_parser_initialize,
yaml_parser_parse, yaml_parser_set_input, YamlAliasEvent,
YamlDocumentEndEvent, YamlDocumentStartEvent,
YamlDoubleQuotedScalarStyle, YamlEventT, YamlEventTypeT,
YamlFoldedScalarStyle, YamlLiteralScalarStyle, YamlMappingEndEvent,
YamlMappingStartEvent, YamlNoEvent, YamlParserT,
YamlPlainScalarStyle, YamlScalarEvent, YamlSequenceEndEvent,
YamlSequenceStartEvent, YamlSingleQuotedScalarStyle,
YamlStreamEndEvent, YamlStreamStartEvent,
};
use std::env;
use std::ffi::c_void;
use std::fs::File;
use std::io::{self, Read, Write};
use std::mem::MaybeUninit;
use std::path::Path;
use std::process::ExitCode;
use std::ptr::addr_of_mut;
use std::slice;
/// The main parsing function that processes YAML input and writes formatted output.
///
/// # Safety
///
/// This function is unsafe because it deals with raw pointers and FFI.
/// Callers must ensure that the provided `stdin` and `stdout` are valid
/// and that the FFI calls are used correctly.
///
/// # Arguments
///
/// * `stdin` - A mutable reference to a type that implements `Read`, from which YAML will be read.
/// * `stdout` - A mutable reference to a type that implements `Write`, to which formatted output will be written.
///
/// # Returns
///
/// Returns `Ok(())` if parsing and formatting succeed, or an `Error` if any issues occur.
pub(crate) unsafe fn unsafe_main(
mut stdin: &mut dyn Read,
stdout: &mut dyn Write,
) -> Result<()> {
let mut parser = MaybeUninit::::uninit();
let parser = parser.as_mut_ptr();
if yaml_parser_initialize(parser).fail {
bail!("Could not initialize the parser object");
}
/// Callback function for reading input from stdio.
///
/// This function is called by the YAML parser to read input data.
///
/// # Safety
///
/// This function is unsafe because it deals with raw pointers.
/// It assumes that `data` is a valid pointer to a `Read` trait object.
unsafe fn read_from_stdio(
data: *mut c_void,
buffer: *mut u8,
size: u64,
size_read: *mut u64,
) -> i32 {
let stdin: *mut &mut dyn Read = data.cast();
let slice =
slice::from_raw_parts_mut(buffer.cast(), size as usize);
match (*stdin).read(slice) {
Ok(n) => {
*size_read = n as u64;
1
}
Err(_) => 0,
}
}
yaml_parser_set_input(
parser,
read_from_stdio,
addr_of_mut!(stdin).cast(),
);
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
loop {
if yaml_parser_parse(parser, event).fail {
let error = format!(
"Parse error: {}",
CStr::from_ptr((*parser).problem)
);
let error = if (*parser).problem_mark.line != 0
|| (*parser).problem_mark.column != 0
{
format!(
"{}\nLine: {} Column: {}",
error,
((*parser).problem_mark.line).wrapping_add(1),
((*parser).problem_mark.column).wrapping_add(1),
)
} else {
error
};
yaml_parser_delete(parser);
return Err(Error::msg(error));
}
let type_: YamlEventTypeT = (*event).type_;
match type_ {
YamlNoEvent => writeln!(stdout, "???")?,
YamlStreamStartEvent => writeln!(stdout, "+STR")?,
YamlStreamEndEvent => writeln!(stdout, "-STR")?,
YamlDocumentStartEvent => {
write!(stdout, "+DOC")?;
if !(*event).data.document_start.implicit {
write!(stdout, " ---")?;
}
writeln!(stdout)?;
}
YamlDocumentEndEvent => {
write!(stdout, "-DOC")?;
if !(*event).data.document_end.implicit {
write!(stdout, " ...")?;
}
writeln!(stdout)?;
}
YamlMappingStartEvent => {
write!(stdout, "+MAP")?;
if !(*event).data.mapping_start.anchor.is_null() {
write!(
stdout,
" &{}",
CStr::from_ptr(
(*event).data.mapping_start.anchor
as *const i8
),
)?;
}
if !(*event).data.mapping_start.tag.is_null() {
write!(
stdout,
" <{}>",
CStr::from_ptr(
(*event).data.mapping_start.tag
as *const i8
),
)?;
}
writeln!(stdout)?;
}
YamlMappingEndEvent => writeln!(stdout, "-MAP")?,
YamlSequenceStartEvent => {
write!(stdout, "+SEQ")?;
if !(*event).data.sequence_start.anchor.is_null() {
write!(
stdout,
" &{}",
CStr::from_ptr(
(*event).data.sequence_start.anchor
as *const i8
),
)?;
}
if !(*event).data.sequence_start.tag.is_null() {
write!(
stdout,
" <{}>",
CStr::from_ptr(
(*event).data.sequence_start.tag
as *const i8
),
)?;
}
writeln!(stdout)?;
}
YamlSequenceEndEvent => writeln!(stdout, "-SEQ")?,
YamlScalarEvent => {
write!(stdout, "=VAL")?;
if !(*event).data.scalar.anchor.is_null() {
write!(
stdout,
" &{}",
CStr::from_ptr(
(*event).data.scalar.anchor as *const i8
),
)?;
}
if !(*event).data.scalar.tag.is_null() {
write!(
stdout,
" <{}>",
CStr::from_ptr(
(*event).data.scalar.tag as *const i8
),
)?;
}
stdout.write_all(match (*event).data.scalar.style {
YamlPlainScalarStyle => b" :",
YamlSingleQuotedScalarStyle => b" '",
YamlDoubleQuotedScalarStyle => b" \"",
YamlLiteralScalarStyle => b" |",
YamlFoldedScalarStyle => b" >",
_ => {
return Err(Error::msg("Unknown scalar style"))
}
})?;
print_escaped(
stdout,
(*event).data.scalar.value,
(*event).data.scalar.length,
)?;
writeln!(stdout)?;
}
YamlAliasEvent => writeln!(
stdout,
"=ALI *{}",
CStr::from_ptr((*event).data.alias.anchor as *const i8),
)?,
_ => return Err(Error::msg("Unknown event type")),
}
yaml_event_delete(event);
if type_ == YamlStreamEndEvent {
break;
}
}
yaml_parser_delete(parser);
Ok(())
}
/// Writes an escaped version of a byte slice to the given output.
///
/// This function handles proper escaping of special characters and
/// preserves UTF-8 encoded characters.
///
/// # Safety
///
/// This function is unsafe because it works with raw pointers.
/// The caller must ensure that `str` points to a valid memory location
/// containing at least `length` bytes.
///
/// # Arguments
///
/// * `stdout` - A mutable reference to a type that implements `Write`, to which the escaped output will be written.
/// * `str` - A raw pointer to the start of the byte slice to be escaped.
/// * `length` - The length of the byte slice.
///
/// # Returns
///
/// Returns `Ok(())` if writing succeeds, or an `io::Error` if any issues occur during writing.
unsafe fn print_escaped(
stdout: &mut dyn Write,
str: *const u8,
length: u64,
) -> io::Result<()> {
let slice = slice::from_raw_parts(str, length as usize);
let mut chars = slice.iter().peekable();
while let Some(&byte) = chars.next() {
if byte >= 128 {
// Start of a UTF-8 sequence
stdout.write_all(slice::from_ref(&byte))?;
while let Some(&&next_byte) = chars.peek() {
if !(128..192).contains(&next_byte) {
break;
}
stdout.write_all(slice::from_ref(&next_byte))?;
let _ = chars.next();
}
} else {
let repr = match byte {
b'\\' => "\\\\",
b'\0' => "\\0",
b'\x08' => "\\b",
b'\n' => "\\n",
b'\r' => "\\r",
b'\t' => "\\t",
_ if byte.is_ascii_graphic() || byte == b' ' => {
stdout.write_all(slice::from_ref(&byte))?;
continue;
}
_ => {
write!(stdout, "\\x{:02x}", byte)?;
continue;
}
};
stdout.write_all(repr.as_bytes())?;
}
}
Ok(())
}
/// The entry point of the program.
///
/// This function processes command-line arguments, reads YAML files,
/// and calls the parsing function for each file.
///
/// # Returns
///
/// Returns `ExitCode::SUCCESS` if all files are processed successfully,
/// or `ExitCode::FAILURE` if any errors occur.
fn main() -> ExitCode {
let args: Vec<_> = env::args_os().skip(1).collect();
if args.is_empty() {
eprintln!("Error: No input files provided.");
eprintln!(
"Usage: {} ...",
env::args().next().unwrap_or_default()
);
eprintln!("Please provide one or more YAML files to parse.");
return ExitCode::FAILURE;
}
for arg in args {
let path = Path::new(&arg);
if !path.exists() {
eprintln!("Error: File {:?} does not exist.", path);
return ExitCode::FAILURE;
}
if !path.is_file() {
eprintln!("Error: {:?} is not a file.", path);
return ExitCode::FAILURE;
}
match File::open(path) {
Ok(mut file) => {
let mut stdout = io::stdout();
eprintln!("Processing file: {:?}", path);
match unsafe { unsafe_main(&mut file, &mut stdout) } {
Ok(()) => eprintln!(
"Successfully processed file: {:?}",
path
),
Err(err) => {
eprintln!(
"Error processing file {:?}: {}",
path, err
);
eprintln!("The parser encountered an error. Please check if the file contains valid YAML.");
return ExitCode::FAILURE;
}
}
}
Err(err) => {
eprintln!("Error opening file {:?}: {}", path, err);
eprintln!("Please check if you have the necessary permissions to read the file.");
return ExitCode::FAILURE;
}
}
}
eprintln!("All files processed successfully.");
ExitCode::SUCCESS
}
libyml-0.0.5/src/decode.rs 0000644 0000000 0000000 00000006500 10461020230 0013477 0 ustar 0000000 0000000 // decode.rs
// Manages the decoding of YAML data structures in Rust, handling the lifecycle of YAML parsers.
use crate::{
libc,
memory::{yaml_free, yaml_malloc},
success::{Success, OK},
yaml::{size_t, yaml_char_t},
yaml_token_delete, YamlMarkT, YamlParserStateT, YamlParserT,
YamlSimpleKeyT, YamlTagDirectiveT, YamlTokenT,
};
use crate::externs::memset;
use core::{
mem::size_of,
ptr::{self, addr_of_mut},
};
const INPUT_RAW_BUFFER_SIZE: usize = 16384;
const INPUT_BUFFER_SIZE: usize = INPUT_RAW_BUFFER_SIZE * 3;
// const OUTPUT_BUFFER_SIZE: usize = 16384;
// const OUTPUT_RAW_BUFFER_SIZE: usize = OUTPUT_BUFFER_SIZE * 2 + 2;
/// Initialize a parser.
///
/// This function creates a new parser object. An application is responsible
/// for destroying the object using the yaml_parser_delete() function.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to an uninitialized `YamlParserT` struct.
/// - The `YamlParserT` struct must be properly aligned and have the expected memory layout.
/// - The caller is responsible for properly destroying the parser object using `yaml_parser_delete`.
///
pub unsafe fn yaml_parser_initialize(
parser: *mut YamlParserT,
) -> Success {
__assert!(!parser.is_null());
let _ = memset(
parser as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
BUFFER_INIT!((*parser).raw_buffer, INPUT_RAW_BUFFER_SIZE);
BUFFER_INIT!((*parser).buffer, INPUT_BUFFER_SIZE);
QUEUE_INIT!((*parser).tokens, YamlTokenT);
STACK_INIT!((*parser).indents, libc::c_int);
STACK_INIT!((*parser).simple_keys, YamlSimpleKeyT);
STACK_INIT!((*parser).states, YamlParserStateT);
STACK_INIT!((*parser).marks, YamlMarkT);
STACK_INIT!((*parser).tag_directives, YamlTagDirectiveT);
OK
}
/// Destroy a parser.
///
/// This function frees all memory associated with a parser object, including
/// any dynamically allocated buffers, tokens, and other data structures.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - The `YamlParserT` struct and its associated data structures must have been properly initialized and their memory allocated correctly.
/// - The `YamlParserT` struct and its associated data structures must be properly aligned and have the expected memory layout.
/// - After calling this function, the `parser` pointer should be considered invalid and should not be used again.
///
pub unsafe fn yaml_parser_delete(parser: *mut YamlParserT) {
__assert!(!parser.is_null());
BUFFER_DEL!((*parser).raw_buffer);
BUFFER_DEL!((*parser).buffer);
while !QUEUE_EMPTY!((*parser).tokens) {
yaml_token_delete(addr_of_mut!(DEQUEUE!((*parser).tokens)));
}
QUEUE_DEL!((*parser).tokens);
STACK_DEL!((*parser).indents);
STACK_DEL!((*parser).simple_keys);
STACK_DEL!((*parser).states);
STACK_DEL!((*parser).marks);
while !STACK_EMPTY!((*parser).tag_directives) {
let tag_directive = POP!((*parser).tag_directives);
yaml_free(tag_directive.handle as *mut libc::c_void);
yaml_free(tag_directive.prefix as *mut libc::c_void);
}
STACK_DEL!((*parser).tag_directives);
let _ = memset(
parser as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
}
libyml-0.0.5/src/document.rs 0000644 0000000 0000000 00000073415 10461020230 0014103 0 ustar 0000000 0000000 use crate::externs::{memcpy, memset, strlen};
use crate::internal::yaml_check_utf8;
use crate::internal::yaml_stack_extend;
use crate::memory::{yaml_free, yaml_malloc, yaml_strdup};
use crate::ops::ForceAdd;
use crate::success::{Success, FAIL, OK};
use crate::yaml::{size_t, yaml_char_t};
use crate::YamlEventT;
use crate::YamlEventTypeT::YamlDocumentEndEvent;
use crate::YamlEventTypeT::YamlDocumentStartEvent;
use crate::{
libc, PointerExt, YamlDocumentT, YamlMappingNode,
YamlMappingStyleT, YamlMarkT, YamlNodeItemT, YamlNodePairT,
YamlNodeT, YamlScalarNode, YamlScalarStyleT, YamlSequenceNode,
YamlSequenceStyleT, YamlTagDirectiveT, YamlVersionDirectiveT,
};
use core::mem::{size_of, MaybeUninit};
use core::ptr::{self, addr_of_mut};
/// Create a YAML document.
///
/// This function initializes a `YamlDocumentT` struct with the provided version directive,
/// tag directives, and implicit flags. It allocates memory for the document data and
/// copies the provided directives.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct that can be safely written to.
/// - `version_directive`, if not null, must point to a valid `YamlVersionDirectiveT` struct.
/// - `tag_directives_start` and `tag_directives_end` must be valid pointers to `YamlTagDirectiveT` structs, or both must be null.
/// - If `tag_directives_start` and `tag_directives_end` are not null, the range they define must contain valid `YamlTagDirectiveT` structs with non-null `handle` and `prefix` members, and the `handle` and `prefix` strings must be valid UTF-8.
/// - The `YamlDocumentT`, `YamlVersionDirectiveT`, and `YamlTagDirectiveT` structs must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing the memory allocated for the document using `yaml_document_delete`.
///
pub unsafe fn yaml_document_initialize(
document: *mut YamlDocumentT,
version_directive: *mut YamlVersionDirectiveT,
tag_directives_start: *mut YamlTagDirectiveT,
tag_directives_end: *mut YamlTagDirectiveT,
start_implicit: bool,
end_implicit: bool,
) -> Success {
let current_block: u64;
struct Nodes {
start: *mut YamlNodeT,
end: *mut YamlNodeT,
top: *mut YamlNodeT,
}
let mut nodes = Nodes {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut version_directive_copy: *mut YamlVersionDirectiveT =
ptr::null_mut::();
struct TagDirectivesCopy {
start: *mut YamlTagDirectiveT,
end: *mut YamlTagDirectiveT,
top: *mut YamlTagDirectiveT,
}
let mut tag_directives_copy = TagDirectivesCopy {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut value = YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
};
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!document.is_null());
__assert!(
!tag_directives_start.is_null()
&& !tag_directives_end.is_null()
|| tag_directives_start == tag_directives_end
);
STACK_INIT!(nodes, YamlNodeT);
if !version_directive.is_null() {
version_directive_copy =
yaml_malloc(
size_of::() as libc::c_ulong
) as *mut YamlVersionDirectiveT;
(*version_directive_copy).major = (*version_directive).major;
(*version_directive_copy).minor = (*version_directive).minor;
}
if tag_directives_start != tag_directives_end {
let mut tag_directive: *mut YamlTagDirectiveT;
STACK_INIT!(tag_directives_copy, YamlTagDirectiveT);
tag_directive = tag_directives_start;
loop {
if tag_directive == tag_directives_end {
current_block = 14818589718467733107;
break;
}
__assert!(!((*tag_directive).handle).is_null());
__assert!(!((*tag_directive).prefix).is_null());
if yaml_check_utf8(
(*tag_directive).handle,
strlen((*tag_directive).handle as *mut libc::c_char),
)
.fail
{
current_block = 8142820162064489797;
break;
}
if yaml_check_utf8(
(*tag_directive).prefix,
strlen((*tag_directive).prefix as *mut libc::c_char),
)
.fail
{
current_block = 8142820162064489797;
break;
}
value.handle = yaml_strdup((*tag_directive).handle);
value.prefix = yaml_strdup((*tag_directive).prefix);
if value.handle.is_null() || value.prefix.is_null() {
current_block = 8142820162064489797;
break;
}
PUSH!(tag_directives_copy, value);
value.handle = ptr::null_mut::();
value.prefix = ptr::null_mut::();
tag_directive = tag_directive.wrapping_offset(1);
}
} else {
current_block = 14818589718467733107;
}
if current_block != 8142820162064489797 {
let _ = memset(
document as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
let fresh176 = addr_of_mut!((*document).nodes.start);
*fresh176 = nodes.start;
let fresh177 = addr_of_mut!((*document).nodes.end);
*fresh177 = nodes.end;
let fresh178 = addr_of_mut!((*document).nodes.top);
*fresh178 = nodes.start;
let fresh179 = addr_of_mut!((*document).version_directive);
*fresh179 = version_directive_copy;
let fresh180 = addr_of_mut!((*document).tag_directives.start);
*fresh180 = tag_directives_copy.start;
let fresh181 = addr_of_mut!((*document).tag_directives.end);
*fresh181 = tag_directives_copy.top;
(*document).start_implicit = start_implicit;
(*document).end_implicit = end_implicit;
(*document).start_mark = mark;
(*document).end_mark = mark;
return OK;
}
STACK_DEL!(nodes);
yaml_free(version_directive_copy as *mut libc::c_void);
while !STACK_EMPTY!(tag_directives_copy) {
let value = POP!(tag_directives_copy);
yaml_free(value.handle as *mut libc::c_void);
yaml_free(value.prefix as *mut libc::c_void);
}
STACK_DEL!(tag_directives_copy);
yaml_free(value.handle as *mut libc::c_void);
yaml_free(value.prefix as *mut libc::c_void);
FAIL
}
/// Delete a YAML document and all its nodes.
///
/// This function frees the memory allocated for a `YamlDocumentT` struct and all its associated
/// nodes, including scalar values, sequences, and mappings.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - The `YamlDocumentT` struct and its associated nodes must have been properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_document_delete(document: *mut YamlDocumentT) {
// Check if the document pointer is null
if document.is_null() {
return; // If the pointer is null, return early to avoid any dereferencing
}
let mut tag_directive: *mut YamlTagDirectiveT;
// Proceed with deletion only if the document pointer is valid (non-null)
while !STACK_EMPTY!((*document).nodes) {
let mut node = POP!((*document).nodes);
yaml_free(node.tag as *mut libc::c_void);
match node.type_ {
YamlScalarNode => {
yaml_free(node.data.scalar.value as *mut libc::c_void);
}
YamlSequenceNode => {
STACK_DEL!(node.data.sequence.items);
}
YamlMappingNode => {
STACK_DEL!(node.data.mapping.pairs);
}
_ => {
__assert!(false);
}
}
}
STACK_DEL!((*document).nodes);
yaml_free((*document).version_directive as *mut libc::c_void);
// Handle tag directives
tag_directive = (*document).tag_directives.start;
while tag_directive != (*document).tag_directives.end {
yaml_free((*tag_directive).handle as *mut libc::c_void);
yaml_free((*tag_directive).prefix as *mut libc::c_void);
tag_directive = tag_directive.wrapping_offset(1);
}
yaml_free((*document).tag_directives.start as *mut libc::c_void);
// Clear the memory of the document structure itself
let _ = memset(
document as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
}
/// Get a node of a YAML document.
///
/// This function returns a pointer to the node at the specified `index` in the document's node
/// stack. The pointer returned by this function is valid until any of the functions modifying the
/// document are called.
///
/// Returns the node object or NULL if `index` is out of range.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `index` must be a valid index within the range of nodes in the `YamlDocumentT` struct.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
/// - The caller must not modify or free the returned pointer, as it is owned by the `YamlDocumentT` struct.
///
pub unsafe fn yaml_document_get_node(
document: *mut YamlDocumentT,
index: libc::c_int,
) -> *mut YamlNodeT {
__assert!(!document.is_null());
if index > 0
&& (*document).nodes.start.wrapping_offset(index as isize)
<= (*document).nodes.top
{
return (*document)
.nodes
.start
.wrapping_offset(index as isize)
.wrapping_offset(-1_isize);
}
ptr::null_mut::()
}
/// Get the root of a YAML document node.
///
/// This function returns a pointer to the root node of the YAML document. The root object is the
/// first object added to the document.
///
/// The pointer returned by this function is valid until any of the functions modifying the
/// document are called.
///
/// An empty document produced by the parser signifies the end of a YAML stream.
///
/// Returns the node object or NULL if the document is empty.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
/// - The caller must not modify or free the returned pointer, as it is owned by the `YamlDocumentT` struct.
///
pub unsafe fn yaml_document_get_root_node(
document: *mut YamlDocumentT,
) -> *mut YamlNodeT {
__assert!(!document.is_null());
if (*document).nodes.top != (*document).nodes.start {
return (*document).nodes.start;
}
ptr::null_mut::()
}
/// Create a SCALAR node and attach it to the document.
///
/// This function creates a new SCALAR node with the provided `tag`, `value`, and `style`, and
/// adds it to the document's node stack.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id or 0 on error.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `value` must be a valid, non-null pointer to a null-terminated UTF-8 string.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing the memory allocated for the document using `yaml_document_delete`.
///
#[must_use]
pub unsafe fn yaml_document_add_scalar(
document: *mut YamlDocumentT,
mut tag: *const yaml_char_t,
value: *const yaml_char_t,
mut length: libc::c_int,
style: YamlScalarStyleT,
) -> libc::c_int {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
let mut value_copy: *mut yaml_char_t =
ptr::null_mut::();
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
__assert!(!document.is_null());
__assert!(!value.is_null());
if tag.is_null() {
tag = b"tag:yaml.org,2002:str\0" as *const u8
as *const libc::c_char as *mut yaml_char_t;
}
if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
tag_copy = yaml_strdup(tag);
if !tag_copy.is_null() {
if length < 0 {
length =
strlen(value as *mut libc::c_char) as libc::c_int;
}
if yaml_check_utf8(value, length as size_t).ok {
value_copy = yaml_malloc(length.force_add(1) as size_t)
as *mut yaml_char_t;
let _ = memcpy(
value_copy as *mut libc::c_void,
value as *const libc::c_void,
length as libc::c_ulong,
);
*value_copy.wrapping_offset(length as isize) = b'\0';
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlScalarNode;
(*node).tag = tag_copy;
(*node).start_mark = mark;
(*node).end_mark = mark;
(*node).data.scalar.value = value_copy;
(*node).data.scalar.length = length as size_t;
(*node).data.scalar.style = style;
PUSH!((*document).nodes, *node);
return (*document)
.nodes
.top
.c_offset_from((*document).nodes.start)
as libc::c_int;
}
}
}
yaml_free(tag_copy as *mut libc::c_void);
yaml_free(value_copy as *mut libc::c_void);
0
}
/// Create a SEQUENCE node and attach it to the document.
///
/// This function creates a new SEQUENCE node with the provided `tag` and `style`, and adds it to
/// the document's node stack.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id or 0 on error.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing the memory allocated for the document using `yaml_document_delete`.
///
#[must_use]
pub unsafe fn yaml_document_add_sequence(
document: *mut YamlDocumentT,
mut tag: *const yaml_char_t,
style: YamlSequenceStyleT,
) -> libc::c_int {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
struct Items {
start: *mut YamlNodeItemT,
end: *mut YamlNodeItemT,
top: *mut YamlNodeItemT,
}
let mut items = Items {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
__assert!(!document.is_null());
if tag.is_null() {
tag = b"tag:yaml.org,2002:seq\0" as *const u8
as *const libc::c_char as *mut yaml_char_t;
}
if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
tag_copy = yaml_strdup(tag);
if !tag_copy.is_null() {
STACK_INIT!(items, YamlNodeItemT);
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlSequenceNode;
(*node).tag = tag_copy;
(*node).start_mark = mark;
(*node).end_mark = mark;
(*node).data.sequence.items.start = items.start;
(*node).data.sequence.items.end = items.end;
(*node).data.sequence.items.top = items.start;
(*node).data.sequence.style = style;
PUSH!((*document).nodes, *node);
return (*document)
.nodes
.top
.c_offset_from((*document).nodes.start)
as libc::c_int;
}
}
STACK_DEL!(items);
yaml_free(tag_copy as *mut libc::c_void);
0
}
/// Create a MAPPING node and attach it to the document.
///
/// This function creates a new MAPPING node with the provided `tag` and `style`, and adds it to
/// the document's node stack.
///
/// The `style` argument may be ignored by the emitter.
///
/// Returns the node id or 0 on error.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `tag`, if not null, must be a valid pointer to a null-terminated UTF-8 string.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing the memory allocated for the document using `yaml_document_delete`.
///
#[must_use]
pub unsafe fn yaml_document_add_mapping(
document: *mut YamlDocumentT,
mut tag: *const yaml_char_t,
style: YamlMappingStyleT,
) -> libc::c_int {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut tag_copy: *mut yaml_char_t = ptr::null_mut::();
struct Pairs {
start: *mut YamlNodePairT,
end: *mut YamlNodePairT,
top: *mut YamlNodePairT,
}
let mut pairs = Pairs {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
__assert!(!document.is_null());
if tag.is_null() {
tag = b"tag:yaml.org,2002:map\0" as *const u8
as *const libc::c_char as *mut yaml_char_t;
}
if yaml_check_utf8(tag, strlen(tag as *mut libc::c_char)).ok {
tag_copy = yaml_strdup(tag);
if !tag_copy.is_null() {
STACK_INIT!(pairs, YamlNodePairT);
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlMappingNode;
(*node).tag = tag_copy;
(*node).start_mark = mark;
(*node).end_mark = mark;
(*node).data.mapping.pairs.start = pairs.start;
(*node).data.mapping.pairs.end = pairs.end;
(*node).data.mapping.pairs.top = pairs.start;
(*node).data.mapping.style = style;
PUSH!((*document).nodes, *node);
return (*document)
.nodes
.top
.c_offset_from((*document).nodes.start)
as libc::c_int;
}
}
STACK_DEL!(pairs);
yaml_free(tag_copy as *mut libc::c_void);
0
}
/// Add an item to a SEQUENCE node.
///
/// This function adds a node with the given `item` id to the sequence node with the given
/// `sequence` id in the document.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `sequence` must be a valid index within the range of nodes in the `YamlDocumentT` struct, and the node at that index must be a `YamlSequenceNode`.
/// - `item` must be a valid index within the range of nodes in the `YamlDocumentT` struct.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_document_append_sequence_item(
document: *mut YamlDocumentT,
sequence: libc::c_int,
item: libc::c_int,
) -> Success {
__assert!(!document.is_null());
__assert!(
sequence > 0
&& ((*document).nodes.start)
.wrapping_offset(sequence as isize)
<= (*document).nodes.top
);
__assert!(
(*((*document).nodes.start)
.wrapping_offset((sequence - 1) as isize))
.type_
== YamlSequenceNode
);
__assert!(
item > 0
&& ((*document).nodes.start).wrapping_offset(item as isize)
<= (*document).nodes.top
);
PUSH!(
(*((*document).nodes.start)
.wrapping_offset((sequence - 1) as isize))
.data
.sequence
.items,
item
);
OK
}
/// Add a pair of a key and a value to a MAPPING node.
///
/// This function adds a key-value pair to the mapping node with the given `mapping` id in the
/// document. The `key` and `value` arguments are the ids of the nodes to be used as the key and
/// value, respectively.
///
/// # Safety
///
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct.
/// - `mapping` must be a valid index within the range of nodes in the `YamlDocumentT` struct, and the node at that index must be a `YamlMappingNode`.
/// - `key` and `value` must be valid indices within the range of nodes in the `YamlDocumentT` struct.
/// - The `YamlDocumentT` struct and its associated nodes must be properly initialized and their memory allocated correctly.
/// - The `YamlDocumentT` struct and its associated nodes must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_document_append_mapping_pair(
document: *mut YamlDocumentT,
mapping: libc::c_int,
key: libc::c_int,
value: libc::c_int,
) -> Success {
__assert!(!document.is_null());
__assert!(
mapping > 0
&& ((*document).nodes.start)
.wrapping_offset(mapping as isize)
<= (*document).nodes.top
);
__assert!(
(*((*document).nodes.start)
.wrapping_offset((mapping - 1) as isize))
.type_
== YamlMappingNode
);
__assert!(
key > 0
&& ((*document).nodes.start).wrapping_offset(key as isize)
<= (*document).nodes.top
);
__assert!(
value > 0
&& ((*document).nodes.start)
.wrapping_offset(value as isize)
<= (*document).nodes.top
);
let pair = YamlNodePairT { key, value };
PUSH!(
(*((*document).nodes.start)
.wrapping_offset((mapping - 1) as isize))
.data
.mapping
.pairs,
pair
);
OK
}
/// Create the DOCUMENT-END event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - The `YamlEventT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_document_end_event_initialize(
event: *mut YamlEventT,
implicit: bool,
) -> Success {
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
(*event).data.document_end.implicit = implicit;
OK
}
/// Create the DOCUMENT-START event.
///
/// The `implicit` argument is considered as a stylistic parameter and may be
/// ignored by the emitter.
///
/// # Safety
///
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely written to.
/// - `version_directive`, if not null, must point to a valid `YamlVersionDirectiveT` struct.
/// - `tag_directives_start` and `tag_directives_end` must be valid pointers to `YamlTagDirectiveT` structs, or both must be null.
/// - If `tag_directives_start` and `tag_directives_end` are not null, the range they define must contain valid `YamlTagDirectiveT` structs with non-null `handle` and `prefix` members, and the `handle` and `prefix` strings must be valid UTF-8.
/// - The `YamlEventT`, `YamlVersionDirectiveT`, and `YamlTagDirectiveT` structs must be properly aligned and have the expected memory layout.
/// - The caller is responsible for freeing any dynamically allocated memory associated with the event using `yaml_event_delete`.
///
pub unsafe fn yaml_document_start_event_initialize(
event: *mut YamlEventT,
version_directive: *mut YamlVersionDirectiveT,
tag_directives_start: *mut YamlTagDirectiveT,
tag_directives_end: *mut YamlTagDirectiveT,
implicit: bool,
) -> Success {
let current_block: u64;
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let mut version_directive_copy: *mut YamlVersionDirectiveT =
ptr::null_mut::();
struct TagDirectivesCopy {
start: *mut YamlTagDirectiveT,
end: *mut YamlTagDirectiveT,
top: *mut YamlTagDirectiveT,
}
let mut tag_directives_copy = TagDirectivesCopy {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut value = YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
};
__assert!(!event.is_null());
__assert!(
!tag_directives_start.is_null()
&& !tag_directives_end.is_null()
|| tag_directives_start == tag_directives_end
);
if !version_directive.is_null() {
version_directive_copy =
yaml_malloc(
size_of::() as libc::c_ulong
) as *mut YamlVersionDirectiveT;
(*version_directive_copy).major = (*version_directive).major;
(*version_directive_copy).minor = (*version_directive).minor;
}
if tag_directives_start != tag_directives_end {
let mut tag_directive: *mut YamlTagDirectiveT;
STACK_INIT!(tag_directives_copy, YamlTagDirectiveT);
tag_directive = tag_directives_start;
loop {
if tag_directive == tag_directives_end {
current_block = 16203760046146113240;
break;
}
__assert!(!((*tag_directive).handle).is_null());
__assert!(!((*tag_directive).prefix).is_null());
if yaml_check_utf8(
(*tag_directive).handle,
strlen((*tag_directive).handle as *mut libc::c_char),
)
.fail
{
current_block = 14964981520188694172;
break;
}
if yaml_check_utf8(
(*tag_directive).prefix,
strlen((*tag_directive).prefix as *mut libc::c_char),
)
.fail
{
current_block = 14964981520188694172;
break;
}
value.handle = yaml_strdup((*tag_directive).handle);
value.prefix = yaml_strdup((*tag_directive).prefix);
if value.handle.is_null() || value.prefix.is_null() {
current_block = 14964981520188694172;
break;
}
PUSH!(tag_directives_copy, value);
value.handle = ptr::null_mut::();
value.prefix = ptr::null_mut::();
tag_directive = tag_directive.wrapping_offset(1);
}
} else {
current_block = 16203760046146113240;
}
if current_block != 14964981520188694172 {
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentStartEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh164 = addr_of_mut!(
(*event).data.document_start.version_directive
);
*fresh164 = version_directive_copy;
let fresh165 = addr_of_mut!(
(*event).data.document_start.tag_directives.start
);
*fresh165 = tag_directives_copy.start;
let fresh166 = addr_of_mut!(
(*event).data.document_start.tag_directives.end
);
*fresh166 = tag_directives_copy.top;
(*event).data.document_start.implicit = implicit;
return OK;
}
yaml_free(version_directive_copy as *mut libc::c_void);
while !STACK_EMPTY!(tag_directives_copy) {
let value = POP!(tag_directives_copy);
yaml_free(value.handle as *mut libc::c_void);
yaml_free(value.prefix as *mut libc::c_void);
}
STACK_DEL!(tag_directives_copy);
yaml_free(value.handle as *mut libc::c_void);
yaml_free(value.prefix as *mut libc::c_void);
FAIL
}
libyml-0.0.5/src/dumper.rs 0000644 0000000 0000000 00000047004 10461020230 0013554 0 ustar 0000000 0000000 use crate::externs::{memset, strcmp};
use crate::fmt::WriteToPtr;
use crate::memory::yaml_free;
use crate::memory::yaml_malloc;
use crate::ops::ForceMul as _;
use crate::success::{Success, FAIL, OK};
use crate::yaml::{
yaml_char_t, YamlAliasEvent, YamlAnchorsT, YamlAnyEncoding,
YamlDocumentEndEvent, YamlDocumentStartEvent, YamlDocumentT,
YamlEmitterT, YamlEventT, YamlMappingEndEvent, YamlMappingNode,
YamlMappingStartEvent, YamlMarkT, YamlNodeItemT, YamlNodePairT,
YamlNodeT, YamlScalarEvent, YamlScalarNode, YamlSequenceEndEvent,
YamlSequenceNode, YamlSequenceStartEvent, YamlStreamEndEvent,
YamlStreamStartEvent,
};
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.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must not be in an opened state.
/// - The `YamlEmitterT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_open(emitter: *mut YamlEmitterT) -> Success {
if emitter.is_null() {
return FAIL;
}
// If the emitter is already opened, return FAIL
if (*emitter).opened {
return FAIL;
}
// If the emitter was previously closed, reset its state
if (*emitter).closed {
(*emitter).closed = false;
}
let mut event = MaybeUninit::::uninit();
let event_ptr = event.as_mut_ptr();
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let _ = memset(
event_ptr as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event_ptr).type_ = YamlStreamStartEvent;
(*event_ptr).start_mark = mark;
(*event_ptr).end_mark = mark;
(*event_ptr).data.stream_start.encoding = YamlAnyEncoding;
if yaml_emitter_emit(emitter, event_ptr).fail {
return FAIL;
}
(*emitter).opened = true;
(*emitter).closed = false;
OK
}
/// Finish a YAML stream.
///
/// This function should be used after yaml_emitter_dump() is called.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - The `YamlEmitterT` struct must be in an opened state and not already closed.
/// - The `YamlEmitterT` struct must be properly aligned and have the expected memory layout.
///
pub unsafe fn yaml_emitter_close(
emitter: *mut YamlEmitterT,
) -> Success {
if emitter.is_null() {
return FAIL;
}
// If the emitter is not opened, we don't need to close it
if !(*emitter).opened {
return OK;
}
// If the emitter is already closed, we don't need to close it again
if (*emitter).closed {
return OK;
}
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlStreamEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
if yaml_emitter_emit(emitter, event).fail {
return FAIL;
}
(*emitter).closed = true;
(*emitter).opened = false;
OK
}
/// Emit a YAML document.
///
/// The document 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.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct that can be safely read from and will be destroyed by the function.
/// - The `YamlEmitterT` and `YamlDocumentT` structs must be properly aligned and have the expected memory layout.
/// - The `YamlEmitterT` struct must be in a valid state to emit the provided document.
///
pub unsafe fn yaml_emitter_dump(
emitter: *mut YamlEmitterT,
document: *mut YamlDocumentT,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
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 && yaml_emitter_open(emitter).fail {
return FAIL;
}
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 YamlAnchorsT;
let _ = 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,
),
);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentStartEvent;
(*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 {
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentEndEvent;
(*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 YamlEmitterT,
) {
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: YamlNodeT = *(*(*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_ == YamlScalarNode {
yaml_free(node.data.scalar.value as *mut libc::c_void);
}
}
if node.type_ == YamlSequenceNode {
STACK_DEL!(node.data.sequence.items);
}
if node.type_ == YamlMappingNode {
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 YamlEmitterT,
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 YamlEmitterT,
index: libc::c_int,
) {
let node: *mut YamlNodeT = (*(*emitter).document)
.nodes
.start
.wrapping_offset(index as isize)
.wrapping_offset(-1_isize);
let mut item: *mut YamlNodeItemT;
let mut pair: *mut YamlNodePairT;
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_ {
YamlSequenceNode => {
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);
}
}
YamlMappingNode => {
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 YamlEmitterT,
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
}
/// Dumps a YAML node to the emitter.
///
/// This function is responsible for emitting a single YAML node from a document.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to an initialized `YamlEmitterT` struct.
/// - `index` must be a valid index within the YAML document associated with the emitter.
/// - The caller must ensure that the node at `index` can be safely emitted without causing memory issues.
pub unsafe fn yaml_emitter_dump_node(
emitter: *mut YamlEmitterT,
index: libc::c_int,
) -> Success {
let node: *mut YamlNodeT = (*(*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_ {
YamlScalarNode => {
yaml_emitter_dump_scalar(emitter, node, anchor)
}
YamlSequenceNode => {
yaml_emitter_dump_sequence(emitter, node, anchor)
}
YamlMappingNode => {
yaml_emitter_dump_mapping(emitter, node, anchor)
}
_ => __assert!(false),
}
}
unsafe fn yaml_emitter_dump_alias(
emitter: *mut YamlEmitterT,
anchor: *mut yaml_char_t,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
};
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlAliasEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
(*event).data.alias.anchor = anchor;
yaml_emitter_emit(emitter, event)
}
/// Dumps a YAML scalar node to the emitter.
///
/// This function handles emitting a scalar node, which is a single key-value pair.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to an initialized `YamlEmitterT` struct.
/// - `node` must be a valid, non-null pointer to a `YamlNodeT` struct representing the scalar node.
/// - `anchor` must be a valid, non-null pointer to a `yaml_char_t` if provided, or null if no anchor is used.
/// - The caller must ensure that the node and anchor pointers are valid and properly aligned.
pub unsafe fn yaml_emitter_dump_scalar(
emitter: *mut YamlEmitterT,
node: *mut YamlNodeT,
anchor: *mut yaml_char_t,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
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;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlScalarEvent;
(*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)
}
/// Dumps a YAML sequence node to the emitter.
///
/// This function handles emitting a sequence node, which is a list of items.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to an initialized `YamlEmitterT` struct.
/// - `node` must be a valid, non-null pointer to a `YamlNodeT` struct representing the sequence node.
/// - `anchor` must be a valid, non-null pointer to a `yaml_char_t` if provided, or null if no anchor is used.
/// - The caller must ensure that the node and anchor pointers are valid and properly aligned.
/// - The sequence node must contain a valid list of items that can be safely iterated and emitted.
pub unsafe fn yaml_emitter_dump_sequence(
emitter: *mut YamlEmitterT,
node: *mut YamlNodeT,
anchor: *mut yaml_char_t,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
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 YamlNodeItemT;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceStartEvent;
(*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);
}
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
yaml_emitter_emit(emitter, event)
}
/// Dumps a YAML mapping node to the emitter.
///
/// This function handles emitting a mapping node, which is a set of key-value pairs.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to an initialized `YamlEmitterT` struct.
/// - `node` must be a valid, non-null pointer to a `YamlNodeT` struct representing the mapping node.
/// - `anchor` must be a valid, non-null pointer to a `yaml_char_t` if provided, or null if no anchor is used.
/// - The caller must ensure that the node and anchor pointers are valid and properly aligned.
/// - The mapping node must contain a valid set of key-value pairs that can be safely iterated and emitted.
pub unsafe fn yaml_emitter_dump_mapping(
emitter: *mut YamlEmitterT,
node: *mut YamlNodeT,
anchor: *mut yaml_char_t,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
let mark = YamlMarkT {
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 YamlNodePairT;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingStartEvent;
(*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);
}
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingEndEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
yaml_emitter_emit(emitter, event)
}
libyml-0.0.5/src/emitter.rs 0000644 0000000 0000000 00000232015 10461020230 0013727 0 ustar 0000000 0000000 use crate::externs::{strcmp, strlen, strncmp};
use crate::internal::{yaml_queue_extend, yaml_stack_extend};
use crate::memory::{yaml_free, yaml_strdup};
use crate::ops::{ForceAdd as _, ForceMul as _};
use crate::success::{Success, FAIL, OK};
use crate::yaml::{size_t, yaml_char_t, YamlStringT};
use crate::{
libc, yaml_emitter_flush, yaml_event_delete, PointerExt,
YamlAliasEvent, YamlAnyBreak, YamlAnyEncoding, YamlAnyScalarStyle,
YamlCrBreak, YamlCrlnBreak, YamlDocumentEndEvent,
YamlDocumentStartEvent, YamlDoubleQuotedScalarStyle,
YamlEmitBlockMappingFirstKeyState, YamlEmitBlockMappingKeyState,
YamlEmitBlockMappingSimpleValueState,
YamlEmitBlockMappingValueState,
YamlEmitBlockSequenceFirstItemState,
YamlEmitBlockSequenceItemState, YamlEmitDocumentContentState,
YamlEmitDocumentEndState, YamlEmitDocumentStartState,
YamlEmitEndState, YamlEmitFirstDocumentStartState,
YamlEmitFlowMappingFirstKeyState, YamlEmitFlowMappingKeyState,
YamlEmitFlowMappingSimpleValueState, YamlEmitFlowMappingValueState,
YamlEmitFlowSequenceFirstItemState, YamlEmitFlowSequenceItemState,
YamlEmitStreamStartState, YamlEmitterError, YamlEmitterT,
YamlEventT, YamlFlowMappingStyle, YamlFlowSequenceStyle,
YamlFoldedScalarStyle, YamlLiteralScalarStyle, YamlLnBreak,
YamlMappingEndEvent, YamlMappingStartEvent, YamlPlainScalarStyle,
YamlScalarEvent, YamlScalarStyleT, YamlSequenceEndEvent,
YamlSequenceStartEvent, YamlSingleQuotedScalarStyle,
YamlStreamEndEvent, YamlStreamStartEvent, YamlTagDirectiveT,
YamlUtf8Encoding, YamlVersionDirectiveT,
};
use core::ptr::{self, addr_of_mut};
unsafe fn flush(emitter: *mut YamlEmitterT) -> Success {
if (*emitter).buffer.pointer.wrapping_offset(5_isize)
< (*emitter).buffer.end
{
OK
} else {
yaml_emitter_flush(emitter)
}
}
unsafe fn put(emitter: *mut YamlEmitterT, value: u8) -> Success {
if flush(emitter).fail {
return FAIL;
}
let fresh40 = addr_of_mut!((*emitter).buffer.pointer);
let fresh41 = *fresh40;
*fresh40 = (*fresh40).wrapping_offset(1);
*fresh41 = value;
let fresh42 = addr_of_mut!((*emitter).column);
*fresh42 += 1;
OK
}
unsafe fn put_break(emitter: *mut YamlEmitterT) -> Success {
if flush(emitter).fail {
return FAIL;
}
if (*emitter).line_break == YamlCrBreak {
let fresh62 = addr_of_mut!((*emitter).buffer.pointer);
let fresh63 = *fresh62;
*fresh62 = (*fresh62).wrapping_offset(1);
*fresh63 = b'\r';
} else if (*emitter).line_break == YamlLnBreak {
let fresh64 = addr_of_mut!((*emitter).buffer.pointer);
let fresh65 = *fresh64;
*fresh64 = (*fresh64).wrapping_offset(1);
*fresh65 = b'\n';
} else if (*emitter).line_break == YamlCrlnBreak {
let fresh66 = addr_of_mut!((*emitter).buffer.pointer);
let fresh67 = *fresh66;
*fresh66 = (*fresh66).wrapping_offset(1);
*fresh67 = b'\r';
let fresh68 = addr_of_mut!((*emitter).buffer.pointer);
let fresh69 = *fresh68;
*fresh68 = (*fresh68).wrapping_offset(1);
*fresh69 = b'\n';
};
(*emitter).column = 0;
let fresh70 = addr_of_mut!((*emitter).line);
*fresh70 += 1;
OK
}
unsafe fn write(
emitter: *mut YamlEmitterT,
string: *mut YamlStringT,
) -> Success {
if flush(emitter).fail {
return FAIL;
}
copy!((*emitter).buffer, *string);
let fresh107 = addr_of_mut!((*emitter).column);
*fresh107 += 1;
OK
}
unsafe fn write_break(
emitter: *mut YamlEmitterT,
string: *mut YamlStringT,
) -> Success {
if flush(emitter).fail {
return FAIL;
}
if CHECK!(*string, b'\n') {
let _ = put_break(emitter);
(*string).pointer = (*string).pointer.wrapping_offset(1);
} else {
copy!((*emitter).buffer, *string);
(*emitter).column = 0;
let fresh300 = addr_of_mut!((*emitter).line);
*fresh300 += 1;
}
OK
}
macro_rules! write {
($emitter:expr, $string:expr) => {
write($emitter, addr_of_mut!($string))
};
}
macro_rules! write_break {
($emitter:expr, $string:expr) => {
write_break($emitter, addr_of_mut!($string))
};
}
unsafe fn yaml_emitter_set_emitter_error(
emitter: *mut YamlEmitterT,
problem: *const libc::c_char,
) -> Success {
(*emitter).error = YamlEmitterError;
let fresh0 = addr_of_mut!((*emitter).problem);
*fresh0 = problem;
FAIL
}
/// Emit an event.
///
/// The event object may be generated using the yaml_parser_parse() function.
/// The emitter takes the responsibility for the event object and destroys its
/// content after it is emitted. The event object is destroyed even if the
/// function fails.
///
/// # Safety
///
/// - `emitter` must be a valid, non-null pointer to a properly initialized `YamlEmitterT` struct.
/// - `event` must be a valid, non-null pointer to a `YamlEventT` struct that can be safely read from and will be destroyed by the function.
/// - The `YamlEmitterT` and `YamlEventT` structs must be properly aligned and have the expected memory layout.
/// - The `YamlEmitterT` struct must be in a valid state to emit the provided event.
pub unsafe fn yaml_emitter_emit(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
ENQUEUE!((*emitter).events, *event);
while yaml_emitter_need_more_events(emitter).fail {
if yaml_emitter_analyze_event(emitter, (*emitter).events.head)
.fail
{
return FAIL;
}
if yaml_emitter_state_machine(emitter, (*emitter).events.head)
.fail
{
return FAIL;
}
yaml_event_delete(addr_of_mut!(DEQUEUE!((*emitter).events)));
}
OK
}
unsafe fn yaml_emitter_need_more_events(
emitter: *mut YamlEmitterT,
) -> Success {
let mut level: libc::c_int = 0;
let mut event: *mut YamlEventT;
if QUEUE_EMPTY!((*emitter).events) {
return OK;
}
let accumulate = match (*(*emitter).events.head).type_ {
YamlDocumentStartEvent => 1,
YamlSequenceStartEvent => 2,
YamlMappingStartEvent => 3,
_ => return FAIL,
};
if (*emitter).events.tail.c_offset_from((*emitter).events.head)
as libc::c_long
> accumulate as libc::c_long
{
return FAIL;
}
event = (*emitter).events.head;
while event != (*emitter).events.tail {
match (*event).type_ {
YamlStreamStartEvent
| YamlDocumentStartEvent
| YamlSequenceStartEvent
| YamlMappingStartEvent => {
level += 1;
}
YamlStreamEndEvent | YamlDocumentEndEvent
| YamlSequenceEndEvent | YamlMappingEndEvent => {
level -= 1;
}
_ => {}
}
if level == 0 {
return FAIL;
}
event = event.wrapping_offset(1);
}
OK
}
unsafe fn yaml_emitter_append_tag_directive(
emitter: *mut YamlEmitterT,
value: YamlTagDirectiveT,
allow_duplicates: bool,
) -> Success {
let mut tag_directive: *mut YamlTagDirectiveT;
let mut copy = YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
};
tag_directive = (*emitter).tag_directives.start;
while tag_directive != (*emitter).tag_directives.top {
if strcmp(
value.handle as *mut libc::c_char,
(*tag_directive).handle as *mut libc::c_char,
) == 0
{
if allow_duplicates {
return OK;
}
return yaml_emitter_set_emitter_error(
emitter,
b"duplicate %TAG directive\0" as *const u8
as *const libc::c_char,
);
}
tag_directive = tag_directive.wrapping_offset(1);
}
copy.handle = yaml_strdup(value.handle);
copy.prefix = yaml_strdup(value.prefix);
PUSH!((*emitter).tag_directives, copy);
OK
}
unsafe fn yaml_emitter_increase_indent(
emitter: *mut YamlEmitterT,
flow: bool,
indentless: bool,
) {
PUSH!((*emitter).indents, (*emitter).indent);
if (*emitter).indent < 0 {
(*emitter).indent =
if flow { (*emitter).best_indent } else { 0 };
} else if !indentless {
(*emitter).indent += (*emitter).best_indent;
}
}
unsafe fn yaml_emitter_state_machine(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
match (*emitter).state {
YamlEmitStreamStartState => {
yaml_emitter_emit_stream_start(emitter, event)
}
YamlEmitFirstDocumentStartState => {
yaml_emitter_emit_document_start(emitter, event, true)
}
YamlEmitDocumentStartState => {
yaml_emitter_emit_document_start(emitter, event, false)
}
YamlEmitDocumentContentState => {
yaml_emitter_emit_document_content(emitter, event)
}
YamlEmitDocumentEndState => {
yaml_emitter_emit_document_end(emitter, event)
}
YamlEmitFlowSequenceFirstItemState => {
yaml_emitter_emit_flow_sequence_item(emitter, event, true)
}
YamlEmitFlowSequenceItemState => {
yaml_emitter_emit_flow_sequence_item(emitter, event, false)
}
YamlEmitFlowMappingFirstKeyState => {
yaml_emitter_emit_flow_mapping_key(emitter, event, true)
}
YamlEmitFlowMappingKeyState => {
yaml_emitter_emit_flow_mapping_key(emitter, event, false)
}
YamlEmitFlowMappingSimpleValueState => {
yaml_emitter_emit_flow_mapping_value(emitter, event, true)
}
YamlEmitFlowMappingValueState => {
yaml_emitter_emit_flow_mapping_value(emitter, event, false)
}
YamlEmitBlockSequenceFirstItemState => {
yaml_emitter_emit_block_sequence_item(emitter, event, true)
}
YamlEmitBlockSequenceItemState => {
yaml_emitter_emit_block_sequence_item(emitter, event, false)
}
YamlEmitBlockMappingFirstKeyState => {
yaml_emitter_emit_block_mapping_key(emitter, event, true)
}
YamlEmitBlockMappingKeyState => {
yaml_emitter_emit_block_mapping_key(emitter, event, false)
}
YamlEmitBlockMappingSimpleValueState => {
yaml_emitter_emit_block_mapping_value(emitter, event, true)
}
YamlEmitBlockMappingValueState => {
yaml_emitter_emit_block_mapping_value(emitter, event, false)
}
YamlEmitEndState => yaml_emitter_set_emitter_error(
emitter,
b"expected nothing after STREAM-END\0" as *const u8
as *const libc::c_char,
),
}
}
unsafe fn yaml_emitter_emit_stream_start(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
(*emitter).open_ended = 0;
if (*event).type_ == YamlStreamStartEvent {
if (*emitter).encoding == YamlAnyEncoding {
(*emitter).encoding = (*event).data.stream_start.encoding;
}
if (*emitter).encoding == YamlAnyEncoding {
(*emitter).encoding = YamlUtf8Encoding;
}
if (*emitter).best_indent < 2 || (*emitter).best_indent > 9 {
(*emitter).best_indent = 2;
}
if (*emitter).best_width >= 0
&& (*emitter).best_width
<= (*emitter).best_indent.force_mul(2)
{
(*emitter).best_width = 80;
}
if (*emitter).best_width < 0 {
(*emitter).best_width = libc::c_int::MAX;
}
if (*emitter).line_break == YamlAnyBreak {
(*emitter).line_break = YamlLnBreak;
}
(*emitter).indent = -1;
(*emitter).line = 0;
(*emitter).column = 0;
(*emitter).whitespace = true;
(*emitter).indention = true;
if (*emitter).encoding != YamlUtf8Encoding
&& yaml_emitter_write_bom(emitter).fail
{
return FAIL;
}
(*emitter).state = YamlEmitFirstDocumentStartState;
return OK;
}
yaml_emitter_set_emitter_error(
emitter,
b"expected STREAM-START\0" as *const u8 as *const libc::c_char,
)
}
unsafe fn yaml_emitter_emit_document_start(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
first: bool,
) -> Success {
if (*event).type_ == YamlDocumentStartEvent {
let mut default_tag_directives: [YamlTagDirectiveT; 3] = [
YamlTagDirectiveT {
handle: b"!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
prefix: b"!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
},
YamlTagDirectiveT {
handle: b"!!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
prefix: b"tag:yaml.org,2002:\0" as *const u8
as *const libc::c_char
as *mut yaml_char_t,
},
YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
},
];
let mut tag_directive: *mut YamlTagDirectiveT;
let mut implicit;
if !(*event).data.document_start.version_directive.is_null()
&& yaml_emitter_analyze_version_directive(
emitter,
*(*event).data.document_start.version_directive,
)
.fail
{
return FAIL;
}
tag_directive =
(*event).data.document_start.tag_directives.start;
while tag_directive
!= (*event).data.document_start.tag_directives.end
{
if yaml_emitter_analyze_tag_directive(
emitter,
*tag_directive,
)
.fail
{
return FAIL;
}
if yaml_emitter_append_tag_directive(
emitter,
*tag_directive,
false,
)
.fail
{
return FAIL;
}
tag_directive = tag_directive.wrapping_offset(1);
}
tag_directive = default_tag_directives.as_mut_ptr();
while !(*tag_directive).handle.is_null() {
if yaml_emitter_append_tag_directive(
emitter,
*tag_directive,
true,
)
.fail
{
return FAIL;
}
tag_directive = tag_directive.wrapping_offset(1);
}
implicit = (*event).data.document_start.implicit;
if !first || (*emitter).canonical {
implicit = false;
}
if (!(*event).data.document_start.version_directive.is_null()
|| (*event).data.document_start.tag_directives.start
!= (*event).data.document_start.tag_directives.end)
&& (*emitter).open_ended != 0
{
if yaml_emitter_write_indicator(
emitter,
b"...\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
}
(*emitter).open_ended = 0;
if !(*event).data.document_start.version_directive.is_null() {
implicit = false;
if yaml_emitter_write_indicator(
emitter,
b"%YAML\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if (*(*event).data.document_start.version_directive).minor
== 1
{
if yaml_emitter_write_indicator(
emitter,
b"1.1\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
} else if yaml_emitter_write_indicator(
emitter,
b"1.2\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
}
if (*event).data.document_start.tag_directives.start
!= (*event).data.document_start.tag_directives.end
{
implicit = false;
tag_directive =
(*event).data.document_start.tag_directives.start;
while tag_directive
!= (*event).data.document_start.tag_directives.end
{
if yaml_emitter_write_indicator(
emitter,
b"%TAG\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_tag_handle(
emitter,
(*tag_directive).handle,
strlen(
(*tag_directive).handle as *mut libc::c_char,
),
)
.fail
{
return FAIL;
}
if yaml_emitter_write_tag_content(
emitter,
(*tag_directive).prefix,
strlen(
(*tag_directive).prefix as *mut libc::c_char,
),
true,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
tag_directive = tag_directive.wrapping_offset(1);
}
}
if yaml_emitter_check_empty_document(emitter) {
implicit = false;
}
if !implicit {
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b"---\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if (*emitter).canonical
&& yaml_emitter_write_indent(emitter).fail
{
return FAIL;
}
}
(*emitter).state = YamlEmitDocumentContentState;
(*emitter).open_ended = 0;
return OK;
} else if (*event).type_ == YamlStreamEndEvent {
if (*emitter).open_ended == 2 {
if yaml_emitter_write_indicator(
emitter,
b"...\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).open_ended = 0;
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
}
if yaml_emitter_flush(emitter).fail {
return FAIL;
}
(*emitter).state = YamlEmitEndState;
return OK;
}
yaml_emitter_set_emitter_error(
emitter,
b"expected DOCUMENT-START or STREAM-END\0" as *const u8
as *const libc::c_char,
)
}
unsafe fn yaml_emitter_emit_document_content(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
PUSH!((*emitter).states, YamlEmitDocumentEndState);
yaml_emitter_emit_node(emitter, event, true, false, false, false)
}
unsafe fn yaml_emitter_emit_document_end(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
if (*event).type_ == YamlDocumentEndEvent {
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if !(*event).data.document_end.implicit {
if yaml_emitter_write_indicator(
emitter,
b"...\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).open_ended = 0;
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
} else if (*emitter).open_ended == 0 {
(*emitter).open_ended = 1;
}
if yaml_emitter_flush(emitter).fail {
return FAIL;
}
(*emitter).state = YamlEmitDocumentStartState;
while !STACK_EMPTY!((*emitter).tag_directives) {
let tag_directive = POP!((*emitter).tag_directives);
yaml_free(tag_directive.handle as *mut libc::c_void);
yaml_free(tag_directive.prefix as *mut libc::c_void);
}
return OK;
}
yaml_emitter_set_emitter_error(
emitter,
b"expected DOCUMENT-END\0" as *const u8 as *const libc::c_char,
)
}
unsafe fn yaml_emitter_emit_flow_sequence_item(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
first: bool,
) -> Success {
if first {
if yaml_emitter_write_indicator(
emitter,
b"[\0" as *const u8 as *const libc::c_char,
true,
true,
false,
)
.fail
{
return FAIL;
}
yaml_emitter_increase_indent(emitter, true, false);
let fresh12 = addr_of_mut!((*emitter).flow_level);
*fresh12 += 1;
}
if (*event).type_ == YamlSequenceEndEvent {
let fresh13 = addr_of_mut!((*emitter).flow_level);
*fresh13 -= 1;
(*emitter).indent = POP!((*emitter).indents);
if (*emitter).canonical && !first {
if yaml_emitter_write_indicator(
emitter,
b",\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
}
if yaml_emitter_write_indicator(
emitter,
b"]\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).state = POP!((*emitter).states);
return OK;
}
if !first
&& yaml_emitter_write_indicator(
emitter,
b",\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
if ((*emitter).canonical
|| (*emitter).column > (*emitter).best_width)
&& yaml_emitter_write_indent(emitter).fail
{
return FAIL;
}
PUSH!((*emitter).states, YamlEmitFlowSequenceItemState);
yaml_emitter_emit_node(emitter, event, false, true, false, false)
}
unsafe fn yaml_emitter_emit_flow_mapping_key(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
first: bool,
) -> Success {
if first {
if yaml_emitter_write_indicator(
emitter,
b"{\0" as *const u8 as *const libc::c_char,
true,
true,
false,
)
.fail
{
return FAIL;
}
yaml_emitter_increase_indent(emitter, true, false);
let fresh18 = addr_of_mut!((*emitter).flow_level);
*fresh18 += 1;
}
if (*event).type_ == YamlMappingEndEvent {
if STACK_EMPTY!((*emitter).indents) {
return FAIL;
}
let fresh19 = addr_of_mut!((*emitter).flow_level);
*fresh19 -= 1;
(*emitter).indent = POP!((*emitter).indents);
if (*emitter).canonical && !first {
if yaml_emitter_write_indicator(
emitter,
b",\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
}
if yaml_emitter_write_indicator(
emitter,
b"}\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).state = POP!((*emitter).states);
return OK;
}
if !first
&& yaml_emitter_write_indicator(
emitter,
b",\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
if ((*emitter).canonical
|| (*emitter).column > (*emitter).best_width)
&& yaml_emitter_write_indent(emitter).fail
{
return FAIL;
}
if !(*emitter).canonical && yaml_emitter_check_simple_key(emitter) {
PUSH!((*emitter).states, YamlEmitFlowMappingSimpleValueState);
yaml_emitter_emit_node(emitter, event, false, false, true, true)
} else {
if yaml_emitter_write_indicator(
emitter,
b"?\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
PUSH!((*emitter).states, YamlEmitFlowMappingValueState);
yaml_emitter_emit_node(
emitter, event, false, false, true, false,
)
}
}
unsafe fn yaml_emitter_emit_flow_mapping_value(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
simple: bool,
) -> Success {
if simple {
if yaml_emitter_write_indicator(
emitter,
b":\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
} else {
if ((*emitter).canonical
|| (*emitter).column > (*emitter).best_width)
&& yaml_emitter_write_indent(emitter).fail
{
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b":\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
}
PUSH!((*emitter).states, YamlEmitFlowMappingKeyState);
yaml_emitter_emit_node(emitter, event, false, false, true, false)
}
unsafe fn yaml_emitter_emit_block_sequence_item(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
first: bool,
) -> Success {
if first {
yaml_emitter_increase_indent(
emitter,
false,
(*emitter).mapping_context && !(*emitter).indention,
);
}
if (*event).type_ == YamlSequenceEndEvent {
(*emitter).indent = POP!((*emitter).indents);
(*emitter).state = POP!((*emitter).states);
return OK;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b"-\0" as *const u8 as *const libc::c_char,
true,
false,
true,
)
.fail
{
return FAIL;
}
PUSH!((*emitter).states, YamlEmitBlockSequenceItemState);
yaml_emitter_emit_node(emitter, event, false, true, false, false)
}
unsafe fn yaml_emitter_emit_block_mapping_key(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
first: bool,
) -> Success {
if first {
yaml_emitter_increase_indent(emitter, false, false);
}
if (*event).type_ == YamlMappingEndEvent {
(*emitter).indent = POP!((*emitter).indents);
(*emitter).state = POP!((*emitter).states);
return OK;
}
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if yaml_emitter_check_simple_key(emitter) {
PUSH!((*emitter).states, YamlEmitBlockMappingSimpleValueState);
yaml_emitter_emit_node(emitter, event, false, false, true, true)
} else {
if yaml_emitter_write_indicator(
emitter,
b"?\0" as *const u8 as *const libc::c_char,
true,
false,
true,
)
.fail
{
return FAIL;
}
PUSH!((*emitter).states, YamlEmitBlockMappingValueState);
yaml_emitter_emit_node(
emitter, event, false, false, true, false,
)
}
}
unsafe fn yaml_emitter_emit_block_mapping_value(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
simple: bool,
) -> Success {
if simple {
if yaml_emitter_write_indicator(
emitter,
b":\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
} else {
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b":\0" as *const u8 as *const libc::c_char,
true,
false,
true,
)
.fail
{
return FAIL;
}
}
PUSH!((*emitter).states, YamlEmitBlockMappingKeyState);
yaml_emitter_emit_node(emitter, event, false, false, true, false)
}
unsafe fn yaml_emitter_emit_node(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
root: bool,
sequence: bool,
mapping: bool,
simple_key: bool,
) -> Success {
(*emitter).root_context = root;
(*emitter).sequence_context = sequence;
(*emitter).mapping_context = mapping;
(*emitter).simple_key_context = simple_key;
match (*event).type_ {
YamlAliasEvent => yaml_emitter_emit_alias(emitter, event),
YamlScalarEvent => yaml_emitter_emit_scalar(emitter, event),
YamlSequenceStartEvent => yaml_emitter_emit_sequence_start(emitter, event),
YamlMappingStartEvent => yaml_emitter_emit_mapping_start(emitter, event),
_ => yaml_emitter_set_emitter_error(
emitter,
b"expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS\0" as *const u8
as *const libc::c_char,
),
}
}
unsafe fn yaml_emitter_emit_alias(
emitter: *mut YamlEmitterT,
_event: *mut YamlEventT,
) -> Success {
if yaml_emitter_process_anchor(emitter).fail {
return FAIL;
}
if (*emitter).simple_key_context && put(emitter, b' ').fail {
return FAIL;
}
(*emitter).state = POP!((*emitter).states);
OK
}
unsafe fn yaml_emitter_emit_scalar(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
if yaml_emitter_select_scalar_style(emitter, event).fail {
return FAIL;
}
if yaml_emitter_process_anchor(emitter).fail {
return FAIL;
}
if yaml_emitter_process_tag(emitter).fail {
return FAIL;
}
yaml_emitter_increase_indent(emitter, true, false);
if yaml_emitter_process_scalar(emitter).fail {
return FAIL;
}
(*emitter).indent = POP!((*emitter).indents);
(*emitter).state = POP!((*emitter).states);
OK
}
unsafe fn yaml_emitter_emit_sequence_start(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
if yaml_emitter_process_anchor(emitter).fail {
return FAIL;
}
if yaml_emitter_process_tag(emitter).fail {
return FAIL;
}
if (*emitter).flow_level != 0
|| (*emitter).canonical
|| (*event).data.sequence_start.style == YamlFlowSequenceStyle
|| yaml_emitter_check_empty_sequence(emitter)
{
(*emitter).state = YamlEmitFlowSequenceFirstItemState;
} else {
(*emitter).state = YamlEmitBlockSequenceFirstItemState;
}
OK
}
unsafe fn yaml_emitter_emit_mapping_start(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
if yaml_emitter_process_anchor(emitter).fail {
return FAIL;
}
if yaml_emitter_process_tag(emitter).fail {
return FAIL;
}
if (*emitter).flow_level != 0
|| (*emitter).canonical
|| (*event).data.mapping_start.style == YamlFlowMappingStyle
|| yaml_emitter_check_empty_mapping(emitter)
{
(*emitter).state = YamlEmitFlowMappingFirstKeyState;
} else {
(*emitter).state = YamlEmitBlockMappingFirstKeyState;
}
OK
}
unsafe fn yaml_emitter_check_empty_document(
_emitter: *mut YamlEmitterT,
) -> bool {
false
}
unsafe fn yaml_emitter_check_empty_sequence(
emitter: *mut YamlEmitterT,
) -> bool {
if ((*emitter).events.tail.c_offset_from((*emitter).events.head)
as libc::c_long)
< 2_i64
{
return false;
}
(*(*emitter).events.head).type_ == YamlSequenceStartEvent
&& (*(*emitter).events.head.wrapping_offset(1_isize)).type_
== YamlSequenceEndEvent
}
unsafe fn yaml_emitter_check_empty_mapping(
emitter: *mut YamlEmitterT,
) -> bool {
if ((*emitter).events.tail.c_offset_from((*emitter).events.head)
as libc::c_long)
< 2_i64
{
return false;
}
(*(*emitter).events.head).type_ == YamlMappingStartEvent
&& (*(*emitter).events.head.wrapping_offset(1_isize)).type_
== YamlMappingEndEvent
}
unsafe fn yaml_emitter_check_simple_key(
emitter: *mut YamlEmitterT,
) -> bool {
let event: *mut YamlEventT = (*emitter).events.head;
let mut length: size_t = 0_u64;
match (*event).type_ {
YamlAliasEvent => {
length =
length.force_add((*emitter).anchor_data.anchor_length);
}
YamlScalarEvent => {
if (*emitter).scalar_data.multiline {
return false;
}
length = length
.force_add((*emitter).anchor_data.anchor_length)
.force_add((*emitter).tag_data.handle_length)
.force_add((*emitter).tag_data.suffix_length)
.force_add((*emitter).scalar_data.length);
}
YamlSequenceStartEvent => {
if !yaml_emitter_check_empty_sequence(emitter) {
return false;
}
length = length
.force_add((*emitter).anchor_data.anchor_length)
.force_add((*emitter).tag_data.handle_length)
.force_add((*emitter).tag_data.suffix_length);
}
YamlMappingStartEvent => {
if !yaml_emitter_check_empty_mapping(emitter) {
return false;
}
length = length
.force_add((*emitter).anchor_data.anchor_length)
.force_add((*emitter).tag_data.handle_length)
.force_add((*emitter).tag_data.suffix_length);
}
_ => return false,
}
if length > 128_u64 {
return false;
}
true
}
unsafe fn yaml_emitter_select_scalar_style(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
let mut style: YamlScalarStyleT = (*event).data.scalar.style;
let no_tag = (*emitter).tag_data.handle.is_null()
&& (*emitter).tag_data.suffix.is_null();
if no_tag
&& !(*event).data.scalar.plain_implicit
&& !(*event).data.scalar.quoted_implicit
{
return yaml_emitter_set_emitter_error(
emitter,
b"neither tag nor implicit flags are specified\0"
as *const u8 as *const libc::c_char,
);
}
if style == YamlAnyScalarStyle {
style = YamlPlainScalarStyle;
}
if (*emitter).canonical {
style = YamlDoubleQuotedScalarStyle;
}
if (*emitter).simple_key_context && (*emitter).scalar_data.multiline
{
style = YamlDoubleQuotedScalarStyle;
}
if style == YamlPlainScalarStyle {
if (*emitter).flow_level != 0
&& !(*emitter).scalar_data.flow_plain_allowed
|| (*emitter).flow_level == 0
&& !(*emitter).scalar_data.block_plain_allowed
{
style = YamlSingleQuotedScalarStyle;
}
if (*emitter).scalar_data.length == 0
&& ((*emitter).flow_level != 0
|| (*emitter).simple_key_context)
{
style = YamlSingleQuotedScalarStyle;
}
if no_tag && !(*event).data.scalar.plain_implicit {
style = YamlSingleQuotedScalarStyle;
}
}
if style == YamlSingleQuotedScalarStyle
&& !(*emitter).scalar_data.single_quoted_allowed
{
style = YamlDoubleQuotedScalarStyle;
}
if (style == YamlLiteralScalarStyle
|| style == YamlFoldedScalarStyle)
&& (!(*emitter).scalar_data.block_allowed
|| (*emitter).flow_level != 0
|| (*emitter).simple_key_context)
{
style = YamlDoubleQuotedScalarStyle;
}
if no_tag
&& !(*event).data.scalar.quoted_implicit
&& style != YamlPlainScalarStyle
{
let fresh46 = addr_of_mut!((*emitter).tag_data.handle);
*fresh46 = b"!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t;
(*emitter).tag_data.handle_length = 1_u64;
}
(*emitter).scalar_data.style = style;
OK
}
unsafe fn yaml_emitter_process_anchor(
emitter: *mut YamlEmitterT,
) -> Success {
if (*emitter).anchor_data.anchor.is_null() {
return OK;
}
if yaml_emitter_write_indicator(
emitter,
if (*emitter).anchor_data.alias {
b"*\0" as *const u8 as *const libc::c_char
} else {
b"&\0" as *const u8 as *const libc::c_char
},
true,
false,
false,
)
.fail
{
return FAIL;
}
yaml_emitter_write_anchor(
emitter,
(*emitter).anchor_data.anchor,
(*emitter).anchor_data.anchor_length,
)
}
unsafe fn yaml_emitter_process_tag(
emitter: *mut YamlEmitterT,
) -> Success {
if (*emitter).tag_data.handle.is_null()
&& (*emitter).tag_data.suffix.is_null()
{
return OK;
}
if !(*emitter).tag_data.handle.is_null() {
if yaml_emitter_write_tag_handle(
emitter,
(*emitter).tag_data.handle,
(*emitter).tag_data.handle_length,
)
.fail
{
return FAIL;
}
if !(*emitter).tag_data.suffix.is_null()
&& yaml_emitter_write_tag_content(
emitter,
(*emitter).tag_data.suffix,
(*emitter).tag_data.suffix_length,
false,
)
.fail
{
return FAIL;
}
} else {
if yaml_emitter_write_indicator(
emitter,
b"!<\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_tag_content(
emitter,
(*emitter).tag_data.suffix,
(*emitter).tag_data.suffix_length,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b">\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
}
OK
}
unsafe fn yaml_emitter_process_scalar(
emitter: *mut YamlEmitterT,
) -> Success {
match (*emitter).scalar_data.style {
YamlPlainScalarStyle => {
return yaml_emitter_write_plain_scalar(
emitter,
(*emitter).scalar_data.value,
(*emitter).scalar_data.length,
!(*emitter).simple_key_context,
);
}
YamlSingleQuotedScalarStyle => {
return yaml_emitter_write_single_quoted_scalar(
emitter,
(*emitter).scalar_data.value,
(*emitter).scalar_data.length,
!(*emitter).simple_key_context,
);
}
YamlDoubleQuotedScalarStyle => {
return yaml_emitter_write_double_quoted_scalar(
emitter,
(*emitter).scalar_data.value,
(*emitter).scalar_data.length,
!(*emitter).simple_key_context,
);
}
YamlLiteralScalarStyle => {
return yaml_emitter_write_literal_scalar(
emitter,
(*emitter).scalar_data.value,
(*emitter).scalar_data.length,
);
}
YamlFoldedScalarStyle => {
return yaml_emitter_write_folded_scalar(
emitter,
(*emitter).scalar_data.value,
(*emitter).scalar_data.length,
);
}
_ => {}
}
FAIL
}
unsafe fn yaml_emitter_analyze_version_directive(
emitter: *mut YamlEmitterT,
version_directive: YamlVersionDirectiveT,
) -> Success {
if version_directive.major != 1
|| version_directive.minor != 1 && version_directive.minor != 2
{
return yaml_emitter_set_emitter_error(
emitter,
b"incompatible %YAML directive\0" as *const u8
as *const libc::c_char,
);
}
OK
}
unsafe fn yaml_emitter_analyze_tag_directive(
emitter: *mut YamlEmitterT,
tag_directive: YamlTagDirectiveT,
) -> Success {
let handle_length: size_t =
strlen(tag_directive.handle as *mut libc::c_char);
let prefix_length: size_t =
strlen(tag_directive.prefix as *mut libc::c_char);
let mut handle =
STRING_ASSIGN!(tag_directive.handle, handle_length);
let prefix = STRING_ASSIGN!(tag_directive.prefix, prefix_length);
if handle.start == handle.end {
return yaml_emitter_set_emitter_error(
emitter,
b"tag handle must not be empty\0" as *const u8
as *const libc::c_char,
);
}
if *handle.start != b'!' {
return yaml_emitter_set_emitter_error(
emitter,
b"tag handle must start with '!'\0" as *const u8
as *const libc::c_char,
);
}
if *handle.end.wrapping_offset(-1_isize) != b'!' {
return yaml_emitter_set_emitter_error(
emitter,
b"tag handle must end with '!'\0" as *const u8
as *const libc::c_char,
);
}
handle.pointer = handle.pointer.wrapping_offset(1);
while handle.pointer < handle.end.wrapping_offset(-1_isize) {
if !IS_ALPHA!(handle) {
return yaml_emitter_set_emitter_error(
emitter,
b"tag handle must contain alphanumerical characters only\0" as *const u8
as *const libc::c_char,
);
}
MOVE!(handle);
}
if prefix.start == prefix.end {
return yaml_emitter_set_emitter_error(
emitter,
b"tag prefix must not be empty\0" as *const u8
as *const libc::c_char,
);
}
OK
}
unsafe fn yaml_emitter_analyze_anchor(
emitter: *mut YamlEmitterT,
anchor: *mut yaml_char_t,
alias: bool,
) -> Success {
let anchor_length: size_t = strlen(anchor as *mut libc::c_char);
let mut string = STRING_ASSIGN!(anchor, anchor_length);
if string.start == string.end {
return yaml_emitter_set_emitter_error(
emitter,
if alias {
b"alias value must not be empty\0" as *const u8
as *const libc::c_char
} else {
b"anchor value must not be empty\0" as *const u8
as *const libc::c_char
},
);
}
while string.pointer != string.end {
if !IS_ALPHA!(string) {
return yaml_emitter_set_emitter_error(
emitter,
if alias {
b"alias value must contain alphanumerical characters only\0" as *const u8
as *const libc::c_char
} else {
b"anchor value must contain alphanumerical characters only\0" as *const u8
as *const libc::c_char
},
);
}
MOVE!(string);
}
let fresh47 = addr_of_mut!((*emitter).anchor_data.anchor);
*fresh47 = string.start;
(*emitter).anchor_data.anchor_length =
string.end.c_offset_from(string.start) as size_t;
(*emitter).anchor_data.alias = alias;
OK
}
unsafe fn yaml_emitter_analyze_tag(
emitter: *mut YamlEmitterT,
tag: *mut yaml_char_t,
) -> Success {
let mut tag_directive: *mut YamlTagDirectiveT;
let tag_length: size_t = strlen(tag as *mut libc::c_char);
let string = STRING_ASSIGN!(tag, tag_length);
if string.start == string.end {
return yaml_emitter_set_emitter_error(
emitter,
b"tag value must not be empty\0" as *const u8
as *const libc::c_char,
);
}
tag_directive = (*emitter).tag_directives.start;
while tag_directive != (*emitter).tag_directives.top {
let prefix_length: size_t =
strlen((*tag_directive).prefix as *mut libc::c_char);
if prefix_length
< string.end.c_offset_from(string.start) as size_t
&& strncmp(
(*tag_directive).prefix as *mut libc::c_char,
string.start as *mut libc::c_char,
prefix_length,
) == 0
{
let fresh48 = addr_of_mut!((*emitter).tag_data.handle);
*fresh48 = (*tag_directive).handle;
(*emitter).tag_data.handle_length =
strlen((*tag_directive).handle as *mut libc::c_char);
let fresh49 = addr_of_mut!((*emitter).tag_data.suffix);
*fresh49 =
string.start.wrapping_offset(prefix_length as isize);
(*emitter).tag_data.suffix_length =
(string.end.c_offset_from(string.start)
as libc::c_ulong)
.wrapping_sub(prefix_length);
return OK;
}
tag_directive = tag_directive.wrapping_offset(1);
}
let fresh50 = addr_of_mut!((*emitter).tag_data.suffix);
*fresh50 = string.start;
(*emitter).tag_data.suffix_length =
string.end.c_offset_from(string.start) as size_t;
OK
}
unsafe fn yaml_emitter_analyze_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
) -> Success {
let mut block_indicators = false;
let mut flow_indicators = false;
let mut line_breaks = false;
let mut special_characters = false;
let mut leading_space = false;
let mut leading_break = false;
let mut trailing_space = false;
let mut trailing_break = false;
let mut break_space = false;
let mut space_break = false;
let mut preceded_by_whitespace;
let mut followed_by_whitespace;
let mut previous_space = false;
let mut previous_break = false;
let mut string = STRING_ASSIGN!(value, length);
let fresh51 = addr_of_mut!((*emitter).scalar_data.value);
*fresh51 = value;
(*emitter).scalar_data.length = length;
if string.start == string.end {
(*emitter).scalar_data.multiline = false;
(*emitter).scalar_data.flow_plain_allowed = false;
(*emitter).scalar_data.block_plain_allowed = true;
(*emitter).scalar_data.single_quoted_allowed = true;
(*emitter).scalar_data.block_allowed = false;
return OK;
}
if CHECK_AT!(string, b'-', 0)
&& CHECK_AT!(string, b'-', 1)
&& CHECK_AT!(string, b'-', 2)
|| CHECK_AT!(string, b'.', 0)
&& CHECK_AT!(string, b'.', 1)
&& CHECK_AT!(string, b'.', 2)
{
block_indicators = true;
flow_indicators = true;
}
preceded_by_whitespace = true;
followed_by_whitespace = IS_BLANKZ_AT!(string, WIDTH!(string));
while string.pointer != string.end {
if string.start == string.pointer {
if CHECK!(string, b'#')
|| CHECK!(string, b',')
|| CHECK!(string, b'[')
|| CHECK!(string, b']')
|| CHECK!(string, b'{')
|| CHECK!(string, b'}')
|| CHECK!(string, b'&')
|| CHECK!(string, b'*')
|| CHECK!(string, b'!')
|| CHECK!(string, b'|')
|| CHECK!(string, b'>')
|| CHECK!(string, b'\'')
|| CHECK!(string, b'"')
|| CHECK!(string, b'%')
|| CHECK!(string, b'@')
|| CHECK!(string, b'`')
{
flow_indicators = true;
block_indicators = true;
}
if CHECK!(string, b'?') || CHECK!(string, b':') {
flow_indicators = true;
if followed_by_whitespace {
block_indicators = true;
}
}
if CHECK!(string, b'-') && followed_by_whitespace {
flow_indicators = true;
block_indicators = true;
}
} else {
if CHECK!(string, b',')
|| CHECK!(string, b'?')
|| CHECK!(string, b'[')
|| CHECK!(string, b']')
|| CHECK!(string, b'{')
|| CHECK!(string, b'}')
{
flow_indicators = true;
}
if CHECK!(string, b':') {
flow_indicators = true;
if followed_by_whitespace {
block_indicators = true;
}
}
if CHECK!(string, b'#') && preceded_by_whitespace {
flow_indicators = true;
block_indicators = true;
}
}
if !IS_PRINTABLE!(string)
|| !IS_ASCII!(string) && !(*emitter).unicode
{
special_characters = true;
}
if IS_BREAK!(string) {
line_breaks = true;
}
if IS_SPACE!(string) {
if string.start == string.pointer {
leading_space = true;
}
if string.pointer.wrapping_offset(WIDTH!(string) as isize)
== string.end
{
trailing_space = true;
}
if previous_break {
break_space = true;
}
previous_space = true;
previous_break = false;
} else if IS_BREAK!(string) {
if string.start == string.pointer {
leading_break = true;
}
if string.pointer.wrapping_offset(WIDTH!(string) as isize)
== string.end
{
trailing_break = true;
}
if previous_space {
space_break = true;
}
previous_space = false;
previous_break = true;
} else {
previous_space = false;
previous_break = false;
}
preceded_by_whitespace = IS_BLANKZ!(string);
MOVE!(string);
if string.pointer != string.end {
followed_by_whitespace =
IS_BLANKZ_AT!(string, WIDTH!(string));
}
}
(*emitter).scalar_data.multiline = line_breaks;
(*emitter).scalar_data.flow_plain_allowed = true;
(*emitter).scalar_data.block_plain_allowed = true;
(*emitter).scalar_data.single_quoted_allowed = true;
(*emitter).scalar_data.block_allowed = true;
if leading_space
|| leading_break
|| trailing_space
|| trailing_break
{
(*emitter).scalar_data.flow_plain_allowed = false;
(*emitter).scalar_data.block_plain_allowed = false;
}
if trailing_space {
(*emitter).scalar_data.block_allowed = false;
}
if break_space {
(*emitter).scalar_data.flow_plain_allowed = false;
(*emitter).scalar_data.block_plain_allowed = false;
(*emitter).scalar_data.single_quoted_allowed = false;
}
if space_break || special_characters {
(*emitter).scalar_data.flow_plain_allowed = false;
(*emitter).scalar_data.block_plain_allowed = false;
(*emitter).scalar_data.single_quoted_allowed = false;
(*emitter).scalar_data.block_allowed = false;
}
if line_breaks {
(*emitter).scalar_data.flow_plain_allowed = false;
(*emitter).scalar_data.block_plain_allowed = false;
}
if flow_indicators {
(*emitter).scalar_data.flow_plain_allowed = false;
}
if block_indicators {
(*emitter).scalar_data.block_plain_allowed = false;
}
OK
}
unsafe fn yaml_emitter_analyze_event(
emitter: *mut YamlEmitterT,
event: *mut YamlEventT,
) -> Success {
let fresh52 = addr_of_mut!((*emitter).anchor_data.anchor);
*fresh52 = ptr::null_mut::();
(*emitter).anchor_data.anchor_length = 0_u64;
let fresh53 = addr_of_mut!((*emitter).tag_data.handle);
*fresh53 = ptr::null_mut::();
(*emitter).tag_data.handle_length = 0_u64;
let fresh54 = addr_of_mut!((*emitter).tag_data.suffix);
*fresh54 = ptr::null_mut::();
(*emitter).tag_data.suffix_length = 0_u64;
let fresh55 = addr_of_mut!((*emitter).scalar_data.value);
*fresh55 = ptr::null_mut::();
(*emitter).scalar_data.length = 0_u64;
match (*event).type_ {
YamlAliasEvent => yaml_emitter_analyze_anchor(
emitter,
(*event).data.alias.anchor,
true,
),
YamlScalarEvent => {
if !(*event).data.scalar.anchor.is_null()
&& yaml_emitter_analyze_anchor(
emitter,
(*event).data.scalar.anchor,
false,
)
.fail
{
return FAIL;
}
if !(*event).data.scalar.tag.is_null()
&& ((*emitter).canonical
|| !(*event).data.scalar.plain_implicit
&& !(*event).data.scalar.quoted_implicit)
&& yaml_emitter_analyze_tag(
emitter,
(*event).data.scalar.tag,
)
.fail
{
return FAIL;
}
yaml_emitter_analyze_scalar(
emitter,
(*event).data.scalar.value,
(*event).data.scalar.length,
)
}
YamlSequenceStartEvent => {
if !(*event).data.sequence_start.anchor.is_null()
&& yaml_emitter_analyze_anchor(
emitter,
(*event).data.sequence_start.anchor,
false,
)
.fail
{
return FAIL;
}
if !(*event).data.sequence_start.tag.is_null()
&& ((*emitter).canonical
|| !(*event).data.sequence_start.implicit)
&& yaml_emitter_analyze_tag(
emitter,
(*event).data.sequence_start.tag,
)
.fail
{
return FAIL;
}
OK
}
YamlMappingStartEvent => {
if !(*event).data.mapping_start.anchor.is_null()
&& yaml_emitter_analyze_anchor(
emitter,
(*event).data.mapping_start.anchor,
false,
)
.fail
{
return FAIL;
}
if !(*event).data.mapping_start.tag.is_null()
&& ((*emitter).canonical
|| !(*event).data.mapping_start.implicit)
&& yaml_emitter_analyze_tag(
emitter,
(*event).data.mapping_start.tag,
)
.fail
{
return FAIL;
}
OK
}
_ => OK,
}
}
unsafe fn yaml_emitter_write_bom(
emitter: *mut YamlEmitterT,
) -> Success {
if flush(emitter).fail {
return FAIL;
}
let fresh56 = addr_of_mut!((*emitter).buffer.pointer);
let fresh57 = *fresh56;
*fresh56 = (*fresh56).wrapping_offset(1);
*fresh57 = b'\xEF';
let fresh58 = addr_of_mut!((*emitter).buffer.pointer);
let fresh59 = *fresh58;
*fresh58 = (*fresh58).wrapping_offset(1);
*fresh59 = b'\xBB';
let fresh60 = addr_of_mut!((*emitter).buffer.pointer);
let fresh61 = *fresh60;
*fresh60 = (*fresh60).wrapping_offset(1);
*fresh61 = b'\xBF';
OK
}
unsafe fn yaml_emitter_write_indent(
emitter: *mut YamlEmitterT,
) -> Success {
let indent: libc::c_int = if (*emitter).indent >= 0 {
(*emitter).indent
} else {
0
};
if (!(*emitter).indention
|| (*emitter).column > indent
|| (*emitter).column == indent && !(*emitter).whitespace)
&& put_break(emitter).fail
{
return FAIL;
}
if (*emitter).column < indent {
loop {
if put(emitter, b' ').fail {
return FAIL;
}
if (*emitter).column >= indent {
break;
}
}
}
(*emitter).whitespace = true;
(*emitter).indention = true;
OK
}
unsafe fn yaml_emitter_write_indicator(
emitter: *mut YamlEmitterT,
indicator: *const libc::c_char,
need_whitespace: bool,
is_whitespace: bool,
is_indention: bool,
) -> Success {
let indicator_length: size_t = strlen(indicator);
let mut string =
STRING_ASSIGN!(indicator as *mut yaml_char_t, indicator_length);
if need_whitespace
&& !(*emitter).whitespace
&& put(emitter, b' ').fail
{
return FAIL;
}
while string.pointer != string.end {
if write!(emitter, string).fail {
return FAIL;
}
}
(*emitter).whitespace = is_whitespace;
(*emitter).indention = (*emitter).indention && is_indention;
OK
}
unsafe fn yaml_emitter_write_anchor(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
) -> Success {
let mut string = STRING_ASSIGN!(value, length);
while string.pointer != string.end {
if write!(emitter, string).fail {
return FAIL;
}
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_tag_handle(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
) -> Success {
let mut string = STRING_ASSIGN!(value, length);
if !(*emitter).whitespace && put(emitter, b' ').fail {
return FAIL;
}
while string.pointer != string.end {
if write!(emitter, string).fail {
return FAIL;
}
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_tag_content(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
need_whitespace: bool,
) -> Success {
let mut string = STRING_ASSIGN!(value, length);
if need_whitespace
&& !(*emitter).whitespace
&& put(emitter, b' ').fail
{
return FAIL;
}
while string.pointer != string.end {
if IS_ALPHA!(string)
|| CHECK!(string, b';')
|| CHECK!(string, b'/')
|| CHECK!(string, b'?')
|| CHECK!(string, b':')
|| CHECK!(string, b'@')
|| CHECK!(string, b'&')
|| CHECK!(string, b'=')
|| CHECK!(string, b'+')
|| CHECK!(string, b'$')
|| CHECK!(string, b',')
|| CHECK!(string, b'_')
|| CHECK!(string, b'.')
|| CHECK!(string, b'~')
|| CHECK!(string, b'*')
|| CHECK!(string, b'\'')
|| CHECK!(string, b'(')
|| CHECK!(string, b')')
|| CHECK!(string, b'[')
|| CHECK!(string, b']')
{
if write!(emitter, string).fail {
return FAIL;
}
} else {
let mut width = WIDTH!(string);
loop {
let fresh207 = width;
width -= 1;
if fresh207 == 0 {
break;
}
let fresh208 = string.pointer;
string.pointer = string.pointer.wrapping_offset(1);
let value = *fresh208;
if put(emitter, b'%').fail {
return FAIL;
}
if put(
emitter,
(value >> 4).force_add(if (value >> 4) < 10 {
b'0'
} else {
b'A' - 10
}),
)
.fail
{
return FAIL;
}
if put(
emitter,
(value & 0x0F).force_add(if (value & 0x0F) < 10 {
b'0'
} else {
b'A' - 10
}),
)
.fail
{
return FAIL;
}
}
}
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_plain_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
allow_breaks: bool,
) -> Success {
let mut spaces = false;
let mut breaks = false;
let mut string = STRING_ASSIGN!(value, length);
if !(*emitter).whitespace
&& (length != 0 || (*emitter).flow_level != 0)
&& put(emitter, b' ').fail
{
return FAIL;
}
while string.pointer != string.end {
if IS_SPACE!(string) {
if allow_breaks
&& !spaces
&& (*emitter).column > (*emitter).best_width
&& !IS_SPACE_AT!(string, 1)
{
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
MOVE!(string);
} else if write!(emitter, string).fail {
return FAIL;
}
spaces = true;
} else if IS_BREAK!(string) {
if !breaks
&& CHECK!(string, b'\n')
&& put_break(emitter).fail
{
return FAIL;
}
if write_break!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = true;
breaks = true;
} else {
if breaks && yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if write!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = false;
spaces = false;
breaks = false;
}
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_single_quoted_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
allow_breaks: bool,
) -> Success {
let mut spaces = false;
let mut breaks = false;
let mut string = STRING_ASSIGN!(value, length);
if yaml_emitter_write_indicator(
emitter,
b"'\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
while string.pointer != string.end {
if IS_SPACE!(string) {
if allow_breaks
&& !spaces
&& (*emitter).column > (*emitter).best_width
&& string.pointer != string.start
&& string.pointer
!= string.end.wrapping_offset(-1_isize)
&& !IS_SPACE_AT!(string, 1)
{
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
MOVE!(string);
} else if write!(emitter, string).fail {
return FAIL;
}
spaces = true;
} else if IS_BREAK!(string) {
if !breaks
&& CHECK!(string, b'\n')
&& put_break(emitter).fail
{
return FAIL;
}
if write_break!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = true;
breaks = true;
} else {
if breaks && yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if CHECK!(string, b'\'') && put(emitter, b'\'').fail {
return FAIL;
}
if write!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = false;
spaces = false;
breaks = false;
}
}
if breaks && yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if yaml_emitter_write_indicator(
emitter,
b"'\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_double_quoted_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
allow_breaks: bool,
) -> Success {
let mut spaces = false;
let mut string = STRING_ASSIGN!(value, length);
if yaml_emitter_write_indicator(
emitter,
b"\"\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
while string.pointer != string.end {
if !IS_PRINTABLE!(string)
|| !(*emitter).unicode && !IS_ASCII!(string)
|| IS_BOM!(string)
|| IS_BREAK!(string)
|| CHECK!(string, b'"')
|| CHECK!(string, b'\\')
{
let mut octet: libc::c_uchar;
let mut width: libc::c_uint;
let mut value_0: libc::c_uint;
let mut k: libc::c_int;
octet = *string.pointer;
width = if octet & 0x80 == 0x00 {
1
} else if octet & 0xE0 == 0xC0 {
2
} else if octet & 0xF0 == 0xE0 {
3
} else if octet & 0xF8 == 0xF0 {
4
} else {
0
};
value_0 = if octet & 0x80 == 0 {
octet & 0x7F
} else if octet & 0xE0 == 0xC0 {
octet & 0x1F
} else if octet & 0xF0 == 0xE0 {
octet & 0x0F
} else if octet & 0xF8 == 0xF0 {
octet & 0x07
} else {
0
} as libc::c_uint;
k = 1;
while k < width as libc::c_int {
octet = *string.pointer.wrapping_offset(k as isize);
value_0 = (value_0 << 6)
.force_add((octet & 0x3F) as libc::c_uint);
k += 1;
}
string.pointer =
string.pointer.wrapping_offset(width as isize);
if put(emitter, b'\\').fail {
return FAIL;
}
match value_0 {
0x00 => {
if put(emitter, b'0').fail {
return FAIL;
}
}
0x07 => {
if put(emitter, b'a').fail {
return FAIL;
}
}
0x08 => {
if put(emitter, b'b').fail {
return FAIL;
}
}
0x09 => {
if put(emitter, b't').fail {
return FAIL;
}
}
0x0A => {
if put(emitter, b'n').fail {
return FAIL;
}
}
0x0B => {
if put(emitter, b'v').fail {
return FAIL;
}
}
0x0C => {
if put(emitter, b'f').fail {
return FAIL;
}
}
0x0D => {
if put(emitter, b'r').fail {
return FAIL;
}
}
0x1B => {
if put(emitter, b'e').fail {
return FAIL;
}
}
0x22 => {
if put(emitter, b'"').fail {
return FAIL;
}
}
0x5C => {
if put(emitter, b'\\').fail {
return FAIL;
}
}
0x85 => {
if put(emitter, b'N').fail {
return FAIL;
}
}
0xA0 => {
if put(emitter, b'_').fail {
return FAIL;
}
}
0x2028 => {
if put(emitter, b'L').fail {
return FAIL;
}
}
0x2029 => {
if put(emitter, b'P').fail {
return FAIL;
}
}
_ => {
if value_0 <= 0xFF {
if put(emitter, b'x').fail {
return FAIL;
}
width = 2;
} else if value_0 <= 0xFFFF {
if put(emitter, b'u').fail {
return FAIL;
}
width = 4;
} else {
if put(emitter, b'U').fail {
return FAIL;
}
width = 8;
}
k = width.wrapping_sub(1).wrapping_mul(4)
as libc::c_int;
while k >= 0 {
let digit: libc::c_int =
(value_0 >> k & 0x0F) as libc::c_int;
if put(
emitter,
(digit
+ if digit < 10 {
b'0'
} else {
b'A' - 10
}
as i32)
as u8,
)
.fail
{
return FAIL;
}
k -= 4;
}
}
}
spaces = false;
} else if IS_SPACE!(string) {
if allow_breaks
&& !spaces
&& (*emitter).column > (*emitter).best_width
&& string.pointer != string.start
&& string.pointer
!= string.end.wrapping_offset(-1_isize)
{
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if IS_SPACE_AT!(string, 1) && put(emitter, b'\\').fail {
return FAIL;
}
MOVE!(string);
} else if write!(emitter, string).fail {
return FAIL;
}
spaces = true;
} else {
if write!(emitter, string).fail {
return FAIL;
}
spaces = false;
}
}
if yaml_emitter_write_indicator(
emitter,
b"\"\0" as *const u8 as *const libc::c_char,
false,
false,
false,
)
.fail
{
return FAIL;
}
(*emitter).whitespace = false;
(*emitter).indention = false;
OK
}
unsafe fn yaml_emitter_write_block_scalar_hints(
emitter: *mut YamlEmitterT,
mut string: YamlStringT,
) -> Success {
let mut indent_hint: [libc::c_char; 2] = [0; 2];
let mut chomp_hint: *const libc::c_char =
ptr::null::();
if IS_SPACE!(string) || IS_BREAK!(string) {
indent_hint[0] = (b'0' as libc::c_int + (*emitter).best_indent)
as libc::c_char;
indent_hint[1] = '\0' as libc::c_char;
if yaml_emitter_write_indicator(
emitter,
indent_hint.as_mut_ptr(),
false,
false,
false,
)
.fail
{
return FAIL;
}
}
(*emitter).open_ended = 0;
string.pointer = string.end;
if string.start == string.pointer {
chomp_hint = b"-\0" as *const u8 as *const libc::c_char;
} else {
loop {
string.pointer = string.pointer.wrapping_offset(-1);
if *string.pointer & 0xC0 != 0x80 {
break;
}
}
if !IS_BREAK!(string) {
chomp_hint = b"-\0" as *const u8 as *const libc::c_char;
} else if string.start == string.pointer {
chomp_hint = b"+\0" as *const u8 as *const libc::c_char;
(*emitter).open_ended = 2;
} else {
loop {
string.pointer = string.pointer.wrapping_offset(-1);
if *string.pointer & 0xC0 != 0x80 {
break;
}
}
if IS_BREAK!(string) {
chomp_hint = b"+\0" as *const u8 as *const libc::c_char;
(*emitter).open_ended = 2;
}
}
}
if !chomp_hint.is_null()
&& yaml_emitter_write_indicator(
emitter, chomp_hint, false, false, false,
)
.fail
{
return FAIL;
}
OK
}
unsafe fn yaml_emitter_write_literal_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
) -> Success {
let mut breaks = true;
let mut string = STRING_ASSIGN!(value, length);
if yaml_emitter_write_indicator(
emitter,
b"|\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_block_scalar_hints(emitter, string).fail {
return FAIL;
}
if put_break(emitter).fail {
return FAIL;
}
(*emitter).indention = true;
(*emitter).whitespace = true;
while string.pointer != string.end {
if IS_BREAK!(string) {
if write_break!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = true;
breaks = true;
} else {
if breaks && yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
if write!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = false;
breaks = false;
}
}
OK
}
unsafe fn yaml_emitter_write_folded_scalar(
emitter: *mut YamlEmitterT,
value: *mut yaml_char_t,
length: size_t,
) -> Success {
let mut breaks = true;
let mut leading_spaces = true;
let mut string = STRING_ASSIGN!(value, length);
if yaml_emitter_write_indicator(
emitter,
b">\0" as *const u8 as *const libc::c_char,
true,
false,
false,
)
.fail
{
return FAIL;
}
if yaml_emitter_write_block_scalar_hints(emitter, string).fail {
return FAIL;
}
if put_break(emitter).fail {
return FAIL;
}
(*emitter).indention = true;
(*emitter).whitespace = true;
while string.pointer != string.end {
if IS_BREAK!(string) {
if !breaks && !leading_spaces && CHECK!(string, b'\n') {
let mut k: libc::c_int = 0;
while IS_BREAK_AT!(string, k as isize) {
k += WIDTH_AT!(string, k as isize);
}
if !IS_BLANKZ_AT!(string, k as isize)
&& put_break(emitter).fail
{
return FAIL;
}
}
if write_break!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = true;
breaks = true;
} else {
if breaks {
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
leading_spaces = IS_BLANK!(string);
}
if !breaks
&& IS_SPACE!(string)
&& !IS_SPACE_AT!(string, 1)
&& (*emitter).column > (*emitter).best_width
{
if yaml_emitter_write_indent(emitter).fail {
return FAIL;
}
MOVE!(string);
} else if write!(emitter, string).fail {
return FAIL;
}
(*emitter).indention = false;
breaks = false;
}
}
OK
}
libyml-0.0.5/src/internal.rs 0000644 0000000 0000000 00000015246 10461020230 0014077 0 ustar 0000000 0000000 use crate::{
externs::memmove,
libc,
memory::yaml_realloc,
ops::{ForceAdd as _, ForceMul as _},
success::{Success, FAIL, OK},
yaml::{size_t, yaml_char_t},
PointerExt,
};
/// Extend a stack by reallocating and copying the existing data.
///
/// This function is used to grow a stack when more space is needed.
///
/// # Safety
///
/// - This function is unsafe because it directly calls the system's `realloc` function,
/// which can lead to undefined behaviour if misused.
/// - The caller must ensure that `start`, `top`, and `end` are valid pointers into the
/// same allocated memory block.
/// - The caller must ensure that the memory block being extended is large enough to
/// accommodate the new size.
/// - The caller is responsible for properly freeing the extended memory block using
/// the corresponding `yaml_free` function when it is no longer needed.
///
pub unsafe fn yaml_stack_extend(
start: *mut *mut libc::c_void,
top: *mut *mut libc::c_void,
end: *mut *mut libc::c_void,
) {
let new_start: *mut libc::c_void = yaml_realloc(
*start,
(((*end as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long)
.force_mul(2_i64)) as size_t,
);
*top = (new_start as *mut libc::c_char).wrapping_offset(
(*top as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long as isize,
) as *mut libc::c_void;
*end = (new_start as *mut libc::c_char).wrapping_offset(
(((*end as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long)
.force_mul(2_i64)) as isize,
) as *mut libc::c_void;
*start = new_start;
}
/// Extend a queue by reallocating and copying the existing data.
///
/// This function is used to grow a queue when more space is needed.
///
/// # Safety
///
/// - This function is unsafe because it directly calls the system's `realloc` and
/// `memmove` functions, which can lead to undefined behaviour if misused.
/// - The caller must ensure that `start`, `head`, `tail`, and `end` are valid pointers
/// into the same allocated memory block.
/// - The caller must ensure that the memory block being extended is large enough to
/// accommodate the new size.
/// - The caller is responsible for properly freeing the extended memory block using
/// the corresponding `yaml_free` function when it is no longer needed.
///
pub unsafe fn yaml_queue_extend(
start: *mut *mut libc::c_void,
head: *mut *mut libc::c_void,
tail: *mut *mut libc::c_void,
end: *mut *mut libc::c_void,
) {
if *start == *head && *tail == *end {
let new_start: *mut libc::c_void = yaml_realloc(
*start,
(((*end as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long)
.force_mul(2_i64)) as size_t,
);
*head = (new_start as *mut libc::c_char).wrapping_offset(
(*head as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long as isize,
) as *mut libc::c_void;
*tail = (new_start as *mut libc::c_char).wrapping_offset(
(*tail as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long as isize,
) as *mut libc::c_void;
*end = (new_start as *mut libc::c_char).wrapping_offset(
(((*end as *mut libc::c_char)
.c_offset_from(*start as *mut libc::c_char)
as libc::c_long)
.force_mul(2_i64)) as isize,
) as *mut libc::c_void;
*start = new_start;
}
if *tail == *end {
if *head != *tail {
let _ = memmove(
*start,
*head,
(*tail as *mut libc::c_char)
.c_offset_from(*head as *mut libc::c_char)
as libc::c_ulong,
);
}
*tail = (*start as *mut libc::c_char).wrapping_offset(
(*tail as *mut libc::c_char)
.c_offset_from(*head as *mut libc::c_char)
as libc::c_long as isize,
) as *mut libc::c_void;
*head = *start;
}
}
/// Checks if the provided UTF-8 encoded string is valid according to the UTF-8 specification.
///
/// # Parameters
///
/// * `start`: A pointer to the start of the UTF-8 encoded string.
/// * `length`: The length of the UTF-8 encoded string in bytes.
///
/// # Return
///
/// Returns `Success::OK` if the string is valid UTF-8, otherwise returns `Success::FAIL`.
///
/// # Safety
///
/// - `start` must be a valid, non-null pointer to a null-terminated UTF-8 string.
/// - The UTF-8 encoded string must be properly formatted and not contain any invalid characters.
/// - The string must be properly null-terminated.
/// - The string must not contain any invalid characters or sequences.
///
pub unsafe fn yaml_check_utf8(
start: *const yaml_char_t,
length: size_t,
) -> Success {
let end: *const yaml_char_t =
start.wrapping_offset(length as isize);
let mut pointer: *const yaml_char_t = start;
while pointer < end {
let mut octet: libc::c_uchar;
let mut value: libc::c_uint;
let mut k: size_t;
octet = *pointer;
let width: libc::c_uint = if octet & 0x80 == 0 {
1
} else if octet & 0xE0 == 0xC0 {
2
} else if octet & 0xF0 == 0xE0 {
3
} else if octet & 0xF8 == 0xF0 {
4
} else {
0
} as libc::c_uint;
value = if octet & 0x80 == 0 {
octet & 0x7F
} else if octet & 0xE0 == 0xC0 {
octet & 0x1F
} else if octet & 0xF0 == 0xE0 {
octet & 0xF
} else if octet & 0xF8 == 0xF0 {
octet & 0x7
} else {
0
} as libc::c_uint;
if width == 0 {
return FAIL;
}
if pointer.wrapping_offset(width as isize) > end {
return FAIL;
}
k = 1_u64;
while k < width as libc::c_ulong {
octet = *pointer.wrapping_offset(k as isize);
if octet & 0xC0 != 0x80 {
return FAIL;
}
value =
(value << 6).force_add((octet & 0x3F) as libc::c_uint);
k = k.force_add(1);
}
if !(width == 1
|| width == 2 && value >= 0x80
|| width == 3 && value >= 0x800
|| width == 4 && value >= 0x10000)
{
return FAIL;
}
pointer = pointer.wrapping_offset(width as isize);
}
OK
}
libyml-0.0.5/src/lib.rs 0000644 0000000 0000000 00000043533 10461020230 0013031 0 ustar 0000000 0000000 //! # LibYML (a fork of unsafe-libyaml)
//!
//! [![Made With Love][made-with-rust]][10]
//! [![Crates.io][crates-badge]][06]
//! [![lib.rs][libs-badge]][11]
//! [![Docs.rs][docs-badge]][07]
//! [![Codecov][codecov-badge]][08]
//! [![Build Status][build-badge]][09]
//! [![GitHub][github-badge]][05]
//!
//! LibYML is a Rust library for working with YAML data, forked from [unsafe-libyaml][01]. It offers a safe and efficient interface for parsing, emitting, and manipulating YAML data.
//!
//! ## Features
//!
//! - **Serialization and Deserialization**: Easy-to-use APIs for serializing Rust structs and enums to YAML and vice versa.
//! - **Custom Struct and Enum Support**: Seamless serialization and deserialization of custom data types.
//! - **Comprehensive Error Handling**: Detailed error messages and recovery mechanisms.
//! - **Streaming Support**: Efficient processing of large YAML documents.
//! - **Alias and Anchor Support**: Handling of complex YAML structures with references.
//! - **Tag Handling**: Support for custom tags and type-specific serialization.
//! - **Configurable Emitter**: Customizable YAML output generation.
//! - **Extensive Documentation**: Detailed docs and examples for easy onboarding.
//! - **Safety and Efficiency**: Minimized unsafe code with an interface designed to prevent common pitfalls.
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! libyml = "0.0.5"
//! ```
//!
//! ## Documentation
//!
//! For full API documentation, please visit [https://doc.libyml.com/libyml/][03] or [https://docs.rs/libyml][07].
//!
//! ## Rust Version Compatibility
//!
//! Compiler support: requires rustc 1.56.0+
//!
//! ## Contributing
//!
//! Contributions are welcome! If you'd like to contribute, please feel free to submit a Pull Request on [GitHub][05].
//!
//! ## Credits and Acknowledgements
//!
//! LibYML is a fork of the work done by [David Tolnay][04] and the maintainers of [unsafe-libyaml][01]. While it has evolved into a separate library, we express our sincere gratitude to them as well as the [libyaml][02] maintainers for their contributions to the Rust and C programming communities.
//!
//! ## License
//!
//! [MIT license](https://opensource.org/license/MIT), same as libyaml.
//!
//! [00]: https://libyml.com
//! [01]: https://github.com/dtolnay/unsafe-libyaml
//! [02]: https://github.com/yaml/libyaml/tree/2c891fc7a770e8ba2fec34fc6b545c672beb37e6
//! [03]: https://doc.libyml.com/libyml/
//! [04]: https://github.com/dtolnay
//! [05]: https://github.com/sebastienrousseau/libyml
//! [06]: https://crates.io/crates/libyml
//! [07]: https://docs.rs/libyml
//! [08]: https://codecov.io/gh/sebastienrousseau/libyml
//! [09]: https://github.com/sebastienrousseau/libyml/actions?query=branch%3Amaster
//! [10]: https://www.rust-lang.org/
//! [11]: https://lib.rs/crates/libyml
//!
//! [build-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/libyml/release.yml?branch=master&style=for-the-badge&logo=github "Build Status"
//! [codecov-badge]: https://img.shields.io/codecov/c/github/sebastienrousseau/libyml?style=for-the-badge&logo=codecov&token=yc9s578xIk "Code Coverage"
//! [crates-badge]: https://img.shields.io/crates/v/libyml.svg?style=for-the-badge&color=fc8d62&logo=rust "View on Crates.io"
//! [libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.5-orange.svg?style=for-the-badge "View on lib.rs"
//! [docs-badge]: https://img.shields.io/badge/docs.rs-libyml-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs "View Documentation"
//! [github-badge]: https://img.shields.io/badge/github-sebastienrousseau/libyml-8da0cb?style=for-the-badge&labelColor=555555&logo=github "View on GitHub"
//! [made-with-rust]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust'
//!
#![no_std]
#![doc(
html_favicon_url = "https://kura.pro/libyml/images/favicon.ico",
html_logo_url = "https://kura.pro/libyml/images/logos/libyml.svg",
html_root_url = "https://docs.rs/libyml"
)]
#![crate_name = "libyml"]
#![crate_type = "lib"]
extern crate alloc;
use core::mem::size_of;
/// Declarations for C library functions used within the LibYML library.
///
/// This module contains the necessary types and constants required for
/// interfacing with C libraries, particularly in the context of memory management
/// and low-level operations within LibYML.
pub mod libc {
pub use core::ffi::c_void;
pub use core::primitive::{
i32 as c_int, i64 as c_long, i8 as c_char, u32 as c_uint,
u64 as c_ulong, u8 as c_uchar,
};
}
/// Extern functions and macros for interacting with the underlying libyaml C library.
///
/// This module includes low-level functions for memory allocation, comparison, and
/// movement that bridge Rust and C. It also contains some internal macros for
/// asserting conditions in a way that integrates with the C code.
#[macro_use]
pub mod externs {
use crate::libc;
use crate::ops::{die, ForceAdd as _, ForceInto as _};
use alloc::alloc::{self as rust, Layout};
use core::mem::MaybeUninit;
use core::mem::{align_of, size_of};
use core::ptr;
use core::slice;
const HEADER: usize = {
let need_len = size_of::();
(need_len + MALLOC_ALIGN - 1) & !(MALLOC_ALIGN - 1)
};
const MALLOC_ALIGN: usize = {
let int_align = align_of::();
let ptr_align = align_of::();
if int_align >= ptr_align {
int_align
} else {
ptr_align
}
};
/// Allocates memory.
///
/// # Safety
///
/// This function is unsafe because it directly manipulates raw memory. The caller must ensure that
/// the allocated memory is properly managed and freed when no longer needed.
pub unsafe fn malloc(size: libc::c_ulong) -> *mut libc::c_void {
let size = HEADER.force_add(size.force_into());
let layout = Layout::from_size_align(size, MALLOC_ALIGN)
.ok()
.unwrap_or_else(die);
let memory = rust::alloc(layout);
if memory.is_null() {
return die();
}
memory.cast::().write(size);
memory.add(HEADER).cast()
}
/// Reallocates memory.
///
/// # Safety
///
/// This function is unsafe because it directly manipulates raw memory.
/// The caller must ensure that the original memory was allocated by `malloc`.
pub(crate) unsafe fn realloc(
ptr: *mut libc::c_void,
new_size: libc::c_ulong,
) -> *mut libc::c_void {
let mut memory = ptr.cast::().sub(HEADER);
let size = memory.cast::().read();
let layout =
Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
let new_size = HEADER.force_add(new_size.force_into());
memory = rust::realloc(memory, layout, new_size);
if memory.is_null() {
return die();
}
memory.cast::().write(new_size);
memory.add(HEADER).cast()
}
/// Frees allocated memory.
///
/// # Safety
///
/// This function is unsafe because it deallocates memory pointed to by `ptr`.
/// The caller must ensure that `ptr` was previously allocated by `malloc` or `realloc`.
pub unsafe fn free(ptr: *mut libc::c_void) {
let memory = ptr.cast::().sub(HEADER);
let size = memory.cast::().read();
let layout =
Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
rust::dealloc(memory, layout);
}
/// Compares two memory blocks.
///
/// # Safety
///
/// This function is unsafe because it compares raw memory. The caller must ensure the pointers
/// and size are correct.
pub(crate) unsafe fn memcmp(
lhs: *const libc::c_void,
rhs: *const libc::c_void,
count: libc::c_ulong,
) -> libc::c_int {
let lhs =
slice::from_raw_parts(lhs.cast::(), count as usize);
let rhs =
slice::from_raw_parts(rhs.cast::(), count as usize);
lhs.cmp(rhs) as libc::c_int
}
/// Copies memory from `src` to `dest`.
///
/// # Safety
///
/// The caller must ensure that the memory areas do not overlap and that the destination is large
/// enough to hold the data.
pub(crate) unsafe fn memcpy(
dest: *mut libc::c_void,
src: *const libc::c_void,
count: libc::c_ulong,
) -> *mut libc::c_void {
if dest.is_null() || src.is_null() {
return die();
}
ptr::copy_nonoverlapping(
src.cast::>(),
dest.cast::>(),
count as usize,
);
dest
}
/// Moves memory from `src` to `dest`.
///
/// # Safety
///
/// The caller must ensure that the memory areas do not overlap or are correctly managed.
pub unsafe fn memmove(
dest: *mut libc::c_void,
src: *const libc::c_void,
count: libc::c_ulong,
) -> *mut libc::c_void {
if dest.is_null() || src.is_null() {
return die();
}
ptr::copy(
src.cast::>(),
dest.cast::>(),
count as usize,
);
dest
}
/// Fills memory with a constant byte.
///
/// # Safety
///
/// The caller must ensure the memory is valid and the length is correct.
pub unsafe fn memset(
dest: *mut libc::c_void,
ch: libc::c_int,
count: libc::c_ulong,
) -> *mut libc::c_void {
ptr::write_bytes(dest.cast::(), ch as u8, count as usize);
dest
}
/// Compares two strings.
///
/// # Safety
///
/// The caller must ensure the strings are null-terminated and valid.
pub(crate) unsafe fn strcmp(
lhs: *const libc::c_char,
rhs: *const libc::c_char,
) -> libc::c_int {
if lhs.is_null() || rhs.is_null() {
return die();
}
let lhs = slice::from_raw_parts(
lhs.cast::(),
strlen(lhs) as usize,
);
let rhs = slice::from_raw_parts(
rhs.cast::(),
strlen(rhs) as usize,
);
lhs.cmp(rhs) as libc::c_int
}
/// Returns the length of a string.
///
/// # Safety
///
/// The caller must ensure the string is null-terminated and valid.
pub(crate) unsafe fn strlen(
str: *const libc::c_char,
) -> libc::c_ulong {
let mut end = str;
while *end != 0 {
end = end.add(1);
}
end.offset_from(str) as libc::c_ulong
}
/// Compares up to `count` characters of two strings.
///
/// # Safety
///
/// The caller must ensure the strings are null-terminated and valid.
pub(crate) unsafe fn strncmp(
lhs: *const libc::c_char,
rhs: *const libc::c_char,
mut count: libc::c_ulong,
) -> libc::c_int {
if lhs.is_null() || rhs.is_null() {
return die();
}
let mut lhs = lhs.cast::();
let mut rhs = rhs.cast::();
while count > 0 && *lhs != 0 && *lhs == *rhs {
lhs = lhs.add(1);
rhs = rhs.add(1);
count -= 1;
}
if count == 0 {
0
} else {
(*lhs).cmp(&*rhs) as libc::c_int
}
}
/// Macro for asserting conditions.
///
/// This macro is used internally to assert conditions and handle failures.
macro_rules! __assert {
(false $(,)?) => {
$crate::externs::__assert_fail(
stringify!(false),
file!(),
line!(),
)
};
($assertion:expr $(,)?) => {
if !$assertion {
$crate::externs::__assert_fail(
stringify!($assertion),
file!(),
line!(),
);
}
};
}
/// Internal function for handling assertion failures.
///
/// # Safety
///
/// This function is called when an assertion fails, and it triggers a panic.
pub(crate) unsafe fn __assert_fail(
__assertion: &'static str,
__file: &'static str,
__line: u32,
) -> ! {
struct Abort;
impl Drop for Abort {
fn drop(&mut self) {
panic!("arithmetic overflow");
}
}
let _abort_on_panic = Abort;
panic!(
"{}:{}: Assertion `{}` failed.",
__file, __line, __assertion
);
}
}
/// Module for formatting utilities.
///
/// This module provides utilities for formatting data,
/// particularly for writing formatted strings to pointers.
mod fmt {
use crate::yaml::yaml_char_t;
use core::fmt::{self, Write};
use core::ptr;
/// Struct for writing formatted data to a pointer.
pub(crate) struct WriteToPtr {
ptr: *mut yaml_char_t,
}
impl WriteToPtr {
/// Creates a new `WriteToPtr`.
///
/// # Safety
///
/// This function is unsafe because it directly manipulates raw pointers.
pub(crate) unsafe fn new(ptr: *mut yaml_char_t) -> Self {
WriteToPtr { ptr }
}
/// Writes formatted data to the pointer.
pub(crate) fn write_fmt(&mut self, args: fmt::Arguments<'_>) {
let _ = Write::write_fmt(self, args);
}
}
impl Write for WriteToPtr {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe {
ptr::copy_nonoverlapping(s.as_ptr(), self.ptr, s.len());
self.ptr = self.ptr.add(s.len());
}
Ok(())
}
}
}
/// Trait extension for pointers.
///
/// This trait provides methods for working with pointers,
/// particularly for calculating the offset between two pointers.
trait PointerExt: Sized {
fn c_offset_from(self, origin: Self) -> isize;
}
impl PointerExt for *const T {
fn c_offset_from(self, origin: *const T) -> isize {
(self as isize - origin as isize) / size_of::() as isize
}
}
impl PointerExt for *mut T {
fn c_offset_from(self, origin: *mut T) -> isize {
(self as isize - origin as isize) / size_of::() as isize
}
}
/// Macros module for LibYML.
///
/// This module contains various macros used throughout the LibYML library.
#[macro_use]
pub mod macros;
/// Utility functions for LibYML.
///
/// This module contains utility functions and macros that are used throughout the LibYML library.
#[macro_use]
pub mod utils;
/// API module for LibYML.
///
/// This module provides the public API functions for working with YAML data.
pub mod api;
/// String utilities for LibYML.
///
/// This module provides utilities for working with YAML strings.
pub mod string;
/// Dumper module for LibYML.
///
/// This module contains functions related to dumping YAML data.
pub mod dumper;
/// Emitter module for LibYML.
///
/// This module provides functions for emitting YAML data.
mod emitter;
/// Loader module for LibYML.
///
/// This module contains functions for loading YAML data.
pub mod loader;
/// Decode module for LibYML.
///
/// This module contains functions for decoding YAML data.
pub mod decode;
/// Document module for LibYML.
///
/// This module provides functions for working with YAML documents.
pub mod document;
/// Internal utilities for LibYML.
///
/// This module contains internal utility functions and structures for the library.
pub mod internal;
/// Memory management for LibYML.
///
/// This module provides functions for managing memory within the library.
pub mod memory;
mod ops;
mod parser;
mod reader;
mod scanner;
/// Success and Failure types for LibYML.
///
/// This module provides types for representing the success and failure of various operations within the library.
pub mod success;
mod writer;
/// YAML API module for LibYML.
///
/// This module provides functions and types for working directly with YAML data structures.
pub mod yaml;
pub use crate::api::{
yaml_alias_event_initialize, yaml_emitter_delete,
yaml_emitter_initialize, yaml_emitter_set_break,
yaml_emitter_set_canonical, yaml_emitter_set_encoding,
yaml_emitter_set_indent, yaml_emitter_set_output,
yaml_emitter_set_output_string, yaml_emitter_set_unicode,
yaml_emitter_set_width, yaml_event_delete,
yaml_mapping_end_event_initialize,
yaml_mapping_start_event_initialize, yaml_parser_set_encoding,
yaml_parser_set_input, yaml_parser_set_input_string,
yaml_scalar_event_initialize, yaml_sequence_end_event_initialize,
yaml_sequence_start_event_initialize,
yaml_stream_end_event_initialize,
yaml_stream_start_event_initialize, yaml_token_delete,
};
pub use crate::decode::{yaml_parser_delete, yaml_parser_initialize};
pub use crate::document::{
yaml_document_delete, yaml_document_get_node,
yaml_document_get_root_node, yaml_document_initialize,
};
pub use crate::dumper::{
yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open,
};
pub use crate::emitter::yaml_emitter_emit;
pub use crate::loader::yaml_parser_load;
pub use crate::parser::yaml_parser_parse;
pub use crate::scanner::yaml_parser_scan;
pub use crate::writer::yaml_emitter_flush;
pub use crate::yaml::{
YamlAliasDataT, YamlBreakT, YamlDocumentT, YamlEmitterStateT,
YamlEmitterT, YamlEncodingT, YamlErrorTypeT, YamlEventT,
YamlEventTypeT, YamlMappingStyleT, YamlMarkT, YamlNodeItemT,
YamlNodePairT, YamlNodeT, YamlNodeTypeT, YamlParserStateT,
YamlParserT, YamlReadHandlerT, YamlScalarStyleT,
YamlSequenceStyleT, YamlSimpleKeyT, YamlStackT, YamlTagDirectiveT,
YamlTokenT, YamlTokenTypeT, YamlVersionDirectiveT,
YamlWriteHandlerT,
};
#[doc(hidden)]
pub use crate::yaml::{
YamlBreakT::*, YamlEmitterStateT::*, YamlEncodingT::*,
YamlErrorTypeT::*, YamlEventTypeT::*, YamlMappingStyleT::*,
YamlNodeTypeT::*, YamlParserStateT::*, YamlScalarStyleT::*,
YamlSequenceStyleT::*, YamlTokenTypeT::*,
};
libyml-0.0.5/src/loader.rs 0000644 0000000 0000000 00000054166 10461020230 0013535 0 ustar 0000000 0000000 use crate::externs::{memset, strcmp};
use crate::internal::yaml_stack_extend;
use crate::memory::{yaml_free, yaml_malloc, yaml_strdup};
use crate::success::{Success, FAIL, OK};
use crate::yaml::yaml_char_t;
use crate::{
libc, yaml_document_delete, yaml_parser_parse, PointerExt,
YamlAliasDataT, YamlAliasEvent, YamlComposerError,
YamlDocumentEndEvent, YamlDocumentStartEvent, YamlDocumentT,
YamlEventT, YamlMappingEndEvent, YamlMappingNode,
YamlMappingStartEvent, YamlMarkT, YamlMemoryError, YamlNodeItemT,
YamlNodePairT, YamlNodeT, YamlParserT, YamlScalarEvent,
YamlScalarNode, YamlSequenceEndEvent, YamlSequenceNode,
YamlSequenceStartEvent, YamlStreamEndEvent, YamlStreamStartEvent,
};
use core::mem::{size_of, MaybeUninit};
use core::ptr::{self, addr_of_mut};
#[repr(C)]
struct LoaderCtx {
start: *mut libc::c_int,
end: *mut libc::c_int,
top: *mut libc::c_int,
}
/// Parse the input stream and produce the next YAML document.
///
/// Call this function subsequently to produce a sequence of documents
/// constituting the input stream.
///
/// If the produced document has no root node, it means that the document end
/// has been reached.
///
/// An application is responsible for freeing any data associated with the
/// produced document object using the yaml_document_delete() function.
///
/// An application must not alternate the calls of yaml_parser_load() with the
/// calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break
/// the parser.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - `document` must be a valid, non-null pointer to a `YamlDocumentT` struct that can be safely written to.
/// - The `YamlParserT` and `YamlDocumentT` structs must be properly aligned and have the expected memory layout.
/// - The caller must call `yaml_document_delete` to free any data associated with the produced document object.
/// - The caller must not alternate calls to `yaml_parser_load` with calls to `yaml_parser_scan` or `yaml_parser_parse` on the same `YamlParserT` instance.
pub unsafe fn yaml_parser_load(
parser: *mut YamlParserT,
document: *mut YamlDocumentT,
) -> Success {
let current_block: u64;
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
__assert!(!parser.is_null());
__assert!(!document.is_null());
let _ = memset(
document as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
STACK_INIT!((*document).nodes, YamlNodeT);
if !(*parser).stream_start_produced {
if yaml_parser_parse(parser, event).fail {
current_block = 6234624449317607669;
} else {
__assert!((*event).type_ == YamlStreamStartEvent);
current_block = 7815301370352969686;
}
} else {
current_block = 7815301370352969686;
}
if current_block != 6234624449317607669 {
if (*parser).stream_end_produced {
return OK;
}
if yaml_parser_parse(parser, event).ok {
if (*event).type_ == YamlStreamEndEvent {
return OK;
}
STACK_INIT!((*parser).aliases, YamlAliasDataT);
let fresh6 = addr_of_mut!((*parser).document);
*fresh6 = document;
if yaml_parser_load_document(parser, event).ok {
yaml_parser_delete_aliases(parser);
let fresh7 = addr_of_mut!((*parser).document);
*fresh7 = ptr::null_mut::();
return OK;
}
}
}
yaml_parser_delete_aliases(parser);
yaml_document_delete(document);
let fresh8 = addr_of_mut!((*parser).document);
*fresh8 = ptr::null_mut::();
FAIL
}
/// Sets the error type to `YamlComposerError` and stores the problem and its mark.
///
/// # Parameters
///
/// * `parser`: A mutable pointer to the `YamlParserT` struct.
/// * `problem`: A pointer to a constant C string representing the problem.
/// * `problem_mark`: A `YamlMarkT` struct representing the mark where the problem occurred.
///
/// # Return
///
/// Returns `FAIL` to indicate an error.
///
/// # Safety
///
/// - `parser` must be a valid, non-null pointer to a properly initialized `YamlParserT` struct.
/// - `problem` must be a valid, non-null pointer to a constant C string.
/// - `problem_mark` must be a valid `YamlMarkT` struct.
/// - The `YamlParserT` struct must be properly aligned and have the expected memory layout.
/// - The `problem` string must be null-terminated.
/// - The `problem_mark` struct must be properly initialized.
/// - The caller must handle the error and clean up any resources.
///
pub unsafe fn yaml_parser_set_composer_error(
parser: *mut YamlParserT,
problem: *const libc::c_char,
problem_mark: YamlMarkT,
) -> Success {
(*parser).error = YamlComposerError;
let fresh9 = addr_of_mut!((*parser).problem);
*fresh9 = problem;
(*parser).problem_mark = problem_mark;
FAIL
}
unsafe fn yaml_parser_set_composer_error_context(
parser: *mut YamlParserT,
context: *const libc::c_char,
context_mark: YamlMarkT,
problem: *const libc::c_char,
problem_mark: YamlMarkT,
) -> Success {
(*parser).error = YamlComposerError;
let fresh10 = addr_of_mut!((*parser).context);
*fresh10 = context;
(*parser).context_mark = context_mark;
let fresh11 = addr_of_mut!((*parser).problem);
*fresh11 = problem;
(*parser).problem_mark = problem_mark;
FAIL
}
unsafe fn yaml_parser_delete_aliases(parser: *mut YamlParserT) {
while !STACK_EMPTY!((*parser).aliases) {
yaml_free(POP!((*parser).aliases).anchor as *mut libc::c_void);
}
STACK_DEL!((*parser).aliases);
}
unsafe fn yaml_parser_load_document(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let mut ctx = LoaderCtx {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
__assert!((*event).type_ == YamlDocumentStartEvent);
let fresh16 = addr_of_mut!((*(*parser).document).version_directive);
*fresh16 = (*event).data.document_start.version_directive;
let fresh17 =
addr_of_mut!((*(*parser).document).tag_directives.start);
*fresh17 = (*event).data.document_start.tag_directives.start;
let fresh18 =
addr_of_mut!((*(*parser).document).tag_directives.end);
*fresh18 = (*event).data.document_start.tag_directives.end;
(*(*parser).document).start_implicit =
(*event).data.document_start.implicit;
(*(*parser).document).start_mark = (*event).start_mark;
STACK_INIT!(ctx, libc::c_int);
if yaml_parser_load_nodes(parser, addr_of_mut!(ctx)).fail {
STACK_DEL!(ctx);
return FAIL;
}
STACK_DEL!(ctx);
OK
}
unsafe fn yaml_parser_load_nodes(
parser: *mut YamlParserT,
ctx: *mut LoaderCtx,
) -> Success {
let mut event = MaybeUninit::::uninit();
let event = event.as_mut_ptr();
loop {
if yaml_parser_parse(parser, event).fail {
return FAIL;
}
match (*event).type_ {
YamlAliasEvent => {
if yaml_parser_load_alias(parser, event, ctx).fail {
return FAIL;
}
}
YamlScalarEvent => {
if yaml_parser_load_scalar(parser, event, ctx).fail {
return FAIL;
}
}
YamlSequenceStartEvent => {
if yaml_parser_load_sequence(parser, event, ctx).fail {
return FAIL;
}
}
YamlSequenceEndEvent => {
if yaml_parser_load_sequence_end(parser, event, ctx)
.fail
{
return FAIL;
}
}
YamlMappingStartEvent => {
if yaml_parser_load_mapping(parser, event, ctx).fail {
return FAIL;
}
}
YamlMappingEndEvent => {
if yaml_parser_load_mapping_end(parser, event, ctx).fail
{
return FAIL;
}
}
YamlDocumentEndEvent => {}
_ => {
__assert!(false);
}
}
if (*event).type_ == YamlDocumentEndEvent {
break;
}
}
(*(*parser).document).end_implicit =
(*event).data.document_end.implicit;
(*(*parser).document).end_mark = (*event).end_mark;
OK
}
unsafe fn yaml_parser_register_anchor(
parser: *mut YamlParserT,
index: libc::c_int,
anchor: *mut yaml_char_t,
) -> Success {
let mut data = MaybeUninit::::uninit();
let data = data.as_mut_ptr();
let mut alias_data: *mut YamlAliasDataT;
if anchor.is_null() {
return OK;
}
(*data).anchor = anchor;
(*data).index = index;
(*data).mark = (*(*(*parser).document)
.nodes
.start
.wrapping_offset((index - 1) as isize))
.start_mark;
alias_data = (*parser).aliases.start;
while alias_data != (*parser).aliases.top {
if strcmp(
(*alias_data).anchor as *mut libc::c_char,
anchor as *mut libc::c_char,
) == 0
{
yaml_free(anchor as *mut libc::c_void);
return yaml_parser_set_composer_error_context(
parser,
b"found duplicate anchor; first occurrence\0"
as *const u8 as *const libc::c_char,
(*alias_data).mark,
b"second occurrence\0" as *const u8
as *const libc::c_char,
(*data).mark,
);
}
alias_data = alias_data.wrapping_offset(1);
}
PUSH!((*parser).aliases, *data);
OK
}
unsafe fn yaml_parser_load_node_add(
parser: *mut YamlParserT,
ctx: *mut LoaderCtx,
index: libc::c_int,
) -> Success {
if STACK_EMPTY!(*ctx) {
return OK;
}
let parent_index: libc::c_int =
*(*ctx).top.wrapping_offset(-1_isize);
let parent: *mut YamlNodeT =
addr_of_mut!(*((*(*parser).document).nodes.start)
.wrapping_offset((parent_index - 1) as isize));
let current_block_17: u64;
match (*parent).type_ {
YamlSequenceNode => {
if STACK_LIMIT!(parser, (*parent).data.sequence.items).fail
{
return FAIL;
}
PUSH!((*parent).data.sequence.items, index);
}
YamlMappingNode => {
let mut pair = MaybeUninit::::uninit();
let pair = pair.as_mut_ptr();
if !STACK_EMPTY!((*parent).data.mapping.pairs) {
let p: *mut YamlNodePairT = (*parent)
.data
.mapping
.pairs
.top
.wrapping_offset(-1_isize);
if (*p).key != 0 && (*p).value == 0 {
(*p).value = index;
current_block_17 = 11307063007268554308;
} else {
current_block_17 = 17407779659766490442;
}
} else {
current_block_17 = 17407779659766490442;
}
match current_block_17 {
11307063007268554308 => {}
_ => {
(*pair).key = index;
(*pair).value = 0;
if STACK_LIMIT!(
parser,
(*parent).data.mapping.pairs
)
.fail
{
return FAIL;
}
PUSH!((*parent).data.mapping.pairs, *pair);
}
}
}
_ => {
__assert!(false);
}
}
OK
}
unsafe fn yaml_parser_load_alias(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
let anchor: *mut yaml_char_t = (*event).data.alias.anchor;
let mut alias_data: *mut YamlAliasDataT;
alias_data = (*parser).aliases.start;
while alias_data != (*parser).aliases.top {
if strcmp(
(*alias_data).anchor as *mut libc::c_char,
anchor as *mut libc::c_char,
) == 0
{
yaml_free(anchor as *mut libc::c_void);
return yaml_parser_load_node_add(
parser,
ctx,
(*alias_data).index,
);
}
alias_data = alias_data.wrapping_offset(1);
}
yaml_free(anchor as *mut libc::c_void);
yaml_parser_set_composer_error(
parser,
b"found undefined alias\0" as *const u8 as *const libc::c_char,
(*event).start_mark,
)
}
unsafe fn yaml_parser_load_scalar(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
let current_block: u64;
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
let index: libc::c_int;
let mut tag: *mut yaml_char_t = (*event).data.scalar.tag;
if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
if tag.is_null()
|| strcmp(
tag as *mut libc::c_char,
b"!\0" as *const u8 as *const libc::c_char,
) == 0
{
yaml_free(tag as *mut libc::c_void);
tag = yaml_strdup(
b"tag:yaml.org,2002:str\0" as *const u8
as *const libc::c_char
as *mut yaml_char_t,
);
if tag.is_null() {
current_block = 10579931339944277179;
} else {
current_block = 11006700562992250127;
}
} else {
current_block = 11006700562992250127;
}
if current_block != 10579931339944277179 {
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlScalarNode;
(*node).tag = tag;
(*node).start_mark = (*event).start_mark;
(*node).end_mark = (*event).end_mark;
(*node).data.scalar.value = (*event).data.scalar.value;
(*node).data.scalar.length = (*event).data.scalar.length;
(*node).data.scalar.style = (*event).data.scalar.style;
PUSH!((*(*parser).document).nodes, *node);
index = (*(*parser).document)
.nodes
.top
.c_offset_from((*(*parser).document).nodes.start)
as libc::c_int;
if yaml_parser_register_anchor(
parser,
index,
(*event).data.scalar.anchor,
)
.fail
{
return FAIL;
}
return yaml_parser_load_node_add(parser, ctx, index);
}
}
yaml_free(tag as *mut libc::c_void);
yaml_free((*event).data.scalar.anchor as *mut libc::c_void);
yaml_free((*event).data.scalar.value as *mut libc::c_void);
FAIL
}
unsafe fn yaml_parser_load_sequence(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
let current_block: u64;
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
struct Items {
start: *mut YamlNodeItemT,
end: *mut YamlNodeItemT,
top: *mut YamlNodeItemT,
}
let mut items = Items {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let index: libc::c_int;
let mut tag: *mut yaml_char_t = (*event).data.sequence_start.tag;
if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
if tag.is_null()
|| strcmp(
tag as *mut libc::c_char,
b"!\0" as *const u8 as *const libc::c_char,
) == 0
{
yaml_free(tag as *mut libc::c_void);
tag = yaml_strdup(
b"tag:yaml.org,2002:seq\0" as *const u8
as *const libc::c_char
as *mut yaml_char_t,
);
if tag.is_null() {
current_block = 13474536459355229096;
} else {
current_block = 6937071982253665452;
}
} else {
current_block = 6937071982253665452;
}
if current_block != 13474536459355229096 {
STACK_INIT!(items, YamlNodeItemT);
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlSequenceNode;
(*node).tag = tag;
(*node).start_mark = (*event).start_mark;
(*node).end_mark = (*event).end_mark;
(*node).data.sequence.items.start = items.start;
(*node).data.sequence.items.end = items.end;
(*node).data.sequence.items.top = items.start;
(*node).data.sequence.style =
(*event).data.sequence_start.style;
PUSH!((*(*parser).document).nodes, *node);
index = (*(*parser).document)
.nodes
.top
.c_offset_from((*(*parser).document).nodes.start)
as libc::c_int;
if yaml_parser_register_anchor(
parser,
index,
(*event).data.sequence_start.anchor,
)
.fail
{
return FAIL;
}
if yaml_parser_load_node_add(parser, ctx, index).fail {
return FAIL;
}
if STACK_LIMIT!(parser, *ctx).fail {
return FAIL;
}
PUSH!(*ctx, index);
return OK;
}
}
yaml_free(tag as *mut libc::c_void);
yaml_free((*event).data.sequence_start.anchor as *mut libc::c_void);
FAIL
}
unsafe fn yaml_parser_load_sequence_end(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
__assert!(
((*ctx).top).c_offset_from((*ctx).start) as libc::c_long
> 0_i64
);
let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
__assert!(
(*((*(*parser).document).nodes.start)
.wrapping_offset((index - 1) as isize))
.type_
== YamlSequenceNode
);
(*(*(*parser).document)
.nodes
.start
.wrapping_offset((index - 1) as isize))
.end_mark = (*event).end_mark;
let _ = POP!(*ctx);
OK
}
unsafe fn yaml_parser_load_mapping(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
let current_block: u64;
let mut node = MaybeUninit::::uninit();
let node = node.as_mut_ptr();
struct Pairs {
start: *mut YamlNodePairT,
end: *mut YamlNodePairT,
top: *mut YamlNodePairT,
}
let mut pairs = Pairs {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let index: libc::c_int;
let mut tag: *mut yaml_char_t = (*event).data.mapping_start.tag;
if STACK_LIMIT!(parser, (*(*parser).document).nodes).ok {
if tag.is_null()
|| strcmp(
tag as *mut libc::c_char,
b"!\0" as *const u8 as *const libc::c_char,
) == 0
{
yaml_free(tag as *mut libc::c_void);
tag = yaml_strdup(
b"tag:yaml.org,2002:map\0" as *const u8
as *const libc::c_char
as *mut yaml_char_t,
);
if tag.is_null() {
current_block = 13635467803606088781;
} else {
current_block = 6937071982253665452;
}
} else {
current_block = 6937071982253665452;
}
if current_block != 13635467803606088781 {
STACK_INIT!(pairs, YamlNodePairT);
let _ = memset(
node as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*node).type_ = YamlMappingNode;
(*node).tag = tag;
(*node).start_mark = (*event).start_mark;
(*node).end_mark = (*event).end_mark;
(*node).data.mapping.pairs.start = pairs.start;
(*node).data.mapping.pairs.end = pairs.end;
(*node).data.mapping.pairs.top = pairs.start;
(*node).data.mapping.style =
(*event).data.mapping_start.style;
PUSH!((*(*parser).document).nodes, *node);
index = (*(*parser).document)
.nodes
.top
.c_offset_from((*(*parser).document).nodes.start)
as libc::c_int;
if yaml_parser_register_anchor(
parser,
index,
(*event).data.mapping_start.anchor,
)
.fail
{
return FAIL;
}
if yaml_parser_load_node_add(parser, ctx, index).fail {
return FAIL;
}
if STACK_LIMIT!(parser, *ctx).fail {
return FAIL;
}
PUSH!(*ctx, index);
return OK;
}
}
yaml_free(tag as *mut libc::c_void);
yaml_free((*event).data.mapping_start.anchor as *mut libc::c_void);
FAIL
}
unsafe fn yaml_parser_load_mapping_end(
parser: *mut YamlParserT,
event: *mut YamlEventT,
ctx: *mut LoaderCtx,
) -> Success {
__assert!(
((*ctx).top).c_offset_from((*ctx).start) as libc::c_long
> 0_i64
);
let index: libc::c_int = *(*ctx).top.wrapping_offset(-1_isize);
__assert!(
(*((*(*parser).document).nodes.start)
.wrapping_offset((index - 1) as isize))
.type_
== YamlMappingNode
);
(*(*(*parser).document)
.nodes
.start
.wrapping_offset((index - 1) as isize))
.end_mark = (*event).end_mark;
let _ = POP!(*ctx);
OK
}
libyml-0.0.5/src/macros.rs 0000644 0000000 0000000 00000113616 10461020230 0013547 0 ustar 0000000 0000000 // ------------------------------------
// Buffer Management Macros
// ------------------------------------
/// Initializes a buffer with a given size.
///
/// # Parameters
///
/// * `buffer`: A mutable reference to a `YamlBufferT` struct that needs to be initialized.
/// * `size`: The size of the buffer in bytes.
///
/// # Return
///
/// This macro does not return a value. It initializes the provided buffer with the given size.
///
/// # Safety
///
/// This macro assumes that the `yaml_malloc` function is correctly implemented and handles memory allocation.
#[macro_export]
macro_rules! BUFFER_INIT {
($buffer:expr, $size:expr) => {{
let start = addr_of_mut!($buffer.start);
*start = yaml_malloc($size as size_t) as *mut yaml_char_t;
let pointer = addr_of_mut!($buffer.pointer);
*pointer = $buffer.start;
let last = addr_of_mut!($buffer.last);
*last = *pointer;
let end = addr_of_mut!($buffer.end);
*end = $buffer.start.wrapping_add($size);
}};
}
/// Deletes the buffer and frees the allocated memory.
///
/// # Parameters
///
/// * `buffer`: A mutable reference to the buffer to be deleted.
///
/// # Return
///
/// This function does not return a value.
#[macro_export]
macro_rules! BUFFER_DEL {
($buffer:expr) => {{
// Free the allocated memory
yaml_free($buffer.start as *mut libc::c_void);
// Set all pointers to null after freeing the memory
$buffer.start = ptr::null_mut::();
$buffer.pointer = ptr::null_mut::();
$buffer.last = ptr::null_mut::();
$buffer.end = ptr::null_mut::();
}};
}
// ------------------------------------
// String Management Macros
// ------------------------------------
/// Assigns a new value to a `YamlStringT` struct.
///
/// This macro creates a new `YamlStringT` instance with the given start and end pointers.
/// The end pointer is calculated by offsetting the start pointer by the given length.
/// The pointer is set to the start pointer.
///
/// # Parameters
///
/// * `string`: A pointer to the start of the string.
/// * `length`: The length of the string.
///
/// # Return
///
/// A new `YamlStringT` instance with the given start, end, and pointer values.
#[macro_export]
macro_rules! STRING_ASSIGN {
($string:expr, $length:expr) => {
YamlStringT {
start: $string,
end: $string.wrapping_offset($length as isize),
pointer: $string,
}
};
}
/// Initializes a string for use with the yaml library.
///
/// This macro allocates memory for a string, initializes the start, pointer, and end pointers,
/// and sets the memory to all zeros.
///
/// # Parameters
///
/// * `$string`: A mutable reference to a `YamlStringT` struct, representing the string to be initialized.
///
/// # Return
///
/// This macro does not return a value.
#[macro_export]
macro_rules! STRING_INIT {
($string:expr) => {{
$string.start = yaml_malloc(16) as *mut yaml_char_t;
$string.pointer = $string.start;
$string.end = $string.start.wrapping_add(16);
let _ = memset($string.start as *mut libc::c_void, 0, 16);
}};
}
/// Deletes a string and frees the allocated memory.
///
/// # Parameters
///
/// * `string`: A mutable reference to a `YamlStringT` struct representing the string to be deleted.
///
/// # Return
///
/// This function does not return a value.
///
/// # Safety
///
/// This function assumes that the `string` parameter is a valid pointer to a `YamlStringT` struct.
/// It calls the `yaml_free` function to free the allocated memory for the string.
#[macro_export]
macro_rules! STRING_DEL {
($string:expr) => {{
yaml_free($string.start as *mut libc::c_void);
$string.end = ptr::null_mut::();
$string.pointer = $string.end;
$string.start = $string.pointer;
}};
}
/// Extends the capacity of a string by reallocating memory if the current capacity is insufficient.
///
/// # Parameters
///
/// * `string`: A mutable reference to a `YamlStringT` struct representing the string.
///
/// # Return
///
/// This macro does not return a value. It extends the capacity of the string by reallocating memory if necessary.
#[macro_export]
macro_rules! STRING_EXTEND {
($string:expr) => {
if $string.pointer.wrapping_add(5) >= $string.end {
yaml_string_extend(
addr_of_mut!($string.start),
addr_of_mut!($string.pointer),
addr_of_mut!($string.end),
);
}
};
}
/// Clears the content of the string by setting the pointer to the start and filling the memory
/// from the start to the end with zeros.
///
/// # Parameters
///
/// * `string`: A mutable reference to a struct containing the start, pointer, and end pointers representing the string.
///
/// # Return
///
/// This macro does not return a value. It modifies the content of the string in place.
#[macro_export]
macro_rules! CLEAR {
($string:expr) => {{
$string.pointer = $string.start;
let _ = memset(
$string.start as *mut libc::c_void,
0,
$string.end.offset_from($string.start) as libc::c_ulong,
);
}};
}
/// Joins two strings together by appending the contents of `string_b` to `string_a`.
///
/// # Parameters
///
/// * `string_a`: A mutable reference to the first string. Its contents will be modified.
/// * `string_b`: A mutable reference to the second string. Its contents will not be modified.
///
/// # Return
///
/// This macro does not return a value. It modifies the contents of `string_a` in-place.
#[macro_export]
macro_rules! JOIN {
($string_a:expr, $string_b:expr) => {{
// Check the length to ensure we don't overflow
let a_len = $string_a.pointer.offset_from($string_a.start) as usize;
let b_len = $string_b.pointer.offset_from($string_b.start) as usize;
// If the combined length would exceed available space, reallocate
if a_len.checked_add(b_len).is_some() && $string_a.pointer.add(b_len) <= $string_a.end {
yaml_string_join(
addr_of_mut!($string_a.start),
addr_of_mut!($string_a.pointer),
addr_of_mut!($string_a.end),
addr_of_mut!($string_b.start),
addr_of_mut!($string_b.pointer),
addr_of_mut!($string_b.end),
);
$string_b.pointer = $string_b.start;
} else {
panic!("String join would overflow memory bounds");
}
}};
}
/// This macro checks if the octet at the specified offset in the given string matches the provided octet.
///
/// # Parameters
///
/// * `string`: A reference to the string where the octet will be checked.
/// * `octet`: The octet to be checked.
/// * `offset`: The offset from the start of the string where the octet will be checked.
///
/// # Return
///
/// * `bool`: Returns `true` if the octet at the specified offset matches the provided octet, otherwise returns `false`.
#[macro_export]
macro_rules! CHECK_AT {
($string:expr, $octet:expr, $offset:expr) => {
*$string.pointer.offset($offset) == $octet
};
}
/// A macro that checks if the current byte in the given string matches a specific octet.
///
/// # Parameters
///
/// * `string`: A reference to the string to be checked.
/// * `octet`: The octet to be matched.
///
/// # Return
///
/// * `bool`: Returns `true` if the current byte in the string matches the given octet, otherwise `false`.
#[macro_export]
macro_rules! CHECK {
($string:expr, $octet:expr) => {
*$string.pointer == $octet
};
}
/// Checks if the current character in the string is an alphabetic character.
///
/// # Parameters
///
/// * `string`: A mutable reference to a struct containing a pointer to a byte array.
///
/// # Return
///
/// Returns `true` if the current character is an alphabetic character (A-Z, a-z, 0-9, '_', '-'),
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_ALPHA {
($string:expr) => {
*$string.pointer >= b'0' && *$string.pointer <= b'9'
|| *$string.pointer >= b'A' && *$string.pointer <= b'Z'
|| *$string.pointer >= b'a' && *$string.pointer <= b'z'
|| *$string.pointer == b'_'
|| *$string.pointer == b'-'
};
}
/// Checks if the byte pointed to by the `pointer` in the given string is a digit (0-9).
///
/// # Parameters
///
/// * `string`: A reference to a struct containing a `pointer` field pointing to a byte in a string.
///
/// # Return value
///
/// Returns `true` if the byte pointed to by the `pointer` is a digit (0-9), and `false` otherwise.
#[macro_export]
macro_rules! IS_DIGIT {
($string:expr) => {
*$string.pointer >= b'0' && *$string.pointer <= b'9'
};
}
/// Converts the byte at the current pointer in the string to its corresponding integer value.
///
/// # Parameters
///
/// * `string`: A mutable reference to a struct containing a pointer to a byte array.
///
/// # Return
///
/// * Returns the integer value of the byte at the current pointer in the string.
/// The byte is assumed to be in the ASCII range (0-9), so the function subtracts the ASCII value of '0' (48)
/// to convert it to its integer representation.
#[macro_export]
macro_rules! AS_DIGIT {
($string:expr) => {
(*$string.pointer - b'0') as libc::c_int
};
}
/// Checks if the character at the given offset in the string is a hexadecimal digit.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
/// * `offset`: The offset in the string to check.
///
/// # Return
///
/// Returns `true` if the character at the given offset is a hexadecimal digit (0-9, A-F, a-f),
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_HEX_AT {
($string:expr, $offset:expr) => {
*$string.pointer.wrapping_offset($offset) >= b'0'
&& *$string.pointer.wrapping_offset($offset) <= b'9'
|| *$string.pointer.wrapping_offset($offset) >= b'A'
&& *$string.pointer.wrapping_offset($offset) <= b'F'
|| *$string.pointer.wrapping_offset($offset) >= b'a'
&& *$string.pointer.wrapping_offset($offset) <= b'f'
};
}
/// Converts a hexadecimal character at a given offset in a string to its corresponding integer value.
///
/// # Parameters
///
/// * `string`: A reference to a string containing hexadecimal characters.
/// * `offset`: The offset in the string where the hexadecimal character is located.
///
/// # Return
///
/// An integer representing the hexadecimal value of the character at the given offset.
///
/// # Note
///
/// This macro assumes that the input string contains valid hexadecimal characters.
#[macro_export]
macro_rules! AS_HEX_AT {
($string:expr, $offset:expr) => {
if *$string.pointer.wrapping_offset($offset) >= b'A'
&& *$string.pointer.wrapping_offset($offset) <= b'F'
{
*$string.pointer.wrapping_offset($offset) - b'A' + 10
} else if *$string.pointer.wrapping_offset($offset) >= b'a'
&& *$string.pointer.wrapping_offset($offset) <= b'f'
{
*$string.pointer.wrapping_offset($offset) - b'a' + 10
} else {
*$string.pointer.wrapping_offset($offset) - b'0'
} as libc::c_int
};
}
/// Checks if the current character in the string is an ASCII character.
///
/// # Parameters
///
/// * `string`: A reference to a struct containing a pointer to the current character in the string.
///
/// # Return
///
/// Returns `true` if the current character is an ASCII character (i.e., its value is less than or equal to 0x7F),
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_ASCII {
($string:expr) => {
*$string.pointer <= b'\x7F'
};
}
/// Checks if the character at the current pointer in the given string is printable.
///
/// # Parameters
///
/// * `string`: A reference to a struct containing a pointer to the current character in the string.
///
/// # Return
///
/// * `bool`: Returns `true` if the character is printable, and `false` otherwise.
///
/// # Details
///
/// This macro checks if the character at the current pointer in the given string is printable.
/// It considers various Unicode ranges and special characters to determine printability.
///
/// The macro uses pattern matching to check the byte value of the character and its position in the string.
/// It checks for ASCII printable characters, Unicode printable characters in specific ranges,
/// and special characters that are considered printable.
///
/// The macro returns `true` if the character is printable, and `false` otherwise.
#[macro_export]
macro_rules! IS_PRINTABLE {
($string:expr) => {
match *$string.pointer {
// ASCII
0x0A | 0x20..=0x7E => true,
// U+A0 ... U+BF
0xC2 => match *$string.pointer.wrapping_offset(1) {
0xA0..=0xBF => true,
_ => false,
},
// U+C0 ... U+CFFF
0xC3..=0xEC => true,
// U+D000 ... U+D7FF
0xED => match *$string.pointer.wrapping_offset(1) {
0x00..=0x9F => true,
_ => false,
},
// U+E000 ... U+EFFF
0xEE => true,
// U+F000 ... U+FFFD
0xEF => match *$string.pointer.wrapping_offset(1) {
0xBB => match *$string.pointer.wrapping_offset(2) {
// except U+FEFF
0xBF => false,
_ => true,
},
0xBF => match *$string.pointer.wrapping_offset(2) {
0xBE | 0xBF => false,
_ => true,
},
_ => true,
},
// U+10000 ... U+10FFFF
0xF0..=0xF4 => true,
_ => false,
}
};
}
/// Checks if the character at the specified offset in the given string is a null character (ASCII 0).
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// Returns `true` if the character at the specified offset is a null character, and `false` otherwise.
#[macro_export]
macro_rules! IS_Z_AT {
($string:expr, $offset:expr) => {
CHECK_AT!($string, b'\0', $offset)
};
}
/// Checks if the character at the current pointer in the given string is a null character (ASCII 0).
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character is a null character, and `false` otherwise.
#[macro_export]
macro_rules! IS_Z {
($string:expr) => {
IS_Z_AT!($string, 0)
};
}
/// Checks if the first three bytes of the given string form the UTF-8 byte order mark (BOM) for UTF-8 encoding.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the first three bytes of the string form the UTF-8 BOM, and `false` otherwise.
#[macro_export]
macro_rules! IS_BOM {
($string:expr) => {
CHECK_AT!($string, b'\xEF', 0)
&& CHECK_AT!($string, b'\xBB', 1)
&& CHECK_AT!($string, b'\xBF', 2)
};
}
/// Checks if the character at the specified offset in the given string is a space character (ASCII 0x20).
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character at the specified offset is a space character, and `false` otherwise.
#[macro_export]
macro_rules! IS_SPACE_AT {
($string:expr, $offset:expr) => {
CHECK_AT!($string, b' ', $offset)
};
}
/// Checks if the character at the current pointer in the given string is a space character (ASCII 0x20).
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character is a space character, and `false` otherwise.
#[macro_export]
macro_rules! IS_SPACE {
($string:expr) => {
IS_SPACE_AT!($string, 0)
};
}
/// Checks if the character at the specified offset in the given string is a tab character (ASCII 0x09).
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character at the specified offset is a tab character, and `false` otherwise.
#[macro_export]
macro_rules! IS_TAB_AT {
($string:expr, $offset:expr) => {
CHECK_AT!($string, b'\t', $offset)
};
}
/// Checks if the character at the current pointer in the given string is a tab character (ASCII 0x09).
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character is a tab character, and `false` otherwise.
#[macro_export]
macro_rules! IS_TAB {
($string:expr) => {
IS_TAB_AT!($string, 0)
};
}
/// Checks if the character at the specified offset in the given string is a space or tab character.
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character at the specified offset is a space or tab character, and `false` otherwise.
#[macro_export]
macro_rules! IS_BLANK_AT {
($string:expr, $offset:expr) => {
IS_SPACE_AT!($string, $offset) || IS_TAB_AT!($string, $offset)
};
}
/// Checks if the character at the current pointer in the given string is a space or tab character.
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
///
/// # Return
///
/// * `bool`: Returns `true` if the character is a space or tab character, and `false` otherwise.
#[macro_export]
macro_rules! IS_BLANK {
($string:expr) => {
IS_BLANK_AT!($string, 0)
};
}
/// Checks if the character at the specified offset in the given string is a line break character.
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// Returns `true` if the character at the specified offset is a line break character (CR, LF, NEL, LS, PS),
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_BREAK_AT {
($string:expr, $offset:expr) => {
CHECK_AT!($string, b'\r', $offset)
|| CHECK_AT!($string, b'\n', $offset)
|| CHECK_AT!($string, b'\xC2', $offset)
&& CHECK_AT!(
$string,
b'\x85',
($offset + 1).try_into().unwrap()
)
|| CHECK_AT!($string, b'\xE2', $offset)
&& CHECK_AT!(
$string,
b'\x80',
($offset + 1).try_into().unwrap()
)
&& CHECK_AT!(
$string,
b'\xA8',
($offset + 2).try_into().unwrap()
)
|| CHECK_AT!($string, b'\xE2', $offset)
&& CHECK_AT!(
$string,
b'\x80',
($offset + 1).try_into().unwrap()
)
&& CHECK_AT!(
$string,
b'\xA9',
($offset + 2).try_into().unwrap()
)
};
}
/// Checks if the character at the current pointer in the given string is a line break character.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// Returns `true` if the character is a line break character (CR, LF, NEL, LS, PS), and `false` otherwise.
#[macro_export]
macro_rules! IS_BREAK {
($string:expr) => {
IS_BREAK_AT!($string, 0)
};
}
/// Checks if the character at the current pointer in the given string is a carriage return followed by a line feed.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// Returns `true` if the character at the current pointer is a carriage return followed by a line feed, and `false` otherwise.
#[macro_export]
macro_rules! IS_CRLF {
($string:expr) => {
CHECK_AT!($string, b'\r', 0) && CHECK_AT!($string, b'\n', 1)
};
}
/// Checks if the character at the specified offset in the given string is a line break character or a null character.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
/// * `offset`: The offset within the string to check.
///
/// # Return
///
/// Returns `true` if the character at the specified offset is a line break character or a null character, and `false` otherwise.
#[macro_export]
macro_rules! IS_BREAKZ_AT {
($string:expr, $offset:expr) => {
IS_BREAK_AT!($string, $offset) || IS_Z_AT!($string, $offset)
};
}
/// Checks if the character at the current pointer in the given string is a line break character or a null character.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// Returns `true` if the character is a line break character (CR, LF, NEL, LS, PS) or a null character, and `false` otherwise.
#[macro_export]
macro_rules! IS_BREAKZ {
($string:expr) => {
IS_BREAKZ_AT!($string, 0)
};
}
/// Checks if the character at the specified offset in the given string is a space, tab, or line break character,
/// or if it is a null character.
///
/// # Parameters
///
/// * `$string`: A reference to the string to check.
/// * `$offset`: The offset within the string to check.
///
/// # Return
///
/// Returns `true` if the character at the specified offset is a space, tab, line break character, or null character,
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_BLANKZ_AT {
($string:expr, $offset:expr) => {
IS_BLANK_AT!($string, $offset)
|| IS_BREAKZ_AT!($string, $offset)
};
}
/// Checks if the character at the current pointer in the given string is a space, tab, line break character,
/// or if it is a null character.
///
/// # Parameters
///
/// * `string`: A reference to the string to check.
///
/// # Return
///
/// Returns `true` if the character is a space, tab, line break character, or null character,
/// and `false` otherwise.
#[macro_export]
macro_rules! IS_BLANKZ {
($string:expr) => {
IS_BLANKZ_AT!($string, 0)
};
}
/// Returns the width of a Unicode character at the given offset in a string.
///
/// # Parameters
///
/// * `string`: A reference to the string containing the Unicode characters.
/// * `offset`: The offset in the string where the Unicode character is located.
///
/// # Return
///
/// The width of the Unicode character at the given offset. The width is determined by the first byte of the character:
/// - If the first byte is 0x00-0x7F, the width is 1.
/// - If the first byte is 0xC0-0xDF, the width is 2.
/// - If the first byte is 0xE0-0xEF, the width is 3.
/// - If the first byte is 0xF0-0xF7, the width is 4.
/// - If the first byte does not match any of the above patterns, the width is 0.
#[macro_export]
macro_rules! WIDTH_AT {
($string:expr, $offset:expr) => {
if *$string.pointer.wrapping_offset($offset) & 0x80 == 0x00 {
1
} else if *$string.pointer.wrapping_offset($offset) & 0xE0
== 0xC0
{
2
} else if *$string.pointer.wrapping_offset($offset) & 0xF0
== 0xE0
{
3
} else if *$string.pointer.wrapping_offset($offset) & 0xF8
== 0xF0
{
4
} else {
0
}
};
}
/// Returns the width of the Unicode character at the current position in a string.
///
/// This macro calculates the width of the Unicode character that the `pointer` in the given string is currently pointing to.
/// The width is determined by checking the first byte of the character at the current position in the string, using the
/// `WIDTH_AT!` macro with an offset of `0`.
///
/// # Parameters
///
/// * `string`: A reference to a struct containing a `pointer` field that points to a byte in a string.
/// This byte is expected to be the start of a Unicode character.
///
/// # Return
///
/// The width of the Unicode character at the current position of the `pointer` in the string:
///
/// - If the first byte is in the range `0x00` to `0x7F`, the width is 1 byte.
/// - If the first byte is in the range `0xC0` to `0xDF`, the width is 2 bytes.
/// - If the first byte is in the range `0xE0` to `0xEF`, the width is 3 bytes.
/// - If the first byte is in the range `0xF0` to `0xF7`, the width is 4 bytes.
/// - If the first byte does not match any of the above patterns, the width is 0, indicating an invalid or unsupported character.
///
/// # Safety
///
/// The caller must ensure that the `pointer` in the `string` is pointing to valid memory and that the memory contains a valid Unicode sequence.
/// Using this macro on an invalid or corrupted string may result in undefined behavior or incorrect results.
#[macro_export]
macro_rules! WIDTH {
($string:expr) => {
WIDTH_AT!($string, 0)
};
}
/// Moves the pointer of the given string to the next Unicode character.
///
/// This macro moves the pointer of the given string to the next Unicode character,
/// taking into account the width of the Unicode character. The width is determined
/// by the first byte of the character.
///
/// # Parameters
///
/// * `string`: A mutable reference to the string whose pointer will be moved.
///
/// # Return
///
/// This macro does not return a value. It moves the pointer of the given string
/// to the next Unicode character.
#[macro_export]
macro_rules! MOVE {
($string:expr) => {
$string.pointer =
$string.pointer.wrapping_offset(WIDTH!($string))
};
}
/// Copies the content of a string to another string.
///
/// This macro copies the content of a string to another string. It handles different Unicode character
/// encodings by checking the first byte of the character. If the character is a single-byte character, it
/// is copied directly. If the character is a multi-byte character, it is copied byte by byte.
///
/// # Parameters
///
/// * `string_a`: A mutable reference to the destination string where the content will be copied.
/// * `string_b`: A mutable reference to the source string from which the content will be copied.
///
/// # Return
///
/// This macro does not return a value. It copies the content of a string to another string.
#[macro_export]
macro_rules! copy {
($string_a:expr, $string_b:expr) => {
if *$string_b.pointer & 0x80 == 0x00 {
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
} else if *$string_b.pointer & 0xE0 == 0xC0 {
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
} else if *$string_b.pointer & 0xF0 == 0xE0 {
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
} else if *$string_b.pointer & 0xF8 == 0xF0 {
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
*$string_a.pointer = *$string_b.pointer;
$string_a.pointer = $string_a.pointer.wrapping_offset(1);
$string_b.pointer = $string_b.pointer.wrapping_offset(1);
}
};
}
// ------------------------------------
// Stack Management Macros
// ------------------------------------
/// Initializes a stack with a specified type and allocates memory for it.
///
/// # Parameters
///
/// * `stack`: A mutable reference to the stack to be initialized.
/// * `type`: The type of elements that will be stored in the stack.
///
/// # Return
///
/// This function does not return a value. It initializes the stack with the given type and allocates memory for it.
/// The memory is allocated using the `yaml_malloc` function, and the start, top, and end pointers of the stack are set accordingly.
#[macro_export]
macro_rules! STACK_INIT {
($stack:expr, $type:ty) => {{
$stack.start =
yaml_malloc(16 * size_of::<$type>() as libc::c_ulong)
as *mut $type;
$stack.top = $stack.start;
$stack.end = $stack.start.offset(16_isize);
}};
}
/// Deallocates the memory used by the stack and sets all pointers to null.
///
/// # Parameters
///
/// * `stack`: A mutable reference to the stack to be deallocated.
///
/// # Return
///
/// This function does not return a value. It deallocates the memory used by the stack and sets all pointers to null.
#[macro_export]
macro_rules! STACK_DEL {
($stack:expr) => {
yaml_free($stack.start as *mut libc::c_void);
$stack.end = ptr::null_mut();
$stack.top = ptr::null_mut();
$stack.start = ptr::null_mut();
};
}
/// Checks if the stack has no elements.
///
/// This macro checks if the stack has no elements by comparing the start and top pointers.
/// If the start and top pointers are equal, it means the stack is empty and the function returns `true`.
/// Otherwise, it means the stack has elements and the function returns `false`.
///
/// # Parameters
///
/// * `stack`: A mutable reference to the stack to be checked.
///
/// # Return
///
/// * `true` if the stack is empty, i.e., the start and top pointers are equal.
/// * `false` if the stack is not empty, i.e., the start and top pointers are not equal.
#[macro_export]
macro_rules! STACK_EMPTY {
($stack:expr) => {
$stack.start == $stack.top
};
}
/// Checks if the stack has enough memory to push a new element.
///
/// This macro checks if the stack has enough memory to push a new element by comparing the distance
/// between the top and start pointers with the maximum allowed distance. If the distance is less than
/// the maximum allowed distance minus one, it means the stack has enough memory and the function
/// returns `OK`. Otherwise, it sets the error field of the context to `YamlMemoryError` and returns
/// `FAIL`.
///
/// # Parameters
///
/// * `$context`: A mutable reference to the context in which the stack is being used.
/// * `$stack`: A mutable reference to the stack being checked.
///
/// # Return
///
/// * `OK` if the stack has enough memory to push a new element.
/// * `FAIL` if the stack does not have enough memory to push a new element.
#[macro_export]
macro_rules! STACK_LIMIT {
($context:expr, $stack:expr) => {
if $stack.top.c_offset_from($stack.start)
< libc::c_int::MAX as isize - 1
{
OK
} else {
(*$context).error = YamlMemoryError;
FAIL
}
};
}
/// Pushes a value onto the stack.
///
/// This macro pushes a value onto the stack. If the stack is full, it extends the stack by allocating
/// additional memory.
///
/// # Parameters
///
/// * `stack`: A mutable reference to the stack onto which the value will be pushed.
/// * `value`: The value to be pushed onto the stack.
///
/// # Return
///
/// This macro does not return a value. It pushes the value onto the stack.
#[macro_export]
macro_rules! PUSH {
(do $stack:expr, $push:expr) => {{
if $stack.top == $stack.end {
yaml_stack_extend(
addr_of_mut!($stack.start) as *mut *mut libc::c_void,
addr_of_mut!($stack.top) as *mut *mut libc::c_void,
addr_of_mut!($stack.end) as *mut *mut libc::c_void,
);
}
$push;
$stack.top = $stack.top.wrapping_offset(1);
}};
($stack:expr, *$value:expr) => {
PUSH!(do $stack, ptr::copy_nonoverlapping($value, $stack.top, 1))
};
($stack:expr, $value:expr) => {
PUSH!(do $stack, ptr::write($stack.top, $value))
};
}
/// Removes and returns the last element from the stack.
///
/// # Parameters
///
/// * `stack`: A mutable reference to the stack from which the last element will be removed.
///
/// # Return
///
/// * The last element from the stack.
#[macro_export]
macro_rules! POP {
($stack:expr) => {
*{
$stack.top = $stack.top.offset(-1);
$stack.top
}
};
}
// ------------------------------------
// Queue Management Macros
// ------------------------------------
/// Initializes a queue with a specified type and allocates memory for it.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue to be initialized.
/// * `type`: The type of elements that will be stored in the queue.
///
/// # Return
///
/// This function does not return a value. It initializes the queue with the given type and allocates memory for it.
#[macro_export]
macro_rules! QUEUE_INIT {
($queue:expr, $type:ty) => {{
$queue.start =
yaml_malloc(16 * size_of::<$type>() as libc::c_ulong)
as *mut $type;
$queue.tail = $queue.start;
$queue.head = $queue.tail;
$queue.end = $queue.start.offset(16_isize);
}};
}
/// Deallocates the memory used by the queue and sets all pointers to null.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue to be deallocated.
///
/// # Return
///
/// This function does not return a value.
#[macro_export]
macro_rules! QUEUE_DEL {
($queue:expr) => {
yaml_free($queue.start as *mut libc::c_void);
$queue.end = ptr::null_mut();
$queue.tail = ptr::null_mut();
$queue.head = ptr::null_mut();
$queue.start = ptr::null_mut();
};
}
/// Checks if the queue is empty.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue to be checked.
///
/// # Return
///
/// * `true` if the queue is empty, i.e., the head and tail pointers are equal.
/// * `false` if the queue is not empty, i.e., the head and tail pointers are not equal.
#[macro_export]
macro_rules! QUEUE_EMPTY {
($queue:expr) => {
$queue.head == $queue.tail
};
}
/// Enqueues a value onto the queue.
///
/// This macro enqueues a value onto the queue. If the queue is full, it extends the queue by allocating additional memory.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue onto which the value will be enqueued.
/// * `value`: The value to be enqueued onto the queue. This can be a reference or a direct value.
///
/// # Return
///
/// This macro does not return a value. It enqueues the value onto the queue.
#[macro_export]
macro_rules! ENQUEUE {
(do $queue:expr, $enqueue:expr) => {{
if $queue.tail == $queue.end {
yaml_queue_extend(
addr_of_mut!($queue.start) as *mut *mut libc::c_void,
addr_of_mut!($queue.head) as *mut *mut libc::c_void,
addr_of_mut!($queue.tail) as *mut *mut libc::c_void,
addr_of_mut!($queue.end) as *mut *mut libc::c_void,
);
}
$enqueue;
$queue.tail = $queue.tail.wrapping_offset(1);
}};
($queue:expr, *$value:expr) => {
ENQUEUE!(do $queue, ptr::copy_nonoverlapping($value, $queue.tail, 1))
};
($queue:expr, $value:expr) => {
ENQUEUE!(do $queue, ptr::write($queue.tail, $value))
};
}
/// Removes and returns the first element from the queue.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue from which the first element will be removed.
///
/// # Return
///
/// * The first element from the queue.
#[macro_export]
macro_rules! DEQUEUE {
($queue:expr) => {
*{
let head = $queue.head;
$queue.head = $queue.head.wrapping_offset(1);
head
}
};
}
/// Inserts a value into the queue at the specified index.
///
/// # Parameters
///
/// * `queue`: A mutable reference to the queue where the value will be inserted.
/// * `index`: The index at which the value will be inserted.
/// * `value`: The value to be inserted into the queue.
///
/// # Return
///
/// This macro does not return a value.
#[macro_export]
macro_rules! QUEUE_INSERT {
($queue:expr, $index:expr, $value:expr) => {{
if $queue.tail == $queue.end {
yaml_queue_extend(
addr_of_mut!($queue.start) as *mut *mut libc::c_void,
addr_of_mut!($queue.head) as *mut *mut libc::c_void,
addr_of_mut!($queue.tail) as *mut *mut libc::c_void,
addr_of_mut!($queue.end) as *mut *mut libc::c_void,
);
}
let _ = memmove(
$queue
.head
.wrapping_offset($index as isize)
.wrapping_offset(1_isize)
as *mut libc::c_void,
$queue.head.wrapping_offset($index as isize)
as *const libc::c_void,
($queue.tail.c_offset_from($queue.head) as libc::c_ulong)
.wrapping_sub($index)
.wrapping_mul(size_of::() as libc::c_ulong),
);
*$queue.head.wrapping_offset($index as isize) = $value;
let fresh14 = addr_of_mut!($queue.tail);
*fresh14 = (*fresh14).wrapping_offset(1);
}};
}
libyml-0.0.5/src/memory.rs 0000644 0000000 0000000 00000013361 10461020230 0013567 0 ustar 0000000 0000000 use crate::{
externs::{free, malloc, realloc, strlen},
libc,
yaml::{size_t, yaml_char_t},
};
use core::{mem::size_of, ptr};
use libc::c_void;
/// Allocate memory using the system's `malloc` function.
///
/// This function allocates `size` bytes of uninitialized memory and returns a pointer to it.
///
/// # Arguments
///
/// * `size` - The number of bytes to allocate.
///
/// # Returns
///
/// Returns a pointer to the allocated memory, or a null pointer if the allocation failed.
///
/// # Safety
///
/// This function is unsafe because:
/// - It directly calls the system's `malloc` function, which is not memory-safe.
/// - The caller must ensure that the allocated memory is properly freed using `yaml_free`.
/// - The caller is responsible for initializing the allocated memory before use.
///
/// # Examples
///
/// ```
/// use libyml::memory::yaml_malloc;
/// use libyml::yaml::size_t;
/// use libyml::memory::yaml_free;
///
/// unsafe {
/// let size: size_t = 1024;
/// let ptr = yaml_malloc(size);
/// if !ptr.is_null() {
/// // Use the allocated memory
/// // ...
/// yaml_free(ptr);
/// }
/// }
/// ```
pub unsafe fn yaml_malloc(size: size_t) -> *mut c_void {
malloc(size)
}
/// Reallocate memory using the system's `realloc` function.
///
/// This function changes the size of the memory block pointed to by `ptr` to `size` bytes.
///
/// # Arguments
///
/// * `ptr` - A pointer to the memory block to reallocate. If null, this function behaves like `yaml_malloc`.
/// * `size` - The new size of the memory block in bytes.
///
/// # Returns
///
/// Returns a pointer to the reallocated memory, which may be different from `ptr`, or a null pointer if the reallocation failed.
///
/// # Safety
///
/// This function is unsafe because:
/// - It directly calls the system's `realloc` function, which is not memory-safe.
/// - The caller must ensure that `ptr` is either null or was previously allocated by `yaml_malloc` or `yaml_realloc`.
/// - The caller must ensure that the reallocated memory is properly freed using `yaml_free`.
/// - The contents of the reallocated memory beyond the original size are undefined.
///
/// # Note
///
/// If the reallocation fails, the original memory block is left untouched and a null pointer is returned.
///
/// # Examples
///
/// ```
/// use libyml::memory::{yaml_malloc, yaml_realloc, yaml_free};
/// use libyml::yaml::size_t;
///
/// unsafe {
/// let mut size: size_t = 1024;
/// let mut ptr = yaml_malloc(size);
/// if !ptr.is_null() {
/// // Use the allocated memory
/// // ...
/// size = 2048;
/// ptr = yaml_realloc(ptr, size);
/// if !ptr.is_null() {
/// // Use the reallocated memory
/// // ...
/// yaml_free(ptr);
/// }
/// }
/// }
/// ```
pub unsafe fn yaml_realloc(
ptr: *mut c_void,
size: size_t,
) -> *mut c_void {
if !ptr.is_null() {
realloc(ptr, size)
} else {
malloc(size)
}
}
/// Free memory allocated by `yaml_malloc` or `yaml_realloc`.
///
/// This function deallocates the memory previously allocated by `yaml_malloc` or `yaml_realloc`.
///
/// # Arguments
///
/// * `ptr` - A pointer to the memory block to free. If null, no operation is performed.
///
/// # Safety
///
/// This function is unsafe because:
/// - It directly calls the system's `free` function, which is not memory-safe.
/// - The caller must ensure that `ptr` was allocated by `yaml_malloc` or `yaml_realloc`.
/// - After calling this function, `ptr` becomes invalid and must not be used.
///
/// # Examples
///
/// ```
/// use libyml::memory::{yaml_malloc, yaml_free};
/// use libyml::yaml::size_t;
///
/// unsafe {
/// let size: size_t = 1024;
/// let ptr = yaml_malloc(size);
/// if !ptr.is_null() {
/// // Use the allocated memory
/// // ...
/// yaml_free(ptr);
/// // ptr is now invalid and must not be used
/// }
/// }
/// ```
pub unsafe fn yaml_free(ptr: *mut c_void) {
if !ptr.is_null() {
free(ptr);
}
}
/// Duplicate a string using the system's `malloc` function and manual copy due to type mismatch.
///
/// This function creates a new copy of the input string, allocating new memory for it.
///
/// # Arguments
///
/// * `str` - A pointer to the null-terminated string to duplicate.
///
/// # Returns
///
/// Returns a pointer to the newly allocated string, or a null pointer if the allocation failed or the input was null.
///
/// # Safety
///
/// This function is unsafe because:
/// - It involves memory allocation and raw pointer manipulation.
/// - The caller must ensure that `str` is a valid, null-terminated string.
/// - The caller is responsible for freeing the returned pointer using `yaml_free`.
///
/// # Examples
///
/// ```
/// use libyml::memory::{yaml_strdup, yaml_free};
/// use libyml::yaml::yaml_char_t;
/// use core::ffi::c_void;
///
/// unsafe {
/// // Note: The cast to *const yaml_char_t is necessary because yaml_char_t
/// // might not be the same as u8 on all systems.
/// let original: *const yaml_char_t = b"Hello, world!\0".as_ptr() as *const yaml_char_t;
/// let copy = yaml_strdup(original);
/// if !copy.is_null() {
/// // Use the duplicated string
/// // ...
/// yaml_free(copy as *mut c_void);
/// }
/// }
/// ```
pub unsafe fn yaml_strdup(str: *const yaml_char_t) -> *mut yaml_char_t {
if str.is_null() {
return ptr::null_mut();
}
let len = strlen(str as *const libc::c_char) as usize;
let new_size = (len + 1) * size_of::();
let new_str =
malloc(new_size.try_into().unwrap()) as *mut yaml_char_t;
if new_str.is_null() {
return ptr::null_mut();
}
ptr::copy_nonoverlapping(str, new_str, len + 1);
new_str
}
libyml-0.0.5/src/ops.rs 0000644 0000000 0000000 00000005531 10461020230 0013060 0 ustar 0000000 0000000 pub(crate) trait ForceAdd: Sized {
fn force_add(self, rhs: Self) -> Self;
}
impl ForceAdd for u8 {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}
impl ForceAdd for i32 {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}
impl ForceAdd for u32 {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}
impl ForceAdd for u64 {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}
impl ForceAdd for usize {
fn force_add(self, rhs: Self) -> Self {
self.checked_add(rhs).unwrap_or_else(die)
}
}
pub(crate) trait ForceMul: Sized {
fn force_mul(self, rhs: Self) -> Self;
}
impl ForceMul for i32 {
fn force_mul(self, rhs: Self) -> Self {
self.checked_mul(rhs).unwrap_or_else(die)
}
}
impl ForceMul for i64 {
fn force_mul(self, rhs: Self) -> Self {
self.checked_mul(rhs).unwrap_or_else(die)
}
}
impl ForceMul for u64 {
fn force_mul(self, rhs: Self) -> Self {
self.checked_mul(rhs).unwrap_or_else(die)
}
}
pub(crate) trait ForceInto {
fn force_into(self) -> U
where
Self: TryInto;
}
impl ForceInto for T {
fn force_into(self) -> U
where
Self: TryInto,
{
>::try_into(self)
.ok()
.unwrap_or_else(die)
}
}
// Deterministically abort on arithmetic overflow, instead of wrapping and
// continuing with invalid behavior.
//
// This is impossible or nearly impossible to hit as the arithmetic computations
// in libyaml are all related to either:
//
// - small integer processing (ascii, hex digits)
// - allocation sizing
//
// and the only allocations in libyaml are for fixed-sized objects and
// geometrically growing buffers with a growth factor of 2. So in order for an
// allocation computation to overflow usize, the previous allocation for that
// container must have been filled to a size of usize::MAX/2, which is an
// allocation that would have failed in the allocator. But we check for this to
// be pedantic and to find out if it ever does happen.
//
// No-std abort is implemented using a double panic. On most platforms the
// current mechanism for this is for core::intrinsics::abort to invoke an
// invalid instruction. On Unix, the process will probably terminate with a
// signal like SIGABRT, SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise
// behaviour is not guaranteed and not stable, but is safe.
#[cold]
pub(crate) fn die() -> T {
struct PanicAgain;
impl Drop for PanicAgain {
fn drop(&mut self) {
panic!("arithmetic overflow");
}
}
fn do_die() -> ! {
let _panic_again = PanicAgain;
panic!("arithmetic overflow");
}
do_die();
}
libyml-0.0.5/src/parser.rs 0000644 0000000 0000000 00000161431 10461020230 0013555 0 ustar 0000000 0000000 use crate::externs::{memcpy, memset, strcmp, strlen};
use crate::internal::yaml_stack_extend;
use crate::memory::{yaml_free, yaml_malloc, yaml_strdup};
use crate::ops::ForceAdd as _;
use crate::scanner::yaml_parser_fetch_more_tokens;
use crate::success::{Success, FAIL, OK};
use crate::yaml::{size_t, yaml_char_t};
use crate::{
libc, YamlAliasEvent, YamlAliasToken, YamlAnchorToken,
YamlBlockEndToken, YamlBlockEntryToken, YamlBlockMappingStartToken,
YamlBlockMappingStyle, YamlBlockSequenceStartToken,
YamlBlockSequenceStyle, YamlDocumentEndEvent, YamlDocumentEndToken,
YamlDocumentStartEvent, YamlDocumentStartToken, YamlEventT,
YamlFlowEntryToken, YamlFlowMappingEndToken,
YamlFlowMappingStartToken, YamlFlowMappingStyle,
YamlFlowSequenceEndToken, YamlFlowSequenceStartToken,
YamlFlowSequenceStyle, YamlKeyToken, YamlMappingEndEvent,
YamlMappingStartEvent, YamlMarkT, YamlNoError,
YamlParseBlockMappingFirstKeyState, YamlParseBlockMappingKeyState,
YamlParseBlockMappingValueState,
YamlParseBlockNodeOrIndentlessSequenceState,
YamlParseBlockNodeState, YamlParseBlockSequenceEntryState,
YamlParseBlockSequenceFirstEntryState,
YamlParseDocumentContentState, YamlParseDocumentEndState,
YamlParseDocumentStartState, YamlParseEndState,
YamlParseFlowMappingEmptyValueState,
YamlParseFlowMappingFirstKeyState, YamlParseFlowMappingKeyState,
YamlParseFlowMappingValueState, YamlParseFlowNodeState,
YamlParseFlowSequenceEntryMappingEndState,
YamlParseFlowSequenceEntryMappingKeyState,
YamlParseFlowSequenceEntryMappingValueState,
YamlParseFlowSequenceEntryState,
YamlParseFlowSequenceFirstEntryState,
YamlParseImplicitDocumentStartState,
YamlParseIndentlessSequenceEntryState, YamlParseStreamStartState,
YamlParserError, YamlParserT, YamlPlainScalarStyle,
YamlScalarEvent, YamlScalarToken, YamlSequenceEndEvent,
YamlSequenceStartEvent, YamlStreamEndEvent, YamlStreamEndToken,
YamlStreamStartEvent, YamlStreamStartToken, YamlTagDirectiveT,
YamlTagDirectiveToken, YamlTagToken, YamlTokenT, YamlValueToken,
YamlVersionDirectiveT, YamlVersionDirectiveToken,
};
use core::mem::size_of;
use core::ptr::{self, addr_of_mut};
unsafe fn peek_token(parser: *mut YamlParserT) -> *mut YamlTokenT {
if (*parser).token_available
|| yaml_parser_fetch_more_tokens(parser).ok
{
(*parser).tokens.head
} else {
ptr::null_mut::()
}
}
unsafe fn skip_token(parser: *mut YamlParserT) {
(*parser).token_available = false;
let fresh3 = addr_of_mut!((*parser).tokens_parsed);
*fresh3 = (*fresh3).wrapping_add(1);
(*parser).stream_end_produced =
(*(*parser).tokens.head).type_ == YamlStreamEndToken;
let fresh4 = addr_of_mut!((*parser).tokens.head);
*fresh4 = (*fresh4).wrapping_offset(1);
}
/// Parse the input stream and produce the next parsing event.
///
/// This function should be called repeatedly to produce a sequence of events
/// corresponding to the input stream. The initial event will be of type
/// `YamlStreamStartEvent`, and the final event will be of type `YamlStreamEndEvent`.
///
/// # Safety
///
/// This function is unsafe because:
/// - It operates on raw pointers.
/// - It assumes certain memory layouts and alignments.
/// - It may cause undefined behavior if the input pointers are invalid or if the
/// function is misused.
///
/// # Arguments
///
/// * `parser` - A pointer to a properly initialized `YamlParserT` struct.
/// * `event` - A pointer to a `YamlEventT` struct that will be filled with the next event.
///
/// # Returns
///
/// Returns `OK` if an event was successfully parsed, or `FAIL` if:
/// - The stream has ended (stream_end_produced is true)
/// - There's an existing error in the parser
/// - The parser is in the end state
///
/// # Errors
///
/// This function will return `FAIL` if any of the above error conditions are met.
/// The caller should check the parser's error state for more details on the failure.
///
/// # Notes
///
/// - The caller is responsible for freeing any buffers associated with the produced
/// event using the `yaml_event_delete()` function.
/// - Do not alternate calls to `yaml_parser_parse()` with calls to `yaml_parser_scan()`
/// or `yaml_parser_load()`. Doing so will break the parser.
///
pub unsafe fn yaml_parser_parse(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
__assert!(!parser.is_null());
__assert!(!event.is_null());
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
if (*parser).stream_end_produced {
return FAIL;
}
if (*parser).error != YamlNoError {
return FAIL;
}
if (*parser).state == YamlParseEndState {
return FAIL;
}
yaml_parser_state_machine(parser, event)
}
unsafe fn yaml_parser_set_parser_error(
parser: *mut YamlParserT,
problem: *const libc::c_char,
problem_mark: YamlMarkT,
) {
(*parser).error = YamlParserError;
let fresh0 = addr_of_mut!((*parser).problem);
*fresh0 = problem;
(*parser).problem_mark = problem_mark;
}
unsafe fn yaml_parser_set_parser_error_context(
parser: *mut YamlParserT,
context: *const libc::c_char,
context_mark: YamlMarkT,
problem: *const libc::c_char,
problem_mark: YamlMarkT,
) {
(*parser).error = YamlParserError;
let fresh1 = addr_of_mut!((*parser).context);
*fresh1 = context;
(*parser).context_mark = context_mark;
let fresh2 = addr_of_mut!((*parser).problem);
*fresh2 = problem;
(*parser).problem_mark = problem_mark;
}
unsafe fn yaml_parser_state_machine(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
match (*parser).state {
YamlParseStreamStartState => {
yaml_parser_parse_stream_start(parser, event)
}
YamlParseImplicitDocumentStartState => {
yaml_parser_parse_document_start(parser, event, true)
}
YamlParseDocumentStartState => {
yaml_parser_parse_document_start(parser, event, false)
}
YamlParseDocumentContentState => {
yaml_parser_parse_document_content(parser, event)
}
YamlParseDocumentEndState => {
yaml_parser_parse_document_end(parser, event)
}
YamlParseBlockNodeState => {
yaml_parser_parse_node(parser, event, true, false)
}
YamlParseBlockNodeOrIndentlessSequenceState => {
yaml_parser_parse_node(parser, event, true, true)
}
YamlParseFlowNodeState => {
yaml_parser_parse_node(parser, event, false, false)
}
YamlParseBlockSequenceFirstEntryState => {
yaml_parser_parse_block_sequence_entry(parser, event, true)
}
YamlParseBlockSequenceEntryState => {
yaml_parser_parse_block_sequence_entry(parser, event, false)
}
YamlParseIndentlessSequenceEntryState => {
yaml_parser_parse_indentless_sequence_entry(parser, event)
}
YamlParseBlockMappingFirstKeyState => {
yaml_parser_parse_block_mapping_key(parser, event, true)
}
YamlParseBlockMappingKeyState => {
yaml_parser_parse_block_mapping_key(parser, event, false)
}
YamlParseBlockMappingValueState => {
yaml_parser_parse_block_mapping_value(parser, event)
}
YamlParseFlowSequenceFirstEntryState => {
yaml_parser_parse_flow_sequence_entry(parser, event, true)
}
YamlParseFlowSequenceEntryState => {
yaml_parser_parse_flow_sequence_entry(parser, event, false)
}
YamlParseFlowSequenceEntryMappingKeyState => {
yaml_parser_parse_flow_sequence_entry_mapping_key(
parser, event,
)
}
YamlParseFlowSequenceEntryMappingValueState => {
yaml_parser_parse_flow_sequence_entry_mapping_value(
parser, event,
)
}
YamlParseFlowSequenceEntryMappingEndState => {
yaml_parser_parse_flow_sequence_entry_mapping_end(
parser, event,
)
}
YamlParseFlowMappingFirstKeyState => {
yaml_parser_parse_flow_mapping_key(parser, event, true)
}
YamlParseFlowMappingKeyState => {
yaml_parser_parse_flow_mapping_key(parser, event, false)
}
YamlParseFlowMappingValueState => {
yaml_parser_parse_flow_mapping_value(parser, event, false)
}
YamlParseFlowMappingEmptyValueState => {
yaml_parser_parse_flow_mapping_value(parser, event, true)
}
_ => FAIL,
}
}
unsafe fn yaml_parser_parse_stream_start(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let token: *mut YamlTokenT = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlStreamStartToken {
yaml_parser_set_parser_error(
parser,
b"did not find expected \0" as *const u8
as *const libc::c_char,
(*token).start_mark,
);
return FAIL;
}
(*parser).state = YamlParseImplicitDocumentStartState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlStreamStartEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).start_mark;
(*event).data.stream_start.encoding =
(*token).data.stream_start.encoding;
skip_token(parser);
OK
}
unsafe fn yaml_parser_parse_document_start(
parser: *mut YamlParserT,
event: *mut YamlEventT,
implicit: bool,
) -> Success {
let mut token: *mut YamlTokenT;
let mut version_directive: *mut YamlVersionDirectiveT =
ptr::null_mut::();
struct TagDirectives {
start: *mut YamlTagDirectiveT,
end: *mut YamlTagDirectiveT,
}
let mut tag_directives = TagDirectives {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
};
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if !implicit {
while (*token).type_ == YamlDocumentEndToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
}
}
if implicit
&& (*token).type_ != YamlVersionDirectiveToken
&& (*token).type_ != YamlTagDirectiveToken
&& (*token).type_ != YamlDocumentStartToken
&& (*token).type_ != YamlStreamEndToken
{
if yaml_parser_process_directives(
parser,
ptr::null_mut::<*mut YamlVersionDirectiveT>(),
ptr::null_mut::<*mut YamlTagDirectiveT>(),
ptr::null_mut::<*mut YamlTagDirectiveT>(),
)
.fail
{
return FAIL;
}
PUSH!((*parser).states, YamlParseDocumentEndState);
(*parser).state = YamlParseBlockNodeState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentStartEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).start_mark;
let fresh9 = addr_of_mut!(
(*event).data.document_start.version_directive
);
*fresh9 = ptr::null_mut::();
let fresh10 = addr_of_mut!(
(*event).data.document_start.tag_directives.start
);
*fresh10 = ptr::null_mut::();
let fresh11 = addr_of_mut!(
(*event).data.document_start.tag_directives.end
);
*fresh11 = ptr::null_mut::();
(*event).data.document_start.implicit = true;
OK
} else if (*token).type_ != YamlStreamEndToken {
let end_mark: YamlMarkT;
let start_mark: YamlMarkT = (*token).start_mark;
if yaml_parser_process_directives(
parser,
addr_of_mut!(version_directive),
addr_of_mut!(tag_directives.start),
addr_of_mut!(tag_directives.end),
)
.fail
{
return FAIL;
}
token = peek_token(parser);
if !token.is_null() {
if (*token).type_ != YamlDocumentStartToken {
yaml_parser_set_parser_error(
parser,
b"did not find expected \0"
as *const u8
as *const libc::c_char,
(*token).start_mark,
);
} else {
PUSH!((*parser).states, YamlParseDocumentEndState);
(*parser).state = YamlParseDocumentContentState;
end_mark = (*token).end_mark;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh14 = addr_of_mut!(
(*event).data.document_start.version_directive
);
*fresh14 = version_directive;
let fresh15 = addr_of_mut!(
(*event).data.document_start.tag_directives.start
);
*fresh15 = tag_directives.start;
let fresh16 = addr_of_mut!(
(*event).data.document_start.tag_directives.end
);
*fresh16 = tag_directives.end;
(*event).data.document_start.implicit = false;
skip_token(parser);
tag_directives.end =
ptr::null_mut::();
tag_directives.start = tag_directives.end;
return OK;
}
}
yaml_free(version_directive as *mut libc::c_void);
while tag_directives.start != tag_directives.end {
yaml_free(
(*tag_directives.end.wrapping_offset(-1_isize)).handle
as *mut libc::c_void,
);
yaml_free(
(*tag_directives.end.wrapping_offset(-1_isize)).prefix
as *mut libc::c_void,
);
tag_directives.end = tag_directives.end.wrapping_offset(-1);
}
yaml_free(tag_directives.start as *mut libc::c_void);
FAIL
} else {
(*parser).state = YamlParseEndState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlStreamEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
skip_token(parser);
OK
}
}
unsafe fn yaml_parser_parse_document_content(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let token: *mut YamlTokenT = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlVersionDirectiveToken
|| (*token).type_ == YamlTagDirectiveToken
|| (*token).type_ == YamlDocumentStartToken
|| (*token).type_ == YamlDocumentEndToken
|| (*token).type_ == YamlStreamEndToken
{
(*parser).state = POP!((*parser).states);
yaml_parser_process_empty_scalar(event, (*token).start_mark)
} else {
yaml_parser_parse_node(parser, event, true, false)
}
}
unsafe fn yaml_parser_parse_document_end(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let mut end_mark: YamlMarkT;
let mut implicit = true;
let token: *mut YamlTokenT = peek_token(parser);
if token.is_null() {
return FAIL;
}
end_mark = (*token).start_mark;
let start_mark: YamlMarkT = end_mark;
if (*token).type_ == YamlDocumentEndToken {
end_mark = (*token).end_mark;
skip_token(parser);
implicit = false;
}
while !STACK_EMPTY!((*parser).tag_directives) {
let tag_directive = POP!((*parser).tag_directives);
yaml_free(tag_directive.handle as *mut libc::c_void);
yaml_free(tag_directive.prefix as *mut libc::c_void);
}
(*parser).state = YamlParseDocumentStartState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlDocumentEndEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
(*event).data.document_end.implicit = implicit;
OK
}
unsafe fn yaml_parser_parse_node(
parser: *mut YamlParserT,
event: *mut YamlEventT,
block: bool,
indentless_sequence: bool,
) -> Success {
let mut current_block: u64;
let mut token: *mut YamlTokenT;
let mut anchor: *mut yaml_char_t = ptr::null_mut::();
let mut tag_handle: *mut yaml_char_t =
ptr::null_mut::();
let mut tag_suffix: *mut yaml_char_t =
ptr::null_mut::();
let mut tag: *mut yaml_char_t = ptr::null_mut::();
let mut start_mark: YamlMarkT;
let mut end_mark: YamlMarkT;
let mut tag_mark = YamlMarkT {
index: 0,
line: 0,
column: 0,
};
let implicit;
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlAliasToken {
(*parser).state = POP!((*parser).states);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlAliasEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
let fresh26 = addr_of_mut!((*event).data.alias.anchor);
*fresh26 = (*token).data.alias.value;
skip_token(parser);
OK
} else {
end_mark = (*token).start_mark;
start_mark = end_mark;
if (*token).type_ == YamlAnchorToken {
anchor = (*token).data.anchor.value;
start_mark = (*token).start_mark;
end_mark = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
current_block = 17786380918591080555;
} else if (*token).type_ == YamlTagToken {
tag_handle = (*token).data.tag.handle;
tag_suffix = (*token).data.tag.suffix;
tag_mark = (*token).start_mark;
end_mark = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
current_block = 17786380918591080555;
} else {
current_block = 11743904203796629665;
}
} else {
current_block = 11743904203796629665;
}
} else if (*token).type_ == YamlTagToken {
tag_handle = (*token).data.tag.handle;
tag_suffix = (*token).data.tag.suffix;
tag_mark = (*token).start_mark;
start_mark = tag_mark;
end_mark = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
current_block = 17786380918591080555;
} else if (*token).type_ == YamlAnchorToken {
anchor = (*token).data.anchor.value;
end_mark = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
current_block = 17786380918591080555;
} else {
current_block = 11743904203796629665;
}
} else {
current_block = 11743904203796629665;
}
} else {
current_block = 11743904203796629665;
}
if current_block == 11743904203796629665 {
if !tag_handle.is_null() {
if *tag_handle == 0 {
tag = tag_suffix;
yaml_free(tag_handle as *mut libc::c_void);
tag_suffix = ptr::null_mut::();
tag_handle = tag_suffix;
current_block = 9437013279121998969;
} else {
let mut tag_directive: *mut YamlTagDirectiveT;
tag_directive = (*parser).tag_directives.start;
loop {
if tag_directive == (*parser).tag_directives.top
{
current_block = 17728966195399430138;
break;
}
if strcmp(
(*tag_directive).handle
as *mut libc::c_char,
tag_handle as *mut libc::c_char,
) == 0
{
let prefix_len: size_t = strlen(
(*tag_directive).prefix
as *mut libc::c_char,
);
let suffix_len: size_t =
strlen(tag_suffix as *mut libc::c_char);
tag = yaml_malloc(
prefix_len
.force_add(suffix_len)
.force_add(1_u64),
)
as *mut yaml_char_t;
let _ = memcpy(
tag as *mut libc::c_void,
(*tag_directive).prefix
as *const libc::c_void,
prefix_len,
);
let _ = memcpy(
tag.wrapping_offset(prefix_len as isize)
as *mut libc::c_void,
tag_suffix as *const libc::c_void,
suffix_len,
);
*tag.wrapping_offset(
prefix_len.force_add(suffix_len)
as isize,
) = b'\0';
yaml_free(tag_handle as *mut libc::c_void);
yaml_free(tag_suffix as *mut libc::c_void);
tag_suffix = ptr::null_mut::();
tag_handle = tag_suffix;
current_block = 17728966195399430138;
break;
} else {
tag_directive =
tag_directive.wrapping_offset(1);
}
}
if current_block != 17786380918591080555 {
if tag.is_null() {
yaml_parser_set_parser_error_context(
parser,
b"while parsing a node\0" as *const u8
as *const libc::c_char,
start_mark,
b"found undefined tag handle\0"
as *const u8
as *const libc::c_char,
tag_mark,
);
current_block = 17786380918591080555;
} else {
current_block = 9437013279121998969;
}
}
}
} else {
current_block = 9437013279121998969;
}
if current_block != 17786380918591080555 {
implicit = tag.is_null() || *tag == 0;
if indentless_sequence
&& (*token).type_ == YamlBlockEntryToken
{
end_mark = (*token).end_mark;
(*parser).state =
YamlParseIndentlessSequenceEntryState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh37 = addr_of_mut!(
(*event).data.sequence_start.anchor
);
*fresh37 = anchor;
let fresh38 =
addr_of_mut!((*event).data.sequence_start.tag);
*fresh38 = tag;
(*event).data.sequence_start.implicit = implicit;
(*event).data.sequence_start.style =
YamlBlockSequenceStyle;
return OK;
} else if (*token).type_ == YamlScalarToken {
let mut plain_implicit = false;
let mut quoted_implicit = false;
end_mark = (*token).end_mark;
if (*token).data.scalar.style
== YamlPlainScalarStyle
&& tag.is_null()
|| !tag.is_null()
&& strcmp(
tag as *mut libc::c_char,
b"!\0" as *const u8
as *const libc::c_char,
) == 0
{
plain_implicit = true;
} else if tag.is_null() {
quoted_implicit = true;
}
(*parser).state = POP!((*parser).states);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlScalarEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh40 =
addr_of_mut!((*event).data.scalar.anchor);
*fresh40 = anchor;
let fresh41 =
addr_of_mut!((*event).data.scalar.tag);
*fresh41 = tag;
let fresh42 =
addr_of_mut!((*event).data.scalar.value);
*fresh42 = (*token).data.scalar.value;
(*event).data.scalar.length =
(*token).data.scalar.length;
(*event).data.scalar.plain_implicit =
plain_implicit;
(*event).data.scalar.quoted_implicit =
quoted_implicit;
(*event).data.scalar.style =
(*token).data.scalar.style;
skip_token(parser);
return OK;
} else if (*token).type_ == YamlFlowSequenceStartToken {
end_mark = (*token).end_mark;
(*parser).state =
YamlParseFlowSequenceFirstEntryState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh45 = addr_of_mut!(
(*event).data.sequence_start.anchor
);
*fresh45 = anchor;
let fresh46 =
addr_of_mut!((*event).data.sequence_start.tag);
*fresh46 = tag;
(*event).data.sequence_start.implicit = implicit;
(*event).data.sequence_start.style =
YamlFlowSequenceStyle;
return OK;
} else if (*token).type_ == YamlFlowMappingStartToken {
end_mark = (*token).end_mark;
(*parser).state = YamlParseFlowMappingFirstKeyState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh47 = addr_of_mut!(
(*event).data.mapping_start.anchor
);
*fresh47 = anchor;
let fresh48 =
addr_of_mut!((*event).data.mapping_start.tag);
*fresh48 = tag;
(*event).data.mapping_start.implicit = implicit;
(*event).data.mapping_start.style =
YamlFlowMappingStyle;
return OK;
} else if block
&& (*token).type_ == YamlBlockSequenceStartToken
{
end_mark = (*token).end_mark;
(*parser).state =
YamlParseBlockSequenceFirstEntryState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh49 = addr_of_mut!(
(*event).data.sequence_start.anchor
);
*fresh49 = anchor;
let fresh50 =
addr_of_mut!((*event).data.sequence_start.tag);
*fresh50 = tag;
(*event).data.sequence_start.implicit = implicit;
(*event).data.sequence_start.style =
YamlBlockSequenceStyle;
return OK;
} else if block
&& (*token).type_ == YamlBlockMappingStartToken
{
end_mark = (*token).end_mark;
(*parser).state =
YamlParseBlockMappingFirstKeyState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingStartEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh51 = addr_of_mut!(
(*event).data.mapping_start.anchor
);
*fresh51 = anchor;
let fresh52 =
addr_of_mut!((*event).data.mapping_start.tag);
*fresh52 = tag;
(*event).data.mapping_start.implicit = implicit;
(*event).data.mapping_start.style =
YamlBlockMappingStyle;
return OK;
} else if !anchor.is_null() || !tag.is_null() {
let value: *mut yaml_char_t =
yaml_malloc(1_u64) as *mut yaml_char_t;
*value = b'\0';
(*parser).state = POP!((*parser).states);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlScalarEvent;
(*event).start_mark = start_mark;
(*event).end_mark = end_mark;
let fresh54 =
addr_of_mut!((*event).data.scalar.anchor);
*fresh54 = anchor;
let fresh55 =
addr_of_mut!((*event).data.scalar.tag);
*fresh55 = tag;
let fresh56 =
addr_of_mut!((*event).data.scalar.value);
*fresh56 = value;
(*event).data.scalar.length = 0_u64;
(*event).data.scalar.plain_implicit = implicit;
(*event).data.scalar.quoted_implicit = false;
(*event).data.scalar.style = YamlPlainScalarStyle;
return OK;
} else {
yaml_parser_set_parser_error_context(
parser,
if block {
b"while parsing a block node\0" as *const u8
as *const libc::c_char
} else {
b"while parsing a flow node\0" as *const u8
as *const libc::c_char
},
start_mark,
b"did not find expected node content\0"
as *const u8
as *const libc::c_char,
(*token).start_mark,
);
}
}
}
yaml_free(anchor as *mut libc::c_void);
yaml_free(tag_handle as *mut libc::c_void);
yaml_free(tag_suffix as *mut libc::c_void);
yaml_free(tag as *mut libc::c_void);
FAIL
}
}
unsafe fn yaml_parser_parse_block_sequence_entry(
parser: *mut YamlParserT,
event: *mut YamlEventT,
first: bool,
) -> Success {
let mut token: *mut YamlTokenT;
if first {
token = peek_token(parser);
PUSH!((*parser).marks, (*token).start_mark);
skip_token(parser);
}
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlBlockEntryToken {
let mark: YamlMarkT = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlBlockEntryToken
&& (*token).type_ != YamlBlockEndToken
{
PUSH!((*parser).states, YamlParseBlockSequenceEntryState);
yaml_parser_parse_node(parser, event, true, false)
} else {
(*parser).state = YamlParseBlockSequenceEntryState;
yaml_parser_process_empty_scalar(event, mark)
}
} else if (*token).type_ == YamlBlockEndToken {
(*parser).state = POP!((*parser).states);
let _ = POP!((*parser).marks);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
skip_token(parser);
OK
} else {
yaml_parser_set_parser_error_context(
parser,
b"while parsing a block collection\0" as *const u8
as *const libc::c_char,
POP!((*parser).marks),
b"did not find expected '-' indicator\0" as *const u8
as *const libc::c_char,
(*token).start_mark,
);
FAIL
}
}
unsafe fn yaml_parser_parse_indentless_sequence_entry(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let mut token: *mut YamlTokenT;
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlBlockEntryToken {
let mark: YamlMarkT = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlBlockEntryToken
&& (*token).type_ != YamlKeyToken
&& (*token).type_ != YamlValueToken
&& (*token).type_ != YamlBlockEndToken
{
PUSH!(
(*parser).states,
YamlParseIndentlessSequenceEntryState
);
yaml_parser_parse_node(parser, event, true, false)
} else {
(*parser).state = YamlParseIndentlessSequenceEntryState;
yaml_parser_process_empty_scalar(event, mark)
}
} else {
(*parser).state = POP!((*parser).states);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).start_mark;
OK
}
}
unsafe fn yaml_parser_parse_block_mapping_key(
parser: *mut YamlParserT,
event: *mut YamlEventT,
first: bool,
) -> Success {
let mut token: *mut YamlTokenT;
if first {
token = peek_token(parser);
PUSH!((*parser).marks, (*token).start_mark);
skip_token(parser);
}
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlKeyToken {
let mark: YamlMarkT = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlKeyToken
&& (*token).type_ != YamlValueToken
&& (*token).type_ != YamlBlockEndToken
{
PUSH!((*parser).states, YamlParseBlockMappingValueState);
yaml_parser_parse_node(parser, event, true, true)
} else {
(*parser).state = YamlParseBlockMappingValueState;
yaml_parser_process_empty_scalar(event, mark)
}
} else if (*token).type_ == YamlBlockEndToken {
(*parser).state = POP!((*parser).states);
let _ = POP!((*parser).marks);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
skip_token(parser);
OK
} else {
yaml_parser_set_parser_error_context(
parser,
b"while parsing a block mapping\0" as *const u8
as *const libc::c_char,
POP!((*parser).marks),
b"did not find expected key\0" as *const u8
as *const libc::c_char,
(*token).start_mark,
);
FAIL
}
}
unsafe fn yaml_parser_parse_block_mapping_value(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let mut token: *mut YamlTokenT;
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlValueToken {
let mark: YamlMarkT = (*token).end_mark;
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlKeyToken
&& (*token).type_ != YamlValueToken
&& (*token).type_ != YamlBlockEndToken
{
PUSH!((*parser).states, YamlParseBlockMappingKeyState);
yaml_parser_parse_node(parser, event, true, true)
} else {
(*parser).state = YamlParseBlockMappingKeyState;
yaml_parser_process_empty_scalar(event, mark)
}
} else {
(*parser).state = YamlParseBlockMappingKeyState;
yaml_parser_process_empty_scalar(event, (*token).start_mark)
}
}
unsafe fn yaml_parser_parse_flow_sequence_entry(
parser: *mut YamlParserT,
event: *mut YamlEventT,
first: bool,
) -> Success {
let mut token: *mut YamlTokenT;
if first {
token = peek_token(parser);
PUSH!((*parser).marks, (*token).start_mark);
skip_token(parser);
}
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlFlowSequenceEndToken {
if !first {
if (*token).type_ == YamlFlowEntryToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
} else {
yaml_parser_set_parser_error_context(
parser,
b"while parsing a flow sequence\0" as *const u8
as *const libc::c_char,
POP!((*parser).marks),
b"did not find expected ',' or ']'\0" as *const u8
as *const libc::c_char,
(*token).start_mark,
);
return FAIL;
}
}
if (*token).type_ == YamlKeyToken {
(*parser).state = YamlParseFlowSequenceEntryMappingKeyState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingStartEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
let fresh99 =
addr_of_mut!((*event).data.mapping_start.anchor);
*fresh99 = ptr::null_mut::();
let fresh100 =
addr_of_mut!((*event).data.mapping_start.tag);
*fresh100 = ptr::null_mut::();
(*event).data.mapping_start.implicit = true;
(*event).data.mapping_start.style = YamlFlowMappingStyle;
skip_token(parser);
return OK;
} else if (*token).type_ != YamlFlowSequenceEndToken {
PUSH!((*parser).states, YamlParseFlowSequenceEntryState);
return yaml_parser_parse_node(parser, event, false, false);
}
}
(*parser).state = POP!((*parser).states);
let _ = POP!((*parser).marks);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlSequenceEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
skip_token(parser);
OK
}
unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_key(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let token: *mut YamlTokenT = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlValueToken
&& (*token).type_ != YamlFlowEntryToken
&& (*token).type_ != YamlFlowSequenceEndToken
{
PUSH!(
(*parser).states,
YamlParseFlowSequenceEntryMappingValueState
);
yaml_parser_parse_node(parser, event, false, false)
} else {
let mark: YamlMarkT = (*token).end_mark;
skip_token(parser);
(*parser).state = YamlParseFlowSequenceEntryMappingValueState;
yaml_parser_process_empty_scalar(event, mark)
}
}
unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_value(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let mut token: *mut YamlTokenT;
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ == YamlValueToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlFlowEntryToken
&& (*token).type_ != YamlFlowSequenceEndToken
{
PUSH!(
(*parser).states,
YamlParseFlowSequenceEntryMappingEndState
);
return yaml_parser_parse_node(parser, event, false, false);
}
}
(*parser).state = YamlParseFlowSequenceEntryMappingEndState;
yaml_parser_process_empty_scalar(event, (*token).start_mark)
}
unsafe fn yaml_parser_parse_flow_sequence_entry_mapping_end(
parser: *mut YamlParserT,
event: *mut YamlEventT,
) -> Success {
let token: *mut YamlTokenT = peek_token(parser);
if token.is_null() {
return FAIL;
}
(*parser).state = YamlParseFlowSequenceEntryState;
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).start_mark;
OK
}
unsafe fn yaml_parser_parse_flow_mapping_key(
parser: *mut YamlParserT,
event: *mut YamlEventT,
first: bool,
) -> Success {
let mut token: *mut YamlTokenT;
if first {
token = peek_token(parser);
PUSH!((*parser).marks, (*token).start_mark);
skip_token(parser);
}
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlFlowMappingEndToken {
if !first {
if (*token).type_ == YamlFlowEntryToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
} else {
yaml_parser_set_parser_error_context(
parser,
b"while parsing a flow mapping\0" as *const u8
as *const libc::c_char,
POP!((*parser).marks),
b"did not find expected ',' or '}'\0" as *const u8
as *const libc::c_char,
(*token).start_mark,
);
return FAIL;
}
}
if (*token).type_ == YamlKeyToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlValueToken
&& (*token).type_ != YamlFlowEntryToken
&& (*token).type_ != YamlFlowMappingEndToken
{
PUSH!((*parser).states, YamlParseFlowMappingValueState);
return yaml_parser_parse_node(
parser, event, false, false,
);
} else {
(*parser).state = YamlParseFlowMappingValueState;
return yaml_parser_process_empty_scalar(
event,
(*token).start_mark,
);
}
} else if (*token).type_ != YamlFlowMappingEndToken {
PUSH!(
(*parser).states,
YamlParseFlowMappingEmptyValueState
);
return yaml_parser_parse_node(parser, event, false, false);
}
}
(*parser).state = POP!((*parser).states);
let _ = POP!((*parser).marks);
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlMappingEndEvent;
(*event).start_mark = (*token).start_mark;
(*event).end_mark = (*token).end_mark;
skip_token(parser);
OK
}
unsafe fn yaml_parser_parse_flow_mapping_value(
parser: *mut YamlParserT,
event: *mut YamlEventT,
empty: bool,
) -> Success {
let mut token: *mut YamlTokenT;
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if empty {
(*parser).state = YamlParseFlowMappingKeyState;
return yaml_parser_process_empty_scalar(
event,
(*token).start_mark,
);
}
if (*token).type_ == YamlValueToken {
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
return FAIL;
}
if (*token).type_ != YamlFlowEntryToken
&& (*token).type_ != YamlFlowMappingEndToken
{
PUSH!((*parser).states, YamlParseFlowMappingKeyState);
return yaml_parser_parse_node(parser, event, false, false);
}
}
(*parser).state = YamlParseFlowMappingKeyState;
yaml_parser_process_empty_scalar(event, (*token).start_mark)
}
unsafe fn yaml_parser_process_empty_scalar(
event: *mut YamlEventT,
mark: YamlMarkT,
) -> Success {
let value: *mut yaml_char_t =
yaml_malloc(1_u64) as *mut yaml_char_t;
*value = b'\0';
let _ = memset(
event as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*event).type_ = YamlScalarEvent;
(*event).start_mark = mark;
(*event).end_mark = mark;
let fresh138 = addr_of_mut!((*event).data.scalar.anchor);
*fresh138 = ptr::null_mut::();
let fresh139 = addr_of_mut!((*event).data.scalar.tag);
*fresh139 = ptr::null_mut::();
let fresh140 = addr_of_mut!((*event).data.scalar.value);
*fresh140 = value;
(*event).data.scalar.length = 0_u64;
(*event).data.scalar.plain_implicit = true;
(*event).data.scalar.quoted_implicit = false;
(*event).data.scalar.style = YamlPlainScalarStyle;
OK
}
unsafe fn yaml_parser_process_directives(
parser: *mut YamlParserT,
version_directive_ref: *mut *mut YamlVersionDirectiveT,
tag_directives_start_ref: *mut *mut YamlTagDirectiveT,
tag_directives_end_ref: *mut *mut YamlTagDirectiveT,
) -> Success {
let mut current_block: u64;
let mut default_tag_directives: [YamlTagDirectiveT; 3] = [
YamlTagDirectiveT {
handle: b"!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
prefix: b"!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
},
YamlTagDirectiveT {
handle: b"!!\0" as *const u8 as *const libc::c_char
as *mut yaml_char_t,
prefix: b"tag:yaml.org,2002:\0" as *const u8
as *const libc::c_char
as *mut yaml_char_t,
},
YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
},
];
let mut default_tag_directive: *mut YamlTagDirectiveT;
let mut version_directive: *mut YamlVersionDirectiveT =
ptr::null_mut::();
struct TagDirectives {
start: *mut YamlTagDirectiveT,
end: *mut YamlTagDirectiveT,
top: *mut YamlTagDirectiveT,
}
let mut tag_directives = TagDirectives {
start: ptr::null_mut::(),
end: ptr::null_mut::(),
top: ptr::null_mut::(),
};
let mut token: *mut YamlTokenT;
STACK_INIT!(tag_directives, YamlTagDirectiveT);
token = peek_token(parser);
if !token.is_null() {
loop {
if !((*token).type_ == YamlVersionDirectiveToken
|| (*token).type_ == YamlTagDirectiveToken)
{
current_block = 16924917904204750491;
break;
}
if (*token).type_ == YamlVersionDirectiveToken {
if !version_directive.is_null() {
yaml_parser_set_parser_error(
parser,
b"found duplicate %YAML directive\0"
as *const u8
as *const libc::c_char,
(*token).start_mark,
);
current_block = 17143798186130252483;
break;
} else if (*token).data.version_directive.major != 1
|| (*token).data.version_directive.minor != 1
&& (*token).data.version_directive.minor != 2
{
yaml_parser_set_parser_error(
parser,
b"found incompatible YAML document\0"
as *const u8
as *const libc::c_char,
(*token).start_mark,
);
current_block = 17143798186130252483;
break;
} else {
version_directive =
yaml_malloc(size_of::()
as libc::c_ulong)
as *mut YamlVersionDirectiveT;
(*version_directive).major =
(*token).data.version_directive.major;
(*version_directive).minor =
(*token).data.version_directive.minor;
}
} else if (*token).type_ == YamlTagDirectiveToken {
let value = YamlTagDirectiveT {
handle: (*token).data.tag_directive.handle,
prefix: (*token).data.tag_directive.prefix,
};
if yaml_parser_append_tag_directive(
parser,
value,
false,
(*token).start_mark,
)
.fail
{
current_block = 17143798186130252483;
break;
}
PUSH!(tag_directives, value);
}
skip_token(parser);
token = peek_token(parser);
if token.is_null() {
current_block = 17143798186130252483;
break;
}
}
if current_block != 17143798186130252483 {
default_tag_directive = default_tag_directives.as_mut_ptr();
loop {
if (*default_tag_directive).handle.is_null() {
current_block = 18377268871191777778;
break;
}
if yaml_parser_append_tag_directive(
parser,
*default_tag_directive,
true,
(*token).start_mark,
)
.fail
{
current_block = 17143798186130252483;
break;
}
default_tag_directive =
default_tag_directive.wrapping_offset(1);
}
if current_block != 17143798186130252483 {
if !version_directive_ref.is_null() {
*version_directive_ref = version_directive;
}
if !tag_directives_start_ref.is_null() {
if STACK_EMPTY!(tag_directives) {
*tag_directives_end_ref =
ptr::null_mut::();
*tag_directives_start_ref =
*tag_directives_end_ref;
STACK_DEL!(tag_directives);
} else {
*tag_directives_start_ref =
tag_directives.start;
*tag_directives_end_ref = tag_directives.top;
}
} else {
STACK_DEL!(tag_directives);
}
if version_directive_ref.is_null() {
yaml_free(version_directive as *mut libc::c_void);
}
return OK;
}
}
}
yaml_free(version_directive as *mut libc::c_void);
while !STACK_EMPTY!(tag_directives) {
let tag_directive = POP!(tag_directives);
yaml_free(tag_directive.handle as *mut libc::c_void);
yaml_free(tag_directive.prefix as *mut libc::c_void);
}
STACK_DEL!(tag_directives);
FAIL
}
unsafe fn yaml_parser_append_tag_directive(
parser: *mut YamlParserT,
value: YamlTagDirectiveT,
allow_duplicates: bool,
mark: YamlMarkT,
) -> Success {
let mut tag_directive: *mut YamlTagDirectiveT;
let mut copy = YamlTagDirectiveT {
handle: ptr::null_mut::(),
prefix: ptr::null_mut::(),
};
tag_directive = (*parser).tag_directives.start;
while tag_directive != (*parser).tag_directives.top {
if strcmp(
value.handle as *mut libc::c_char,
(*tag_directive).handle as *mut libc::c_char,
) == 0
{
if allow_duplicates {
return OK;
}
yaml_parser_set_parser_error(
parser,
b"found duplicate %TAG directive\0" as *const u8
as *const libc::c_char,
mark,
);
return FAIL;
}
tag_directive = tag_directive.wrapping_offset(1);
}
copy.handle = yaml_strdup(value.handle);
copy.prefix = yaml_strdup(value.prefix);
PUSH!((*parser).tag_directives, copy);
OK
}
libyml-0.0.5/src/reader.rs 0000644 0000000 0000000 00000050524 10461020230 0013523 0 ustar 0000000 0000000 use crate::externs::{memcmp, memmove};
use crate::ops::ForceAdd as _;
use crate::success::{Success, FAIL, OK};
use crate::yaml::{size_t, yaml_char_t};
use crate::{
libc, PointerExt, YamlAnyEncoding, YamlParserT, YamlReaderError,
YamlUtf16beEncoding, YamlUtf16leEncoding, YamlUtf8Encoding,
};
use core::ptr::addr_of_mut;
unsafe fn yaml_parser_set_reader_error(
parser: *mut YamlParserT,
problem: *const libc::c_char,
offset: size_t,
value: libc::c_int,
) -> Success {
(*parser).error = YamlReaderError;
let fresh0 = addr_of_mut!((*parser).problem);
*fresh0 = problem;
(*parser).problem_offset = offset;
(*parser).problem_value = value;
FAIL
}
const BOM_UTF8: *const libc::c_char =
b"\xEF\xBB\xBF\0" as *const u8 as *const libc::c_char;
const BOM_UTF16LE: *const libc::c_char =
b"\xFF\xFE\0" as *const u8 as *const libc::c_char;
const BOM_UTF16BE: *const libc::c_char =
b"\xFE\xFF\0" as *const u8 as *const libc::c_char;
unsafe fn yaml_parser_determine_encoding(
parser: *mut YamlParserT,
) -> Success {
while !(*parser).eof
&& ((*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as libc::c_long)
< 3_i64
{
if yaml_parser_update_raw_buffer(parser).fail {
return FAIL;
}
}
if (*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as libc::c_long
>= 2_i64
&& memcmp(
(*parser).raw_buffer.pointer as *const libc::c_void,
BOM_UTF16LE as *const libc::c_void,
2_u64,
) == 0
{
(*parser).encoding = YamlUtf16leEncoding;
let fresh1 = addr_of_mut!((*parser).raw_buffer.pointer);
*fresh1 = (*fresh1).wrapping_offset(2_isize);
let fresh2 = addr_of_mut!((*parser).offset);
*fresh2 = (*fresh2).force_add(3_u64);
} else if (*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as libc::c_long
>= 2_i64
&& memcmp(
(*parser).raw_buffer.pointer as *const libc::c_void,
BOM_UTF16BE as *const libc::c_void,
2_u64,
) == 0
{
(*parser).encoding = YamlUtf16beEncoding;
let fresh3 = addr_of_mut!((*parser).raw_buffer.pointer);
*fresh3 = (*fresh3).wrapping_offset(2_isize);
let fresh4 = addr_of_mut!((*parser).offset);
*fresh4 = (*fresh4).force_add(3_u64);
} else if (*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as libc::c_long
>= 3_i64
&& memcmp(
(*parser).raw_buffer.pointer as *const libc::c_void,
BOM_UTF8 as *const libc::c_void,
3_u64,
) == 0
{
(*parser).encoding = YamlUtf8Encoding;
let fresh5 = addr_of_mut!((*parser).raw_buffer.pointer);
*fresh5 = (*fresh5).wrapping_offset(3_isize);
let fresh6 = addr_of_mut!((*parser).offset);
*fresh6 = (*fresh6).force_add(3_u64);
} else {
(*parser).encoding = YamlUtf8Encoding;
}
OK
}
unsafe fn yaml_parser_update_raw_buffer(
parser: *mut YamlParserT,
) -> Success {
let mut size_read: size_t = 0_u64;
if (*parser).raw_buffer.start == (*parser).raw_buffer.pointer
&& (*parser).raw_buffer.last == (*parser).raw_buffer.end
{
return OK;
}
if (*parser).eof {
return OK;
}
if (*parser).raw_buffer.start < (*parser).raw_buffer.pointer
&& (*parser).raw_buffer.pointer < (*parser).raw_buffer.last
{
let _ = memmove(
(*parser).raw_buffer.start as *mut libc::c_void,
(*parser).raw_buffer.pointer as *const libc::c_void,
(*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as libc::c_long as libc::c_ulong,
);
}
let fresh7 = addr_of_mut!((*parser).raw_buffer.last);
*fresh7 = (*fresh7).wrapping_offset(
-((*parser)
.raw_buffer
.pointer
.c_offset_from((*parser).raw_buffer.start)
as libc::c_long as isize),
);
let fresh8 = addr_of_mut!((*parser).raw_buffer.pointer);
*fresh8 = (*parser).raw_buffer.start;
if (*parser).read_handler.expect("non-null function pointer")(
(*parser).read_handler_data,
(*parser).raw_buffer.last,
(*parser)
.raw_buffer
.end
.c_offset_from((*parser).raw_buffer.last) as size_t,
addr_of_mut!(size_read),
) == 0
{
return yaml_parser_set_reader_error(
parser,
b"input error\0" as *const u8 as *const libc::c_char,
(*parser).offset,
-1,
);
}
let fresh9 = addr_of_mut!((*parser).raw_buffer.last);
*fresh9 = (*fresh9).wrapping_offset(size_read as isize);
if size_read == 0 {
(*parser).eof = true;
}
OK
}
pub(crate) unsafe fn yaml_parser_update_buffer(
parser: *mut YamlParserT,
length: size_t,
) -> Success {
let mut first = true;
__assert!(((*parser).read_handler).is_some());
if (*parser).eof
&& (*parser).raw_buffer.pointer == (*parser).raw_buffer.last
{
return OK;
}
if (*parser).unread >= length {
return OK;
}
if (*parser).encoding == YamlAnyEncoding
&& yaml_parser_determine_encoding(parser).fail
{
return FAIL;
}
if (*parser).buffer.start < (*parser).buffer.pointer
&& (*parser).buffer.pointer < (*parser).buffer.last
{
let size: size_t = (*parser)
.buffer
.last
.c_offset_from((*parser).buffer.pointer)
as size_t;
let _ = memmove(
(*parser).buffer.start as *mut libc::c_void,
(*parser).buffer.pointer as *const libc::c_void,
size,
);
let fresh10 = addr_of_mut!((*parser).buffer.pointer);
*fresh10 = (*parser).buffer.start;
let fresh11 = addr_of_mut!((*parser).buffer.last);
*fresh11 =
(*parser).buffer.start.wrapping_offset(size as isize);
} else if (*parser).buffer.pointer == (*parser).buffer.last {
let fresh12 = addr_of_mut!((*parser).buffer.pointer);
*fresh12 = (*parser).buffer.start;
let fresh13 = addr_of_mut!((*parser).buffer.last);
*fresh13 = (*parser).buffer.start;
}
while (*parser).unread < length {
if (!first
|| (*parser).raw_buffer.pointer
== (*parser).raw_buffer.last)
&& yaml_parser_update_raw_buffer(parser).fail
{
return FAIL;
}
first = false;
while (*parser).raw_buffer.pointer != (*parser).raw_buffer.last
{
let mut value: libc::c_uint = 0;
let value2: libc::c_uint;
let mut incomplete = false;
let mut octet: libc::c_uchar;
let mut width: libc::c_uint = 0;
let low: libc::c_int;
let high: libc::c_int;
let mut k: size_t;
let raw_unread: size_t = (*parser)
.raw_buffer
.last
.c_offset_from((*parser).raw_buffer.pointer)
as size_t;
match (*parser).encoding {
YamlUtf8Encoding => {
octet = *(*parser).raw_buffer.pointer;
width = if octet & 0x80 == 0 {
1
} else if octet & 0xE0 == 0xC0 {
2
} else if octet & 0xF0 == 0xE0 {
3
} else if octet & 0xF8 == 0xF0 {
4
} else {
0
} as libc::c_uint;
if width == 0 {
return yaml_parser_set_reader_error(
parser,
b"invalid leading UTF-8 octet\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
octet as libc::c_int,
);
}
if width as libc::c_ulong > raw_unread {
if (*parser).eof {
return yaml_parser_set_reader_error(
parser,
b"incomplete UTF-8 octet sequence\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
-1,
);
}
incomplete = true;
} else {
value = if octet & 0x80 == 0 {
octet & 0x7F
} else if octet & 0xE0 == 0xC0 {
octet & 0x1F
} else if octet & 0xF0 == 0xE0 {
octet & 0xF
} else if octet & 0xF8 == 0xF0 {
octet & 0x7
} else {
0
}
as libc::c_uint;
k = 1_u64;
while k < width as libc::c_ulong {
octet = *(*parser)
.raw_buffer
.pointer
.wrapping_offset(k as isize);
if octet & 0xC0 != 0x80 {
return yaml_parser_set_reader_error(
parser,
b"invalid trailing UTF-8 octet\0"
as *const u8
as *const libc::c_char,
(*parser).offset.force_add(k),
octet as libc::c_int,
);
}
value = (value << 6).force_add(
(octet & 0x3F) as libc::c_uint,
);
k = k.force_add(1);
}
if !(width == 1
|| width == 2 && value >= 0x80
|| width == 3 && value >= 0x800
|| width == 4 && value >= 0x10000)
{
return yaml_parser_set_reader_error(
parser,
b"invalid length of a UTF-8 sequence\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
-1,
);
}
if (0xD800..=0xDFFF).contains(&value)
|| value > 0x10FFFF
{
return yaml_parser_set_reader_error(
parser,
b"invalid Unicode character\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
value as libc::c_int,
);
}
}
}
YamlUtf16leEncoding | YamlUtf16beEncoding => {
low = if (*parser).encoding == YamlUtf16leEncoding {
0
} else {
1
};
high = if (*parser).encoding == YamlUtf16leEncoding
{
1
} else {
0
};
if raw_unread < 2_u64 {
if (*parser).eof {
return yaml_parser_set_reader_error(
parser,
b"incomplete UTF-16 character\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
-1,
);
}
incomplete = true;
} else {
value = (*(*parser)
.raw_buffer
.pointer
.wrapping_offset(low as isize)
as libc::c_int
+ ((*(*parser)
.raw_buffer
.pointer
.wrapping_offset(high as isize)
as libc::c_int)
<< 8))
as libc::c_uint;
if value & 0xFC00 == 0xDC00 {
return yaml_parser_set_reader_error(
parser,
b"unexpected low surrogate area\0"
as *const u8
as *const libc::c_char,
(*parser).offset,
value as libc::c_int,
);
}
if value & 0xFC00 == 0xD800 {
width = 4;
if raw_unread < 4_u64 {
if (*parser).eof {
return yaml_parser_set_reader_error(
parser,
b"incomplete UTF-16 surrogate pair\0" as *const u8
as *const libc::c_char,
(*parser).offset,
-1,
);
}
incomplete = true;
} else {
value2 = (*(*parser)
.raw_buffer
.pointer
.wrapping_offset((low + 2) as isize)
as libc::c_int
+ ((*(*parser)
.raw_buffer
.pointer
.wrapping_offset(
(high + 2) as isize,
)
as libc::c_int)
<< 8))
as libc::c_uint;
if value2 & 0xFC00 != 0xDC00 {
return yaml_parser_set_reader_error(
parser,
b"expected low surrogate area\0" as *const u8
as *const libc::c_char,
(*parser).offset.force_add(2_u64),
value2 as libc::c_int,
);
}
value = 0x10000_u32
.force_add((value & 0x3FF) << 10)
.force_add(value2 & 0x3FF);
}
} else {
width = 2;
}
}
}
_ => {}
}
if incomplete {
break;
}
if !(value == 0x9
|| value == 0xA
|| value == 0xD
|| (0x20..=0x7E).contains(&value)
|| value == 0x85
|| (0xA0..=0xD7FF).contains(&value)
|| (0xE000..=0xFFFD).contains(&value)
|| (0x10000..=0x10FFFF).contains(&value))
{
return yaml_parser_set_reader_error(
parser,
b"control characters are not allowed\0" as *const u8
as *const libc::c_char,
(*parser).offset,
value as libc::c_int,
);
}
let fresh14 = addr_of_mut!((*parser).raw_buffer.pointer);
*fresh14 = (*fresh14).wrapping_offset(width as isize);
let fresh15 = addr_of_mut!((*parser).offset);
*fresh15 = (*fresh15).force_add(width as size_t);
if value <= 0x7F {
let fresh16 = addr_of_mut!((*parser).buffer.last);
let fresh17 = *fresh16;
*fresh16 = (*fresh16).wrapping_offset(1);
*fresh17 = value as yaml_char_t;
} else if value <= 0x7FF {
let fresh18 = addr_of_mut!((*parser).buffer.last);
let fresh19 = *fresh18;
*fresh18 = (*fresh18).wrapping_offset(1);
*fresh19 =
0xC0_u32.force_add(value >> 6) as yaml_char_t;
let fresh20 = addr_of_mut!((*parser).buffer.last);
let fresh21 = *fresh20;
*fresh20 = (*fresh20).wrapping_offset(1);
*fresh21 =
0x80_u32.force_add(value & 0x3F) as yaml_char_t;
} else if value <= 0xFFFF {
let fresh22 = addr_of_mut!((*parser).buffer.last);
let fresh23 = *fresh22;
*fresh22 = (*fresh22).wrapping_offset(1);
*fresh23 =
0xE0_u32.force_add(value >> 12) as yaml_char_t;
let fresh24 = addr_of_mut!((*parser).buffer.last);
let fresh25 = *fresh24;
*fresh24 = (*fresh24).wrapping_offset(1);
*fresh25 = 0x80_u32.force_add(value >> 6 & 0x3F)
as yaml_char_t;
let fresh26 = addr_of_mut!((*parser).buffer.last);
let fresh27 = *fresh26;
*fresh26 = (*fresh26).wrapping_offset(1);
*fresh27 =
0x80_u32.force_add(value & 0x3F) as yaml_char_t;
} else {
let fresh28 = addr_of_mut!((*parser).buffer.last);
let fresh29 = *fresh28;
*fresh28 = (*fresh28).wrapping_offset(1);
*fresh29 =
0xF0_u32.force_add(value >> 18) as yaml_char_t;
let fresh30 = addr_of_mut!((*parser).buffer.last);
let fresh31 = *fresh30;
*fresh30 = (*fresh30).wrapping_offset(1);
*fresh31 = 0x80_u32.force_add(value >> 12 & 0x3F)
as yaml_char_t;
let fresh32 = addr_of_mut!((*parser).buffer.last);
let fresh33 = *fresh32;
*fresh32 = (*fresh32).wrapping_offset(1);
*fresh33 = 0x80_u32.force_add(value >> 6 & 0x3F)
as yaml_char_t;
let fresh34 = addr_of_mut!((*parser).buffer.last);
let fresh35 = *fresh34;
*fresh34 = (*fresh34).wrapping_offset(1);
*fresh35 =
0x80_u32.force_add(value & 0x3F) as yaml_char_t;
}
let fresh36 = addr_of_mut!((*parser).unread);
*fresh36 = (*fresh36).force_add(1);
}
if (*parser).eof {
let fresh37 = addr_of_mut!((*parser).buffer.last);
let fresh38 = *fresh37;
*fresh37 = (*fresh37).wrapping_offset(1);
*fresh38 = b'\0';
let fresh39 = addr_of_mut!((*parser).unread);
*fresh39 = (*fresh39).force_add(1);
return OK;
}
}
if (*parser).offset >= (!0_u64).wrapping_div(2_u64) {
return yaml_parser_set_reader_error(
parser,
b"input is too long\0" as *const u8 as *const libc::c_char,
(*parser).offset,
-1,
);
}
OK
}
libyml-0.0.5/src/scanner.rs 0000644 0000000 0000000 00000334775 10461020230 0013727 0 ustar 0000000 0000000 use crate::externs::{memcpy, memmove, memset, strcmp, strlen};
use crate::internal::{yaml_queue_extend, yaml_stack_extend};
use crate::memory::yaml_free;
use crate::memory::yaml_malloc;
use crate::ops::{ForceAdd as _, ForceMul as _};
use crate::reader::yaml_parser_update_buffer;
use crate::string::{yaml_string_extend, yaml_string_join};
use crate::success::{Success, FAIL, OK};
use crate::yaml::{
ptrdiff_t, size_t, yaml_char_t, YamlStringT, NULL_STRING,
};
use crate::{
libc, PointerExt, YamlAliasToken, YamlAnchorToken,
YamlBlockEndToken, YamlBlockEntryToken, YamlBlockMappingStartToken,
YamlBlockSequenceStartToken, YamlDocumentEndToken,
YamlDocumentStartToken, YamlDoubleQuotedScalarStyle,
YamlFlowEntryToken, YamlFlowMappingEndToken,
YamlFlowMappingStartToken, YamlFlowSequenceEndToken,
YamlFlowSequenceStartToken, YamlFoldedScalarStyle, YamlKeyToken,
YamlLiteralScalarStyle, YamlMarkT, YamlMemoryError, YamlNoError,
YamlParserT, YamlPlainScalarStyle, YamlScalarToken,
YamlScannerError, YamlSimpleKeyT, YamlSingleQuotedScalarStyle,
YamlStreamEndToken, YamlStreamStartToken, YamlTagDirectiveToken,
YamlTagToken, YamlTokenT, YamlTokenTypeT, YamlValueToken,
YamlVersionDirectiveToken,
};
use core::mem::{size_of, MaybeUninit};
use core::ptr::{self, addr_of_mut};
unsafe fn cache(parser: *mut YamlParserT, length: size_t) -> Success {
if (*parser).unread >= length {
OK
} else {
yaml_parser_update_buffer(parser, length)
}
}
unsafe fn skip(parser: *mut YamlParserT) {
let width = WIDTH!((*parser).buffer);
(*parser).mark.index = (*parser).mark.index.force_add(width as u64);
(*parser).mark.column = (*parser).mark.column.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(width as isize);
}
unsafe fn skip_line(parser: *mut YamlParserT) {
if IS_CRLF!((*parser).buffer) {
(*parser).mark.index = (*parser).mark.index.force_add(2);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(2);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(2);
} else if IS_BREAK!((*parser).buffer) {
let width = WIDTH!((*parser).buffer);
(*parser).mark.index =
(*parser).mark.index.force_add(width as u64);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(width as isize);
};
}
unsafe fn read(parser: *mut YamlParserT, string: *mut YamlStringT) {
STRING_EXTEND!(*string);
let width = WIDTH!((*parser).buffer);
copy!(*string, (*parser).buffer);
(*parser).mark.index = (*parser).mark.index.force_add(width as u64);
(*parser).mark.column = (*parser).mark.column.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
}
unsafe fn read_line(
parser: *mut YamlParserT,
string: *mut YamlStringT,
) {
STRING_EXTEND!(*string);
if CHECK_AT!((*parser).buffer, b'\r', 0)
&& CHECK_AT!((*parser).buffer, b'\n', 1)
{
*(*string).pointer = b'\n';
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(2);
(*parser).mark.index = (*parser).mark.index.force_add(2);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(2);
} else if CHECK_AT!((*parser).buffer, b'\r', 0)
|| CHECK_AT!((*parser).buffer, b'\n', 0)
{
*(*string).pointer = b'\n';
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(1);
(*parser).mark.index = (*parser).mark.index.force_add(1);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
} else if CHECK_AT!((*parser).buffer, b'\xC2', 0)
&& CHECK_AT!((*parser).buffer, b'\x85', 1)
{
*(*string).pointer = b'\n';
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(2);
(*parser).mark.index = (*parser).mark.index.force_add(2);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
} else if CHECK_AT!((*parser).buffer, b'\xE2', 0)
&& CHECK_AT!((*parser).buffer, b'\x80', 1)
&& (CHECK_AT!((*parser).buffer, b'\xA8', 2)
|| CHECK_AT!((*parser).buffer, b'\xA9', 2))
{
*(*string).pointer = *(*parser).buffer.pointer;
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(1);
*(*string).pointer = *(*parser).buffer.pointer;
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(1);
*(*string).pointer = *(*parser).buffer.pointer;
(*string).pointer = (*string).pointer.wrapping_offset(1);
(*parser).buffer.pointer =
(*parser).buffer.pointer.wrapping_offset(1);
(*parser).mark.index = (*parser).mark.index.force_add(3);
(*parser).mark.column = 0;
(*parser).mark.line = (*parser).mark.line.force_add(1);
(*parser).unread = (*parser).unread.wrapping_sub(1);
};
}
macro_rules! read {
($parser:expr, $string:expr) => {
read($parser, addr_of_mut!($string))
};
}
macro_rules! read_line {
($parser:expr, $string:expr) => {
read_line($parser, addr_of_mut!($string))
};
}
/// Scan the input stream and produce the next token.
///
/// Call the function subsequently to produce a sequence of tokens corresponding
/// to the input stream. The initial token has the type YamlStreamStartToken
/// while the ending token has the type YamlStreamEndToken.
///
/// An application is responsible for freeing any buffers associated with the
/// produced token object using the yaml_token_delete function.
///
/// An application must not alternate the calls of yaml_parser_scan() with the
/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
/// the parser.
///
/// # Safety
///
/// - The `parser` and `token` pointers must be valid and non-null.
/// - The `parser` must be properly initialized and not already in an error state.
/// - The `token` must be properly allocated and have enough capacity to store the
/// produced token.
/// - The function should not be called alternately with `yaml_parser_parse()` or
/// `yaml_parser_load()`, as it may break the parser state.
/// - The caller is responsible for freeing any buffers associated with the produced
/// token using the `yaml_token_delete` function.
///
pub unsafe fn yaml_parser_scan(
parser: *mut YamlParserT,
token: *mut YamlTokenT,
) -> Success {
__assert!(!parser.is_null());
__assert!(!token.is_null());
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
if (*parser).stream_end_produced || (*parser).error != YamlNoError {
return OK;
}
if !(*parser).token_available
&& yaml_parser_fetch_more_tokens(parser).fail
{
return FAIL;
}
*token = DEQUEUE!((*parser).tokens);
(*parser).token_available = false;
let fresh2 = addr_of_mut!((*parser).tokens_parsed);
*fresh2 = (*fresh2).force_add(1);
if (*token).type_ == YamlStreamEndToken {
(*parser).stream_end_produced = true;
}
OK
}
unsafe fn yaml_parser_set_scanner_error(
parser: *mut YamlParserT,
context: *const libc::c_char,
context_mark: YamlMarkT,
problem: *const libc::c_char,
) {
(*parser).error = YamlScannerError;
let fresh3 = addr_of_mut!((*parser).context);
*fresh3 = context;
(*parser).context_mark = context_mark;
let fresh4 = addr_of_mut!((*parser).problem);
*fresh4 = problem;
(*parser).problem_mark = (*parser).mark;
}
pub(crate) unsafe fn yaml_parser_fetch_more_tokens(
parser: *mut YamlParserT,
) -> Success {
let mut need_more_tokens;
loop {
need_more_tokens = false;
if (*parser).tokens.head == (*parser).tokens.tail {
need_more_tokens = true;
} else {
let mut simple_key: *mut YamlSimpleKeyT;
if yaml_parser_stale_simple_keys(parser).fail {
return FAIL;
}
simple_key = (*parser)
.simple_keys
.start
.add((*parser).not_simple_keys as usize);
while simple_key != (*parser).simple_keys.top {
if (*simple_key).possible
&& (*simple_key).token_number
== (*parser).tokens_parsed
{
need_more_tokens = true;
break;
} else {
simple_key = simple_key.wrapping_offset(1);
}
}
}
if !need_more_tokens {
break;
}
if yaml_parser_fetch_next_token(parser).fail {
return FAIL;
}
}
(*parser).token_available = true;
OK
}
unsafe fn yaml_parser_fetch_next_token(
parser: *mut YamlParserT,
) -> Success {
if cache(parser, 1_u64).fail {
return FAIL;
}
if !(*parser).stream_start_produced {
yaml_parser_fetch_stream_start(parser);
return OK;
}
if yaml_parser_scan_to_next_token(parser).fail {
return FAIL;
}
if yaml_parser_stale_simple_keys(parser).fail {
return FAIL;
}
yaml_parser_unroll_indent(
parser,
(*parser).mark.column as ptrdiff_t,
);
if cache(parser, 4_u64).fail {
return FAIL;
}
if IS_Z!((*parser).buffer) {
return yaml_parser_fetch_stream_end(parser);
}
if (*parser).mark.column == 0_u64 && CHECK!((*parser).buffer, b'%')
{
return yaml_parser_fetch_directive(parser);
}
if (*parser).mark.column == 0_u64
&& CHECK_AT!((*parser).buffer, b'-', 0)
&& CHECK_AT!((*parser).buffer, b'-', 1)
&& CHECK_AT!((*parser).buffer, b'-', 2)
&& IS_BLANKZ_AT!((*parser).buffer, 3)
{
return yaml_parser_fetch_document_indicator(
parser,
YamlDocumentStartToken,
);
}
if (*parser).mark.column == 0_u64
&& CHECK_AT!((*parser).buffer, b'.', 0)
&& CHECK_AT!((*parser).buffer, b'.', 1)
&& CHECK_AT!((*parser).buffer, b'.', 2)
&& IS_BLANKZ_AT!((*parser).buffer, 3)
{
return yaml_parser_fetch_document_indicator(
parser,
YamlDocumentEndToken,
);
}
if CHECK!((*parser).buffer, b'[') {
return yaml_parser_fetch_flow_collection_start(
parser,
YamlFlowSequenceStartToken,
);
}
if CHECK!((*parser).buffer, b'{') {
return yaml_parser_fetch_flow_collection_start(
parser,
YamlFlowMappingStartToken,
);
}
if CHECK!((*parser).buffer, b']') {
return yaml_parser_fetch_flow_collection_end(
parser,
YamlFlowSequenceEndToken,
);
}
if CHECK!((*parser).buffer, b'}') {
return yaml_parser_fetch_flow_collection_end(
parser,
YamlFlowMappingEndToken,
);
}
if CHECK!((*parser).buffer, b',') {
return yaml_parser_fetch_flow_entry(parser);
}
if CHECK!((*parser).buffer, b'-')
&& IS_BLANKZ_AT!((*parser).buffer, 1)
{
return yaml_parser_fetch_block_entry(parser);
}
if CHECK!((*parser).buffer, b'?')
&& ((*parser).flow_level != 0
|| IS_BLANKZ_AT!((*parser).buffer, 1))
{
return yaml_parser_fetch_key(parser);
}
if CHECK!((*parser).buffer, b':')
&& ((*parser).flow_level != 0
|| IS_BLANKZ_AT!((*parser).buffer, 1))
{
return yaml_parser_fetch_value(parser);
}
if CHECK!((*parser).buffer, b'*') {
return yaml_parser_fetch_anchor(parser, YamlAliasToken);
}
if CHECK!((*parser).buffer, b'&') {
return yaml_parser_fetch_anchor(parser, YamlAnchorToken);
}
if CHECK!((*parser).buffer, b'!') {
return yaml_parser_fetch_tag(parser);
}
if CHECK!((*parser).buffer, b'|') && (*parser).flow_level == 0 {
return yaml_parser_fetch_block_scalar(parser, true);
}
if CHECK!((*parser).buffer, b'>') && (*parser).flow_level == 0 {
return yaml_parser_fetch_block_scalar(parser, false);
}
if CHECK!((*parser).buffer, b'\'') {
return yaml_parser_fetch_flow_scalar(parser, true);
}
if CHECK!((*parser).buffer, b'"') {
return yaml_parser_fetch_flow_scalar(parser, false);
}
if !(IS_BLANKZ!((*parser).buffer)
|| CHECK!((*parser).buffer, b'-')
|| CHECK!((*parser).buffer, b'?')
|| CHECK!((*parser).buffer, b':')
|| CHECK!((*parser).buffer, b',')
|| CHECK!((*parser).buffer, b'[')
|| CHECK!((*parser).buffer, b']')
|| CHECK!((*parser).buffer, b'{')
|| CHECK!((*parser).buffer, b'}')
|| CHECK!((*parser).buffer, b'#')
|| CHECK!((*parser).buffer, b'&')
|| CHECK!((*parser).buffer, b'*')
|| CHECK!((*parser).buffer, b'!')
|| CHECK!((*parser).buffer, b'|')
|| CHECK!((*parser).buffer, b'>')
|| CHECK!((*parser).buffer, b'\'')
|| CHECK!((*parser).buffer, b'"')
|| CHECK!((*parser).buffer, b'%')
|| CHECK!((*parser).buffer, b'@')
|| CHECK!((*parser).buffer, b'`'))
|| CHECK!((*parser).buffer, b'-')
&& !IS_BLANK_AT!((*parser).buffer, 1)
|| (*parser).flow_level == 0
&& (CHECK!((*parser).buffer, b'?')
|| CHECK!((*parser).buffer, b':'))
&& !IS_BLANKZ_AT!((*parser).buffer, 1)
{
return yaml_parser_fetch_plain_scalar(parser);
}
yaml_parser_set_scanner_error(
parser,
b"while scanning for the next token\0" as *const u8
as *const libc::c_char,
(*parser).mark,
b"found character that cannot start any token\0" as *const u8
as *const libc::c_char,
);
FAIL
}
unsafe fn yaml_parser_stale_simple_keys(
parser: *mut YamlParserT,
) -> Success {
let mut simple_key: *mut YamlSimpleKeyT;
simple_key = (*parser)
.simple_keys
.start
.add((*parser).not_simple_keys as usize);
while simple_key != (*parser).simple_keys.top {
if (*simple_key).possible
&& ((*simple_key).mark.line < (*parser).mark.line
|| (*simple_key).mark.index.force_add(1024_u64)
< (*parser).mark.index)
{
if (*simple_key).required {
yaml_parser_set_scanner_error(
parser,
b"while scanning a simple key\0" as *const u8
as *const libc::c_char,
(*simple_key).mark,
b"could not find expected ':'\0" as *const u8
as *const libc::c_char,
);
return FAIL;
}
(*simple_key).possible = false;
if (*parser)
.simple_keys
.start
.add((*parser).not_simple_keys as usize)
== simple_key
{
(*parser).not_simple_keys += 1;
}
}
simple_key = simple_key.wrapping_offset(1);
}
OK
}
unsafe fn yaml_parser_save_simple_key(
parser: *mut YamlParserT,
) -> Success {
let required = (*parser).flow_level == 0
&& (*parser).indent as libc::c_long
== (*parser).mark.column as ptrdiff_t;
if (*parser).simple_key_allowed {
let simple_key = YamlSimpleKeyT {
possible: true,
required,
token_number: (*parser).tokens_parsed.force_add(
(*parser)
.tokens
.tail
.c_offset_from((*parser).tokens.head)
as libc::c_ulong,
),
mark: (*parser).mark,
};
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
*(*parser).simple_keys.top.wrapping_offset(-1_isize) =
simple_key;
if (*parser)
.simple_keys
.start
.add((*parser).not_simple_keys as usize)
== (*parser).simple_keys.top
{
(*parser).not_simple_keys -= 1;
}
}
OK
}
unsafe fn yaml_parser_remove_simple_key(
parser: *mut YamlParserT,
) -> Success {
let simple_key: *mut YamlSimpleKeyT =
(*parser).simple_keys.top.wrapping_offset(-1_isize);
if (*simple_key).possible && (*simple_key).required {
yaml_parser_set_scanner_error(
parser,
b"while scanning a simple key\0" as *const u8
as *const libc::c_char,
(*simple_key).mark,
b"could not find expected ':'\0" as *const u8
as *const libc::c_char,
);
return FAIL;
}
(*simple_key).possible = false;
OK
}
unsafe fn yaml_parser_increase_flow_level(
parser: *mut YamlParserT,
) -> Success {
let empty_simple_key = YamlSimpleKeyT {
possible: false,
required: false,
token_number: 0_u64,
mark: YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
},
};
PUSH!((*parser).simple_keys, empty_simple_key);
if (*parser).flow_level == libc::c_int::MAX {
(*parser).error = YamlMemoryError;
return FAIL;
}
let fresh7 = addr_of_mut!((*parser).flow_level);
*fresh7 += 1;
OK
}
unsafe fn yaml_parser_decrease_flow_level(parser: *mut YamlParserT) {
if (*parser).flow_level != 0 {
let fresh8 = addr_of_mut!((*parser).flow_level);
*fresh8 -= 1;
if (*parser)
.simple_keys
.start
.add((*parser).not_simple_keys as usize)
== (*parser).simple_keys.top
{
(*parser).not_simple_keys -= 1;
}
let _ = POP!((*parser).simple_keys);
}
}
unsafe fn yaml_parser_roll_indent(
parser: *mut YamlParserT,
column: ptrdiff_t,
number: ptrdiff_t,
type_: YamlTokenTypeT,
mark: YamlMarkT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if (*parser).flow_level != 0 {
return OK;
}
if ((*parser).indent as libc::c_long) < column {
PUSH!((*parser).indents, (*parser).indent);
if column > ptrdiff_t::from(libc::c_int::MAX) {
(*parser).error = YamlMemoryError;
return FAIL;
}
(*parser).indent = column as libc::c_int;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = type_;
(*token).start_mark = mark;
(*token).end_mark = mark;
if number == -1_i64 {
ENQUEUE!((*parser).tokens, *token);
} else {
QUEUE_INSERT!(
(*parser).tokens,
(number as libc::c_ulong)
.wrapping_sub((*parser).tokens_parsed),
*token
);
}
}
OK
}
unsafe fn yaml_parser_unroll_indent(
parser: *mut YamlParserT,
column: ptrdiff_t,
) {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if (*parser).flow_level != 0 {
return;
}
while (*parser).indent as libc::c_long > column {
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlBlockEndToken;
(*token).start_mark = (*parser).mark;
(*token).end_mark = (*parser).mark;
ENQUEUE!((*parser).tokens, *token);
(*parser).indent = POP!((*parser).indents);
}
}
unsafe fn yaml_parser_fetch_stream_start(parser: *mut YamlParserT) {
let simple_key = YamlSimpleKeyT {
possible: false,
required: false,
token_number: 0_u64,
mark: YamlMarkT {
index: 0_u64,
line: 0_u64,
column: 0_u64,
},
};
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
(*parser).indent = -1;
PUSH!((*parser).simple_keys, simple_key);
(*parser).not_simple_keys = 1;
(*parser).simple_key_allowed = true;
(*parser).stream_start_produced = true;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlStreamStartToken;
(*token).start_mark = (*parser).mark;
(*token).end_mark = (*parser).mark;
(*token).data.stream_start.encoding = (*parser).encoding;
ENQUEUE!((*parser).tokens, *token);
}
unsafe fn yaml_parser_fetch_stream_end(
parser: *mut YamlParserT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if (*parser).mark.column != 0_u64 {
(*parser).mark.column = 0_u64;
let fresh22 = addr_of_mut!((*parser).mark.line);
*fresh22 = (*fresh22).force_add(1);
}
yaml_parser_unroll_indent(parser, -1_i64);
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = false;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlStreamEndToken;
(*token).start_mark = (*parser).mark;
(*token).end_mark = (*parser).mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_directive(
parser: *mut YamlParserT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
yaml_parser_unroll_indent(parser, -1_i64);
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = false;
if yaml_parser_scan_directive(parser, token).fail {
return FAIL;
}
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_document_indicator(
parser: *mut YamlParserT,
type_: YamlTokenTypeT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
yaml_parser_unroll_indent(parser, -1_i64);
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = false;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
skip(parser);
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = type_;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_flow_collection_start(
parser: *mut YamlParserT,
type_: YamlTokenTypeT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if yaml_parser_save_simple_key(parser).fail {
return FAIL;
}
if yaml_parser_increase_flow_level(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = true;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = type_;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_flow_collection_end(
parser: *mut YamlParserT,
type_: YamlTokenTypeT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
yaml_parser_decrease_flow_level(parser);
(*parser).simple_key_allowed = false;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = type_;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_flow_entry(
parser: *mut YamlParserT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = true;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlFlowEntryToken;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_block_entry(
parser: *mut YamlParserT,
) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if (*parser).flow_level == 0 {
if !(*parser).simple_key_allowed {
yaml_parser_set_scanner_error(
parser,
ptr::null::(),
(*parser).mark,
b"block sequence entries are not allowed in this context\0" as *const u8
as *const libc::c_char,
);
return FAIL;
}
if yaml_parser_roll_indent(
parser,
(*parser).mark.column as ptrdiff_t,
-1_i64,
YamlBlockSequenceStartToken,
(*parser).mark,
)
.fail
{
return FAIL;
}
}
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = true;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlBlockEntryToken;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_key(parser: *mut YamlParserT) -> Success {
let mut token = MaybeUninit::::uninit();
let token = token.as_mut_ptr();
if (*parser).flow_level == 0 {
if !(*parser).simple_key_allowed {
yaml_parser_set_scanner_error(
parser,
ptr::null::(),
(*parser).mark,
b"mapping keys are not allowed in this context\0"
as *const u8 as *const libc::c_char,
);
return FAIL;
}
if yaml_parser_roll_indent(
parser,
(*parser).mark.column as ptrdiff_t,
-1_i64,
YamlBlockMappingStartToken,
(*parser).mark,
)
.fail
{
return FAIL;
}
}
if yaml_parser_remove_simple_key(parser).fail {
return FAIL;
}
(*parser).simple_key_allowed = (*parser).flow_level == 0;
let start_mark: YamlMarkT = (*parser).mark;
skip(parser);
let end_mark: YamlMarkT = (*parser).mark;
let _ = memset(
token as *mut libc::c_void,
0,
size_of::() as libc::c_ulong,
);
(*token).type_ = YamlKeyToken;
(*token).start_mark = start_mark;
(*token).end_mark = end_mark;
ENQUEUE!((*parser).tokens, *token);
OK
}
unsafe fn yaml_parser_fetch_value(parser: *mut YamlParserT) -> Success {
let mut token = MaybeUninit::