use std::ptr::{drop_in_place, null_mut};
use crate::{
globals::{GLOBAL_STATE, GenericError, GenericErrorContext, StructuredError},
hash::XmlHashTableRef,
libxml::{
globals::{xml_free, xml_malloc},
relaxng::{
XmlRelaxNGDocumentPtr, XmlRelaxNGGrammarPtr, XmlRelaxNGIncludePtr,
XmlRelaxNGParserFlag, XmlRelaxNGPtr, XmlRelaxNGValidErr, xml_relaxng_free_document,
xml_relaxng_free_document_list, xml_relaxng_free_include_list,
},
xmlautomata::XmlAutomata,
},
tree::{XmlDocPtr, xml_copy_doc, xml_free_doc},
};
use super::{XmlRelaxNGDefinePtr, xml_relaxng_free_define, xml_rng_perr_memory};
pub type XmlRelaxNGParserCtxtPtr = *mut XmlRelaxNGParserCtxt;
#[repr(C)]
pub struct XmlRelaxNGParserCtxt {
pub(crate) user_data: Option<GenericErrorContext>, pub(crate) error: Option<GenericError>, pub(crate) warning: Option<GenericError>, pub(crate) serror: Option<StructuredError>,
err: XmlRelaxNGValidErr,
schema: XmlRelaxNGPtr, pub(crate) grammar: XmlRelaxNGGrammarPtr, pub(crate) parentgrammar: XmlRelaxNGGrammarPtr, pub(crate) flags: i32, pub(crate) nb_errors: i32, nb_warnings: i32, pub(crate) define: *const u8, pub(crate) def: XmlRelaxNGDefinePtr,
pub(crate) nb_interleaves: i32,
pub(crate) interleaves: Option<XmlHashTableRef<'static, XmlRelaxNGDefinePtr>>,
pub(crate) documents: XmlRelaxNGDocumentPtr, pub(crate) includes: XmlRelaxNGIncludePtr, pub(crate) url: Option<String>,
pub(crate) document: Option<XmlDocPtr>,
pub(crate) def_tab: Vec<XmlRelaxNGDefinePtr>,
pub(crate) buffer: *const i8,
pub(crate) size: i32,
pub(crate) doc: XmlRelaxNGDocumentPtr, pub(crate) doc_tab: Vec<XmlRelaxNGDocumentPtr>,
pub(crate) inc: XmlRelaxNGIncludePtr, pub(crate) inc_tab: Vec<XmlRelaxNGIncludePtr>,
pub(crate) idref: i32,
pub(crate) am: Option<XmlAutomata>, pub(crate) state: usize,
pub(crate) crng: i32, pub(crate) freedoc: i32, }
impl XmlRelaxNGParserCtxt {
#[doc(alias = "xmlRelaxNGDocumentPush")]
pub(crate) fn document_push(&mut self, value: XmlRelaxNGDocumentPtr) -> usize {
self.doc_tab.push(value);
self.doc = value;
self.doc_tab.len() - 1
}
#[doc(alias = "xmlRelaxNGDocumentPop")]
pub(crate) fn document_pop(&mut self) -> XmlRelaxNGDocumentPtr {
let Some(doc) = self.doc_tab.pop() else {
return null_mut();
};
self.doc = *self.doc_tab.last().unwrap_or(&null_mut());
doc
}
#[doc(alias = "xmlRelaxNGIncludePush")]
pub(crate) fn include_push(&mut self, value: XmlRelaxNGIncludePtr) -> usize {
self.inc_tab.push(value);
self.inc = value;
self.inc_tab.len() - 1
}
#[doc(alias = "xmlRelaxNGIncludePop")]
pub(crate) fn include_pop(&mut self) -> XmlRelaxNGIncludePtr {
let Some(inc) = self.inc_tab.pop() else {
return null_mut();
};
self.inc = *self.inc_tab.last().unwrap_or(&null_mut());
inc
}
#[doc(alias = "xmlRelaxParserSetFlag")]
pub fn set_flag(&mut self, mut flags: i32) -> i32 {
if flags & XmlRelaxNGParserFlag::FreeDoc as i32 != 0 {
self.crng |= XmlRelaxNGParserFlag::FreeDoc as i32;
flags -= XmlRelaxNGParserFlag::FreeDoc as i32;
}
if flags & XmlRelaxNGParserFlag::Crng as i32 != 0 {
self.crng |= XmlRelaxNGParserFlag::Crng as i32;
flags -= XmlRelaxNGParserFlag::Crng as i32;
}
if flags != 0 {
return -1;
}
0
}
#[doc(alias = "xmlRelaxNGGetParserErrors")]
pub fn get_parser_errors(
&self,
) -> (
Option<GenericError>,
Option<GenericError>,
Option<GenericErrorContext>,
) {
(self.error, self.warning, self.user_data.clone())
}
#[doc(alias = "xmlRelaxNGSetParserErrors")]
pub fn set_parser_errors(
&mut self,
err: Option<GenericError>,
warn: Option<GenericError>,
ctx: Option<GenericErrorContext>,
) {
self.error = err;
self.warning = warn;
self.serror = None;
self.user_data = ctx;
}
#[doc(alias = "xmlRelaxNGSetParserStructuredErrors")]
pub fn set_parser_structured_errors(
&mut self,
serror: Option<StructuredError>,
ctx: Option<GenericErrorContext>,
) {
self.serror = serror;
self.error = None;
self.warning = None;
self.user_data = ctx;
}
}
impl Default for XmlRelaxNGParserCtxt {
fn default() -> Self {
Self {
user_data: None,
error: None,
warning: None,
serror: None,
err: XmlRelaxNGValidErr::default(),
schema: null_mut(),
grammar: null_mut(),
parentgrammar: null_mut(),
flags: 0,
nb_errors: 0,
nb_warnings: 0,
define: null_mut(),
def: null_mut(),
nb_interleaves: 0,
interleaves: None,
documents: null_mut(),
includes: null_mut(),
url: None,
document: None,
def_tab: vec![],
buffer: null_mut(),
size: 0,
doc: null_mut(),
doc_tab: vec![],
inc: null_mut(),
inc_tab: vec![],
idref: 0,
am: None,
state: usize::MAX,
crng: 0,
freedoc: 0,
}
}
}
#[doc(alias = "xmlRelaxNGNewParserCtxt")]
pub unsafe fn xml_relaxng_new_parser_ctxt(url: &str) -> XmlRelaxNGParserCtxtPtr {
unsafe {
let ret: XmlRelaxNGParserCtxtPtr = xml_malloc(size_of::<XmlRelaxNGParserCtxt>()) as _;
if ret.is_null() {
xml_rng_perr_memory(null_mut(), Some("building parser\n"));
return null_mut();
}
std::ptr::write(&mut *ret, XmlRelaxNGParserCtxt::default());
(*ret).url = Some(url.to_owned());
GLOBAL_STATE.with_borrow(|state| {
(*ret).error = Some(state.generic_error);
(*ret).user_data = state.generic_error_context.clone();
});
ret
}
}
#[doc(alias = "xmlRelaxNGNewMemParserCtxt")]
pub unsafe fn xml_relaxng_new_mem_parser_ctxt(
buffer: *const i8,
size: i32,
) -> XmlRelaxNGParserCtxtPtr {
unsafe {
if buffer.is_null() || size <= 0 {
return null_mut();
}
let ret: XmlRelaxNGParserCtxtPtr = xml_malloc(size_of::<XmlRelaxNGParserCtxt>()) as _;
if ret.is_null() {
xml_rng_perr_memory(null_mut(), Some("building parser\n"));
return null_mut();
}
std::ptr::write(&mut *ret, XmlRelaxNGParserCtxt::default());
(*ret).buffer = buffer;
(*ret).size = size;
GLOBAL_STATE.with_borrow(|state| {
(*ret).error = Some(state.generic_error);
(*ret).user_data = state.generic_error_context.clone();
});
ret
}
}
#[doc(alias = "xmlRelaxNGNewDocParserCtxt")]
pub unsafe fn xml_relaxng_new_doc_parser_ctxt(doc: XmlDocPtr) -> XmlRelaxNGParserCtxtPtr {
unsafe {
let Some(copy) = xml_copy_doc(doc, 1) else {
return null_mut();
};
let ret: XmlRelaxNGParserCtxtPtr = xml_malloc(size_of::<XmlRelaxNGParserCtxt>()) as _;
if ret.is_null() {
xml_rng_perr_memory(null_mut(), Some("building parser\n"));
xml_free_doc(copy);
return null_mut();
}
std::ptr::write(&mut *ret, XmlRelaxNGParserCtxt::default());
(*ret).document = Some(copy);
(*ret).freedoc = 1;
GLOBAL_STATE.with_borrow(|state| {
(*ret).user_data = state.generic_error_context.clone();
});
ret
}
}
#[doc(alias = "xmlRelaxNGFreeParserCtxt")]
pub unsafe fn xml_relaxng_free_parser_ctxt(ctxt: XmlRelaxNGParserCtxtPtr) {
unsafe {
if ctxt.is_null() {
return;
}
(*ctxt).url.take();
if !(*ctxt).doc.is_null() {
xml_relaxng_free_document((*ctxt).doc);
}
if let Some(mut table) = (*ctxt).interleaves.take().map(|t| t.into_inner()) {
table.clear();
}
if !(*ctxt).documents.is_null() {
xml_relaxng_free_document_list((*ctxt).documents);
}
if !(*ctxt).includes.is_null() {
xml_relaxng_free_include_list((*ctxt).includes);
}
for def in (*ctxt).def_tab.drain(..) {
xml_relaxng_free_define(def);
}
if let Some(document) = (*ctxt).document.take().filter(|_| (*ctxt).freedoc != 0) {
xml_free_doc(document);
}
drop_in_place(ctxt);
xml_free(ctxt as _);
}
}