#![allow(non_snake_case)]
use core::ffi::c_void;
use core::ptr;
use std::os::raw::{c_char, c_int};
use crate::abi::allocator;
use crate::abi::callbacks::*;
use crate::abi::structs::*;
use crate::abi::types::xmlChar;
use crate::abi::types::xmlDocProperties::{XML_DOC_DTDVALID, XML_DOC_NSVALID, XML_DOC_WELLFORMED};
use crate::abi::types::xmlElementType::*;
use crate::abi::types::XML_PARSE_COMPACT;
use crate::xml::tree;
pub(crate) mod default_sax_handler {
use super::*;
const unsafe fn ctxt_from_ctx(ctx: *mut c_void) -> *mut _xmlParserCtxt {
ctx as *mut _xmlParserCtxt
}
unsafe fn current_line(ctxt: *mut _xmlParserCtxt) -> u16 {
if ctxt.is_null() || (*ctxt).input.is_null() {
return 0;
}
let l = (*(*ctxt).input).line;
if l < 0 {
0
} else {
l as u16
}
}
unsafe fn merge_into_text_node(node: *mut _xmlNode, ch: *const xmlChar, len: c_int) {
if node.is_null() || ch.is_null() || len <= 0 {
return;
}
unsafe {
let existing_len = crate::xml::string::xml_strlen((*node).content);
let total = existing_len + len as usize;
if content_is_inline(node) {
let merged = allocator::xmlMallocImpl(total + 1) as *mut xmlChar;
if merged.is_null() {
return;
}
ptr::copy_nonoverlapping((*node).content, merged, existing_len);
ptr::copy_nonoverlapping(ch, merged.add(existing_len), len as usize);
*merged.add(total) = 0;
(*node).content = merged;
} else {
let new = allocator::xmlReallocImpl((*node).content as *mut c_void, total + 1)
as *mut xmlChar;
if new.is_null() {
return;
}
ptr::copy_nonoverlapping(ch, new.add(existing_len), len as usize);
*new.add(total) = 0;
(*node).content = new;
}
}
}
unsafe fn content_is_inline(node: *mut _xmlNode) -> bool {
if node.is_null() {
return false;
}
unsafe {
let inline_addr =
std::ptr::addr_of_mut!((*node).properties) as *mut xmlChar as *const c_void;
(*node).content as *const c_void == inline_addr
}
}
unsafe fn parser_new_text_node(
ctxt: *mut _xmlParserCtxt,
ch: *const xmlChar,
len: c_int,
force_noncompact: bool,
) -> *mut _xmlNode {
unsafe {
let compact = !force_noncompact
&& !ctxt.is_null()
&& ((*ctxt).options & XML_PARSE_COMPACT) != 0
&& (len as usize) < 16;
if compact {
let node = allocator::xmlMallocZero(size_of::<_xmlNode>()) as *mut _xmlNode;
if !node.is_null() {
(*node).type_ = XML_TEXT_NODE as c_int;
(*node).name = allocator::xmlMemStrdupImpl(c"text".as_ptr() as *const c_char)
as *mut xmlChar;
let inline = std::ptr::addr_of_mut!((*node).properties) as *mut xmlChar;
ptr::copy_nonoverlapping(ch, inline, len as usize);
*inline.add(len as usize) = 0;
(*node).content = inline;
crate::abi::data_globals::register_node_hook(node);
}
node
} else {
let content = allocator::xmlMallocImpl((len + 1) as usize) as *mut xmlChar;
if content.is_null() {
return ptr::null_mut();
}
ptr::copy_nonoverlapping(ch, content, len as usize);
*content.add(len as usize) = 0;
let text = tree::new_text(content as *const xmlChar);
allocator::xmlFreeImpl(content as *mut c_void);
text
}
}
}
unsafe fn parser_set_prop(
ctxt: *mut _xmlParserCtxt,
node: *mut _xmlNode,
name: *const xmlChar,
prefix: *const xmlChar,
value: *const xmlChar,
value_len: isize,
had_ref: bool,
) -> *mut _xmlAttr {
if node.is_null() || name.is_null() || value.is_null() || value_len <= 0 {
return ptr::null_mut();
}
unsafe {
let n = &mut *node;
let ns = if prefix.is_null() {
ptr::null_mut()
} else {
let mut found = ptr::null_mut();
let mut own = (*node).nsDef;
while !own.is_null() {
let d = &*own;
if !d.prefix.is_null()
&& crate::abi::exports_xml2::xmlStrEqual(d.prefix, prefix) != 0
{
found = own;
break;
}
own = (*own).next;
}
if found.is_null() {
let scope = if (*ctxt).node.is_null() {
(*ctxt).myDoc as *mut _xmlNode
} else {
(*ctxt).node
};
if !scope.is_null() {
found = tree::search_ns(n.doc, scope, prefix);
}
}
found
};
let mut existing = n.properties;
while !existing.is_null() {
let attr = &*existing;
let same_name = !attr.name.is_null()
&& crate::abi::exports_xml2::xmlStrEqual(attr.name, name) != 0;
let same_ns = match (attr.ns, ns) {
(a, b) if a == b => true,
(a, b) if a.is_null() || b.is_null() => false,
(a, b) => {
let (ah, bh) = ((*a).href, (*b).href);
!ah.is_null()
&& !bh.is_null()
&& crate::abi::exports_xml2::xmlStrEqual(ah, bh) != 0
}
};
if same_name && same_ns {
if !attr.children.is_null() {
tree::free_node_list(attr.children);
let attr_mut = existing;
(*attr_mut).children = ptr::null_mut();
(*attr_mut).last = ptr::null_mut();
}
let text = parser_new_text_node(ctxt, value, value_len as c_int, had_ref);
if !text.is_null() {
let attr_mut = existing;
(*attr_mut).children = text;
(*attr_mut).last = text;
(*text).parent = existing as *mut _xmlNode;
(*text).doc = (*ctxt).myDoc;
}
return existing;
}
existing = (*existing).next;
}
let attr = allocator::xmlMallocZero(size_of::<_xmlAttr>() as usize) as *mut _xmlAttr;
if attr.is_null() {
return ptr::null_mut();
}
(*attr).type_ = XML_ATTRIBUTE_NODE as c_int;
(*attr).name = crate::xml::string::xml_strdup(name);
(*attr).ns = ns;
(*attr).parent = node;
(*attr).doc = (*ctxt).myDoc;
let text = parser_new_text_node(ctxt, value, value_len as c_int, had_ref);
if !text.is_null() {
(*attr).children = text;
(*attr).last = text;
(*text).parent = attr as *mut _xmlNode;
(*text).doc = (*ctxt).myDoc;
}
if n.properties.is_null() {
n.properties = attr;
} else {
let mut last = n.properties;
while !(*last).next.is_null() {
last = (*last).next;
}
(*last).next = attr;
(*attr).prev = last;
}
attr
}
}
pub unsafe extern "C" fn startDocument(ctx: *mut c_void) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
let doc = tree::new_doc(ptr::null());
if doc.is_null() {
return;
}
c.myDoc = doc;
c.wellFormed = 1;
if !c.input.is_null() && !(*c.input).filename.is_null() {
(*doc).URL = crate::xml::string::xml_strdup(
(*c.input).filename as *const crate::abi::types::xmlChar,
);
}
(*doc).properties = 0;
(*doc).parseFlags = c.options;
(*doc).standalone = c.standalone;
if c.dictNames != 0 {
if c.dict.is_null() {
c.dict = crate::abi::exports_xml2::xmlDictCreate();
}
if !c.dict.is_null() {
(*doc).dict = c.dict;
crate::abi::exports_hash::xmlDictReference(c.dict);
}
}
}
}
pub unsafe extern "C" fn endDocument(ctx: *mut c_void) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return;
}
unsafe {
let c = &*ctxt;
if !c.myDoc.is_null() {
if !c.version.is_null() && (*c.myDoc).version.is_null() {
let dup = allocator::xmlMemStrdupImpl(c.version as *const c_char);
(*c.myDoc).version = dup as *mut xmlChar;
}
if !c.encoding.is_null() && (*c.myDoc).encoding.is_null() {
let dup = allocator::xmlMemStrdupImpl(c.encoding as *const c_char);
(*c.myDoc).encoding = dup as *mut xmlChar;
}
if c.wellFormed != 0 {
(*(c.myDoc)).properties |= XML_DOC_WELLFORMED as c_int;
if c.valid != 0 {
(*(c.myDoc)).properties |= XML_DOC_DTDVALID as c_int;
}
if c.nsWellFormed != 0 {
(*(c.myDoc)).properties |= XML_DOC_NSVALID as c_int;
}
}
}
}
}
#[allow(clippy::too_many_arguments)]
pub unsafe extern "C" fn startElementNs(
ctx: *mut c_void,
localname: *const xmlChar,
prefix: *const xmlChar,
URI: *const xmlChar,
nb_namespaces: c_int,
namespaces: *mut *const xmlChar,
nb_attributes: c_int,
_nb_defaulted: c_int,
attributes: *mut *const xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || localname.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
ptr::null_mut()
};
let name_owned: Vec<u8>;
let (node_name, ns) = if URI.is_null() && !prefix.is_null() {
let mut q = Vec::new();
q.extend_from_slice({
core::slice::from_raw_parts(
prefix,
crate::xml::tree::xml_strlen(prefix) as usize,
)
});
q.push(b':');
q.extend_from_slice({
core::slice::from_raw_parts(
localname,
crate::xml::tree::xml_strlen(localname) as usize,
)
});
q.push(0);
name_owned = q;
(name_owned.as_ptr() as *const xmlChar, ptr::null_mut())
} else if URI.is_null() && prefix.is_null() {
(localname, ptr::null_mut())
} else {
(localname, tree::search_ns(c.myDoc, parent, prefix))
};
let node = tree::new_node(ns, node_name);
if node.is_null() {
return;
}
(*node).line = current_line(ctxt);
let mut own_ns: *mut _xmlNs = ptr::null_mut();
if nb_namespaces > 0 && !namespaces.is_null() {
let mut i: c_int = 0;
while i < nb_namespaces {
let ns_prefix = *namespaces.add((i * 2) as usize);
let ns_uri = *namespaces.add((i * 2 + 1) as usize);
let new_ns = tree::new_ns(node, ns_uri, ns_prefix);
if own_ns.is_null() && !URI.is_null() && !new_ns.is_null() {
let same = if ns_prefix.is_null() {
prefix.is_null()
} else if prefix.is_null() {
false
} else {
crate::abi::exports_xml2::xmlStrEqual(ns_prefix, prefix) != 0
};
if same {
own_ns = new_ns;
}
}
i += 1;
}
}
if !own_ns.is_null() {
(*node).ns = own_ns;
}
if nb_attributes > 0 && !attributes.is_null() {
let mut i: c_int = 0;
while i < nb_attributes {
let attr_idx = (i * 5) as usize;
let attr_name = *attributes.add(attr_idx); let attr_prefix = *attributes.add(attr_idx + 1); let attr_uri = *attributes.add(attr_idx + 2); let attr_value_start = *attributes.add(attr_idx + 3); let attr_value_end = *attributes.add(attr_idx + 4);
if !attr_name.is_null() && !attr_value_start.is_null() {
let had_ref = !attr_value_end.is_null();
let value_len = if attr_value_end.is_null() {
let mut len: isize = 0;
{
while *attr_value_start.offset(len) != 0 {
len += 1;
}
}
len
} else {
attr_value_end.offset_from(attr_value_start)
};
if value_len > 0 {
let qname_owned: Vec<u8>;
let (attr_name_eff, attr_prefix_eff) =
if !attr_prefix.is_null() && attr_uri.is_null() {
let mut q: Vec<u8> = Vec::new();
q.extend_from_slice({
core::slice::from_raw_parts(
attr_prefix,
crate::xml::tree::xml_strlen(attr_prefix) as usize,
)
});
q.push(b':');
q.extend_from_slice({
core::slice::from_raw_parts(
attr_name,
crate::xml::tree::xml_strlen(attr_name) as usize,
)
});
q.push(0);
qname_owned = q;
(qname_owned.as_ptr() as *const xmlChar, ptr::null())
} else {
(attr_name, attr_prefix)
};
let attr = parser_set_prop(
ctxt,
node,
attr_name_eff,
attr_prefix_eff,
attr_value_start,
value_len,
had_ref,
);
if !attr.is_null() {
let av = (*attr).children;
let v = if av.is_null() || (*av).content.is_null() {
ptr::null()
} else {
(*av).content
};
if !v.is_null() {
let res = crate::xml::validation::is_id(c.myDoc, node, attr);
if res > 0 {
crate::xml::validation::add_id(
ptr::null_mut(),
c.myDoc,
v,
attr,
);
} else if crate::xml::validation::is_ref(c.myDoc, node, attr)
> 0
{
crate::xml::validation::add_ref(
ptr::null_mut(),
c.myDoc,
v,
attr,
);
}
}
}
}
}
i += 1;
}
}
if !parent.is_null() {
tree::add_child(parent, node);
} else {
if !c.myDoc.is_null() {
tree::add_child(c.myDoc as *mut _xmlNode, node);
}
}
c.node = node;
let max_depth = if (c.options & crate::abi::types::XML_PARSE_HUGE) != 0 {
2048
} else {
256
};
if c.nodeNr >= max_depth {
let msg = std::ffi::CString::new(format!(
"Excessive depth in document: {}, use XML_PARSE_HUGE option\n",
c.nodeNr
))
.unwrap_or_default();
c.errNo = crate::abi::types::XML_ERR_RESOURCE_LIMIT;
c.wellFormed = 0;
c.nbErrors = c.nbErrors.wrapping_add(1);
c.disableSAX = 2;
crate::xml::errors::raise_error(
ctxt as *mut c_void,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
crate::abi::types::XML_FROM_PARSER,
crate::abi::types::XML_ERR_RESOURCE_LIMIT,
crate::abi::types::xmlErrorLevel::XML_ERR_FATAL as c_int,
ptr::null(),
0,
ptr::null(),
ptr::null(),
ptr::null(),
0,
0,
msg.as_ptr(),
);
return;
}
if c.nodeNr >= c.nodeMax {
let new_max = if c.nodeMax == 0 { 8 } else { c.nodeMax * 2 };
let new_size = (new_max as usize) * size_of::<*mut _xmlNode>();
let new_tab = allocator::xmlReallocImpl(c.nodeTab as *mut c_void, new_size)
as *mut *mut _xmlNode;
if !new_tab.is_null() {
c.nodeTab = new_tab;
c.nodeMax = new_max;
}
}
if c.nodeNr < c.nodeMax && !c.nodeTab.is_null() {
*c.nodeTab.add(c.nodeNr as usize) = node;
c.nodeNr += 1;
}
}
}
pub unsafe extern "C" fn endElementNs(
ctx: *mut c_void,
_localname: *const xmlChar,
_prefix: *const xmlChar,
_URI: *const xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
if c.nodeNr > 0 {
c.nodeNr -= 1;
}
if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
c.node = *c.nodeTab.add(idx);
} else {
c.node = ptr::null_mut();
}
}
}
pub unsafe extern "C" fn characters(ctx: *mut c_void, ch: *const xmlChar, len: c_int) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || ch.is_null() || len <= 0 {
return;
}
unsafe {
let c = &*ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
c.myDoc as *mut _xmlNode
};
if parent.is_null() {
return;
}
let mut last = (*parent).children;
if !last.is_null() {
while !(*last).next.is_null() {
last = (*last).next;
}
if (*last).type_ == XML_TEXT_NODE as c_int {
merge_into_text_node(last, ch, len);
return;
}
}
let text = parser_new_text_node(ctxt, ch, len, false);
if !text.is_null() {
(*text).line = current_line(ctxt);
tree::add_child(parent, text);
}
}
}
pub unsafe extern "C" fn ignorableWhitespace(ctx: *mut c_void, ch: *const xmlChar, len: c_int) {
unsafe { characters(ctx, ch, len) };
}
pub unsafe extern "C" fn comment(ctx: *mut c_void, value: *const xmlChar) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return;
}
unsafe {
let c = &*ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
c.myDoc as *mut _xmlNode
};
if parent.is_null() {
return;
}
let comment_node = tree::new_comment(value);
if !comment_node.is_null() {
(*comment_node).line = current_line(ctxt);
tree::add_child(parent, comment_node);
}
}
}
pub unsafe extern "C" fn processingInstruction(
ctx: *mut c_void,
target: *const xmlChar,
data: *const xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || target.is_null() {
return;
}
unsafe {
let c = &*ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
c.myDoc as *mut _xmlNode
};
if parent.is_null() {
return;
}
let pi_node = tree::new_pi(target, data);
if !pi_node.is_null() {
(*pi_node).line = current_line(ctxt);
tree::add_child(parent, pi_node);
}
}
}
pub unsafe extern "C" fn cdataBlock(ctx: *mut c_void, value: *const xmlChar, len: c_int) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || value.is_null() || len <= 0 {
return;
}
unsafe {
let c = &*ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
c.myDoc as *mut _xmlNode
};
if parent.is_null() {
return;
}
let cdata = tree::new_cdata_block(c.myDoc, value, len);
if !cdata.is_null() {
(*cdata).line = current_line(ctxt);
tree::add_child(parent, cdata);
}
}
}
pub unsafe extern "C" fn internalSubset(
ctx: *mut c_void,
name: *const xmlChar,
ext_id: *const xmlChar,
sys_id: *const xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
if c.myDoc.is_null() {
return;
}
let old = (*(c.myDoc)).intSubset;
if !old.is_null() {
tree::unlink_node(old as *mut crate::abi::structs::_xmlNode);
crate::xml::dtd::free_dtd(old);
(*(c.myDoc)).intSubset = ptr::null_mut();
}
crate::xml::dtd::create_int_subset(c.myDoc, name, ext_id, sys_id);
}
}
pub unsafe extern "C" fn externalSubset(
ctx: *mut c_void,
name: *const xmlChar,
ext_id: *const xmlChar,
sys_id: *const xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
if c.myDoc.is_null() {
return;
}
if (*(c.myDoc)).intSubset.is_null() {
let dtd = tree::new_dtd(c.myDoc, name, ext_id, sys_id);
if !dtd.is_null() {
(*(c.myDoc)).extSubset = dtd;
}
} else {
let dtd = (*(c.myDoc)).intSubset;
if !ext_id.is_null() {
let ext_copy = tree::xml_strlen(ext_id);
if ext_copy > 0 {
(*(c.myDoc)).extSubset = dtd;
}
}
}
}
}
pub unsafe extern "C" fn entityDecl(
ctx: *mut c_void,
name: *const xmlChar,
type_: c_int,
pub_id: *const xmlChar,
sys_id: *const xmlChar,
content: *mut xmlChar,
) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return;
}
unsafe {
let c = &*ctxt;
if c.myDoc.is_null() {
return;
}
let _entity = tree::new_entity(
c.myDoc,
name,
type_,
pub_id,
sys_id,
content as *const xmlChar,
);
}
}
pub const unsafe extern "C" fn attributeDecl(
_ctx: *mut c_void,
_elem: *const xmlChar,
_fullname: *const xmlChar,
_type_: c_int,
_def: c_int,
_default_value: *const xmlChar,
_tree: *mut _xmlEnumeration,
) {
}
pub const unsafe extern "C" fn elementDecl(
_ctx: *mut c_void,
_name: *const xmlChar,
_type_: c_int,
_content: *mut _xmlElementContent,
) {
}
pub const unsafe extern "C" fn notationDecl(
_ctx: *mut c_void,
_name: *const xmlChar,
_pub_id: *const xmlChar,
_sys_id: *const xmlChar,
) {
}
pub const unsafe extern "C" fn unparsedEntityDecl(
_ctx: *mut c_void,
_name: *const xmlChar,
_pub_id: *const xmlChar,
_sys_id: *const xmlChar,
_notation: *const xmlChar,
) {
}
pub const unsafe extern "C" fn resolveEntity(
_ctx: *mut c_void,
_pub_id: *const xmlChar,
_sys_id: *const xmlChar,
) -> *mut _xmlParserInput {
ptr::null_mut()
}
pub const unsafe extern "C" fn isStandalone(_ctx: *mut c_void) -> c_int {
-1
}
pub unsafe extern "C" fn hasInternalSubset(ctx: *mut c_void) -> c_int {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return 0;
}
unsafe {
let c = &*ctxt;
if c.myDoc.is_null() {
return 0;
}
if (*(c.myDoc)).intSubset.is_null() {
0
} else {
1
}
}
}
pub unsafe extern "C" fn hasExternalSubset(ctx: *mut c_void) -> c_int {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() {
return 0;
}
unsafe {
let c = &*ctxt;
if c.myDoc.is_null() {
return 0;
}
if (*(c.myDoc)).extSubset.is_null() {
0
} else {
1
}
}
}
pub unsafe extern "C" fn getEntity(ctx: *mut c_void, name: *const xmlChar) -> *mut _xmlEntity {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return ptr::null_mut();
}
unsafe {
let c = &*ctxt;
if c.myDoc.is_null() {
return ptr::null_mut();
}
tree::get_doc_entity(c.myDoc, name)
}
}
pub unsafe extern "C" fn getParameterEntity(
ctx: *mut c_void,
name: *const xmlChar,
) -> *mut _xmlEntity {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return ptr::null_mut();
}
unsafe {
let c = &*ctxt;
if c.myDoc.is_null() {
return ptr::null_mut();
}
tree::get_parameter_entity(c.myDoc, name)
}
}
pub const unsafe extern "C" fn setDocumentLocator(
_ctx: *mut c_void,
_loc: *mut _xmlSAXLocator,
) {
}
pub const unsafe extern "C" fn getPublicId(_ctx: *mut c_void) -> *const xmlChar {
ptr::null()
}
pub unsafe extern "C" fn getSystemId(ctx: *mut c_void) -> *const xmlChar {
if ctx.is_null() {
return ptr::null();
}
let ctxt = ctx as *mut crate::abi::structs::_xmlParserCtxt;
unsafe {
if (*ctxt).input.is_null() {
return ptr::null();
}
let filename = (*(*ctxt).input).filename;
if filename.is_null() {
ptr::null()
} else {
filename as *const xmlChar
}
}
}
pub unsafe extern "C" fn getLineNumber(ctx: *mut c_void) -> c_int {
if ctx.is_null() {
return 0;
}
let ctxt = ctx as *mut crate::abi::structs::_xmlParserCtxt;
unsafe {
if (*ctxt).input.is_null() {
0
} else {
(*(*ctxt).input).line
}
}
}
pub unsafe extern "C" fn getColumnNumber(ctx: *mut c_void) -> c_int {
if ctx.is_null() {
return 0;
}
let ctxt = ctx as *mut crate::abi::structs::_xmlParserCtxt;
unsafe {
if (*ctxt).input.is_null() {
0
} else {
(*(*ctxt).input).col
}
}
}
pub unsafe extern "C" fn reference(ctx: *mut c_void, name: *const xmlChar) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || name.is_null() {
return;
}
unsafe {
let c = &*ctxt;
let parent = if c.nodeNr > 0 && !c.nodeTab.is_null() {
let idx = (c.nodeNr - 1) as usize;
*c.nodeTab.add(idx)
} else {
c.myDoc as *mut _xmlNode
};
if parent.is_null() {
return;
}
let ent = crate::xml::entities::get_entity(c.myDoc, name);
let ref_node = allocator::xmlMallocZero(size_of::<_xmlNode>()) as *mut _xmlNode;
if !ref_node.is_null() {
(*ref_node).type_ = XML_ENTITY_REF_NODE as c_int;
(*ref_node).name = crate::xml::string::xml_strdup(name);
(*ref_node).doc = c.myDoc;
(*ref_node).line = current_line(ctxt);
if !ent.is_null() {
(*ref_node).content = (*ent).content;
(*ref_node).children = ent as *mut _xmlNode;
(*ref_node).last = ent as *mut _xmlNode;
}
tree::add_child(parent, ref_node);
}
}
}
#[allow(dead_code)]
pub unsafe extern "C" fn warning(ctx: *mut c_void, msg: *const c_char) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || msg.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
c.nbWarnings += 1;
}
}
pub unsafe extern "C" fn error(ctx: *mut c_void, msg: *const c_char) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || msg.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
c.nbErrors += 1;
c.wellFormed = 0;
}
}
#[allow(dead_code)]
pub unsafe extern "C" fn fatalError(ctx: *mut c_void, msg: *const c_char) {
let ctxt = unsafe { ctxt_from_ctx(ctx) };
if ctxt.is_null() || msg.is_null() {
return;
}
unsafe {
let c = &mut *ctxt;
c.nbErrors += 1;
c.wellFormed = 0;
}
}
}