use std::{
ffi::c_void,
ptr::{drop_in_place, null_mut},
rc::Rc,
};
use crate::{
hash::{XmlHashTablePtr, xml_hash_free},
libxml::{
globals::{xml_free, xml_malloc},
relaxng::{XmlRelaxNGPartitionPtr, XmlRelaxNGType, xml_relaxng_free_partition},
xmlregexp::XmlRegexp,
},
tree::XmlNodePtr,
};
use super::{XmlRelaxNGParserCtxtPtr, XmlRelaxNGTypeLibraryPtr, xml_rng_perr_memory};
pub type XmlRelaxNGDefinePtr = *mut XmlRelaxNGDefine;
#[repr(C)]
pub struct XmlRelaxNGDefine {
pub(crate) typ: XmlRelaxNGType, pub(crate) node: Option<XmlNodePtr>, pub(crate) name: *mut u8, pub(crate) ns: *mut u8, pub(crate) value: *mut u8, pub(crate) data: *mut c_void, pub(crate) content: XmlRelaxNGDefinePtr, pub(crate) parent: XmlRelaxNGDefinePtr, pub(crate) next: XmlRelaxNGDefinePtr, pub(crate) attrs: XmlRelaxNGDefinePtr, pub(crate) name_class: XmlRelaxNGDefinePtr, pub(crate) next_hash: XmlRelaxNGDefinePtr, pub(crate) depth: i16, pub(crate) dflags: i16, pub(crate) cont_model: Option<Rc<XmlRegexp>>, }
impl XmlRelaxNGDefine {
#[doc(alias = "xmlRelaxNGDefName")]
pub(crate) fn name(&self) -> &'static str {
match self.typ {
XmlRelaxNGType::Empty => "empty",
XmlRelaxNGType::NotAllowed => "notAllowed",
XmlRelaxNGType::Except => "except",
XmlRelaxNGType::Text => "text",
XmlRelaxNGType::Element => "element",
XmlRelaxNGType::Datatype => "datatype",
XmlRelaxNGType::Value => "value",
XmlRelaxNGType::List => "list",
XmlRelaxNGType::Attribute => "attribute",
XmlRelaxNGType::Def => "def",
XmlRelaxNGType::Ref => "ref",
XmlRelaxNGType::Externalref => "externalRef",
XmlRelaxNGType::Parentref => "parentRef",
XmlRelaxNGType::Optional => "optional",
XmlRelaxNGType::Zeroormore => "zeroOrMore",
XmlRelaxNGType::Oneormore => "oneOrMore",
XmlRelaxNGType::Choice => "choice",
XmlRelaxNGType::Group => "group",
XmlRelaxNGType::Interleave => "interleave",
XmlRelaxNGType::Start => "start",
XmlRelaxNGType::Noop => "noop",
XmlRelaxNGType::Param => "param",
}
}
}
impl Default for XmlRelaxNGDefine {
fn default() -> Self {
Self {
typ: XmlRelaxNGType::default(),
node: None,
name: null_mut(),
ns: null_mut(),
value: null_mut(),
data: null_mut(),
content: null_mut(),
parent: null_mut(),
next: null_mut(),
attrs: null_mut(),
name_class: null_mut(),
next_hash: null_mut(),
depth: 0,
dflags: 0,
cont_model: None,
}
}
}
#[doc(alias = "xmlRelaxNGNewDefine")]
pub(crate) unsafe fn xml_relaxng_new_define(
ctxt: XmlRelaxNGParserCtxtPtr,
node: Option<XmlNodePtr>,
) -> XmlRelaxNGDefinePtr {
unsafe {
let ret: XmlRelaxNGDefinePtr = xml_malloc(size_of::<XmlRelaxNGDefine>()) as _;
if ret.is_null() {
xml_rng_perr_memory(ctxt, Some("allocating define\n"));
return null_mut();
}
std::ptr::write(&mut *ret, XmlRelaxNGDefine::default());
(*ctxt).def_tab.push(ret);
(*ret).node = node;
(*ret).depth = -1;
ret
}
}
#[doc(alias = "xmlRelaxNGFreeDefine")]
pub(crate) unsafe fn xml_relaxng_free_define(define: XmlRelaxNGDefinePtr) {
unsafe {
if define.is_null() {
return;
}
if (*define).typ == XmlRelaxNGType::Value && !(*define).attrs.is_null() {
let lib: XmlRelaxNGTypeLibraryPtr = (*define).data as _;
if !lib.is_null() {
if let Some(freef) = (*lib).freef {
freef((*lib).data, (*define).attrs as _);
}
}
}
if !(*define).data.is_null() && (*define).typ == XmlRelaxNGType::Interleave {
xml_relaxng_free_partition((*define).data as XmlRelaxNGPartitionPtr);
}
if !(*define).data.is_null() && (*define).typ == XmlRelaxNGType::Choice {
xml_hash_free((*define).data as XmlHashTablePtr, None);
}
if !(*define).name.is_null() {
xml_free((*define).name as _);
}
if !(*define).ns.is_null() {
xml_free((*define).ns as _);
}
if !(*define).value.is_null() {
xml_free((*define).value as _);
}
drop_in_place(define);
xml_free(define as _);
}
}