use std::{
borrow::Cow,
ffi::{CStr, CString, c_char},
mem::{size_of, take},
os::raw::c_void,
ptr::{drop_in_place, fn_addr_eq, null, null_mut},
rc::Rc,
slice::from_raw_parts,
};
use libc::{memset, strchr};
#[cfg(feature = "libxml_automata")]
use crate::libxml::xmlautomata::XmlAutomata;
#[cfg(feature = "libxml_pattern")]
use crate::pattern::{XmlPattern, XmlPatternFlags, XmlStreamCtxt, xml_pattern_compile};
use crate::{
chvalid::XmlCharValid,
dom::elementdecl::ElementContent,
encoding::XmlCharEncoding,
error::{XmlErrorDomain, XmlParserErrors},
generic_error,
globals::{GLOBAL_STATE, GenericErrorContext},
io::XmlParserInputBuffer,
libxml::{
dict::{XmlDictPtr, xml_dict_free, xml_dict_lookup, xml_dict_reference},
globals::{xml_free, xml_malloc, xml_realloc},
hash::{
XmlHashTablePtr, xml_hash_add_entry, xml_hash_add_entry2, xml_hash_create,
xml_hash_free, xml_hash_lookup, xml_hash_lookup2,
},
sax2::xml_sax2_get_line_number,
schemas_internals::{
XML_SCHEMAS_ANY_LAX, XML_SCHEMAS_ANY_SKIP, XML_SCHEMAS_ANY_STRICT,
XML_SCHEMAS_ATTR_FIXED, XML_SCHEMAS_ATTR_INTERNAL_RESOLVED,
XML_SCHEMAS_ATTR_USE_OPTIONAL, XML_SCHEMAS_ATTR_USE_REQUIRED,
XML_SCHEMAS_ATTRGROUP_GLOBAL, XML_SCHEMAS_ATTRGROUP_HAS_REFS,
XML_SCHEMAS_ATTRGROUP_MARKED, XML_SCHEMAS_ATTRGROUP_REDEFINED,
XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED, XML_SCHEMAS_ELEM_ABSTRACT,
XML_SCHEMAS_ELEM_BLOCK_EXTENSION, XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, XML_SCHEMAS_ELEM_CIRCULAR,
XML_SCHEMAS_ELEM_FINAL_EXTENSION, XML_SCHEMAS_ELEM_FINAL_RESTRICTION,
XML_SCHEMAS_ELEM_FIXED, XML_SCHEMAS_ELEM_GLOBAL, XML_SCHEMAS_ELEM_INTERNAL_CHECKED,
XML_SCHEMAS_ELEM_INTERNAL_RESOLVED, XML_SCHEMAS_ELEM_NILLABLE,
XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD, XML_SCHEMAS_FACET_COLLAPSE,
XML_SCHEMAS_FACET_PRESERVE, XML_SCHEMAS_FACET_REPLACE,
XML_SCHEMAS_INCLUDING_CONVERT_NS, XML_SCHEMAS_TYPE_ABSTRACT,
XML_SCHEMAS_TYPE_BLOCK_EXTENSION, XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE, XML_SCHEMAS_TYPE_FACETSNEEDVALUE,
XML_SCHEMAS_TYPE_FINAL_EXTENSION, XML_SCHEMAS_TYPE_FINAL_LIST,
XML_SCHEMAS_TYPE_FINAL_RESTRICTION, XML_SCHEMAS_TYPE_FINAL_UNION,
XML_SCHEMAS_TYPE_FIXUP_1, XML_SCHEMAS_TYPE_HAS_FACETS,
XML_SCHEMAS_TYPE_INTERNAL_INVALID, XML_SCHEMAS_TYPE_INTERNAL_RESOLVED,
XML_SCHEMAS_TYPE_MARKED, XML_SCHEMAS_TYPE_MIXED, XML_SCHEMAS_TYPE_NORMVALUENEEDED,
XML_SCHEMAS_TYPE_REDEFINED, XML_SCHEMAS_TYPE_VARIETY_ATOMIC,
XML_SCHEMAS_TYPE_VARIETY_LIST, XML_SCHEMAS_TYPE_VARIETY_UNION,
XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE, XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE,
XML_SCHEMAS_TYPE_WHITESPACE_REPLACE, XmlSchemaAnnot, XmlSchemaAnnotPtr,
XmlSchemaContentType, XmlSchemaFacetLink, XmlSchemaFacetLinkPtr, XmlSchemaFacetPtr,
XmlSchemaTypeLink, XmlSchemaTypeLinkPtr, XmlSchemaTypeType, XmlSchemaValType,
XmlSchemaWildcard, XmlSchemaWildcardNs, XmlSchemaWildcardNsPtr, XmlSchemaWildcardPtr,
xml_schema_free_annot, xml_schema_free_type, xml_schema_free_wildcard,
xml_schema_free_wildcard_ns_set,
},
xmlregexp::{XmlRegExecCtxtPtr, xml_regexp_exec},
xmlschemastypes::{
XmlSchemaValPtr, XmlSchemaWhitespaceValueType, xml_schema_check_facet,
xml_schema_compare_values, xml_schema_compare_values_whtsp, xml_schema_copy_value,
xml_schema_free_value, xml_schema_get_built_in_type, xml_schema_get_canon_value,
xml_schema_get_val_type, xml_schema_is_built_in_type_facet,
xml_schema_new_notation_value, xml_schema_new_qname_value,
xml_schema_val_predef_type_node_no_norm, xml_schema_validate_facet_whtsp,
xml_schema_validate_length_facet_whtsp, xml_schema_validate_list_simple_type_facet,
xml_schema_value_append, xml_schema_value_get_as_boolean,
xml_schema_value_get_as_string, xml_schema_value_get_next,
},
xmlstring::{
XmlChar, xml_str_equal, xml_strcat, xml_strdup, xml_strlen, xml_strncat,
xml_strncat_new, xml_strndup,
},
},
parser::{
XML_SAX2_MAGIC, XmlParserCtxt, XmlParserCtxtPtr, XmlParserInput, XmlParserOption,
XmlSAXHandler, XmlSAXLocator, split_qname2, xml_ctxt_read_file, xml_ctxt_read_memory,
},
tree::{
NodeCommon, XmlAttrPtr, XmlAttributeDefault, XmlAttributeType, XmlDocPtr, XmlElementType,
XmlElementTypeVal, XmlEntityPtr, XmlEntityType, XmlEnumeration, XmlGenericNodePtr,
XmlNodePtr, validate_ncname, validate_qname, xml_free_doc, xml_free_node, xml_new_doc_text,
xml_new_ns, xml_new_ns_prop, xml_new_prop,
},
uri::build_uri,
valid::xml_add_id,
xmlschemas::{
context::{
XmlSchemaParserCtxtPtr, XmlSchemaValidCtxtPtr, xml_schema_new_parser_ctxt,
xml_schema_new_parser_ctxt_use_dict, xml_schema_new_valid_ctxt,
},
error::{
xml_schema_complex_type_err, xml_schema_custom_err, xml_schema_custom_err4,
xml_schema_custom_warning, xml_schema_derive_facet_err, xml_schema_facet_err,
xml_schema_illegal_attr_err, xml_schema_internal_err2, xml_schema_keyref_err,
xml_schema_pattr_use_err4, xml_schema_pcustom_attr_err, xml_schema_pcustom_err,
xml_schema_pcustom_err_ext, xml_schema_perr, xml_schema_perr_memory,
xml_schema_pillegal_facet_atomic_err, xml_schema_pillegal_facet_list_union_err,
xml_schema_pres_comp_attr_err, xml_schema_psimple_internal_err,
xml_schema_psimple_type_err, xml_schema_simple_type_err, xml_schema_verr_memory,
},
is_schema,
item_list::{XmlSchemaItemListPtr, xml_schema_item_list_create, xml_schema_item_list_free},
items::{
XmlSchemaAnnotItemPtr, XmlSchemaAttribute, XmlSchemaAttributeGroup,
XmlSchemaAttributeGroupPtr, XmlSchemaAttributePtr, XmlSchemaAttributeUse,
XmlSchemaAttributeUseProhib, XmlSchemaAttributeUseProhibPtr, XmlSchemaAttributeUsePtr,
XmlSchemaBasicItemPtr, XmlSchemaElement, XmlSchemaElementPtr, XmlSchemaIDC,
XmlSchemaIDCPtr, XmlSchemaItem, XmlSchemaModelGroup, XmlSchemaModelGroupDef,
XmlSchemaModelGroupDefPtr, XmlSchemaModelGroupPtr, XmlSchemaNotation,
XmlSchemaNotationPtr, XmlSchemaParticle, XmlSchemaParticlePtr, XmlSchemaQNameRef,
XmlSchemaQNameRefPtr, XmlSchemaTreeItemPtr, XmlSchemaType, XmlSchemaTypePtr,
xml_schema_free_attribute_use_prohib,
},
schema::{XmlSchemaPtr, xml_schema_free},
wxs_is_any_simple_type, wxs_is_anytype, wxs_is_complex, wxs_is_simple,
},
xmlschemastypes::{xml_schema_collapse_string, xml_schema_white_space_replace},
};
use super::xmlregexp::XmlRegExecCtxt;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum XmlSchemaValidError {
XmlSchemasErrOK = 0,
XmlSchemasErrNoRoot = 1,
XmlSchemasErrUndeclaredElem,
XmlSchemasErrNotTopLevel,
XmlSchemasErrMissing,
XmlSchemasErrWrongElem,
XmlSchemasErrNoType,
XmlSchemasErrNoRollback,
XmlSchemasErrIsAbstract,
XmlSchemasErrNotEmpty,
XmlSchemasErrElemCont,
XmlSchemasErrHaveDefault,
XmlSchemasErrNotNillable,
XmlSchemasErrExtraContent,
XmlSchemasErrInvalidAttr,
XmlSchemasErrInvalidElem,
XmlSchemasErrNotDeterminist,
XmlSchemasErrConstruct,
XmlSchemasErrInternal,
XmlSchemasErrNotSimple,
XmlSchemasErrAttrUnknown,
XmlSchemasErrAttrInvalid,
XmlSchemasErrValue,
XmlSchemasErrFacet,
XmlSchemasErr,
XmlSchemasErrXxx,
}
#[doc(alias = "xmlSchemaValidOption")]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum XmlSchemaValidOption {
XmlSchemaValVcICreate = 1 << 0,
}
#[doc(alias = "xmlSchemaValidityErrorFunc")]
pub type XmlSchemaValidityErrorFunc = unsafe fn(ctx: *mut c_void, msg: *const c_char);
#[doc(alias = "xmlSchemaValidityWarningFunc")]
pub type XmlSchemaValidityWarningFunc = unsafe fn(ctx: *mut c_void, msg: *const c_char);
#[doc(alias = "xmlSchemaValidityLocatorFunc")]
pub type XmlSchemaValidityLocatorFunc =
unsafe fn(ctx: *mut c_void, file: *mut Option<String>, line: *mut u64) -> i32;
const UNBOUNDED: usize = 1 << 30;
pub(crate) const XML_SCHEMAS_NO_NAMESPACE: &str = "##";
pub(crate) const XML_SCHEMA_NS: &CStr = c"http://www.w3.org/2001/XMLSchema";
pub(crate) const XML_SCHEMA_INSTANCE_NS: &CStr = c"http://www.w3.org/2001/XMLSchema-instance";
const XML_NAMESPACE_NS: &CStr = c"http://www.w3.org/2000/xmlns/";
macro_rules! WXS_ATTR_TYPEDEF {
($a:expr) => {
(*$a).subtypes
};
}
macro_rules! WXS_ATTRUSE_DECL {
($au:expr) => {
(*($au as XmlSchemaAttributeUsePtr)).attr_decl
};
}
macro_rules! WXS_ATTRUSE_TYPEDEF {
($au:expr) => {
WXS_ATTR_TYPEDEF!(WXS_ATTRUSE_DECL!($au as XmlSchemaAttributeUsePtr))
};
}
macro_rules! WXS_ATTRUSE_DECL_NAME {
($au:expr) => {
(*WXS_ATTRUSE_DECL!($au)).name
};
}
macro_rules! WXS_ATTRUSE_DECL_TNS {
($au:expr) => {
(*WXS_ATTRUSE_DECL!($au)).target_namespace
};
}
macro_rules! WXS_ATTR_GROUP_HAS_REFS {
($ag:expr) => {
(*($ag as XmlSchemaAttributeGroupPtr)).flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS != 0
};
}
macro_rules! WXS_ATTR_GROUP_EXPANDED {
($ag:expr) => {
(*($ag as XmlSchemaAttributeGroupPtr)).flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED != 0
};
}
macro_rules! WXS_PARTICLE {
($p:expr) => {
$p as XmlSchemaParticlePtr
};
}
macro_rules! WXS_PARTICLE_TERM {
($p:expr) => {
(*WXS_PARTICLE!($p)).children
};
}
macro_rules! WXS_MODELGROUPDEF_MODEL {
($mgd:expr) => {
(*($mgd as XmlSchemaModelGroupPtr)).children
};
}
macro_rules! WXS_IS_MODEL_GROUP {
($i:expr) => {
(*$i).typ == XmlSchemaTypeType::XmlSchemaTypeSequence
|| (*$i).typ == XmlSchemaTypeType::XmlSchemaTypeChoice
|| (*$i).typ == XmlSchemaTypeType::XmlSchemaTypeAll
};
}
macro_rules! WXS_MODELGROUP_PARTICLE {
($mg:expr) => {
(*$mg).children as XmlSchemaParticlePtr
};
}
macro_rules! WXS_IS_BUCKET_INCREDEF {
($t:expr) => {
$t == XML_SCHEMA_SCHEMA_INCLUDE || $t == XML_SCHEMA_SCHEMA_REDEFINE
};
}
macro_rules! WXS_IS_BUCKET_IMPMAIN {
($t:expr) => {
$t == XML_SCHEMA_SCHEMA_MAIN || $t == XML_SCHEMA_SCHEMA_IMPORT
};
}
macro_rules! WXS_IMPBUCKET {
($b:expr) => {
$b as XmlSchemaImportPtr
};
}
macro_rules! WXS_INCBUCKET {
($b:expr) => {
$b as XmlSchemaIncludePtr
};
}
macro_rules! WXS_IS_TYPE_NOT_FIXED {
($i:expr) => {
(*$i).typ != XmlSchemaTypeType::XmlSchemaTypeBasic
&& (*$i).flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED == 0
};
}
macro_rules! WXS_IS_TYPE_NOT_FIXED_1 {
($item:expr) => {
(*$item).typ != XmlSchemaTypeType::XmlSchemaTypeBasic
&& (*$item).flags & XML_SCHEMAS_TYPE_FIXUP_1 == 0
};
}
macro_rules! WXS_HAS_SIMPLE_CONTENT {
($item:expr) => {
(*$item).content_type == XmlSchemaContentType::XmlSchemaContentSimple
|| (*$item).content_type == XmlSchemaContentType::XmlSchemaContentBasic
};
}
macro_rules! WXS_HAS_MIXED_CONTENT {
($item:expr) => {
(*$item).content_type == XmlSchemaContentType::XmlSchemaContentMixed
};
}
macro_rules! WXS_EMPTIABLE {
($t:expr) => {
xml_schema_is_particle_emptiable((*$t).subtypes as XmlSchemaParticlePtr) != 0
};
}
macro_rules! WXS_TYPE_PARTICLE {
($t:expr) => {
(*$t).subtypes as XmlSchemaParticlePtr
};
}
macro_rules! WXS_TYPE_PARTICLE_TERM {
($t:expr) => {
WXS_PARTICLE_TERM!(WXS_TYPE_PARTICLE!($t))
};
}
macro_rules! WXS_CONSTRUCTOR {
($ctx:expr) => {
(*$ctx).constructor
};
}
macro_rules! WXS_HAS_BUCKETS {
($ctx:expr) => {
!(*WXS_CONSTRUCTOR!($ctx)).buckets.is_null()
&& (*(*WXS_CONSTRUCTOR!($ctx)).buckets).items.len() > 0
};
}
macro_rules! WXS_SUBST_GROUPS {
($ctx:expr) => {
(*WXS_CONSTRUCTOR!($ctx)).subst_groups
};
}
macro_rules! WXS_BUCKET {
($ctx:expr) => {
(*WXS_CONSTRUCTOR!($ctx)).bucket
};
}
macro_rules! WXS_ADD_LOCAL {
($ctx:expr, $item:expr) => {
if xml_schema_add_item_size(&raw mut (*WXS_BUCKET!($ctx)).locals, 10, $item as _) < 0 {
xml_free($item as _);
$item = null_mut();
}
};
}
macro_rules! WXS_ADD_GLOBAL {
($ctx:expr, $item:expr) => {
if xml_schema_add_item_size(&raw mut (*WXS_BUCKET!($ctx)).globals, 5, $item as _) < 0 {
xml_free($item as _);
$item = null_mut();
}
};
}
macro_rules! WXS_ADD_PENDING {
($ctx:expr, $item:expr) => {
xml_schema_add_item_size(&raw mut (*(*$ctx).constructor).pending, 10, $item as _)
};
}
macro_rules! WXS_ILIST_IS_EMPTY {
($l:expr) => {
$l.is_null() || (*$l).items.is_empty()
};
}
macro_rules! FREE_AND_NULL {
($str:expr) => {
if !$str.is_null() {
$crate::libxml::globals::xml_free($str as _);
#[allow(unused_assignments)]
{
$str = null_mut();
}
}
};
}
macro_rules! WXS_ARE_DEFAULT_STR_EQUAL {
($v1:expr, $v2:expr) => {
$v1 == $v2
};
}
macro_rules! INODE_NILLED {
($item:expr) => {
(*$item).flags & XML_SCHEMA_ELEM_INFO_NILLED != 0
};
}
pub(crate) unsafe fn can_parse_schema(b: XmlSchemaBucketPtr) -> bool {
unsafe { (*b).doc.is_some() && (*b).parsed == 0 }
}
macro_rules! HFAILURE {
($res:expr, $label:tt) => {
if $res == -1 {
break $label;
}
};
}
macro_rules! HERROR {
($res:expr, $label:tt) => {
if $res != 0 {
break $label;
}
};
}
const SUBSET_RESTRICTION: i32 = 1 << 0;
const SUBSET_EXTENSION: i32 = 1 << 1;
pub(crate) const XML_SCHEMA_CTXT_PARSER: i32 = 1;
pub(crate) const XML_SCHEMA_CTXT_VALIDATOR: i32 = 2;
#[doc(alias = "xmlSchemaAbstractCtxtPtr")]
pub type XmlSchemaAbstractCtxtPtr = *mut XmlSchemaAbstractCtxt;
#[doc(alias = "xmlSchemaAbstractCtxt")]
#[repr(C)]
pub struct XmlSchemaAbstractCtxt {
pub(crate) typ: i32,
pub(crate) dummy: *mut c_void,
}
pub(crate) const XML_SCHEMA_SCHEMA_MAIN: i32 = 0;
pub(crate) const XML_SCHEMA_SCHEMA_IMPORT: i32 = 1;
pub(crate) const XML_SCHEMA_SCHEMA_INCLUDE: i32 = 2;
pub(crate) const XML_SCHEMA_SCHEMA_REDEFINE: i32 = 3;
#[doc(alias = "xmlSchemaSchemaRelationPtr")]
pub type XmlSchemaSchemaRelationPtr = *mut XmlSchemaSchemaRelation;
#[doc(alias = "xmlSchemaSchemaRelation")]
#[repr(C)]
pub struct XmlSchemaSchemaRelation {
next: XmlSchemaSchemaRelationPtr,
typ: i32,
import_namespace: *const XmlChar,
bucket: XmlSchemaBucketPtr,
}
const XML_SCHEMA_BUCKET_MARKED: i32 = 1 << 0;
const XML_SCHEMA_BUCKET_COMPS_ADDED: i32 = 1 << 1;
#[doc(alias = "xmlSchemaBucketPtr")]
pub type XmlSchemaBucketPtr = *mut XmlSchemaBucket;
#[doc(alias = "xmlSchemaBucket")]
#[repr(C)]
pub struct XmlSchemaBucket {
typ: i32,
flags: i32,
pub(crate) schema_location: *const XmlChar,
pub(crate) orig_target_namespace: *const XmlChar,
pub(crate) target_namespace: *const XmlChar,
pub(crate) doc: Option<XmlDocPtr>,
relations: XmlSchemaSchemaRelationPtr,
located: i32,
pub(crate) parsed: i32,
imported: i32,
preserve_doc: i32,
globals: XmlSchemaItemListPtr<*mut c_void>,
locals: XmlSchemaItemListPtr<*mut c_void>,
}
#[doc(alias = "xmlSchemaImportPtr")]
pub type XmlSchemaImportPtr = *mut XmlSchemaImport;
#[doc(alias = "xmlSchemaImport")]
#[repr(C)]
pub struct XmlSchemaImport {
typ: i32,
flags: i32,
schema_location: *const XmlChar,
orig_target_namespace: *const XmlChar,
target_namespace: *const XmlChar,
doc: Option<XmlDocPtr>,
relations: XmlSchemaSchemaRelationPtr,
located: i32,
parsed: i32,
imported: i32,
preserve_doc: i32,
globals: XmlSchemaItemListPtr<*mut c_void>,
locals: XmlSchemaItemListPtr<*mut c_void>,
pub(crate) schema: XmlSchemaPtr,
}
#[doc(alias = "xmlSchemaIncludePtr")]
pub type XmlSchemaIncludePtr = *mut XmlSchemaInclude;
#[doc(alias = "xmlSchemaInclude")]
#[repr(C)]
pub struct XmlSchemaInclude {
typ: i32,
flags: i32,
schema_location: *const XmlChar,
orig_target_namespace: *const XmlChar,
target_namespace: *const XmlChar,
doc: Option<XmlDocPtr>,
relations: XmlSchemaSchemaRelationPtr,
located: i32,
parsed: i32,
imported: i32,
preserve_doc: i32,
globals: XmlSchemaItemListPtr<*mut c_void>,
locals: XmlSchemaItemListPtr<*mut c_void>,
owner_import: XmlSchemaImportPtr,
}
pub(crate) const XML_SCHEMA_ATTR_USE_FIXED: i32 = 1 << 0;
#[doc(alias = "xmlSchemaRedefPtr")]
pub type XmlSchemaRedefPtr = *mut XmlSchemaRedef;
#[doc(alias = "xmlSchemaRedef")]
#[repr(C)]
pub struct XmlSchemaRedef {
next: XmlSchemaRedefPtr,
pub(crate) item: XmlSchemaBasicItemPtr,
pub(crate) reference: XmlSchemaBasicItemPtr,
target: XmlSchemaBasicItemPtr,
pub(crate) ref_name: *const XmlChar,
pub(crate) ref_target_ns: *const XmlChar,
target_bucket: XmlSchemaBucketPtr,
}
#[doc(alias = "xmlSchemaConstructionCtxtPtr")]
pub type XmlSchemaConstructionCtxtPtr = *mut XmlSchemaConstructionCtxt;
#[doc(alias = "xmlSchemaConstructionCtxt")]
#[repr(C)]
pub struct XmlSchemaConstructionCtxt {
pub(crate) main_schema: XmlSchemaPtr,
pub(crate) main_bucket: XmlSchemaBucketPtr,
dict: XmlDictPtr,
buckets: XmlSchemaItemListPtr<*mut c_void>,
pub(crate) bucket: XmlSchemaBucketPtr,
pub(crate) pending: XmlSchemaItemListPtr<*mut c_void>,
subst_groups: XmlHashTablePtr,
redefs: XmlSchemaRedefPtr,
last_redef: XmlSchemaRedefPtr,
}
const SCHEMAS_PARSE_OPTIONS: i32 = XmlParserOption::XmlParseNoEnt as i32;
const XML_SCHEMA_MODEL_GROUP_DEF_MARKED: i32 = 1 << 0;
const XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED: i32 = 1 << 1;
#[doc(alias = "xmlSchemaIDCSelectPtr")]
pub type XmlSchemaIdcselectPtr = *mut XmlSchemaIdcselect;
#[doc(alias = "xmlSchemaIDCSelect")]
#[repr(C)]
pub struct XmlSchemaIdcselect {
pub(crate) next: XmlSchemaIdcselectPtr,
idc: XmlSchemaIDCPtr,
pub(crate) index: i32,
pub(crate) xpath: *const XmlChar,
xpath_comp: Option<Box<XmlPattern>>,
}
#[doc(alias = "xmlSchemaIDCAugPtr")]
pub type XmlSchemaIDCAugPtr = *mut XmlSchemaIDCAug;
#[doc(alias = "xmlSchemaIDCAug")]
#[repr(C)]
pub struct XmlSchemaIDCAug {
pub(crate) next: XmlSchemaIDCAugPtr,
def: XmlSchemaIDCPtr,
keyref_depth: i32,
}
#[doc(alias = "xmlSchemaPSVIIDCKeyPtr")]
pub type XmlSchemaPSVIIDCKeyPtr = *mut XmlSchemaPSVIIDCKey;
#[doc(alias = "xmlSchemaPSVIIDCKeySequence")]
#[repr(C)]
pub struct XmlSchemaPSVIIDCKey {
typ: XmlSchemaTypePtr,
val: XmlSchemaValPtr,
}
#[doc(alias = "xmlSchemaPSVIIDCNodePtr")]
pub type XmlSchemaPSVIIDCNodePtr = *mut XmlSchemaPSVIIDCNode;
#[doc(alias = "xmlSchemaPSVIIDCNode")]
#[repr(C)]
pub struct XmlSchemaPSVIIDCNode {
node: Option<XmlNodePtr>,
pub(crate) keys: *mut XmlSchemaPSVIIDCKeyPtr,
pub(crate) node_line: i32,
pub(crate) node_qname_id: i32,
}
#[doc(alias = "xmlSchemaPSVIIDCBindingPtr")]
pub type XmlSchemaPSVIIDCBindingPtr = *mut XmlSchemaPSVIIDCBinding;
#[doc(alias = "xmlSchemaPSVIIDCBinding")]
#[repr(C)]
pub struct XmlSchemaPSVIIDCBinding {
next: XmlSchemaPSVIIDCBindingPtr,
definition: XmlSchemaIDCPtr,
node_table: Vec<XmlSchemaPSVIIDCNodePtr>,
dupls: XmlSchemaItemListPtr<*mut c_void>,
}
impl Default for XmlSchemaPSVIIDCBinding {
fn default() -> Self {
Self {
next: null_mut(),
definition: null_mut(),
node_table: vec![],
dupls: null_mut(),
}
}
}
const XPATH_STATE_OBJ_TYPE_IDC_SELECTOR: i32 = 1;
const XPATH_STATE_OBJ_TYPE_IDC_FIELD: i32 = 2;
#[doc(alias = "xmlSchemaIDCStateObjPtr")]
pub type XmlSchemaIDCStateObjPtr = *mut XmlSchemaIDCStateObj;
#[doc(alias = "xmlSchemaIDCStateObj")]
#[repr(C)]
pub struct XmlSchemaIDCStateObj {
typ: i32,
next: XmlSchemaIDCStateObjPtr,
depth: i32,
history: *mut i32,
nb_history: i32,
size_history: i32,
matcher: XmlSchemaIDCMatcherPtr,
sel: XmlSchemaIdcselectPtr,
xpath_ctxt: Option<Box<XmlStreamCtxt>>,
}
const IDC_MATCHER: i32 = 0;
#[doc(alias = "xmlSchemaIDCMatcherPtr")]
pub type XmlSchemaIDCMatcherPtr = *mut XmlSchemaIDCMatcher;
#[doc(alias = "xmlSchemaIDCMatcher")]
#[repr(C)]
pub struct XmlSchemaIDCMatcher {
typ: i32,
depth: i32,
next: XmlSchemaIDCMatcherPtr,
pub(crate) next_cached: XmlSchemaIDCMatcherPtr,
aidc: XmlSchemaIDCAugPtr,
idc_type: i32,
key_seqs: *mut *mut XmlSchemaPSVIIDCKeyPtr,
size_key_seqs: i32,
targets: XmlSchemaItemListPtr<*mut c_void>,
htab: XmlHashTablePtr,
}
pub(crate) const XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES: i32 = 1 << 0;
pub(crate) const XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES: i32 = 1 << 1;
const XML_SCHEMA_ELEM_INFO_NILLED: i32 = 1 << 2;
const XML_SCHEMA_ELEM_INFO_LOCAL_TYPE: i32 = 1 << 3;
const XML_SCHEMA_NODE_INFO_VALUE_NEEDED: i32 = 1 << 4;
const XML_SCHEMA_ELEM_INFO_EMPTY: i32 = 1 << 5;
const XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT: i32 = 1 << 7;
const XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT: i32 = 1 << 8;
const XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED: i32 = 1 << 9;
const XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE: i32 = 1 << 10;
#[doc(alias = "xmlSchemaNodeInfoPtr")]
pub type XmlSchemaNodeInfoPtr = *mut XmlSchemaNodeInfo;
#[doc(alias = "xmlSchemaNodeInfo")]
#[repr(C)]
pub struct XmlSchemaNodeInfo {
pub(crate) node_type: i32,
pub(crate) node: Option<XmlNodePtr>,
node_line: i32,
pub(crate) local_name: Option<String>,
pub(crate) ns_name: Option<String>,
pub(crate) value: *const XmlChar,
pub(crate) val: XmlSchemaValPtr,
type_def: XmlSchemaTypePtr,
pub(crate) flags: i32,
val_needed: i32,
norm_val: i32,
decl: XmlSchemaElementPtr,
depth: i32,
pub(crate) idc_table: XmlSchemaPSVIIDCBindingPtr,
pub(crate) idc_matchers: XmlSchemaIDCMatcherPtr,
pub(crate) regex_ctxt: Option<Box<XmlRegExecCtxt>>,
pub(crate) ns_bindings: *mut *const XmlChar,
pub(crate) nb_ns_bindings: i32,
pub(crate) size_ns_bindings: i32,
pub(crate) has_keyrefs: i32,
pub(crate) applied_xpath: i32,
}
impl Default for XmlSchemaNodeInfo {
fn default() -> Self {
Self {
node_type: 0,
node: None,
node_line: 0,
local_name: None,
ns_name: None,
value: null_mut(),
val: null_mut(),
type_def: null_mut(),
flags: 0,
val_needed: 0,
norm_val: 0,
decl: null_mut(),
depth: 0,
idc_table: null_mut(),
idc_matchers: null_mut(),
regex_ctxt: None,
ns_bindings: null_mut(),
nb_ns_bindings: 0,
size_ns_bindings: 0,
has_keyrefs: 0,
applied_xpath: 0,
}
}
}
const XML_SCHEMAS_ATTR_UNKNOWN: i32 = 1;
const XML_SCHEMAS_ATTR_ASSESSED: i32 = 2;
const XML_SCHEMAS_ATTR_ERR_MISSING: i32 = 4;
const XML_SCHEMAS_ATTR_INVALID_VALUE: i32 = 5;
const XML_SCHEMAS_ATTR_ERR_NO_TYPE: i32 = 6;
const XML_SCHEMAS_ATTR_ERR_FIXED_VALUE: i32 = 7;
const XML_SCHEMAS_ATTR_DEFAULT: i32 = 8;
const XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL: i32 = 10;
const XML_SCHEMAS_ATTR_WILD_SKIP: i32 = 13;
const XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL: i32 = 14;
const XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID: i32 = 15;
const XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID: i32 = 16;
const XML_SCHEMAS_ATTR_META: i32 = 17;
const XML_SCHEMA_ATTR_INFO_META_XSI_TYPE: i32 = 1;
const XML_SCHEMA_ATTR_INFO_META_XSI_NIL: i32 = 2;
const XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC: i32 = 3;
const XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC: i32 = 4;
const XML_SCHEMA_ATTR_INFO_META_XMLNS: i32 = 5;
#[doc(alias = "xmlSchemaAttrInfoPtr")]
pub type XmlSchemaAttrInfoPtr = *mut XmlSchemaAttrInfo;
#[doc(alias = "xmlSchemaAttrInfo")]
#[repr(C)]
pub struct XmlSchemaAttrInfo {
node_type: i32,
node: Option<XmlAttrPtr>,
node_line: i32,
pub(crate) local_name: Option<String>,
pub(crate) ns_name: Option<String>,
pub(crate) value: *const XmlChar,
pub(crate) val: XmlSchemaValPtr,
type_def: XmlSchemaTypePtr,
pub(crate) flags: i32,
decl: XmlSchemaAttributePtr,
using: XmlSchemaAttributeUsePtr,
state: i32,
meta_type: i32,
vc_value: *const XmlChar,
parent: XmlSchemaNodeInfoPtr,
}
impl Default for XmlSchemaAttrInfo {
fn default() -> Self {
Self {
node_type: 0,
node: None,
node_line: 0,
local_name: None,
ns_name: None,
value: null_mut(),
val: null_mut(),
type_def: null_mut(),
flags: 0,
decl: null_mut(),
using: null_mut(),
state: 0,
meta_type: 0,
vc_value: null_mut(),
parent: null_mut(),
}
}
}
const XML_SCHEMA_VALID_CTXT_FLAG_STREAM: i32 = 1;
#[doc(alias = "xmlSchemaSubstGroupPtr")]
pub type XmlSchemaSubstGroupPtr = *mut XmlSchemaSubstGroup;
#[doc(alias = "xmlSchemaSubstGroup")]
#[repr(C)]
pub struct XmlSchemaSubstGroup {
head: XmlSchemaElementPtr,
members: XmlSchemaItemListPtr<*mut c_void>,
}
#[doc(alias = "xmlIDCHashEntryPtr")]
pub type XmlIDCHashEntryPtr = *mut XmlIDCHashEntry;
#[doc(alias = "xmlIDCHashEntry")]
#[repr(C)]
pub struct XmlIDCHashEntry {
next: XmlIDCHashEntryPtr,
index: i32,
}
pub(crate) unsafe fn xml_schema_add_item_size(
list: *mut XmlSchemaItemListPtr<*mut c_void>,
_initial_size: i32,
item: *mut c_void,
) -> i32 {
unsafe {
if (*list).is_null() {
*list = xml_schema_item_list_create::<*mut c_void>();
if (*list).is_null() {
return -1;
}
}
(**list).push(item)
}
}
#[doc(alias = "xmlSchemaItemTypeToStr")]
pub(crate) fn xml_schema_item_type_to_str(typ: XmlSchemaTypeType) -> &'static str {
match typ {
XmlSchemaTypeType::XmlSchemaTypeBasic => "simple type definition",
XmlSchemaTypeType::XmlSchemaTypeSimple => "simple type definition",
XmlSchemaTypeType::XmlSchemaTypeComplex => "complex type definition",
XmlSchemaTypeType::XmlSchemaTypeElement => "element declaration",
XmlSchemaTypeType::XmlSchemaTypeAttributeUse => "attribute use",
XmlSchemaTypeType::XmlSchemaTypeAttribute => "attribute declaration",
XmlSchemaTypeType::XmlSchemaTypeGroup => "model group definition",
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => "attribute group definition",
XmlSchemaTypeType::XmlSchemaTypeNotation => "notation declaration",
XmlSchemaTypeType::XmlSchemaTypeSequence => "model group (sequence)",
XmlSchemaTypeType::XmlSchemaTypeChoice => "model group (choice)",
XmlSchemaTypeType::XmlSchemaTypeAll => "model group (all)",
XmlSchemaTypeType::XmlSchemaTypeParticle => "particle",
XmlSchemaTypeType::XmlSchemaTypeIDCUnique => "unique identity-constraint",
XmlSchemaTypeType::XmlSchemaTypeIDCKey => "key identity-constraint",
XmlSchemaTypeType::XmlSchemaTypeIDCKeyref => "keyref identity-constraint",
XmlSchemaTypeType::XmlSchemaTypeAny => "wildcard (any)",
XmlSchemaTypeType::XmlSchemaExtraQNameRef => "[helper component] QName reference",
XmlSchemaTypeType::XmlSchemaExtraAttrUseProhib => {
"[helper component] attribute use prohibition"
}
_ => "Not a schema component",
}
}
pub(crate) unsafe fn xml_schema_get_component_type_str(
item: XmlSchemaBasicItemPtr,
) -> &'static str {
unsafe {
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeBasic => {
if wxs_is_complex(item as XmlSchemaTypePtr) {
"complex type definition"
} else {
"simple type definition"
}
}
_ => xml_schema_item_type_to_str((*item).typ),
}
}
}
pub(crate) unsafe fn xml_schema_get_component_qname(item: *mut c_void) -> String {
unsafe {
let namespace_name = (*(item as XmlSchemaBasicItemPtr)).target_namespace();
let local_name = (*(item as XmlSchemaBasicItemPtr)).name();
xml_schema_format_qname(namespace_name.as_deref(), local_name.as_deref())
}
}
pub(crate) unsafe fn xml_schema_get_component_designation(item: *mut c_void) -> String {
unsafe {
let typestr = xml_schema_get_component_type_str(item as _);
let mut res = typestr.to_owned();
res.push_str(" '");
res.push_str(xml_schema_get_component_qname(item).as_str());
res.push('\'');
res
}
}
macro_rules! VERROR {
($vctxt:expr, $err:expr, $typ:expr, $msg:expr) => {
$crate::xmlschemas::error::xml_schema_custom_err(
$vctxt as XmlSchemaAbstractCtxtPtr,
$err,
None,
$typ,
$msg,
None,
None,
);
};
}
macro_rules! VERROR_INT {
($vctxt:expr, $func:expr, $msg:expr) => {
$crate::xmlschemas::error::xml_schema_internal_err(
$vctxt as XmlSchemaAbstractCtxtPtr,
$func,
$msg,
);
};
}
macro_rules! PERROR_INT {
($pctxt:expr, $func:expr, $msg:expr) => {
$crate::xmlschemas::error::xml_schema_internal_err(
$pctxt as XmlSchemaAbstractCtxtPtr,
$func,
$msg,
);
};
}
macro_rules! PERROR_INT2 {
($ctxt:expr, $func:expr, $msg:expr) => {
$crate::xmlschemas::error::xml_schema_internal_err(
$ctxt as XmlSchemaAbstractCtxtPtr,
$func,
$msg,
);
};
}
macro_rules! AERROR_INT {
($actxt:expr, $func:expr, $msg:expr) => {
$crate::xmlschemas::error::xml_schema_internal_err($actxt, $func, $msg);
};
}
pub(crate) unsafe fn xml_schema_get_component_node(
item: XmlSchemaBasicItemPtr,
) -> Option<XmlNodePtr> {
unsafe {
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeElement => (*(item as XmlSchemaElementPtr)).node,
XmlSchemaTypeType::XmlSchemaTypeAttribute => (*(item as XmlSchemaAttributePtr)).node,
XmlSchemaTypeType::XmlSchemaTypeComplex | XmlSchemaTypeType::XmlSchemaTypeSimple => {
(*(item as XmlSchemaTypePtr)).node
}
XmlSchemaTypeType::XmlSchemaTypeAny | XmlSchemaTypeType::XmlSchemaTypeAnyAttribute => {
(*(item as XmlSchemaWildcardPtr)).node
}
XmlSchemaTypeType::XmlSchemaTypeParticle => (*(item as XmlSchemaParticlePtr)).node,
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice
| XmlSchemaTypeType::XmlSchemaTypeAll => Some((*(item as XmlSchemaModelGroupPtr)).node),
XmlSchemaTypeType::XmlSchemaTypeGroup => {
Some((*(item as XmlSchemaModelGroupDefPtr)).node)
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
(*(item as XmlSchemaAttributeGroupPtr)).node
}
XmlSchemaTypeType::XmlSchemaTypeIDCUnique
| XmlSchemaTypeType::XmlSchemaTypeIDCKey
| XmlSchemaTypeType::XmlSchemaTypeIDCKeyref => Some((*(item as XmlSchemaIDCPtr)).node),
XmlSchemaTypeType::XmlSchemaExtraQNameRef => (*(item as XmlSchemaQNameRefPtr)).node,
XmlSchemaTypeType::XmlSchemaTypeAttributeUse => {
Some((*(item as XmlSchemaAttributeUsePtr)).node)
}
_ => None,
}
}
}
unsafe fn xml_schema_validate_notation(
vctxt: XmlSchemaValidCtxtPtr,
schema: XmlSchemaPtr,
node: Option<XmlGenericNodePtr>,
value: &str,
val: *mut XmlSchemaValPtr,
val_needed: i32,
) -> i32 {
unsafe {
let mut ret = 0;
if !vctxt.is_null() && (*vctxt).schema.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaValidateNotation",
"a schema is needed on the validation context"
);
return -1;
}
if validate_qname::<true>(value).is_err() {
return 1;
}
if let Some((prefix, local_name)) = split_qname2(value) {
let mut ns_name = None;
if !vctxt.is_null() {
ns_name = (*vctxt).lookup_namespace(Some(prefix));
} else if let Some(node) = node {
let ns = node.search_ns(node.document(), Some(prefix));
if let Some(ns) = ns {
ns_name = ns.href.as_deref().map(|href| href.to_owned());
}
} else {
return 1;
}
let Some(ns_name) = ns_name else {
return 1;
};
if !(*schema).get_notation(local_name, Some(&ns_name)).is_null() {
if val_needed != 0 && !val.is_null() {
*val = xml_schema_new_notation_value(
xml_strndup(local_name.as_ptr(), local_name.len() as i32),
xml_strndup(ns_name.as_ptr(), ns_name.len() as i32),
);
if (*val).is_null() {
ret = -1;
}
}
} else {
ret = 1;
}
} else if !(*schema).get_notation(value, None).is_null() {
if val_needed != 0 && !val.is_null() {
*val = xml_schema_new_notation_value(
xml_strndup(value.as_ptr(), value.len() as i32),
null_mut(),
);
if (*val).is_null() {
ret = -1;
}
}
} else {
return 1;
}
ret
}
}
unsafe fn xml_schema_validate_qname(
vctxt: XmlSchemaValidCtxtPtr,
value: &str,
val: *mut XmlSchemaValPtr,
val_needed: i32,
) -> i32 {
unsafe {
let mut ret = 0;
if validate_qname::<true>(value).is_err() {
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateQName",
"calling xmlValidateQName()"
);
return -1;
}
return XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1 as i32;
}
let loc = value;
let stripped = xml_schema_collapse_string(loc);
let mut prefix = None;
let mut local = loc;
if let Some((pre, loc)) = split_qname2(stripped.as_deref().unwrap_or(loc.as_ref())) {
prefix = Some(pre);
local = loc;
}
let ns_name = (*vctxt).lookup_namespace(prefix);
if prefix.is_some() {
if ns_name.is_none() {
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1 as i32;
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::try_from(ret).unwrap(),
None,
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasQName) as _,
format!(
"The QName value '{}' has no corresponding namespace declaration in scope",
value
)
.as_str(),
Some(value),
None,
);
return ret;
}
}
if val_needed != 0 && !val.is_null() {
if let Some(ns_name) = ns_name {
*val = xml_schema_new_qname_value(
xml_strndup(ns_name.as_ptr(), ns_name.len() as i32),
xml_strndup(local.as_ptr(), local.len() as i32),
);
} else {
*val = xml_schema_new_qname_value(
null_mut(),
xml_strndup(local.as_ptr(), local.len() as i32),
);
}
}
0
}
}
#[doc(alias = "xmlSchemaGetPrimitiveType")]
unsafe fn xml_schema_get_primitive_type(mut typ: XmlSchemaTypePtr) -> XmlSchemaTypePtr {
unsafe {
while !typ.is_null() {
if (*typ).built_in_type == XmlSchemaValType::XmlSchemasAnySimpletype
|| (*typ).flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE != 0
{
return typ;
}
typ = (*typ).base_type;
}
null_mut()
}
}
#[doc(alias = "xmlSchemaGetCanonValueWhtspExt")]
unsafe fn xml_schema_get_canon_value_whtsp_ext_1(
mut val: XmlSchemaValPtr,
ws: XmlSchemaWhitespaceValueType,
ret_value: *mut *mut XmlChar,
for_hash: i32,
) -> i32 {
unsafe {
let mut val_type: XmlSchemaValType;
let mut value: *const XmlChar;
let mut value2: *const XmlChar = null();
if ret_value.is_null() || val.is_null() {
return -1;
}
let list: i32 = (!xml_schema_value_get_next(val).is_null()) as i32;
*ret_value = null_mut();
while {
val_type = xml_schema_get_val_type(val);
match val_type {
XmlSchemaValType::XmlSchemasString
| XmlSchemaValType::XmlSchemasNormString
| XmlSchemaValType::XmlSchemasAnySimpletype => {
value = xml_schema_value_get_as_string(val);
if !value.is_null() {
if ws == XmlSchemaWhitespaceValueType::XmlSchemaWhitespaceCollapse {
value2 = xml_schema_collapse_string(
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
)
.map_or(null_mut(), |res| {
xml_strndup(res.as_ptr(), res.len() as i32)
});
} else if ws == XmlSchemaWhitespaceValueType::XmlSchemaWhitespaceReplace {
value2 = xml_schema_white_space_replace(
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
)
.map_or(null_mut(), |res| {
xml_strndup(res.as_ptr(), res.len() as i32)
});
}
if !value2.is_null() {
value = value2;
}
}
}
_ => {
if xml_schema_get_canon_value(val, &raw mut value2) == -1 {
if !value2.is_null() {
xml_free(value2 as _);
}
if !(*ret_value).is_null() {
xml_free(*ret_value as _);
}
if !value2.is_null() {
xml_free(value2 as _);
}
return -1;
}
if for_hash != 0 && val_type == XmlSchemaValType::XmlSchemasDecimal {
let len: i32 = xml_strlen(value2);
if len > 2
&& *value2.add(len as usize - 1) == b'0'
&& *value2.add(len as usize - 2) == b'.'
{
*(value2 as *mut u8).add(len as usize - 2) = 0;
}
}
value = value2;
}
}
if (*ret_value).is_null() {
if value.is_null() {
if list == 0 {
*ret_value = xml_strdup(c"".as_ptr() as _);
}
} else {
*ret_value = xml_strdup(value);
}
} else if !value.is_null() {
*ret_value = xml_strcat(*ret_value, c" ".as_ptr() as _);
*ret_value = xml_strcat(*ret_value, value);
}
FREE_AND_NULL!(value2);
val = xml_schema_value_get_next(val);
!val.is_null()
} {}
0
}
}
pub(crate) unsafe fn xml_schema_get_canon_value_whtsp_ext(
val: XmlSchemaValPtr,
ws: XmlSchemaWhitespaceValueType,
ret_value: *mut *mut XmlChar,
) -> i32 {
unsafe { xml_schema_get_canon_value_whtsp_ext_1(val, ws, ret_value, 0) }
}
unsafe fn xml_schema_are_values_equal(mut x: XmlSchemaValPtr, mut y: XmlSchemaValPtr) -> i32 {
unsafe {
let mut tx: XmlSchemaTypePtr;
let mut ty: XmlSchemaTypePtr;
let mut ptx: XmlSchemaTypePtr;
let mut pty: XmlSchemaTypePtr;
let mut ret: i32;
while !x.is_null() {
tx = xml_schema_get_built_in_type(xml_schema_get_val_type(x));
ty = xml_schema_get_built_in_type(xml_schema_get_val_type(y));
ptx = xml_schema_get_primitive_type(tx);
pty = xml_schema_get_primitive_type(ty);
if ptx != pty {
return 0;
}
if (*ptx).built_in_type == XmlSchemaValType::XmlSchemasString
|| wxs_is_any_simple_type(ptx)
{
if !xml_str_equal(
xml_schema_value_get_as_string(x),
xml_schema_value_get_as_string(y),
) {
return 0;
}
} else {
ret = xml_schema_compare_values_whtsp(
x,
XmlSchemaWhitespaceValueType::XmlSchemaWhitespacePreserve,
y,
XmlSchemaWhitespaceValueType::XmlSchemaWhitespacePreserve,
);
if ret == -2 {
return -1;
}
if ret != 0 {
return 0;
}
}
x = xml_schema_value_get_next(x);
if !x.is_null() {
y = xml_schema_value_get_next(y);
if y.is_null() {
return 0;
}
} else if !xml_schema_value_get_next(y).is_null() {
return 0;
} else {
return 1;
}
}
0
}
}
macro_rules! ACTIVATE_ATTRIBUTE {
($vctxt:expr, $item:expr) => {
(*$vctxt).inode = $item as XmlSchemaNodeInfoPtr;
};
}
macro_rules! ACTIVATE_ELEM {
($vctxt:expr) => {
(*$vctxt).inode = *(*$vctxt).elem_infos.add((*$vctxt).depth as usize);
};
}
macro_rules! ACTIVATE_PARENT_ELEM {
($vctxt:expr) => {
(*$vctxt).inode = *(*$vctxt).elem_infos.add((*$vctxt).depth as usize - 1);
};
}
#[allow(clippy::too_many_arguments)]
unsafe fn xml_schema_validate_facets(
actxt: XmlSchemaAbstractCtxtPtr,
node: Option<XmlGenericNodePtr>,
typ: XmlSchemaTypePtr,
mut val_type: XmlSchemaValType,
value: *const XmlChar,
val: XmlSchemaValPtr,
length: u64,
fire_errors: i32,
) -> i32 {
unsafe {
let mut ret: i32;
let mut error: i32 = 0;
let mut found: i32;
let mut tmp_type: XmlSchemaTypePtr;
let mut facet_link: XmlSchemaFacetLinkPtr;
let mut facet: XmlSchemaFacetPtr;
let mut len: u64 = 0;
let ws: XmlSchemaWhitespaceValueType;
if (*typ).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
return 0;
}
'pattern_and_enum: {
if (*typ).facet_set.is_null() {
break 'pattern_and_enum;
}
'wxs_is_list: {
if !(*typ).wxs_is_atomic() {
if (*typ).wxs_is_list() {
break 'wxs_is_list;
} else {
break 'pattern_and_enum;
}
}
tmp_type = xml_schema_get_primitive_type(typ);
if (*tmp_type).built_in_type == XmlSchemaValType::XmlSchemasString
|| wxs_is_any_simple_type(tmp_type)
{
ws = (*typ).white_space_facet_value().unwrap();
} else {
ws = XmlSchemaWhitespaceValueType::XmlSchemaWhitespaceCollapse;
}
if !val.is_null() {
val_type = xml_schema_get_val_type(val);
}
facet_link = (*typ).facet_set;
while !facet_link.is_null() {
'to_continue: {
match (*(*facet_link).facet).typ {
XmlSchemaTypeType::XmlSchemaFacetWhitespace
| XmlSchemaTypeType::XmlSchemaFacetPattern
| XmlSchemaTypeType::XmlSchemaFacetEnumeration => {
break 'to_continue;
}
XmlSchemaTypeType::XmlSchemaFacetLength
| XmlSchemaTypeType::XmlSchemaFacetMinLength
| XmlSchemaTypeType::XmlSchemaFacetMaxLength => {
ret = xml_schema_validate_length_facet_whtsp(
(*facet_link).facet,
val_type,
value,
val,
&raw mut len,
ws,
);
}
_ => {
ret = xml_schema_validate_facet_whtsp(
(*facet_link).facet,
ws,
val_type,
value,
val,
ws,
);
}
}
match ret.cmp(&0) {
std::cmp::Ordering::Less => {
AERROR_INT!(
actxt,
"xmlSchemaValidateFacets",
"validating against a atomic type facet"
);
return -1;
}
std::cmp::Ordering::Greater => {
if fire_errors != 0 {
let value =
CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_facet_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
len,
&*typ,
&*(*facet_link).facet,
None,
None,
None,
);
} else {
return ret;
}
if error == 0 {
error = ret;
}
}
_ => {}
}
}
facet_link = (*facet_link).next;
}
}
if !(*typ).wxs_is_list() {
break 'pattern_and_enum;
}
facet_link = (*typ).facet_set;
while !facet_link.is_null() {
'to_continue: {
match (*(*facet_link).facet).typ {
XmlSchemaTypeType::XmlSchemaFacetLength
| XmlSchemaTypeType::XmlSchemaFacetMinLength
| XmlSchemaTypeType::XmlSchemaFacetMaxLength => {
ret = xml_schema_validate_list_simple_type_facet(
(*facet_link).facet,
value,
length,
null_mut(),
);
}
_ => {
break 'to_continue;
}
}
match ret.cmp(&0) {
std::cmp::Ordering::Less => {
AERROR_INT!(
actxt,
"xmlSchemaValidateFacets",
"validating against a list type facet"
);
return -1;
}
std::cmp::Ordering::Greater => {
if fire_errors != 0 {
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_facet_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
length,
&*typ,
&*(*facet_link).facet,
None,
None,
None,
);
} else {
return ret;
}
if error == 0 {
error = ret;
}
}
_ => {}
}
}
facet_link = (*facet_link).next;
}
}
found = 0;
ret = 0;
tmp_type = typ;
loop {
facet = (*tmp_type).facets;
while !facet.is_null() {
if (*facet).typ != XmlSchemaTypeType::XmlSchemaFacetEnumeration {
facet = (*facet).next;
continue;
}
found = 1;
ret = xml_schema_are_values_equal((*facet).val, val);
if ret == 1 {
break;
} else if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaValidateFacets",
"validating against an enumeration facet"
);
return -1;
}
facet = (*facet).next;
}
if ret != 0 {
break;
}
if found != 0 {
break;
}
tmp_type = (*tmp_type).base_type;
if tmp_type.is_null() || (*tmp_type).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
break;
}
}
if found != 0 && ret == 0 {
ret = XmlParserErrors::XmlSchemavCvcEnumerationValid as i32;
if fire_errors != 0 {
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_facet_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
0,
&*typ,
&*facet,
None,
None,
None,
);
} else {
return ret;
}
if error == 0 {
error = ret;
}
}
tmp_type = typ;
facet = null_mut();
loop {
found = 0;
facet_link = (*tmp_type).facet_set;
while !facet_link.is_null() {
if (*(*facet_link).facet).typ != XmlSchemaTypeType::XmlSchemaFacetPattern {
facet_link = (*facet_link).next;
continue;
}
found = 1;
ret = xml_regexp_exec(
(*(*facet_link).facet).regexp.clone().unwrap(),
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
);
if ret == 1 {
break;
} else if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaValidateFacets",
"validating against a pattern facet"
);
return -1;
} else {
facet = (*facet_link).facet;
}
facet_link = (*facet_link).next;
}
if found != 0 && ret != 1 {
ret = XmlParserErrors::XmlSchemavCvcPatternValid as i32;
if fire_errors != 0 {
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_facet_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
0,
&*typ,
&*facet,
None,
None,
None,
);
} else {
return ret;
}
if error == 0 {
error = ret;
}
break;
}
tmp_type = (*tmp_type).base_type;
if tmp_type.is_null() || (*tmp_type).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
break;
}
}
error
}
}
#[doc(alias = "xmlSchemaGetUnionSimpleTypeMemberTypes")]
unsafe fn xml_schema_get_union_simple_type_member_types(
mut typ: XmlSchemaTypePtr,
) -> XmlSchemaTypeLinkPtr {
unsafe {
while !typ.is_null() && (*typ).typ == XmlSchemaTypeType::XmlSchemaTypeSimple {
if !(*typ).member_types.is_null() {
return (*typ).member_types;
} else {
typ = (*typ).base_type;
}
}
null_mut()
}
}
macro_rules! NORMALIZE {
($atype:expr, $value:expr, $norm_value:expr, $typ:expr, $is_normalized:expr, $normalize:expr) => {
if $is_normalized == 0
&& ($normalize != 0
|| (*$typ).flags
& $crate::libxml::schemas_internals::XML_SCHEMAS_TYPE_NORMVALUENEEDED
!= 0)
{
$norm_value = (*$atype)
.normalize_value(
CStr::from_ptr($value as *const i8)
.to_string_lossy()
.as_ref(),
)
.map_or(null_mut(), |res| {
xml_strndup(res.as_ptr(), res.len() as i32)
});
if !$norm_value.is_null() {
$value = $norm_value;
}
#[allow(unused_assignments)]
{
$is_normalized = 1;
}
}
};
}
#[allow(clippy::too_many_arguments)]
pub(crate) unsafe fn xml_schema_vcheck_cvc_simple_type(
actxt: XmlSchemaAbstractCtxtPtr,
node: Option<XmlGenericNodePtr>,
typ: XmlSchemaTypePtr,
mut value: *const XmlChar,
ret_val: *mut XmlSchemaValPtr,
fire_errors: i32,
mut normalize: i32,
mut is_normalized: i32,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let mut val_needed: i32 = if !ret_val.is_null() { 1 } else { 0 };
let mut val: XmlSchemaValPtr = null_mut();
let mut norm_value: *mut XmlChar = null_mut();
if !ret_val.is_null() && !(*ret_val).is_null() {
xml_schema_free_value(*ret_val);
*ret_val = null_mut();
}
if val_needed == 0 && (*typ).flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE != 0 {
val_needed = 1;
}
if value.is_null() {
value = c"".as_ptr() as _;
}
'internal_error: {
if wxs_is_any_simple_type(typ) || (*typ).wxs_is_atomic() {
let mut bi_type: XmlSchemaTypePtr;
NORMALIZE!(typ, value, norm_value, typ, is_normalized, normalize);
if (*typ).typ != XmlSchemaTypeType::XmlSchemaTypeBasic {
bi_type = (*typ).base_type;
while !bi_type.is_null()
&& (*bi_type).typ != XmlSchemaTypeType::XmlSchemaTypeBasic
{
bi_type = (*bi_type).base_type;
}
if bi_type.is_null() {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"could not get the built-in type"
);
break 'internal_error;
}
} else {
bi_type = typ;
}
if (*actxt).typ == XML_SCHEMA_CTXT_VALIDATOR {
match (*bi_type).built_in_type {
XmlSchemaValType::XmlSchemasNotation => {
ret = xml_schema_validate_notation(
actxt as XmlSchemaValidCtxtPtr,
(*(actxt as XmlSchemaValidCtxtPtr)).schema,
None,
&CStr::from_ptr(value as *const i8).to_string_lossy(),
&raw mut val,
val_needed,
);
}
XmlSchemaValType::XmlSchemasQName => {
ret = xml_schema_validate_qname(
actxt as XmlSchemaValidCtxtPtr,
&CStr::from_ptr(value as *const i8).to_string_lossy(),
&raw mut val,
val_needed,
);
}
_ => {
if val_needed != 0 {
ret = xml_schema_val_predef_type_node_no_norm(
bi_type,
value,
&raw mut val,
node,
);
} else {
ret = xml_schema_val_predef_type_node_no_norm(
bi_type,
value,
null_mut(),
node,
);
}
}
}
} else if (*actxt).typ == XML_SCHEMA_CTXT_PARSER {
match (*bi_type).built_in_type {
XmlSchemaValType::XmlSchemasNotation => {
ret = xml_schema_validate_notation(
null_mut(),
(*(actxt as XmlSchemaParserCtxtPtr)).schema,
node,
&CStr::from_ptr(value as *const i8).to_string_lossy(),
&raw mut val,
val_needed,
);
}
_ => {
if val_needed != 0 {
ret = xml_schema_val_predef_type_node_no_norm(
bi_type,
value,
&raw mut val,
node,
);
} else {
ret = xml_schema_val_predef_type_node_no_norm(
bi_type,
value,
null_mut(),
node,
);
}
}
}
} else {
break 'internal_error;
}
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating against a built-in type"
);
break 'internal_error;
}
if (*typ).wxs_is_list() {
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_2 as i32;
} else {
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1 as i32;
}
}
if ret == 0 && (*typ).flags & XML_SCHEMAS_TYPE_HAS_FACETS != 0 {
ret = xml_schema_validate_facets(
actxt,
node,
typ,
(*bi_type).built_in_type,
value,
val,
0,
fire_errors,
);
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating facets of atomic simple type"
);
break 'internal_error;
}
if (*typ).wxs_is_list() {
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_2 as i32;
} else {
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1 as i32;
}
}
} else if fire_errors != 0 && ret > 0 {
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_simple_type_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
&*typ,
1,
);
}
} else if (*typ).wxs_is_list() {
let mut cur: *const XmlChar;
let mut end: *const XmlChar;
let mut tmp_value: *mut XmlChar = null_mut();
let mut len: u64 = 0;
let mut prev_val: XmlSchemaValPtr = null_mut();
let mut cur_val: XmlSchemaValPtr = null_mut();
NORMALIZE!(typ, value, norm_value, typ, is_normalized, normalize);
let item_type: XmlSchemaTypePtr = (*typ).subtypes;
cur = value;
loop {
while (*cur).is_xml_blank_char() {
cur = cur.add(1);
}
end = cur;
while *end != 0 && !(*end).is_xml_blank_char() {
end = end.add(1);
}
if end == cur {
break;
}
tmp_value = xml_strndup(cur, end.offset_from(cur) as _);
len += 1;
if val_needed != 0 {
ret = xml_schema_vcheck_cvc_simple_type(
actxt,
node,
item_type,
tmp_value,
&raw mut cur_val,
fire_errors,
0,
1,
);
} else {
ret = xml_schema_vcheck_cvc_simple_type(
actxt,
node,
item_type,
tmp_value,
null_mut(),
fire_errors,
0,
1,
);
}
FREE_AND_NULL!(tmp_value);
if !cur_val.is_null() {
if val.is_null() {
val = cur_val;
} else {
xml_schema_value_append(prev_val, cur_val);
}
prev_val = cur_val;
cur_val = null_mut();
}
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating an item of list simple type"
);
break 'internal_error;
}
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_2 as i32;
break;
}
cur = end;
if *cur == 0 {
break;
}
}
FREE_AND_NULL!(tmp_value);
if ret == 0 && (*typ).flags & XML_SCHEMAS_TYPE_HAS_FACETS != 0 {
ret = xml_schema_validate_facets(
actxt,
node,
typ,
XmlSchemaValType::XmlSchemasUnknown,
value,
val,
len,
fire_errors,
);
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating facets of list simple type"
);
break 'internal_error;
}
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_2 as i32;
}
}
if fire_errors != 0 && ret > 0 {
normalize = 1;
NORMALIZE!(typ, value, norm_value, typ, is_normalized, normalize);
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_simple_type_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
&*typ,
1,
);
}
} else if (*typ).wxs_is_union() {
let mut member_link: XmlSchemaTypeLinkPtr;
member_link = xml_schema_get_union_simple_type_member_types(typ);
if member_link.is_null() {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"union simple type has no member types"
);
break 'internal_error;
}
while !member_link.is_null() {
if val_needed != 0 {
ret = xml_schema_vcheck_cvc_simple_type(
actxt,
node,
(*member_link).typ,
value,
&raw mut val,
0,
1,
0,
);
} else {
ret = xml_schema_vcheck_cvc_simple_type(
actxt,
node,
(*member_link).typ,
value,
null_mut(),
0,
1,
0,
);
}
if ret <= 0 {
break;
}
member_link = (*member_link).next;
}
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating members of union simple type"
);
break 'internal_error;
}
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_3 as i32;
}
if ret == 0 && (*typ).flags & XML_SCHEMAS_TYPE_HAS_FACETS != 0 {
NORMALIZE!(
(*member_link).typ,
value,
norm_value,
typ,
is_normalized,
normalize
);
ret = xml_schema_validate_facets(
actxt,
node,
typ,
XmlSchemaValType::XmlSchemasUnknown,
value,
val,
0,
fire_errors,
);
if ret != 0 {
if ret < 0 {
AERROR_INT!(
actxt,
"xmlSchemaVCheckCVCSimpleType",
"validating facets of union simple type"
);
break 'internal_error;
}
ret = XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_3 as i32;
}
}
if fire_errors != 0 && ret > 0 {
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_simple_type_err(
actxt,
ret.try_into().unwrap(),
node,
&value,
&*typ,
1,
);
}
}
if !norm_value.is_null() {
xml_free(norm_value as _);
}
if ret == 0 {
if !ret_val.is_null() {
*ret_val = val;
} else if !val.is_null() {
xml_schema_free_value(val);
}
} else if !val.is_null() {
xml_schema_free_value(val);
}
return ret;
}
if !norm_value.is_null() {
xml_free(norm_value as _);
}
if !val.is_null() {
xml_schema_free_value(val);
}
-1
}
}
#[doc(alias = "xmlSchemaFormatQName")]
pub(crate) fn xml_schema_format_qname(
namespace_name: Option<&str>,
local_name: Option<&str>,
) -> String {
let mut res = String::new();
if let Some(namespace_name) = namespace_name {
res.push('{');
res.push_str(namespace_name);
res.push('}');
}
if let Some(local_name) = local_name {
res.push_str(local_name);
} else {
res.push_str("(NULL)");
}
res
}
pub(crate) fn xml_schema_facet_type_to_string(typ: XmlSchemaTypeType) -> &'static str {
match typ {
XmlSchemaTypeType::XmlSchemaFacetPattern => "pattern",
XmlSchemaTypeType::XmlSchemaFacetMaxExclusive => "maxExclusive",
XmlSchemaTypeType::XmlSchemaFacetMaxInclusive => "maxInclusive",
XmlSchemaTypeType::XmlSchemaFacetMinExclusive => "minExclusive",
XmlSchemaTypeType::XmlSchemaFacetMinInclusive => "minInclusive",
XmlSchemaTypeType::XmlSchemaFacetWhitespace => "whiteSpace",
XmlSchemaTypeType::XmlSchemaFacetEnumeration => "enumeration",
XmlSchemaTypeType::XmlSchemaFacetLength => "length",
XmlSchemaTypeType::XmlSchemaFacetMaxLength => "maxLength",
XmlSchemaTypeType::XmlSchemaFacetMinLength => "minLength",
XmlSchemaTypeType::XmlSchemaFacetTotalDigits => "totalDigits",
XmlSchemaTypeType::XmlSchemaFacetFractionDigits => "fractionDigits",
_ => "Internal Error",
}
}
#[doc(alias = "xmlSchemaIsValid")]
pub unsafe fn xml_schema_is_valid(ctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
if ctxt.is_null() {
return -1;
}
((*ctxt).err == 0) as i32
}
}
unsafe fn xml_schema_subst_group_free(group: XmlSchemaSubstGroupPtr) {
unsafe {
if group.is_null() {
return;
}
if !(*group).members.is_null() {
xml_schema_item_list_free((*group).members);
}
xml_free(group as _);
}
}
extern "C" fn xml_schema_subst_group_free_entry(group: *mut c_void, _name: *const XmlChar) {
unsafe {
xml_schema_subst_group_free(group as XmlSchemaSubstGroupPtr);
}
}
unsafe fn xml_schema_redef_list_free(mut redef: XmlSchemaRedefPtr) {
unsafe {
let mut prev: XmlSchemaRedefPtr;
while !redef.is_null() {
prev = redef;
redef = (*redef).next;
xml_free(prev as _);
}
}
}
pub(crate) unsafe fn xml_schema_construction_ctxt_free(con: XmlSchemaConstructionCtxtPtr) {
unsafe {
if !(*con).buckets.is_null() {
xml_schema_item_list_free((*con).buckets);
}
if !(*con).pending.is_null() {
xml_schema_item_list_free((*con).pending);
}
if !(*con).subst_groups.is_null() {
xml_hash_free((*con).subst_groups, Some(xml_schema_subst_group_free_entry));
}
if !(*con).redefs.is_null() {
xml_schema_redef_list_free((*con).redefs);
}
if !(*con).dict.is_null() {
xml_dict_free((*con).dict);
}
xml_free(con as _);
}
}
pub(crate) unsafe fn xml_schema_construction_ctxt_create(
dict: XmlDictPtr,
) -> XmlSchemaConstructionCtxtPtr {
unsafe {
let ret: XmlSchemaConstructionCtxtPtr =
xml_malloc(size_of::<XmlSchemaConstructionCtxt>()) as XmlSchemaConstructionCtxtPtr;
if ret.is_null() {
xml_schema_perr_memory(null_mut(), "allocating schema construction context", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaConstructionCtxt>());
(*ret).buckets = xml_schema_item_list_create::<*mut c_void>();
if (*ret).buckets.is_null() {
xml_schema_perr_memory(null_mut(), "allocating list of schema buckets", None);
xml_free(ret as _);
return null_mut();
}
(*ret).pending = xml_schema_item_list_create::<*mut c_void>();
if (*ret).pending.is_null() {
xml_schema_perr_memory(
null_mut(),
"allocating list of pending global components",
None,
);
xml_schema_construction_ctxt_free(ret);
return null_mut();
}
(*ret).dict = dict;
xml_dict_reference(dict);
ret
}
}
#[doc(alias = "xmlSchemaGetSchemaBucket")]
unsafe fn xml_schema_get_schema_bucket(
pctxt: XmlSchemaParserCtxtPtr,
schema_location: *const XmlChar,
) -> XmlSchemaBucketPtr {
unsafe {
let list: XmlSchemaItemListPtr<*mut c_void> = (*(*pctxt).constructor).buckets;
for cur in (*list).items.iter().map(|&cur| cur as XmlSchemaBucketPtr) {
if (*cur).schema_location == schema_location {
return cur;
}
}
null_mut()
}
}
unsafe fn xml_schema_schema_relation_create() -> XmlSchemaSchemaRelationPtr {
unsafe {
let ret: XmlSchemaSchemaRelationPtr =
xml_malloc(size_of::<XmlSchemaSchemaRelation>()) as XmlSchemaSchemaRelationPtr;
if ret.is_null() {
xml_schema_perr_memory(null_mut(), "allocating schema relation", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaSchemaRelation>());
ret
}
}
unsafe fn xml_schema_schema_relation_add_child(
bucket: XmlSchemaBucketPtr,
rel: XmlSchemaSchemaRelationPtr,
) {
unsafe {
let mut cur: XmlSchemaSchemaRelationPtr = (*bucket).relations;
if cur.is_null() {
(*bucket).relations = rel;
return;
}
while !(*cur).next.is_null() {
cur = (*cur).next;
}
(*cur).next = rel;
}
}
macro_rules! IS_BAD_SCHEMA_DOC {
($b:expr) => {
(*$b).doc.is_none() && !(*$b).schema_location.is_null()
};
}
unsafe fn xml_schema_get_schema_bucket_by_tns(
pctxt: XmlSchemaParserCtxtPtr,
target_namespace: *const XmlChar,
imported: i32,
) -> XmlSchemaBucketPtr {
unsafe {
let list: XmlSchemaItemListPtr<*mut c_void> = (*(*pctxt).constructor).buckets;
for cur in (*list).items.iter().map(|&cur| cur as XmlSchemaBucketPtr) {
if !IS_BAD_SCHEMA_DOC!(cur)
&& (*cur).orig_target_namespace == target_namespace
&& ((imported != 0 && (*cur).imported != 0)
|| (imported == 0 && (*cur).imported == 0))
{
return cur;
}
}
null_mut()
}
}
unsafe fn xml_schema_get_chameleon_schema_bucket(
pctxt: XmlSchemaParserCtxtPtr,
schema_location: *const XmlChar,
target_namespace: *const XmlChar,
) -> XmlSchemaBucketPtr {
unsafe {
let list: XmlSchemaItemListPtr<*mut c_void> = (*(*pctxt).constructor).buckets;
for cur in (*list).items.iter().map(|&cur| cur as XmlSchemaBucketPtr) {
if (*cur).orig_target_namespace.is_null()
&& (*cur).schema_location == schema_location
&& (*cur).target_namespace == target_namespace
{
return cur;
}
}
null_mut()
}
}
fn is_blank_node(node: XmlNodePtr) -> bool {
node.element_type() == XmlElementType::XmlTextNode
&& node
.content
.as_deref()
.is_some_and(|content| content.chars().all(|c| c.is_xml_blank_char()))
}
fn xml_schema_is_blank(s: Option<&str>) -> bool {
s.is_none_or(|s| s.chars().all(|c| c.is_xml_blank_char()))
}
#[doc(alias = "xmlSchemaCleanupDoc")]
unsafe fn xml_schema_cleanup_doc(ctxt: XmlSchemaParserCtxtPtr, root: XmlNodePtr) {
unsafe {
if ctxt.is_null() {
return;
}
let mut delete: Option<XmlNodePtr> = None;
let mut cur = Some(root);
'main: while let Some(cur_node) = cur {
if let Some(mut delete) = delete.take() {
delete.unlink();
xml_free_node(delete);
}
'skip_children: {
if cur_node.element_type() == XmlElementType::XmlTextNode {
if is_blank_node(cur_node) && cur_node.get_space_preserve() != 1 {
delete = cur;
}
} else if !matches!(
cur_node.element_type(),
XmlElementType::XmlElementNode | XmlElementType::XmlCDATASectionNode
) {
delete = cur;
break 'skip_children;
}
if let Some(children) = cur_node
.children()
.filter(|children| {
!matches!(
children.element_type(),
XmlElementType::XmlEntityDecl
| XmlElementType::XmlEntityRefNode
| XmlElementType::XmlEntityNode
)
})
.map(|children| XmlNodePtr::try_from(children).unwrap())
{
cur = Some(children);
continue 'main;
}
}
if let Some(next) = cur_node
.next
.map(|node| XmlNodePtr::try_from(node).unwrap())
{
cur = Some(next);
continue;
}
let mut cur_node = cur_node;
cur = loop {
let Some(parent) = cur_node
.parent
.and_then(|parent| XmlNodePtr::try_from(parent).ok())
else {
break None;
};
cur_node = parent;
if cur_node == root {
break None;
}
if let Some(next) = cur_node
.next
.map(|node| XmlNodePtr::try_from(node).unwrap())
{
break Some(next);
}
}
}
if let Some(mut delete) = delete {
delete.unlink();
xml_free_node(delete);
}
}
}
#[doc(alias = "xmlSchemaFreeAttribute")]
unsafe fn xml_schema_free_attribute(attr: XmlSchemaAttributePtr) {
unsafe {
if attr.is_null() {
return;
}
if !(*attr).annot.is_null() {
xml_schema_free_annot((*attr).annot);
}
if !(*attr).def_val.is_null() {
xml_schema_free_value((*attr).def_val);
}
xml_free(attr as _);
}
}
#[doc(alias = "xmlSchemaFreeAttributeUse")]
unsafe fn xml_schema_free_attribute_use(using: XmlSchemaAttributeUsePtr) {
unsafe {
if using.is_null() {
return;
}
if !(*using).annot.is_null() {
xml_schema_free_annot((*using).annot);
}
if !(*using).def_val.is_null() {
xml_schema_free_value((*using).def_val);
}
xml_free(using as _);
}
}
#[doc(alias = "xmlSchemaFreeElement")]
unsafe fn xml_schema_free_element(elem: XmlSchemaElementPtr) {
unsafe {
if elem.is_null() {
return;
}
if !(*elem).annot.is_null() {
xml_schema_free_annot((*elem).annot);
}
if !(*elem).def_val.is_null() {
xml_schema_free_value((*elem).def_val);
}
drop_in_place(elem);
xml_free(elem as _);
}
}
#[doc(alias = "xmlSchemaFreeModelGroup")]
unsafe fn xml_schema_free_model_group(item: XmlSchemaModelGroupPtr) {
unsafe {
if !(*item).annot.is_null() {
xml_schema_free_annot((*item).annot);
}
xml_free(item as _);
}
}
#[doc(alias = "xmlSchemaFreeAttributeGroup")]
unsafe fn xml_schema_free_attribute_group(attr_gr: XmlSchemaAttributeGroupPtr) {
unsafe {
if attr_gr.is_null() {
return;
}
if !(*attr_gr).annot.is_null() {
xml_schema_free_annot((*attr_gr).annot);
}
if !(*attr_gr).attr_uses.is_null() {
xml_schema_item_list_free((*attr_gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>);
}
xml_free(attr_gr as _);
}
}
#[doc(alias = "xmlSchemaFreeModelGroupDef")]
unsafe fn xml_schema_free_model_group_def(item: XmlSchemaModelGroupDefPtr) {
unsafe {
if !(*item).annot.is_null() {
xml_schema_free_annot((*item).annot);
}
xml_free(item as _);
}
}
#[doc(alias = "xmlSchemaFreeIDC")]
unsafe fn xml_schema_free_idc(idc_def: XmlSchemaIDCPtr) {
unsafe {
let mut cur: XmlSchemaIdcselectPtr;
let mut prev: XmlSchemaIdcselectPtr;
if idc_def.is_null() {
return;
}
if !(*idc_def).annot.is_null() {
xml_schema_free_annot((*idc_def).annot);
}
if !(*idc_def).selector.is_null() {
(*(*idc_def).selector).xpath_comp.take();
xml_free((*idc_def).selector as _);
}
if !(*idc_def).fields.is_null() {
cur = (*idc_def).fields;
while {
prev = cur;
cur = (*cur).next;
(*prev).xpath_comp.take();
xml_free(prev as _);
!cur.is_null()
} {}
}
xml_free(idc_def as _);
}
}
#[doc(alias = "xmlSchemaFreeNotation")]
unsafe fn xml_schema_free_notation(nota: XmlSchemaNotationPtr) {
unsafe {
if nota.is_null() {
return;
}
xml_free(nota as _);
}
}
#[doc(alias = "xmlSchemaFreeQNameRef")]
unsafe fn xml_schema_free_qname_ref(item: XmlSchemaQNameRefPtr) {
unsafe {
xml_free(item as _);
}
}
unsafe fn xml_schema_component_list_free(list: XmlSchemaItemListPtr<*mut c_void>) {
unsafe {
if list.is_null() || (*list).items.is_empty() {
return;
}
for item in (*list)
.items
.drain(..)
.map(|item| item as XmlSchemaTreeItemPtr)
{
if item.is_null() {
continue;
}
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeSimple
| XmlSchemaTypeType::XmlSchemaTypeComplex => {
xml_schema_free_type(item as XmlSchemaTypePtr);
}
XmlSchemaTypeType::XmlSchemaTypeAttribute => {
xml_schema_free_attribute(item as XmlSchemaAttributePtr);
}
XmlSchemaTypeType::XmlSchemaTypeAttributeUse => {
xml_schema_free_attribute_use(item as XmlSchemaAttributeUsePtr);
}
XmlSchemaTypeType::XmlSchemaExtraAttrUseProhib => {
xml_schema_free_attribute_use_prohib(item as XmlSchemaAttributeUseProhibPtr);
}
XmlSchemaTypeType::XmlSchemaTypeElement => {
xml_schema_free_element(item as XmlSchemaElementPtr);
}
XmlSchemaTypeType::XmlSchemaTypeParticle => {
if !(*item).annot.is_null() {
xml_schema_free_annot((*item).annot);
}
xml_free(item as _);
}
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice
| XmlSchemaTypeType::XmlSchemaTypeAll => {
xml_schema_free_model_group(item as XmlSchemaModelGroupPtr);
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
xml_schema_free_attribute_group(item as XmlSchemaAttributeGroupPtr);
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
xml_schema_free_model_group_def(item as XmlSchemaModelGroupDefPtr);
}
XmlSchemaTypeType::XmlSchemaTypeAny
| XmlSchemaTypeType::XmlSchemaTypeAnyAttribute => {
xml_schema_free_wildcard(item as XmlSchemaWildcardPtr);
}
XmlSchemaTypeType::XmlSchemaTypeIDCKey
| XmlSchemaTypeType::XmlSchemaTypeIDCUnique
| XmlSchemaTypeType::XmlSchemaTypeIDCKeyref => {
xml_schema_free_idc(item as XmlSchemaIDCPtr);
}
XmlSchemaTypeType::XmlSchemaTypeNotation => {
xml_schema_free_notation(item as XmlSchemaNotationPtr);
}
XmlSchemaTypeType::XmlSchemaExtraQNameRef => {
xml_schema_free_qname_ref(item as XmlSchemaQNameRefPtr);
}
_ => {
let name = xml_schema_get_component_type_str(item as _);
xml_schema_psimple_internal_err(
None,
format!(
"Internal error: xmlSchemaComponentListFree, unexpected component type '{}'\n",
name
).as_str(),
);
}
}
}
}
}
pub(crate) unsafe fn xml_schema_bucket_free(bucket: XmlSchemaBucketPtr) {
unsafe {
if bucket.is_null() {
return;
}
if !(*bucket).globals.is_null() {
xml_schema_component_list_free((*bucket).globals);
xml_schema_item_list_free((*bucket).globals);
}
if !(*bucket).locals.is_null() {
xml_schema_component_list_free((*bucket).locals);
xml_schema_item_list_free((*bucket).locals);
}
if !(*bucket).relations.is_null() {
let mut prev: XmlSchemaSchemaRelationPtr;
let mut cur: XmlSchemaSchemaRelationPtr = (*bucket).relations;
while {
prev = cur;
cur = (*cur).next;
xml_free(prev as _);
!cur.is_null()
} {}
}
if let Some(doc) = (*bucket).doc.filter(|_| (*bucket).preserve_doc == 0) {
xml_free_doc(doc);
}
if (*bucket).typ == XML_SCHEMA_SCHEMA_IMPORT && !(*WXS_IMPBUCKET!(bucket)).schema.is_null()
{
xml_schema_free((*WXS_IMPBUCKET!(bucket)).schema);
}
xml_free(bucket as _);
}
}
unsafe fn xml_schema_bucket_create(
pctxt: XmlSchemaParserCtxtPtr,
typ: i32,
target_namespace: *const XmlChar,
) -> XmlSchemaBucketPtr {
unsafe {
if (*WXS_CONSTRUCTOR!(pctxt)).main_schema.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaBucketCreate",
"no main schema on constructor"
);
return null_mut();
}
let main_schema: XmlSchemaPtr = (*WXS_CONSTRUCTOR!(pctxt)).main_schema;
let size = if WXS_IS_BUCKET_INCREDEF!(typ) {
size_of::<XmlSchemaInclude>()
} else {
size_of::<XmlSchemaImport>()
};
let ret: XmlSchemaBucketPtr = xml_malloc(size) as _;
if ret.is_null() {
xml_schema_perr_memory(null_mut(), "allocating schema bucket", None);
return null_mut();
}
memset(ret as _, 0, size);
(*ret).target_namespace = target_namespace;
(*ret).typ = typ;
(*ret).globals = xml_schema_item_list_create::<*mut c_void>();
if (*ret).globals.is_null() {
xml_schema_bucket_free(ret);
return null_mut();
}
(*ret).locals = xml_schema_item_list_create::<*mut c_void>();
if (*ret).locals.is_null() {
xml_schema_bucket_free(ret);
return null_mut();
}
if !WXS_HAS_BUCKETS!(pctxt) {
if WXS_IS_BUCKET_INCREDEF!(typ) {
PERROR_INT!(
pctxt,
"xmlSchemaBucketCreate",
"first bucket but it's an include or redefine"
);
xml_schema_bucket_free(ret);
return null_mut();
}
(*ret).typ = XML_SCHEMA_SCHEMA_MAIN;
(*WXS_CONSTRUCTOR!(pctxt)).main_bucket = ret;
(*WXS_IMPBUCKET!(ret)).schema = main_schema;
(*main_schema).target_namespace = (!target_namespace.is_null()).then(|| {
CStr::from_ptr(target_namespace as *const i8)
.to_string_lossy()
.into_owned()
.into()
});
} else if typ == XML_SCHEMA_SCHEMA_MAIN {
PERROR_INT!(
pctxt,
"xmlSchemaBucketCreate",
"main bucket but it's not the first one"
);
xml_schema_bucket_free(ret);
return null_mut();
} else if typ == XML_SCHEMA_SCHEMA_IMPORT {
(*WXS_IMPBUCKET!(ret)).schema = (*pctxt).new_schema();
if (*WXS_IMPBUCKET!(ret)).schema.is_null() {
xml_schema_bucket_free(ret);
return null_mut();
}
(*(*WXS_IMPBUCKET!(ret)).schema).target_namespace =
(!target_namespace.is_null()).then(|| {
CStr::from_ptr(target_namespace as *const i8)
.to_string_lossy()
.into_owned()
.into()
});
}
if WXS_IS_BUCKET_IMPMAIN!(typ) {
let duplicate = if target_namespace.is_null() {
(*main_schema)
.schemas_imports
.insert(XML_SCHEMAS_NO_NAMESPACE.to_owned(), ret as _)
.is_some()
} else {
(*main_schema)
.schemas_imports
.insert(
CStr::from_ptr(target_namespace as *const i8)
.to_string_lossy()
.into_owned(),
ret as _,
)
.is_some()
};
if duplicate {
PERROR_INT!(
pctxt,
"xmlSchemaBucketCreate",
"failed to add the schema bucket to the hash"
);
xml_schema_bucket_free(ret);
return null_mut();
}
} else {
if WXS_IS_BUCKET_IMPMAIN!((*(*WXS_CONSTRUCTOR!(pctxt)).bucket).typ) {
(*WXS_INCBUCKET!(ret)).owner_import =
WXS_IMPBUCKET!((*WXS_CONSTRUCTOR!(pctxt)).bucket);
} else {
(*WXS_INCBUCKET!(ret)).owner_import =
(*WXS_INCBUCKET!((*WXS_CONSTRUCTOR!(pctxt)).bucket)).owner_import;
}
if (*main_schema).includes.is_null() {
(*main_schema).includes = xml_schema_item_list_create::<*mut c_void>() as _;
if (*main_schema).includes.is_null() {
xml_schema_bucket_free(ret);
return null_mut();
}
}
if (*((*main_schema).includes as XmlSchemaItemListPtr<*mut c_void>)).push(ret as _) < 0
{
xml_schema_bucket_free(ret);
return null_mut();
}
}
if (*(*WXS_CONSTRUCTOR!(pctxt)).buckets).push(ret as _) == -1 {
return null_mut();
}
ret
}
}
#[doc(alias = "xmlSchemaAddSchemaDoc")]
#[allow(clippy::too_many_arguments)]
pub(crate) unsafe fn xml_schema_add_schema_doc(
pctxt: XmlSchemaParserCtxtPtr,
typ: i32,
mut schema_location: *const XmlChar,
schema_doc: Option<XmlDocPtr>,
schema_buffer: *const c_char,
schema_buffer_len: i32,
invoking_node: Option<XmlGenericNodePtr>,
source_target_namespace: *const XmlChar,
import_namespace: *const XmlChar,
bucket: *mut XmlSchemaBucketPtr,
) -> i32 {
unsafe {
let mut target_namespace: *const XmlChar = null();
let mut relation: XmlSchemaSchemaRelationPtr = null_mut();
let mut doc = None;
let res: i32;
let mut err = 0;
let mut located: i32 = 0;
let mut preserve_doc: i32 = 0;
let mut bkt: XmlSchemaBucketPtr = null_mut();
if !bucket.is_null() {
*bucket = null_mut();
}
match typ {
_ if typ == XML_SCHEMA_SCHEMA_IMPORT || typ == XML_SCHEMA_SCHEMA_MAIN => {
err = XmlParserErrors::XmlSchemapSrcImport as i32;
}
_ if typ == XML_SCHEMA_SCHEMA_INCLUDE => {
err = XmlParserErrors::XmlSchemapSrcInclude as i32;
}
_ if typ == XML_SCHEMA_SCHEMA_REDEFINE => {
err = XmlParserErrors::XmlSchemapSrcRedefine as i32;
}
_ => {}
}
'exit_failure: {
'exit_error: {
'exit: {
if typ == XML_SCHEMA_SCHEMA_MAIN || !WXS_HAS_BUCKETS!(pctxt) {
} else {
if !schema_location.is_null() {
bkt = xml_schema_get_schema_bucket(pctxt, schema_location);
if !bkt.is_null() && (*(*pctxt).constructor).bucket == bkt {
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
err.try_into().unwrap(),
invoking_node,
null_mut(),
"The schema must not import/include/redefine itself",
None,
None,
);
break 'exit;
}
}
relation = xml_schema_schema_relation_create();
if relation.is_null() {
return -1;
}
xml_schema_schema_relation_add_child(
(*(*pctxt).constructor).bucket,
relation,
);
(*relation).typ = typ;
if WXS_IS_BUCKET_IMPMAIN!(typ) {
(*relation).import_namespace = import_namespace;
if schema_location.is_null() {
break 'exit;
}
target_namespace = import_namespace;
}
if !bkt.is_null() {
if WXS_IS_BUCKET_IMPMAIN!(typ) && (*bkt).imported == 0 {
if schema_location.is_null() {
schema_location = c"in_memory_buffer".as_ptr() as _;
}
if !xml_str_equal(schema_location, (*bkt).schema_location) {
let schema_location =
CStr::from_ptr(schema_location as *const i8)
.to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
err.try_into().unwrap(),
invoking_node,
null_mut(),
format!("The schema document '{schema_location}' cannot be imported, since it was already included or redefined").as_str(),
Some(&schema_location),
None
);
break 'exit;
}
} else if !WXS_IS_BUCKET_IMPMAIN!(typ) && (*bkt).imported != 0 {
if schema_location.is_null() {
schema_location = c"in_memory_buffer".as_ptr() as _;
}
if !xml_str_equal(schema_location, (*bkt).schema_location) {
let schema_location =
CStr::from_ptr(schema_location as *const i8)
.to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
err.try_into().unwrap(),
invoking_node,
null_mut(),
format!("The schema document '{schema_location}' cannot be included or redefined, since it was already imported").as_str(),
Some(&schema_location),
None
);
break 'exit;
}
}
}
if WXS_IS_BUCKET_IMPMAIN!(typ) {
if !bkt.is_null() {
(*relation).bucket = bkt;
break 'exit;
}
bkt = xml_schema_get_schema_bucket_by_tns(pctxt, import_namespace, 1);
if !bkt.is_null() {
(*relation).bucket = bkt;
if (*bkt).schema_location.is_null() {
(*bkt).schema_location = schema_location;
} else {
if !xml_str_equal(schema_location, (*bkt).schema_location) {
if schema_location.is_null() {
schema_location = c"in_memory_buffer".as_ptr() as _;
}
let schema_location =
CStr::from_ptr(schema_location as *const i8)
.to_string_lossy();
let import_namespace =
CStr::from_ptr(import_namespace as *const i8)
.to_string_lossy();
let bkt_schema_location =
CStr::from_ptr((*bkt).schema_location as *const i8)
.to_string_lossy();
xml_schema_custom_warning(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapWarnSkipSchema,
invoking_node,
None,
format!("Skipping import of schema located at '{schema_location}' for the namespace '{import_namespace}', since this namespace was already imported with the schema located at '{bkt_schema_location}'").as_str(),
Some(&schema_location),
Some(&import_namespace),
Some(&bkt_schema_location)
);
}
break 'exit;
}
}
} else {
if !bkt.is_null() {
if (*bkt).orig_target_namespace.is_null()
&& (*bkt).target_namespace != source_target_namespace
{
let chamel: XmlSchemaBucketPtr =
xml_schema_get_chameleon_schema_bucket(
pctxt,
schema_location,
source_target_namespace,
);
if !chamel.is_null() {
(*relation).bucket = chamel;
break 'exit;
}
bkt = null_mut();
} else {
(*relation).bucket = bkt;
break 'exit;
}
}
}
if !bkt.is_null() && (*bkt).doc.is_some() {
PERROR_INT!(
pctxt,
"xmlSchemaAddSchemaDoc",
"trying to load a schema doc, but a doc is already assigned to the schema bucket"
);
break 'exit_failure;
}
}
if let Some(schema_doc) = schema_doc {
doc = Some(schema_doc);
preserve_doc = 1;
if let Some(url) = schema_doc.url.as_deref() {
let url = CString::new(url).unwrap();
schema_location =
xml_dict_lookup((*pctxt).dict, url.as_ptr() as *const u8, -1);
} else {
schema_location = c"in_memory_buffer".as_ptr() as _;
}
} else if !schema_location.is_null() || !schema_buffer.is_null() {
let Some(mut parser_ctxt) = XmlParserCtxt::new() else {
xml_schema_perr_memory(
null_mut(),
"xmlSchemaGetDoc, allocating a parser context",
None,
);
break 'exit_failure;
};
if !schema_location.is_null() {
doc = xml_ctxt_read_file(
&mut parser_ctxt,
CStr::from_ptr(schema_location as *const i8)
.to_string_lossy()
.as_ref(),
None,
SCHEMAS_PARSE_OPTIONS,
);
} else if !schema_buffer.is_null() {
let mem = from_raw_parts(
schema_buffer as *const u8,
schema_buffer_len as usize,
);
doc = xml_ctxt_read_memory(
&mut parser_ctxt,
mem,
None,
None,
SCHEMAS_PARSE_OPTIONS,
);
schema_location = c"in_memory_buffer".as_ptr() as _;
if let Some(mut doc) = doc {
doc.url = Some(
CStr::from_ptr(schema_location as *const i8)
.to_string_lossy()
.into_owned(),
);
}
}
if doc.is_none() {
let lerr = GLOBAL_STATE.with_borrow(|state| state.last_error.clone());
if lerr.is_ok() || lerr.domain() != XmlErrorDomain::XmlFromIO {
located = 1;
res = XmlParserErrors::XmlSchemapSrcImport2_1 as i32;
let schema_location =
CStr::from_ptr(schema_location as *const i8).to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
res.try_into().unwrap(),
invoking_node,
null_mut(),
format!("Failed to parse the XML resource '{schema_location}'")
.as_str(),
Some(&schema_location),
None,
);
}
}
if doc.is_none() && located != 0 {
break 'exit_error;
}
} else {
xml_schema_perr(
pctxt,
None,
XmlParserErrors::XmlSchemapNothingToParse,
"No information for parsing was provided with the given schema parser context.\n",
None,
None,
);
break 'exit_failure;
}
if let Some(doc) = doc {
located = 1;
let Some(doc_elem) = doc.get_root_element() else {
let schema_location =
CStr::from_ptr(schema_location as *const i8).to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapNoroot,
invoking_node,
null_mut(),
format!("The document '{schema_location}' has no document element")
.as_str(),
Some(&schema_location),
None,
);
break 'exit_error;
};
xml_schema_cleanup_doc(pctxt, doc_elem);
if !is_schema(Some(doc_elem), "schema") {
let schema_location =
CStr::from_ptr(schema_location as *const i8).to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapNotSchema,
invoking_node,
null_mut(),
format!(
"The XML document '{schema_location}' is not a schema document"
)
.as_str(),
Some(&schema_location),
None,
);
break 'exit_error;
}
target_namespace = (*pctxt)
.get_prop(doc_elem, "targetNamespace")
.map_or(null_mut(), |prop| {
xml_dict_lookup((*pctxt).dict, prop.as_ptr(), prop.len() as i32)
});
}
if bkt.is_null() && located != 0 {
bkt = xml_schema_bucket_create(pctxt, typ, target_namespace);
if bkt.is_null() {
break 'exit_failure;
}
}
if !bkt.is_null() {
(*bkt).schema_location = schema_location;
(*bkt).located = located;
if doc.is_some() {
(*bkt).doc = doc;
(*bkt).target_namespace = target_namespace;
(*bkt).orig_target_namespace = target_namespace;
if preserve_doc != 0 {
(*bkt).preserve_doc = 1;
}
}
if WXS_IS_BUCKET_IMPMAIN!(typ) {
(*bkt).imported += 1;
}
if !relation.is_null() {
(*relation).bucket = bkt;
}
}
}
if !bucket.is_null() {
*bucket = bkt;
}
return 0;
}
if let Some(doc) = doc.filter(|_| preserve_doc == 0) {
xml_free_doc(doc);
if !bkt.is_null() {
(*bkt).doc = None;
}
}
return (*pctxt).err;
}
if let Some(doc) = doc.filter(|_| preserve_doc == 0) {
xml_free_doc(doc);
if !bkt.is_null() {
(*bkt).doc = None;
}
}
-1
}
}
#[doc(alias = "xmlSchemaGetPropNode")]
pub(crate) fn xml_schema_get_prop_node(node: XmlNodePtr, name: &str) -> Option<XmlAttrPtr> {
let mut prop = node.properties;
while let Some(now) = prop {
if now.ns.is_none() && now.name().as_deref() == Some(name) {
return Some(now);
}
prop = now.next;
}
None
}
fn xml_schema_get_node_content_no_dict(node: XmlGenericNodePtr) -> Option<String> {
node.get_content()
}
#[doc(alias = "xmlSchemaPValAttrID")]
pub(crate) fn xml_schema_pval_attr_node_id(
ctxt: XmlSchemaParserCtxtPtr,
attr: Option<XmlAttrPtr>,
) -> i32 {
let Some(mut attr) = attr else {
return 0;
};
let Some(value) = xml_schema_get_node_content_no_dict(attr.into()).map(Cow::Owned) else {
return -1;
};
let ret = validate_ncname::<true>(&value);
match ret {
Ok(_) => {
if !matches!(attr.atype, Some(XmlAttributeType::XmlAttributeID)) {
let res = if let Some(strip) = xml_schema_collapse_string(&value) {
xml_add_id(None, attr.doc.unwrap(), &strip, attr)
} else {
xml_add_id(None, attr.doc.unwrap(), &value, attr)
};
if res.is_none() {
unsafe {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
Some(&*xml_schema_get_built_in_type(
XmlSchemaValType::XmlSchemasID,
)),
None,
None,
Some(
format!("Duplicate value '{value}' of simple type 'xs:ID'")
.as_str(),
),
Some(&value),
None,
);
}
return XmlParserErrors::XmlSchemapS4sAttrInvalidValue as i32;
} else {
attr.atype = Some(XmlAttributeType::XmlAttributeID);
}
}
0
}
Err(_) => unsafe {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
Some(&*xml_schema_get_built_in_type(
XmlSchemaValType::XmlSchemasID,
)),
None,
None,
Some(
format!(
"The value '{value}' of simple type 'xs:ID' is not a valid 'xs:NCName'"
)
.as_str(),
),
Some(&value),
None,
);
XmlParserErrors::XmlSchemapS4sAttrInvalidValue as i32
},
}
}
pub(crate) fn xml_schema_pval_attr_id(
ctxt: XmlSchemaParserCtxtPtr,
owner_elem: XmlNodePtr,
name: &str,
) -> i32 {
let Some(attr) = xml_schema_get_prop_node(owner_elem, name) else {
return 0;
};
xml_schema_pval_attr_node_id(ctxt, Some(attr))
}
#[doc(alias = "xmlSchemaPValAttrFormDefault")]
pub(crate) unsafe fn xml_schema_pval_attr_form_default(
value: *const XmlChar,
flags: *mut i32,
flag_qualified: i32,
) -> i32 {
unsafe {
if xml_str_equal(value, c"qualified".as_ptr() as _) {
if *flags & flag_qualified == 0 {
*flags |= flag_qualified;
}
} else if !xml_str_equal(value, c"unqualified".as_ptr() as _) {
return 1;
}
0
}
}
#[doc(alias = "xmlSchemaPValAttrBlockFinal")]
#[allow(clippy::too_many_arguments)]
pub(crate) unsafe fn xml_schema_pval_attr_block_final(
value: *const XmlChar,
flags: *mut i32,
flag_all: i32,
flag_extension: i32,
flag_restriction: i32,
flag_substitution: i32,
flag_list: i32,
flag_union: i32,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
if flags.is_null() || value.is_null() {
return -1;
}
if *value.add(0) == 0 {
return 0;
}
if xml_str_equal(value, c"#all".as_ptr() as _) {
if flag_all != -1 {
*flags |= flag_all;
} else {
if flag_extension != -1 {
*flags |= flag_extension;
}
if flag_restriction != -1 {
*flags |= flag_restriction;
}
if flag_substitution != -1 {
*flags |= flag_substitution;
}
if flag_list != -1 {
*flags |= flag_list;
}
if flag_union != -1 {
*flags |= flag_union;
}
}
} else {
let mut end: *const XmlChar;
let mut cur: *const XmlChar = value;
let mut item: *mut XmlChar;
loop {
while (*cur).is_xml_blank_char() {
cur = cur.add(1);
}
end = cur;
while *end != 0 && !(*end).is_xml_blank_char() {
end = end.add(1);
}
if end == cur {
break;
}
item = xml_strndup(cur, end.offset_from(cur) as _);
if xml_str_equal(item, c"extension".as_ptr() as _) {
if flag_extension != -1 {
if *flags & flag_extension == 0 {
*flags |= flag_extension;
}
} else {
ret = 1;
}
} else if xml_str_equal(item, c"restriction".as_ptr() as _) {
if flag_restriction != -1 {
if *flags & flag_restriction == 0 {
*flags |= flag_restriction;
}
} else {
ret = 1;
}
} else if xml_str_equal(item, c"substitution".as_ptr() as _) {
if flag_substitution != -1 {
if *flags & flag_substitution == 0 {
*flags |= flag_substitution;
}
} else {
ret = 1;
}
} else if xml_str_equal(item, c"list".as_ptr() as _) {
if flag_list != -1 {
if *flags & flag_list == 0 {
*flags |= flag_list;
}
} else {
ret = 1;
}
} else if xml_str_equal(item, c"union".as_ptr() as _) {
if flag_union != -1 {
if *flags & flag_union == 0 {
*flags |= flag_union;
}
} else {
ret = 1;
}
} else {
ret = 1;
}
if !item.is_null() {
xml_free(item as _);
}
cur = end;
if ret != 0 || *cur == 0 {
break;
}
}
}
ret
}
}
#[doc(alias = "xmlSchemaNewAnnot")]
pub(crate) unsafe fn xml_schema_new_annot(
ctxt: XmlSchemaParserCtxtPtr,
node: XmlNodePtr,
) -> XmlSchemaAnnotPtr {
unsafe {
let ret: XmlSchemaAnnotPtr = xml_malloc(size_of::<XmlSchemaAnnot>()) as _;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating annotation", Some(node.into()));
return null_mut();
}
std::ptr::write(
&mut *ret,
XmlSchemaAnnot {
next: null_mut(),
content: node,
},
);
ret
}
}
#[doc(alias = "xmlSchemaGetPropNodeNs")]
pub(crate) fn xml_schema_get_prop_node_ns(
node: XmlNodePtr,
uri: &str,
name: &str,
) -> Option<XmlAttrPtr> {
let mut prop = node.properties;
while let Some(now) = prop {
if now.name().as_deref() == Some(name)
&& now
.ns
.as_deref()
.and_then(|ns| ns.href.as_deref())
.is_some_and(|href| href == uri)
{
return Some(now);
}
prop = now.next;
}
None
}
pub(crate) unsafe fn xml_schema_build_absolute_uri(
dict: XmlDictPtr,
location: *const XmlChar,
ctxt_node: Option<XmlGenericNodePtr>,
) -> *const XmlChar {
unsafe {
if !location.is_null() {
if let Some(ctxt_node) = ctxt_node {
let location = CStr::from_ptr(location as *const i8).to_string_lossy();
let uri = if let Some(base) = ctxt_node.get_base(ctxt_node.document()) {
build_uri(&location, &base)
} else {
ctxt_node.document().as_deref().and_then(|doc| {
doc.url
.as_deref()
.and_then(|base| build_uri(&location, base))
})
};
if let Some(uri) = uri {
let uri = CString::new(uri).unwrap();
return xml_dict_lookup(dict, uri.as_ptr() as *const u8, -1);
}
} else {
return location;
}
}
null_mut()
}
}
#[doc(alias = "xmlSchemaAddRedef")]
unsafe fn xml_schema_add_redef(
pctxt: XmlSchemaParserCtxtPtr,
target_bucket: XmlSchemaBucketPtr,
item: *mut c_void,
ref_name: *const XmlChar,
ref_target_ns: *const XmlChar,
) -> XmlSchemaRedefPtr {
unsafe {
let ret: XmlSchemaRedefPtr = xml_malloc(size_of::<XmlSchemaRedef>()) as XmlSchemaRedefPtr;
if ret.is_null() {
xml_schema_perr_memory(pctxt, "allocating redefinition info", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaRedef>());
(*ret).item = item as _;
(*ret).target_bucket = target_bucket;
(*ret).ref_name = ref_name;
(*ret).ref_target_ns = ref_target_ns;
if (*WXS_CONSTRUCTOR!(pctxt)).redefs.is_null() {
(*WXS_CONSTRUCTOR!(pctxt)).redefs = ret;
} else {
(*(*WXS_CONSTRUCTOR!(pctxt)).last_redef).next = ret;
}
(*WXS_CONSTRUCTOR!(pctxt)).last_redef = ret;
ret
}
}
#[doc(alias = "xmlSchemaAddType")]
pub(crate) unsafe fn xml_schema_add_type(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
typ: XmlSchemaTypeType,
name: *const XmlChar,
ns_name: *const XmlChar,
node: Option<XmlNodePtr>,
top_level: i32,
) -> XmlSchemaTypePtr {
unsafe {
let mut ret: XmlSchemaTypePtr;
if ctxt.is_null() || schema.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaType>()) as XmlSchemaTypePtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating type", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaType>());
(*ret).typ = typ;
(*ret).name = name;
(*ret).target_namespace = ns_name;
(*ret).node = node;
if top_level != 0 {
if (*ctxt).is_redefine != 0 {
(*ctxt).redef =
xml_schema_add_redef(ctxt, (*ctxt).redefined, ret as _, name, ns_name);
if (*ctxt).redef.is_null() {
xml_free(ret as _);
return null_mut();
}
(*ctxt).redef_counter = 0;
}
WXS_ADD_GLOBAL!(ctxt, ret);
} else {
WXS_ADD_LOCAL!(ctxt, ret);
}
WXS_ADD_PENDING!(ctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaPValAttrNodeQNameValue")]
pub(crate) unsafe fn xml_schema_pval_attr_node_qname_value(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
owner_item: XmlSchemaBasicItemPtr,
attr: XmlAttrPtr,
value: *const XmlChar,
uri: *mut *const XmlChar,
local: *mut *const XmlChar,
) -> i32 {
unsafe {
*uri = null_mut();
*local = null_mut();
if validate_qname::<true>(
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
)
.is_err()
{
let v = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
owner_item,
attr.into(),
Some(&*xml_schema_get_built_in_type(
XmlSchemaValType::XmlSchemasQName,
)),
None,
Some(&v),
None,
None,
None,
);
*local = value;
return (*ctxt).err;
}
if strchr(value as *mut c_char, b':' as _).is_null() {
let ns = attr.parent().unwrap().search_ns(attr.doc, None);
if let Some(href) = ns
.as_deref()
.and_then(|ns| ns.href.as_deref())
.filter(|href| !href.is_empty())
{
*uri = xml_dict_lookup((*ctxt).dict, href.as_ptr(), href.len() as i32);
} else if (*schema).flags & XML_SCHEMAS_INCLUDING_CONVERT_NS != 0 {
*uri = (*ctxt).target_namespace;
}
*local = xml_dict_lookup((*ctxt).dict, value, -1);
return 0;
}
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
let (pre, loc) = split_qname2(&value).unwrap();
*local = xml_dict_lookup((*ctxt).dict, loc.as_ptr(), loc.len() as i32);
let pref: *const u8 = xml_dict_lookup((*ctxt).dict, pre.as_ptr(), pre.len() as i32);
let Some(ns) = attr.parent().unwrap().search_ns(
attr.doc,
Some(CStr::from_ptr(pref as *const i8).to_string_lossy()).as_deref(),
) else {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
owner_item,
attr.into(),
Some(&*xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasQName)),
None,
Some(&value),
Some(
format!(
"The value '{}' of simple type 'xs:QName' has no corresponding namespace declaration in scope",
value
).as_str()
),
Some(&value),
None
);
return (*ctxt).err;
};
if let Some(href) = ns.href.as_deref() {
*uri = xml_dict_lookup((*ctxt).dict, href.as_ptr(), href.len() as i32);
} else {
*uri = null_mut();
}
0
}
}
#[doc(alias = "xmlSchemaPValAttrNodeQName")]
pub(crate) unsafe fn xml_schema_pval_attr_node_qname(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
owner_item: XmlSchemaBasicItemPtr,
attr: XmlAttrPtr,
uri: *mut *const XmlChar,
local: *mut *const XmlChar,
) -> i32 {
unsafe {
let value = (*ctxt).get_node_content(Some(attr.into()));
let value = CString::new(value).unwrap();
xml_schema_pval_attr_node_qname_value(
ctxt,
schema,
owner_item,
attr,
value.as_ptr() as *const u8,
uri,
local,
)
}
}
#[doc(alias = "xmlSchemaPValAttrQName")]
pub(crate) unsafe fn xml_schema_pval_attr_qname(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
owner_item: XmlSchemaBasicItemPtr,
owner_elem: XmlNodePtr,
name: &str,
uri: *mut *const XmlChar,
local: *mut *const XmlChar,
) -> i32 {
unsafe {
let Some(attr) = xml_schema_get_prop_node(owner_elem, name) else {
*local = null_mut();
*uri = null_mut();
return 0;
};
xml_schema_pval_attr_node_qname(ctxt, schema, owner_item, attr, uri, local)
}
}
macro_rules! ADD_ANNOTATION {
($item:expr, $annot:ident) => {
let mut cur: XmlSchemaAnnotPtr;
if (*$item).$annot.is_null() {
(*$item).$annot = $annot;
return $annot;
}
cur = (*$item).$annot;
if !(*cur).next.is_null() {
cur = (*cur).next;
}
(*cur).next = $annot;
};
}
#[doc(alias = "xmlSchemaAssignAnnotation")]
pub(crate) unsafe fn xml_schema_add_annotation(
ann_item: XmlSchemaAnnotItemPtr,
annot: XmlSchemaAnnotPtr,
) -> XmlSchemaAnnotPtr {
unsafe {
if ann_item.is_null() || annot.is_null() {
return null_mut();
}
match (*ann_item).typ {
XmlSchemaTypeType::XmlSchemaTypeElement => {
let item: XmlSchemaElementPtr = ann_item as XmlSchemaElementPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeAttribute => {
let item: XmlSchemaAttributePtr = ann_item as XmlSchemaAttributePtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeAnyAttribute | XmlSchemaTypeType::XmlSchemaTypeAny => {
let item: XmlSchemaWildcardPtr = ann_item as XmlSchemaWildcardPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeParticle
| XmlSchemaTypeType::XmlSchemaTypeIDCKey
| XmlSchemaTypeType::XmlSchemaTypeIDCKeyref
| XmlSchemaTypeType::XmlSchemaTypeIDCUnique => {
let item: XmlSchemaAnnotItemPtr = ann_item as XmlSchemaAnnotItemPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
let item: XmlSchemaAttributeGroupPtr = ann_item as XmlSchemaAttributeGroupPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeNotation => {
let item: XmlSchemaNotationPtr = ann_item as XmlSchemaNotationPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaFacetMinInclusive
| XmlSchemaTypeType::XmlSchemaFacetMinExclusive
| XmlSchemaTypeType::XmlSchemaFacetMaxInclusive
| XmlSchemaTypeType::XmlSchemaFacetMaxExclusive
| XmlSchemaTypeType::XmlSchemaFacetTotalDigits
| XmlSchemaTypeType::XmlSchemaFacetFractionDigits
| XmlSchemaTypeType::XmlSchemaFacetPattern
| XmlSchemaTypeType::XmlSchemaFacetEnumeration
| XmlSchemaTypeType::XmlSchemaFacetWhitespace
| XmlSchemaTypeType::XmlSchemaFacetLength
| XmlSchemaTypeType::XmlSchemaFacetMaxLength
| XmlSchemaTypeType::XmlSchemaFacetMinLength => {
let item: XmlSchemaFacetPtr = ann_item as _;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeSimple | XmlSchemaTypeType::XmlSchemaTypeComplex => {
let item: XmlSchemaTypePtr = ann_item as XmlSchemaTypePtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
let item: XmlSchemaModelGroupDefPtr = ann_item as XmlSchemaModelGroupDefPtr;
ADD_ANNOTATION!(item, annot);
}
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice
| XmlSchemaTypeType::XmlSchemaTypeAll => {
let item: XmlSchemaModelGroupPtr = ann_item as XmlSchemaModelGroupPtr;
ADD_ANNOTATION!(item, annot);
}
_ => {
xml_schema_pcustom_err(
null_mut(),
XmlParserErrors::XmlSchemapInternal,
null_mut(),
None,
"Internal error: xmlSchemaAddAnnotation, The item is not a annotated schema component",
None,
);
}
}
annot
}
}
#[doc(alias = "xmlSchemaAddModelGroup")]
pub(crate) unsafe fn xml_schema_add_model_group(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
typ: XmlSchemaTypeType,
node: XmlNodePtr,
) -> XmlSchemaModelGroupPtr {
unsafe {
let mut ret: XmlSchemaModelGroupPtr;
if ctxt.is_null() || schema.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaModelGroup>()) as XmlSchemaModelGroupPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating model group component", None);
return null_mut();
}
std::ptr::write(
&mut *ret,
XmlSchemaModelGroup {
typ,
annot: null_mut(),
next: null_mut(),
children: null_mut(),
node,
},
);
WXS_ADD_LOCAL!(ctxt, ret);
if matches!(
typ,
XmlSchemaTypeType::XmlSchemaTypeSequence | XmlSchemaTypeType::XmlSchemaTypeChoice
) {
WXS_ADD_PENDING!(ctxt, ret);
}
ret
}
}
#[doc(alias = "xmlGetMinOccurs")]
pub(crate) unsafe fn xml_get_min_occurs(
ctxt: XmlSchemaParserCtxtPtr,
node: XmlNodePtr,
min: i32,
max: i32,
def: i32,
expected: &str,
) -> i32 {
unsafe {
let Some(attr) = xml_schema_get_prop_node(node, "minOccurs") else {
return def;
};
let val = (*ctxt).get_node_content(Some(attr.into()));
let mut cur = val.as_str();
cur = cur.trim_start_matches(|c: char| c.is_xml_blank_char());
if cur.is_empty() {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
None,
Some(expected),
Some(&val),
None,
None,
None,
);
return def;
}
cur = cur.trim_end_matches(|c: char| c.is_xml_blank_char());
if cur.bytes().all(|b| b.is_ascii_digit()) {
if let Some(ret) = cur
.parse::<i32>()
.ok()
.filter(|&ret| min <= ret && (max == -1 || ret <= max))
{
return ret;
}
}
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
None,
Some(expected),
Some(&val),
None,
None,
None,
);
def
}
}
#[doc(alias = "xmlGetMaxOccurs")]
pub(crate) unsafe fn xml_get_max_occurs(
ctxt: XmlSchemaParserCtxtPtr,
node: XmlNodePtr,
min: i32,
max: i32,
def: i32,
expected: &str,
) -> i32 {
unsafe {
let Some(attr) = xml_schema_get_prop_node(node, "maxOccurs") else {
return def;
};
let val = (*ctxt).get_node_content(Some(attr.into()));
if val == "unbounded" {
if max != UNBOUNDED as i32 {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
None,
Some(expected),
Some(&val),
None,
None,
None,
);
return def;
} else {
return UNBOUNDED as _;
}
}
let mut cur = val.as_str();
cur = cur.trim_start_matches(|c: char| c.is_xml_blank_char());
if cur.is_empty() {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
None,
Some(expected),
Some(&val),
None,
None,
None,
);
return def;
}
cur = cur.trim_end_matches(|c: char| c.is_xml_blank_char());
if cur.bytes().all(|b| b.is_ascii_digit()) {
if let Some(ret) = cur
.parse::<i32>()
.ok()
.filter(|&ret| min <= ret && (max == -1 || ret <= max))
{
return ret;
}
}
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
attr.into(),
None,
Some(expected),
Some(&val),
None,
None,
None,
);
def
}
}
pub(crate) unsafe fn xml_schema_pcheck_particle_correct_2(
ctxt: XmlSchemaParserCtxtPtr,
_item: XmlSchemaParticlePtr,
node: XmlNodePtr,
min_occurs: i32,
max_occurs: i32,
) -> i32 {
unsafe {
if max_occurs == 0 && min_occurs == 0 {
return 0;
}
if max_occurs != UNBOUNDED as i32 {
if max_occurs < 1 {
xml_schema_pcustom_attr_err(
ctxt,
XmlParserErrors::XmlSchemapPPropsCorrect2_2,
null_mut(),
null_mut(),
xml_schema_get_prop_node(node, "maxOccurs"),
"The value must be greater than or equal to 1",
);
return XmlParserErrors::XmlSchemapPPropsCorrect2_2 as i32;
} else if min_occurs > max_occurs {
xml_schema_pcustom_attr_err(
ctxt,
XmlParserErrors::XmlSchemapPPropsCorrect2_1,
null_mut(),
null_mut(),
xml_schema_get_prop_node(node, "minOccurs"),
"The value must not be greater than the value of 'maxOccurs'",
);
return XmlParserErrors::XmlSchemapPPropsCorrect2_1 as i32;
}
}
0
}
}
#[doc(alias = "xmlSchemaAddParticle")]
pub(crate) unsafe fn xml_schema_add_particle(
ctxt: XmlSchemaParserCtxtPtr,
node: Option<XmlNodePtr>,
min: i32,
max: i32,
) -> XmlSchemaParticlePtr {
unsafe {
let mut ret: XmlSchemaParticlePtr;
if ctxt.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaParticle>()) as XmlSchemaParticlePtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating particle component", None);
return null_mut();
}
(*ret).typ = XmlSchemaTypeType::XmlSchemaTypeParticle;
(*ret).annot = null_mut();
(*ret).node = node;
(*ret).min_occurs = min;
(*ret).max_occurs = max;
(*ret).next = null_mut();
(*ret).children = null_mut();
WXS_ADD_LOCAL!(ctxt, ret);
ret
}
}
pub(crate) unsafe fn xml_schema_check_reference(
pctxt: XmlSchemaParserCtxtPtr,
_schema: XmlSchemaPtr,
node: XmlNodePtr,
attr: Option<XmlAttrPtr>,
namespace_name: *const XmlChar,
) -> i32 {
unsafe {
if xml_str_equal((*pctxt).target_namespace, namespace_name) {
return 0;
}
if xml_str_equal(XML_SCHEMA_NS.as_ptr() as _, namespace_name) {
return 0;
}
if !(*WXS_BUCKET!(pctxt)).relations.is_null() {
let mut rel: XmlSchemaSchemaRelationPtr;
rel = (*WXS_BUCKET!(pctxt)).relations;
while {
if WXS_IS_BUCKET_IMPMAIN!((*rel).typ)
&& xml_str_equal(namespace_name, (*rel).import_namespace)
{
return 0;
}
rel = (*rel).next;
!rel.is_null()
} {}
}
{
let n = attr.map_or(Some(XmlGenericNodePtr::from(node)), |attr| {
Some(attr.into())
});
if namespace_name.is_null() {
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapSrcResolve,
n,
null_mut(),
"References from this schema to components in no namespace are not allowed, since not indicated by an import statement",
None,
None,
);
} else {
let namespace_name = CStr::from_ptr(namespace_name as *const i8).to_string_lossy();
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapSrcResolve,
n,
null_mut(),
format!("References from this schema to components in the namespace '{namespace_name}' are not allowed, since not indicated by an import statement").as_str(),
Some(&namespace_name),
None
);
}
}
XmlParserErrors::XmlSchemapSrcResolve as i32
}
}
pub(crate) unsafe fn xml_schema_new_qname_ref(
pctxt: XmlSchemaParserCtxtPtr,
ref_type: XmlSchemaTypeType,
ref_name: *const XmlChar,
ref_ns: *const XmlChar,
) -> XmlSchemaQNameRefPtr {
unsafe {
let mut ret: XmlSchemaQNameRefPtr;
ret = xml_malloc(size_of::<XmlSchemaQNameRef>()) as XmlSchemaQNameRefPtr;
if ret.is_null() {
xml_schema_perr_memory(pctxt, "allocating QName reference item", None);
return null_mut();
}
(*ret).node = None;
(*ret).typ = XmlSchemaTypeType::XmlSchemaExtraQNameRef;
(*ret).name = ref_name;
(*ret).target_namespace = ref_ns;
(*ret).item = null_mut();
(*ret).item_type = ref_type;
WXS_ADD_LOCAL!(pctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaAddElement")]
pub(crate) unsafe fn xml_schema_add_element(
ctxt: XmlSchemaParserCtxtPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
node: XmlNodePtr,
top_level: i32,
) -> XmlSchemaElementPtr {
unsafe {
let mut ret: XmlSchemaElementPtr;
if ctxt.is_null() || name.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaElement>()) as XmlSchemaElementPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating element", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaElement>());
(*ret).typ = XmlSchemaTypeType::XmlSchemaTypeElement;
(*ret).name = name;
(*ret).target_namespace = ns_name;
(*ret).node = node.into();
if top_level != 0 {
WXS_ADD_GLOBAL!(ctxt, ret);
} else {
WXS_ADD_LOCAL!(ctxt, ret);
}
WXS_ADD_PENDING!(ctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaPGetBoolNodeValue")]
pub(crate) unsafe fn xml_schema_pget_bool_node_value(
ctxt: XmlSchemaParserCtxtPtr,
owner_item: XmlSchemaBasicItemPtr,
node: XmlGenericNodePtr,
) -> i32 {
unsafe {
let mut res: i32 = 0;
let value = node.get_content();
if value.as_deref() == Some("true") {
res = 1;
} else if value.as_deref() == Some("false") {
res = 0;
} else if value.as_deref() == Some("1") {
res = 1;
} else if value.as_deref() == Some("0") {
res = 0;
} else {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapInvalidBoolean,
owner_item,
node,
Some(&*xml_schema_get_built_in_type(
XmlSchemaValType::XmlSchemasBoolean,
)),
None,
value.as_deref(),
None,
None,
None,
);
}
res
}
}
#[doc(alias = "xmlSchemaAddAttributeUse")]
pub(crate) unsafe fn xml_schema_add_attribute_use(
pctxt: XmlSchemaParserCtxtPtr,
node: XmlNodePtr,
) -> XmlSchemaAttributeUsePtr {
unsafe {
let mut ret: XmlSchemaAttributeUsePtr;
if pctxt.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaAttributeUse>()) as XmlSchemaAttributeUsePtr;
if ret.is_null() {
xml_schema_perr_memory(pctxt, "allocating attribute", None);
return null_mut();
}
std::ptr::write(
&mut *ret,
XmlSchemaAttributeUse {
typ: XmlSchemaTypeType::XmlSchemaTypeAttributeUse,
node,
annot: null_mut(),
next: null_mut(),
attr_decl: null_mut(),
flags: 0,
occurs: 0,
def_val: null_mut(),
def_value: null(),
},
);
WXS_ADD_LOCAL!(pctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaAddAttribute")]
pub(crate) unsafe fn xml_schema_add_attribute(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
node: XmlNodePtr,
top_level: i32,
) -> XmlSchemaAttributePtr {
unsafe {
let mut ret: XmlSchemaAttributePtr;
if ctxt.is_null() || schema.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaAttribute>()) as XmlSchemaAttributePtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating attribute", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaAttribute>());
(*ret).typ = XmlSchemaTypeType::XmlSchemaTypeAttribute;
(*ret).node = node.into();
(*ret).name = name;
(*ret).target_namespace = ns_name;
if top_level != 0 {
WXS_ADD_GLOBAL!(ctxt, ret);
} else {
WXS_ADD_LOCAL!(ctxt, ret);
}
WXS_ADD_PENDING!(ctxt, ret);
ret
}
}
pub(crate) unsafe fn xml_schema_add_attribute_use_prohib(
pctxt: XmlSchemaParserCtxtPtr,
) -> XmlSchemaAttributeUseProhibPtr {
unsafe {
let mut ret: XmlSchemaAttributeUseProhibPtr;
ret =
xml_malloc(size_of::<XmlSchemaAttributeUseProhib>()) as XmlSchemaAttributeUseProhibPtr;
if ret.is_null() {
xml_schema_perr_memory(pctxt, "allocating attribute use prohibition", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaAttributeUseProhib>());
(*ret).typ = XmlSchemaTypeType::XmlSchemaExtraAttrUseProhib;
WXS_ADD_LOCAL!(pctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaAddWildcard")]
pub(crate) unsafe fn xml_schema_add_wildcard(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
typ: XmlSchemaTypeType,
node: Option<XmlNodePtr>,
) -> XmlSchemaWildcardPtr {
unsafe {
let mut ret: XmlSchemaWildcardPtr;
if ctxt.is_null() || schema.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaWildcard>()) as XmlSchemaWildcardPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "adding wildcard", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaWildcard>());
(*ret).typ = typ;
(*ret).node = node;
WXS_ADD_LOCAL!(ctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaNewWildcardNs")]
pub(crate) unsafe fn xml_schema_new_wildcard_ns_constraint(
ctxt: XmlSchemaParserCtxtPtr,
) -> XmlSchemaWildcardNsPtr {
unsafe {
let ret: XmlSchemaWildcardNsPtr =
xml_malloc(size_of::<XmlSchemaWildcardNs>()) as XmlSchemaWildcardNsPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "creating wildcard namespace constraint", None);
return null_mut();
}
(*ret).value = null_mut();
(*ret).next = null_mut();
ret
}
}
#[doc(alias = "xmlGetBooleanProp")]
pub(crate) unsafe fn xml_get_boolean_prop(
ctxt: XmlSchemaParserCtxtPtr,
node: XmlNodePtr,
name: &str,
mut def: i32,
) -> i32 {
unsafe {
let Some(val) = (*ctxt).get_prop(node, name) else {
return def;
};
if val == "true" {
def = 1;
} else if val == "false" {
def = 0;
} else if val == "1" {
def = 1;
} else if val == "0" {
def = 0;
} else {
xml_schema_psimple_type_err(
ctxt,
XmlParserErrors::XmlSchemapInvalidBoolean,
null_mut(),
xml_schema_get_prop_node(node, name).unwrap().into(),
Some(&*xml_schema_get_built_in_type(
XmlSchemaValType::XmlSchemasBoolean,
)),
None,
Some(&val),
None,
None,
None,
);
}
def
}
}
pub(crate) unsafe fn xml_schema_add_idc(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
category: XmlSchemaTypeType,
node: XmlNodePtr,
) -> XmlSchemaIDCPtr {
unsafe {
let mut ret: XmlSchemaIDCPtr;
if ctxt.is_null() || schema.is_null() || name.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaIDC>()) as XmlSchemaIDCPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "allocating an identity-constraint definition", None);
return null_mut();
}
std::ptr::write(
&mut *ret,
XmlSchemaIDC {
typ: category,
annot: null_mut(),
next: null_mut(),
node,
name,
target_namespace: ns_name,
selector: null_mut(),
fields: null_mut(),
nb_fields: 0,
refe: null_mut(),
},
);
WXS_ADD_GLOBAL!(ctxt, ret);
if category == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
WXS_ADD_PENDING!(ctxt, ret);
}
ret
}
}
pub(crate) unsafe fn xml_schema_check_cselector_xpath(
ctxt: XmlSchemaParserCtxtPtr,
idc: XmlSchemaIDCPtr,
selector: XmlSchemaIdcselectPtr,
attr: Option<XmlAttrPtr>,
is_field: i32,
) -> i32 {
unsafe {
if selector.is_null() {
xml_schema_perr(
ctxt,
Some(XmlGenericNodePtr::from((*idc).node)),
XmlParserErrors::XmlSchemapInternal,
"Internal error: xmlSchemaCheckCSelectorXPath, the selector is not specified.\n",
None,
None,
);
return -1;
}
let node = attr.map_or(Some(XmlGenericNodePtr::from((*idc).node)), |attr| {
Some(attr.into())
});
if (*selector).xpath.is_null() {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
node,
"The XPath expression of the selector is not valid",
None,
);
return XmlParserErrors::XmlSchemapS4sAttrInvalidValue as i32;
} else {
let ns_list = attr.and_then(|attr| attr.parent().unwrap().get_ns_list(attr.doc));
let mut ns_array = None;
if let Some(ns_list) = ns_list {
ns_array = Some(
ns_list
.into_iter()
.map(|ns| {
(
ns.href().unwrap().into_owned(),
ns.prefix().map(|pref| pref.into_owned()),
)
})
.collect(),
);
}
if is_field != 0 {
(*selector).xpath_comp = xml_pattern_compile(
CStr::from_ptr((*selector).xpath as *const i8)
.to_string_lossy()
.as_ref(),
XmlPatternFlags::XmlPatternXSField as i32,
ns_array,
) as _;
} else {
(*selector).xpath_comp = xml_pattern_compile(
CStr::from_ptr((*selector).xpath as *const i8)
.to_string_lossy()
.as_ref(),
XmlPatternFlags::XmlPatternXSSel as i32,
ns_array,
) as _;
}
if (*selector).xpath_comp.is_none() {
let xpath = CStr::from_ptr((*selector).xpath as *const i8).to_string_lossy();
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapS4sAttrInvalidValue,
null_mut(),
node,
format!("The XPath expression '{xpath}' could not be compiled").as_str(),
Some(&xpath),
);
return XmlParserErrors::XmlSchemapS4sAttrInvalidValue as i32;
}
}
0
}
}
pub(crate) unsafe fn xml_schema_get_qname_ref_name(refe: *mut c_void) -> *const XmlChar {
unsafe { (*(refe as XmlSchemaQNameRefPtr)).name }
}
pub(crate) unsafe fn xml_schema_get_qname_ref_target_ns(refe: *mut c_void) -> *const XmlChar {
unsafe { (*(refe as XmlSchemaQNameRefPtr)).target_namespace }
}
#[doc(alias = "xmlSchemaAddModelGroupDefinition")]
pub(crate) unsafe fn xml_schema_add_model_group_definition(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
node: XmlNodePtr,
) -> XmlSchemaModelGroupDefPtr {
unsafe {
let mut ret: XmlSchemaModelGroupDefPtr;
if ctxt.is_null() || schema.is_null() || name.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaModelGroupDef>()) as XmlSchemaModelGroupDefPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "adding group", None);
return null_mut();
}
std::ptr::write(
&mut *ret,
XmlSchemaModelGroupDef {
typ: XmlSchemaTypeType::XmlSchemaTypeGroup,
annot: null_mut(),
next: null_mut(),
children: null_mut(),
name,
target_namespace: ns_name,
node,
flags: 0,
},
);
if (*ctxt).is_redefine != 0 {
(*ctxt).redef = xml_schema_add_redef(ctxt, (*ctxt).redefined, ret as _, name, ns_name);
if (*ctxt).redef.is_null() {
xml_free(ret as _);
return null_mut();
}
(*ctxt).redef_counter = 0;
}
WXS_ADD_GLOBAL!(ctxt, ret);
WXS_ADD_PENDING!(ctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaAddAttributeGroupDefinition")]
pub(crate) unsafe fn xml_schema_add_attribute_group_definition(
pctxt: XmlSchemaParserCtxtPtr,
_schema: XmlSchemaPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
node: XmlNodePtr,
) -> XmlSchemaAttributeGroupPtr {
unsafe {
let mut ret: XmlSchemaAttributeGroupPtr;
if pctxt.is_null() || name.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaAttributeGroup>()) as XmlSchemaAttributeGroupPtr;
if ret.is_null() {
xml_schema_perr_memory(pctxt, "allocating attribute group", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaAttributeGroup>());
(*ret).typ = XmlSchemaTypeType::XmlSchemaTypeAttributeGroup;
(*ret).name = name as _;
(*ret).target_namespace = ns_name;
(*ret).node = node.into();
(*ret).flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
if (*pctxt).is_redefine != 0 {
(*pctxt).redef =
xml_schema_add_redef(pctxt, (*pctxt).redefined, ret as _, name, ns_name);
if (*pctxt).redef.is_null() {
xml_free(ret as _);
return null_mut();
}
(*pctxt).redef_counter = 0;
}
WXS_ADD_GLOBAL!(pctxt, ret);
WXS_ADD_PENDING!(pctxt, ret);
ret
}
}
#[doc(alias = "xmlSchemaAddNotation")]
pub(crate) unsafe fn xml_schema_add_notation(
ctxt: XmlSchemaParserCtxtPtr,
schema: XmlSchemaPtr,
name: *const XmlChar,
ns_name: *const XmlChar,
_node: XmlNodePtr,
) -> XmlSchemaNotationPtr {
unsafe {
let mut ret: XmlSchemaNotationPtr;
if ctxt.is_null() || schema.is_null() || name.is_null() {
return null_mut();
}
ret = xml_malloc(size_of::<XmlSchemaNotation>()) as XmlSchemaNotationPtr;
if ret.is_null() {
xml_schema_perr_memory(ctxt, "add annotation", None);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaNotation>());
(*ret).typ = XmlSchemaTypeType::XmlSchemaTypeNotation;
(*ret).name = name;
(*ret).target_namespace = ns_name;
WXS_ADD_GLOBAL!(ctxt, ret);
ret
}
}
macro_rules! WXS_COMP_NAME {
($c:expr, $t:ty) => {
(*($c as $t)).name
};
}
macro_rules! WXS_COMP_TNS {
($c:expr, $t:ty) => {
(*($c as $t)).target_namespace
};
}
#[doc(alias = "xmlSchemaFindRedefCompInGraph")]
unsafe fn xml_schema_find_redef_comp_in_graph(
bucket: XmlSchemaBucketPtr,
typ: XmlSchemaTypeType,
name: *const XmlChar,
ns_name: *const XmlChar,
) -> XmlSchemaBasicItemPtr {
unsafe {
let mut ret: XmlSchemaBasicItemPtr;
if bucket.is_null() || name.is_null() {
return null_mut();
}
if !(*bucket).globals.is_null() && !(*(*bucket).globals).items.is_empty() {
for ret in (*(*bucket).globals)
.items
.iter()
.map(|&ret| ret as XmlSchemaBasicItemPtr)
{
if (*ret).typ == typ {
match typ {
XmlSchemaTypeType::XmlSchemaTypeComplex
| XmlSchemaTypeType::XmlSchemaTypeSimple => {
if WXS_COMP_NAME!(ret, XmlSchemaTypePtr) == name
&& WXS_COMP_TNS!(ret, XmlSchemaTypePtr) == ns_name
{
return ret;
}
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
if WXS_COMP_NAME!(ret, XmlSchemaModelGroupDefPtr) == name
&& WXS_COMP_TNS!(ret, XmlSchemaModelGroupDefPtr) == ns_name
{
return ret;
}
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
if WXS_COMP_NAME!(ret, XmlSchemaAttributeGroupPtr) == name as _
&& WXS_COMP_TNS!(ret, XmlSchemaAttributeGroupPtr) == ns_name
{
return ret;
}
}
_ => {
return null_mut();
}
}
}
}
}
if !(*bucket).relations.is_null() {
let mut rel: XmlSchemaSchemaRelationPtr = (*bucket).relations;
(*bucket).flags |= XML_SCHEMA_BUCKET_MARKED;
while {
if !(*rel).bucket.is_null()
&& (*(*rel).bucket).flags & XML_SCHEMA_BUCKET_MARKED == 0
{
ret = xml_schema_find_redef_comp_in_graph((*rel).bucket, typ, name, ns_name);
if !ret.is_null() {
return ret;
}
}
rel = (*rel).next;
!rel.is_null()
} {}
(*bucket).flags ^= XML_SCHEMA_BUCKET_MARKED;
}
null_mut()
}
}
unsafe fn xml_schema_check_srcredefine_first(pctxt: XmlSchemaParserCtxtPtr) -> i32 {
unsafe {
let mut err: i32 = 0;
let mut redef: XmlSchemaRedefPtr = (*WXS_CONSTRUCTOR!(pctxt)).redefs;
let mut prev: XmlSchemaBasicItemPtr;
let mut item: XmlSchemaBasicItemPtr;
let mut was_redefined: i32;
if redef.is_null() {
return 0;
}
while !redef.is_null() {
item = (*redef).item;
prev = xml_schema_find_redef_comp_in_graph(
(*redef).target_bucket,
(*item).typ,
(*redef).ref_name,
(*redef).ref_target_ns,
);
if prev.is_null() {
let node = if !(*redef).reference.is_null() {
xml_schema_get_component_node(((*redef).reference) as _)
} else {
xml_schema_get_component_node(item as _)
};
let typename = xml_schema_get_component_type_str(item as _);
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*redef).ref_target_ns as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*redef).ref_name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapSrcRedefine,
node.map(|node| node.into()),
null_mut(),
format!("The {typename} '{qname}' to be redefined could not be found in the redefined schema").as_str(),
Some(typename),
Some(&qname),
);
err = (*pctxt).err;
redef = (*redef).next;
continue;
}
was_redefined = 0;
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeComplex
| XmlSchemaTypeType::XmlSchemaTypeSimple => {
if (*(prev as XmlSchemaTypePtr)).flags & XML_SCHEMAS_TYPE_REDEFINED != 0 {
was_redefined = 1;
} else {
(*(prev as XmlSchemaTypePtr)).flags |= XML_SCHEMAS_TYPE_REDEFINED;
(*(item as XmlSchemaTypePtr)).base_type = prev as XmlSchemaTypePtr;
}
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
if (*(prev as XmlSchemaModelGroupDefPtr)).flags
& XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED
!= 0
{
was_redefined = 1;
} else {
(*(prev as XmlSchemaModelGroupDefPtr)).flags |=
XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
if !(*redef).reference.is_null() {
(*((*redef).reference as XmlSchemaParticlePtr)).children =
prev as XmlSchemaTreeItemPtr;
}
(*redef).target = prev;
}
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
if (*(prev as XmlSchemaAttributeGroupPtr)).flags
& XML_SCHEMAS_ATTRGROUP_REDEFINED
!= 0
{
was_redefined = 1;
} else {
(*(prev as XmlSchemaAttributeGroupPtr)).flags |=
XML_SCHEMAS_ATTRGROUP_REDEFINED;
if !(*redef).reference.is_null() {
(*((*redef).reference as XmlSchemaQNameRefPtr)).item = prev;
(*redef).target = null_mut();
} else {
(*redef).target = prev;
}
}
}
_ => {
PERROR_INT!(
pctxt,
"xmlSchemaResolveRedefReferences",
"Unexpected redefined component type"
);
return -1;
}
}
if was_redefined != 0 {
let node = if !(*redef).reference.is_null() {
xml_schema_get_component_node(((*redef).reference) as _)
} else {
xml_schema_get_component_node(((*redef).item) as _)
};
let desig = xml_schema_get_component_designation(prev as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapSrcRedefine,
node.map(|node| node.into()),
null_mut(),
format!("The referenced {desig} was already redefined. Multiple redefinition of the same component is not supported").as_str(),
Some(&desig),
None
);
err = (*pctxt).err;
redef = (*redef).next;
continue;
}
redef = (*redef).next;
}
err
}
}
macro_rules! WXS_REDEFINED_TYPE {
($item:expr) => {
(*($item as XmlSchemaTypePtr)).flags & XML_SCHEMAS_TYPE_REDEFINED != 0
};
}
macro_rules! WXS_REDEFINED_MODEL_GROUP_DEF {
($item:expr) => {
(*($item as XmlSchemaModelGroupDefPtr)).flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED != 0
};
}
macro_rules! WXS_REDEFINED_ATTR_GROUP {
($item:expr) => {
(*($item as XmlSchemaAttributeGroupPtr)).flags & XML_SCHEMAS_ATTRGROUP_REDEFINED != 0
};
}
unsafe fn xml_schema_add_components(
pctxt: XmlSchemaParserCtxtPtr,
bucket: XmlSchemaBucketPtr,
) -> i32 {
unsafe {
let mut name: *const XmlChar;
if bucket.is_null() {
return -1;
}
if (*bucket).flags & XML_SCHEMA_BUCKET_COMPS_ADDED != 0 {
return 0;
}
(*bucket).flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
for item in (*(*bucket).globals)
.items
.iter()
.map(|&item| item as XmlSchemaBasicItemPtr)
{
let duplicate = match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeComplex
| XmlSchemaTypeType::XmlSchemaTypeSimple => {
if WXS_REDEFINED_TYPE!(item) {
continue;
}
name = (*(item as XmlSchemaTypePtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).type_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).type_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeElement => {
name = (*(item as XmlSchemaElementPtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).elem_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).elem_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeAttribute => {
name = (*(item as XmlSchemaAttributePtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).attr_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).attr_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
if WXS_REDEFINED_MODEL_GROUP_DEF!(item) {
continue;
}
name = (*(item as XmlSchemaModelGroupDefPtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).group_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).group_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
if WXS_REDEFINED_ATTR_GROUP!(item) {
continue;
}
name = (*(item as XmlSchemaAttributeGroupPtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).attrgrp_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).attrgrp_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeIDCKey
| XmlSchemaTypeType::XmlSchemaTypeIDCUnique
| XmlSchemaTypeType::XmlSchemaTypeIDCKeyref => {
name = (*(item as XmlSchemaIDCPtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).idc_def
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).idc_def
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
XmlSchemaTypeType::XmlSchemaTypeNotation => {
name = (*(item as XmlSchemaNotationPtr)).name;
let table = if WXS_IS_BUCKET_IMPMAIN!((*bucket).typ) {
&mut (*(*WXS_IMPBUCKET!(bucket)).schema).nota_decl
} else {
&mut (*(*(*WXS_INCBUCKET!(bucket)).owner_import).schema).nota_decl
};
table
.insert(
CStr::from_ptr(name as *const i8)
.to_string_lossy()
.into_owned(),
item as _,
)
.is_some()
}
_ => {
PERROR_INT!(
pctxt,
"xmlSchemaAddComponents",
"Unexpected global component type"
);
continue;
}
};
if duplicate {
let typename = xml_schema_get_component_type_str(item as _);
let qname = xml_schema_get_component_qname(item as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapRedefinedType,
xml_schema_get_component_node(item as _).map(|node| node.into()),
item as XmlSchemaBasicItemPtr,
format!("A global {typename} '{qname}' does already exist").as_str(),
Some(typename),
Some(&qname),
);
}
}
if !(*bucket).relations.is_null() {
let mut rel: XmlSchemaSchemaRelationPtr = (*bucket).relations;
while {
if !(*rel).bucket.is_null()
&& (*(*rel).bucket).flags & XML_SCHEMA_BUCKET_COMPS_ADDED == 0
&& xml_schema_add_components(pctxt, (*rel).bucket) == -1
{
return -1;
}
rel = (*rel).next;
!rel.is_null()
} {}
}
0
}
}
#[doc(alias = "xmlSchemaResolveElementReferences")]
unsafe fn xml_schema_resolve_element_references(
elem_decl: XmlSchemaElementPtr,
ctxt: XmlSchemaParserCtxtPtr,
) {
unsafe {
if ctxt.is_null()
|| elem_decl.is_null()
|| (!elem_decl.is_null()
&& (*elem_decl).flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED != 0)
{
return;
}
(*elem_decl).flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
if (*elem_decl).subtypes.is_null() && !(*elem_decl).named_type.is_null() {
let typ: XmlSchemaTypePtr = (*(*ctxt).schema).get_type(
CStr::from_ptr((*elem_decl).named_type as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).named_type_ns.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).named_type_ns as *const i8).to_string_lossy()
})
.as_deref(),
);
if typ.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
elem_decl as XmlSchemaBasicItemPtr,
(*elem_decl).node.map(|node| node.into()),
"type",
(!(*elem_decl).named_type.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).named_type as *const i8).to_string_lossy()
})
.as_deref(),
(!(*elem_decl).named_type_ns.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).named_type_ns as *const i8)
.to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeBasic,
Some("type definition"),
);
} else {
(*elem_decl).subtypes = typ;
}
}
if !(*elem_decl).subst_group.is_null() {
let subst_head: XmlSchemaElementPtr = (*(*ctxt).schema).get_elem(
CStr::from_ptr((*elem_decl).subst_group as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).subst_group_ns.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).subst_group_ns as *const i8).to_string_lossy()
})
.as_deref(),
);
if subst_head.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
elem_decl as XmlSchemaBasicItemPtr,
None,
"substitutionGroup",
(!(*elem_decl).subst_group.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).subst_group as *const i8).to_string_lossy()
})
.as_deref(),
(!(*elem_decl).subst_group_ns.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).subst_group_ns as *const i8)
.to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeElement,
None,
);
} else {
xml_schema_resolve_element_references(subst_head, ctxt);
(*elem_decl).ref_decl = subst_head;
if (*elem_decl).subtypes.is_null() {
if (*subst_head).subtypes.is_null() {
(*elem_decl).subtypes =
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasAnytype);
} else {
(*elem_decl).subtypes = (*subst_head).subtypes;
}
}
}
}
if (*elem_decl).subtypes.is_null()
&& (*elem_decl).named_type.is_null()
&& (*elem_decl).subst_group.is_null()
{
(*elem_decl).subtypes =
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasAnytype);
}
}
}
#[doc(alias = "xmlSchemaResolveUnionMemberTypes")]
unsafe fn xml_schema_resolve_union_member_types(
ctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let mut link: XmlSchemaTypeLinkPtr;
let mut last_link: XmlSchemaTypeLinkPtr;
let mut new_link: XmlSchemaTypeLinkPtr;
let mut member_type: XmlSchemaTypePtr;
link = (*typ).member_types;
last_link = null_mut();
while !link.is_null() {
let name: *const XmlChar = (*((*link).typ as XmlSchemaQNameRefPtr)).name;
let ns_name: *const XmlChar = (*((*link).typ as XmlSchemaQNameRefPtr)).target_namespace;
member_type = (*(*ctxt).schema).get_type(
CStr::from_ptr(name as *const i8).to_string_lossy().as_ref(),
(!ns_name.is_null())
.then(|| CStr::from_ptr(ns_name as *const i8).to_string_lossy())
.as_deref(),
);
if member_type.is_null() || !wxs_is_simple(member_type) {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
typ as XmlSchemaBasicItemPtr,
(*typ).node.map(|node| node.into()),
"memberTypes",
(!name.is_null())
.then(|| CStr::from_ptr(name as *const i8).to_string_lossy())
.as_deref(),
(!ns_name.is_null())
.then(|| CStr::from_ptr(ns_name as *const i8).to_string_lossy())
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeSimple,
None,
);
if last_link.is_null() {
(*typ).member_types = (*link).next;
} else {
(*last_link).next = (*link).next;
}
new_link = link;
link = (*link).next;
xml_free(new_link as _);
} else {
(*link).typ = member_type;
last_link = link;
link = (*link).next;
}
}
member_type = (*typ).subtypes;
while !member_type.is_null() {
link = xml_malloc(size_of::<XmlSchemaTypeLink>()) as XmlSchemaTypeLinkPtr;
if link.is_null() {
xml_schema_perr_memory(ctxt, "allocating a type link", None);
return -1;
}
(*link).typ = member_type;
(*link).next = null_mut();
if last_link.is_null() {
(*typ).member_types = link;
} else {
(*last_link).next = link;
}
last_link = link;
member_type = (*member_type).next;
}
0
}
}
#[doc(alias = "xmlSchemaResolveTypeReferences")]
unsafe fn xml_schema_resolve_type_references(
type_def: XmlSchemaTypePtr,
ctxt: XmlSchemaParserCtxtPtr,
) {
unsafe {
if type_def.is_null() {
return;
}
if (*type_def).base_type.is_null() {
(*type_def).base_type = (*(*ctxt).schema).get_type(
CStr::from_ptr((*type_def).base as *const i8)
.to_string_lossy()
.as_ref(),
(!(*type_def).base_ns.is_null())
.then(|| CStr::from_ptr((*type_def).base_ns as *const i8).to_string_lossy())
.as_deref(),
);
if (*type_def).base_type.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
type_def as XmlSchemaBasicItemPtr,
(*type_def).node.map(|node| node.into()),
"base",
(!(*type_def).base.is_null())
.then(|| CStr::from_ptr((*type_def).base as *const i8).to_string_lossy())
.as_deref(),
(!(*type_def).base_ns.is_null())
.then(|| CStr::from_ptr((*type_def).base_ns as *const i8).to_string_lossy())
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeSimple,
None,
);
return;
}
}
if wxs_is_simple(type_def) {
if (*type_def).wxs_is_union() {
xml_schema_resolve_union_member_types(ctxt, type_def);
} else if (*type_def).wxs_is_list() {
if (*type_def).subtypes.is_null() && !(*type_def).base.is_null() {
(*type_def).subtypes = (*(*ctxt).schema).get_type(
CStr::from_ptr((*type_def).base as *const i8)
.to_string_lossy()
.as_ref(),
(!(*type_def).base_ns.is_null())
.then(|| {
CStr::from_ptr((*type_def).base_ns as *const i8).to_string_lossy()
})
.as_deref(),
);
if (*type_def).subtypes.is_null() || !wxs_is_simple((*type_def).subtypes) {
(*type_def).subtypes = null_mut();
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
type_def as XmlSchemaBasicItemPtr,
(*type_def).node.map(|node| node.into()),
"itemType",
(!(*type_def).base.is_null())
.then(|| {
CStr::from_ptr((*type_def).base as *const i8).to_string_lossy()
})
.as_deref(),
(!(*type_def).base_ns.is_null())
.then(|| {
CStr::from_ptr((*type_def).base_ns as *const i8)
.to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeSimple,
None,
);
}
}
return;
}
}
else if !(*type_def).subtypes.is_null()
&& (*(*type_def).subtypes).typ == XmlSchemaTypeType::XmlSchemaTypeParticle
&& !WXS_TYPE_PARTICLE_TERM!(type_def).is_null()
&& (*WXS_TYPE_PARTICLE_TERM!(type_def)).typ == XmlSchemaTypeType::XmlSchemaExtraQNameRef
{
let refe: XmlSchemaQNameRefPtr =
WXS_TYPE_PARTICLE_TERM!(type_def) as XmlSchemaQNameRefPtr;
WXS_TYPE_PARTICLE_TERM!(type_def) = null_mut();
let group_def: XmlSchemaModelGroupDefPtr = (*(*ctxt).schema).get_named_component(
(*refe).item_type,
CStr::from_ptr((*refe).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
) as XmlSchemaModelGroupDefPtr;
if group_def.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
null_mut(),
xml_schema_get_component_node((WXS_TYPE_PARTICLE!(type_def)) as _)
.map(|node| node.into()),
"ref",
(!(*refe).name.is_null())
.then(|| CStr::from_ptr((*refe).name as *const i8).to_string_lossy())
.as_deref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
(*refe).item_type,
None,
);
(*type_def).subtypes = null_mut();
} else if WXS_MODELGROUPDEF_MODEL!(group_def).is_null() {
(*type_def).subtypes = null_mut();
} else {
WXS_TYPE_PARTICLE_TERM!(type_def) = WXS_MODELGROUPDEF_MODEL!(group_def);
if (*WXS_MODELGROUPDEF_MODEL!(group_def)).typ == XmlSchemaTypeType::XmlSchemaTypeAll
{
if (*WXS_TYPE_PARTICLE!(type_def)).max_occurs != 1 {
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCosAllLimited,
xml_schema_get_component_node((WXS_TYPE_PARTICLE!(type_def)) as _)
.map(|node| node.into()),
null_mut(),
"The particle's {max occurs} must be 1, since the reference resolves to an 'all' model group",
None,
None,
);
}
}
}
}
}
}
#[doc(alias = "xmlSchemaResolveAttrTypeReferences")]
unsafe fn xml_schema_resolve_attr_type_references(
item: XmlSchemaAttributePtr,
ctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if (*item).flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED != 0 {
return 0;
}
(*item).flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
if !(*item).subtypes.is_null() {
return 0;
}
if !(*item).type_name.is_null() {
let typ: XmlSchemaTypePtr = (*(*ctxt).schema).get_type(
CStr::from_ptr((*item).type_name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*item).type_ns.is_null())
.then(|| CStr::from_ptr((*item).type_ns as *const i8).to_string_lossy())
.as_deref(),
);
if typ.is_null() || !wxs_is_simple(typ) {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
item as XmlSchemaBasicItemPtr,
(*item).node.map(|node| node.into()),
"type",
(!(*item).type_name.is_null())
.then(|| CStr::from_ptr((*item).type_name as *const i8).to_string_lossy())
.as_deref(),
(!(*item).type_ns.is_null())
.then(|| CStr::from_ptr((*item).type_ns as *const i8).to_string_lossy())
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeSimple,
None,
);
return (*ctxt).err;
} else {
(*item).subtypes = typ;
}
} else {
(*item).subtypes =
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasAnySimpletype);
}
0
}
}
#[doc(alias = "xmlSchemaResolveAttrUseReferences")]
unsafe fn xml_schema_resolve_attr_use_references(
ause: XmlSchemaAttributeUsePtr,
ctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if ctxt.is_null() || ause.is_null() {
return -1;
}
if (*ause).attr_decl.is_null()
|| (*(*ause).attr_decl).typ != XmlSchemaTypeType::XmlSchemaExtraQNameRef
{
return 0;
}
{
let refe: XmlSchemaQNameRefPtr = (*ause).attr_decl as XmlSchemaQNameRefPtr;
(*ause).attr_decl = (*(*ctxt).schema).get_attribute_decl(
CStr::from_ptr((*refe).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
);
if (*ause).attr_decl.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
ause as XmlSchemaBasicItemPtr,
Some(XmlGenericNodePtr::from((*ause).node)),
"ref",
(!(*refe).name.is_null())
.then(|| CStr::from_ptr((*refe).name as *const i8).to_string_lossy())
.as_deref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeAttribute,
None,
);
return (*ctxt).err;
}
}
0
}
}
#[doc(alias = "xmlSchemaResolveAttrGroupReferences")]
unsafe fn xml_schema_resolve_attr_group_references(
refe: XmlSchemaQNameRefPtr,
ctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if !(*refe).item.is_null() {
return 0;
}
let group: XmlSchemaAttributeGroupPtr = (*(*ctxt).schema).get_attribute_group(
CStr::from_ptr((*refe).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*refe).target_namespace.is_null())
.then(|| CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy())
.as_deref(),
);
if group.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
null_mut(),
(*refe).node.map(|node| node.into()),
"ref",
(!(*refe).name.is_null())
.then(|| CStr::from_ptr((*refe).name as *const i8).to_string_lossy())
.as_deref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
(*refe).item_type,
None,
);
return (*ctxt).err;
}
(*refe).item = group as XmlSchemaBasicItemPtr;
0
}
}
#[doc(alias = "xmlSchemaResolveModelGroupParticleReferences")]
unsafe fn xml_schema_resolve_model_group_particle_references(
ctxt: XmlSchemaParserCtxtPtr,
mg: XmlSchemaModelGroupPtr,
) {
unsafe {
let mut particle: XmlSchemaParticlePtr = WXS_MODELGROUP_PARTICLE!(mg);
let mut refe: XmlSchemaQNameRefPtr;
let mut ref_item: XmlSchemaBasicItemPtr;
while !particle.is_null() {
'next_particle: {
if WXS_PARTICLE_TERM!(particle).is_null()
|| (*WXS_PARTICLE_TERM!(particle)).typ
!= XmlSchemaTypeType::XmlSchemaExtraQNameRef
{
break 'next_particle;
}
refe = WXS_PARTICLE_TERM!(particle) as XmlSchemaQNameRefPtr;
(*particle).children = null_mut();
ref_item = (*(*ctxt).schema).get_named_component(
(*refe).item_type,
CStr::from_ptr((*refe).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
);
if ref_item.is_null() {
xml_schema_pres_comp_attr_err(
ctxt,
XmlParserErrors::XmlSchemapSrcResolve,
null_mut(),
xml_schema_get_component_node(particle as _).map(|node| node.into()),
"ref",
(!(*refe).name.is_null())
.then(|| CStr::from_ptr((*refe).name as *const i8).to_string_lossy())
.as_deref(),
(!(*refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*refe).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
(*refe).item_type,
None,
);
break 'next_particle;
}
if (*ref_item).typ == XmlSchemaTypeType::XmlSchemaTypeGroup {
if WXS_MODELGROUPDEF_MODEL!(ref_item).is_null() {
break 'next_particle;
}
if (*WXS_MODELGROUPDEF_MODEL!(ref_item)).typ
== XmlSchemaTypeType::XmlSchemaTypeAll
{
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCosAllLimited,
xml_schema_get_component_node(particle as _).map(|node| node.into()),
null_mut(),
"A model group definition is referenced, but it contains an 'all' model group, which cannot be contained by model groups",
None,
None,
);
break 'next_particle;
}
(*particle).children = ref_item as XmlSchemaTreeItemPtr;
} else {
(*particle).children = ref_item as XmlSchemaTreeItemPtr;
}
}
particle = (*particle).next as XmlSchemaParticlePtr;
}
}
}
#[doc(alias = "xmlSchemaResolveIDCKeyReferences")]
unsafe fn xml_schema_resolve_idckey_references(
idc: XmlSchemaIDCPtr,
pctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if (*idc).typ != XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
return 0;
}
if !(*(*idc).refe).name.is_null() {
(*(*idc).refe).item = (*(*pctxt).schema).get_idc(
CStr::from_ptr((*(*idc).refe).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*(*idc).refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*(*idc).refe).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
) as XmlSchemaBasicItemPtr;
if (*(*idc).refe).item.is_null() {
xml_schema_pres_comp_attr_err(
pctxt,
XmlParserErrors::XmlSchemapSrcResolve,
idc as XmlSchemaBasicItemPtr,
Some(XmlGenericNodePtr::from((*idc).node)),
"refer",
(!(*(*idc).refe).name.is_null())
.then(|| CStr::from_ptr((*(*idc).refe).name as *const i8).to_string_lossy())
.as_deref(),
(!(*(*idc).refe).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*(*idc).refe).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeIDCKey,
None,
);
return (*pctxt).err;
} else if (*(*(*idc).refe).item).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCPropsCorrect,
None,
idc as XmlSchemaBasicItemPtr,
"The keyref references a keyref",
None,
None,
);
(*(*idc).refe).item = null_mut();
return (*pctxt).err;
} else if (*idc).nb_fields != (*((*(*idc).refe).item as XmlSchemaIDCPtr)).nb_fields {
let refer: XmlSchemaIDCPtr = (*(*idc).refe).item as XmlSchemaIDCPtr;
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*refer).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*refer).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCPropsCorrect,
None,
idc as XmlSchemaBasicItemPtr,
format!("The cardinality of the keyref differs from the cardinality of the referenced key/unique '{qname}'").as_str(),
Some(&qname),
None
);
return (*pctxt).err;
}
}
0
}
}
unsafe fn xml_schema_resolve_attr_use_prohib_references(
prohib: XmlSchemaAttributeUseProhibPtr,
pctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if (*(*pctxt).schema)
.get_attribute_decl(
CStr::from_ptr((*prohib).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*prohib).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*prohib).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
)
.is_null()
{
xml_schema_pres_comp_attr_err(
pctxt,
XmlParserErrors::XmlSchemapSrcResolve,
null_mut(),
(*prohib).node.map(|node| node.into()),
"ref",
(!(*prohib).name.is_null())
.then(|| CStr::from_ptr((*prohib).name as *const i8).to_string_lossy())
.as_deref(),
(!(*prohib).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*prohib).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
XmlSchemaTypeType::XmlSchemaTypeAttribute,
None,
);
return XmlParserErrors::XmlSchemapSrcResolve as i32;
}
0
}
}
#[doc(alias = "xmlSchemaCheckTypeDefCircularInternal")]
unsafe fn xml_schema_check_type_def_circular_internal(
pctxt: XmlSchemaParserCtxtPtr,
ctxt_type: XmlSchemaTypePtr,
ancestor: XmlSchemaTypePtr,
) -> i32 {
unsafe {
if ancestor.is_null() || (*ancestor).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
return 0;
}
if ctxt_type == ancestor {
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapStPropsCorrect2,
ctxt_type as XmlSchemaBasicItemPtr,
xml_schema_get_component_node(ctxt_type as _).map(|node| node.into()),
"The definition is circular",
None,
);
return XmlParserErrors::XmlSchemapStPropsCorrect2 as i32;
}
if (*ancestor).flags & XML_SCHEMAS_TYPE_MARKED != 0 {
return 0;
}
(*ancestor).flags |= XML_SCHEMAS_TYPE_MARKED;
let ret: i32 =
xml_schema_check_type_def_circular_internal(pctxt, ctxt_type, (*ancestor).base_type);
(*ancestor).flags ^= XML_SCHEMAS_TYPE_MARKED;
ret
}
}
#[doc(alias = "xmlSchemaCheckTypeDefCircular")]
unsafe fn xml_schema_check_type_def_circular(item: XmlSchemaTypePtr, ctxt: XmlSchemaParserCtxtPtr) {
unsafe {
if item.is_null()
|| (*item).typ == XmlSchemaTypeType::XmlSchemaTypeBasic
|| (*item).base_type.is_null()
{
return;
}
xml_schema_check_type_def_circular_internal(ctxt, item, (*item).base_type);
}
}
#[doc(alias = "xmlSchemaGetCircModelGrDefRef")]
unsafe fn xml_schema_get_circ_model_gr_def_ref(
group_def: XmlSchemaModelGroupDefPtr,
mut particle: XmlSchemaTreeItemPtr,
) -> XmlSchemaTreeItemPtr {
unsafe {
let mut circ: XmlSchemaTreeItemPtr;
let mut term: XmlSchemaTreeItemPtr;
let mut gdef: XmlSchemaModelGroupDefPtr;
while !particle.is_null() {
term = (*particle).children;
if term.is_null() {
particle = (*particle).next;
continue;
}
match (*term).typ {
XmlSchemaTypeType::XmlSchemaTypeGroup => {
gdef = term as XmlSchemaModelGroupDefPtr;
if gdef == group_def {
return particle;
}
if (*gdef).flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED != 0 {
particle = (*particle).next;
continue;
}
if !(*gdef).children.is_null() {
(*gdef).flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
circ = xml_schema_get_circ_model_gr_def_ref(
group_def,
(*(*gdef).children).children,
);
(*gdef).flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
if !circ.is_null() {
return circ;
}
}
}
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice
| XmlSchemaTypeType::XmlSchemaTypeAll => {
circ = xml_schema_get_circ_model_gr_def_ref(group_def, (*term).children);
if !circ.is_null() {
return circ;
}
}
_ => {}
}
particle = (*particle).next;
}
null_mut()
}
}
#[doc(alias = "xmlSchemaCheckGroupDefCircular")]
unsafe fn xml_schema_check_group_def_circular(
item: XmlSchemaModelGroupDefPtr,
ctxt: XmlSchemaParserCtxtPtr,
) {
unsafe {
if item.is_null()
|| (*item).typ != XmlSchemaTypeType::XmlSchemaTypeGroup
|| (*item).children.is_null()
{
return;
}
{
let circ: XmlSchemaTreeItemPtr =
xml_schema_get_circ_model_gr_def_ref(item, (*(*item).children).children);
if !circ.is_null() {
let q1 = xml_schema_format_qname(
Some(
CStr::from_ptr((*item).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*item).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapMgPropsCorrect2,
null_mut(),
xml_schema_get_component_node(circ as _).map(|node| node.into()),
format!("Circular reference to the model group definition '{q1}' defined")
.as_str(),
Some(&q1),
);
(*circ).children = null_mut();
}
}
}
}
#[doc(alias = "xmlSchemaCheckAttrGroupCircularRecur")]
unsafe fn xml_schema_check_attr_group_circular_recur(
ctxt_gr: XmlSchemaAttributeGroupPtr,
list: XmlSchemaItemListPtr<*mut c_void>,
) -> XmlSchemaQNameRefPtr {
unsafe {
let mut gr: XmlSchemaAttributeGroupPtr;
let mut circ: XmlSchemaQNameRefPtr;
for refe in (*list)
.items
.iter()
.map(|&refe| refe as XmlSchemaQNameRefPtr)
{
if (*refe).typ == XmlSchemaTypeType::XmlSchemaExtraQNameRef
&& (*refe).item_type == XmlSchemaTypeType::XmlSchemaTypeAttributeGroup
&& !(*refe).item.is_null()
{
gr = (*refe).item as XmlSchemaAttributeGroupPtr;
if gr == ctxt_gr {
return refe;
}
if (*gr).flags & XML_SCHEMAS_ATTRGROUP_MARKED != 0 {
continue;
}
if !(*gr).attr_uses.is_null() && (*gr).flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS != 0 {
(*gr).flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
circ = xml_schema_check_attr_group_circular_recur(
ctxt_gr,
(*gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>,
);
(*gr).flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
if !circ.is_null() {
return circ;
}
}
}
}
null_mut()
}
}
#[doc(alias = "xmlSchemaCheckAttrGroupCircular")]
unsafe fn xml_schema_check_attr_group_circular(
attr_gr: XmlSchemaAttributeGroupPtr,
ctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
if (*attr_gr).attr_uses.is_null() || (*attr_gr).flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS == 0
{
return 0;
} else {
let circ: XmlSchemaQNameRefPtr = xml_schema_check_attr_group_circular_recur(
attr_gr,
(*attr_gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>,
);
if !circ.is_null() {
let q1 = xml_schema_get_component_qname(attr_gr as _);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcAttributeGroup3,
null_mut(),
xml_schema_get_component_node((circ as XmlSchemaBasicItemPtr) as _)
.map(|node| node.into()),
format!("Circular reference to the attribute group '{q1}' defined").as_str(),
Some(&q1),
);
(*circ).item = null_mut();
return (*ctxt).err;
}
}
0
}
}
#[doc(alias = "xmlSchemaModelGroupToModelGroupDefFixup")]
unsafe fn xml_schema_model_group_to_model_group_def_fixup(
_ctxt: XmlSchemaParserCtxtPtr,
mg: XmlSchemaModelGroupPtr,
) {
unsafe {
let mut particle: XmlSchemaParticlePtr = WXS_MODELGROUP_PARTICLE!(mg);
while !particle.is_null() {
if WXS_PARTICLE_TERM!(particle).is_null()
|| (*WXS_PARTICLE_TERM!(particle)).typ != XmlSchemaTypeType::XmlSchemaTypeGroup
{
particle = (*particle).next as XmlSchemaParticlePtr;
continue;
}
if WXS_MODELGROUPDEF_MODEL!(WXS_PARTICLE_TERM!(particle)).is_null() {
WXS_PARTICLE_TERM!(particle) = null_mut();
particle = (*particle).next as XmlSchemaParticlePtr;
continue;
}
WXS_PARTICLE_TERM!(particle) =
WXS_MODELGROUPDEF_MODEL!(WXS_PARTICLE_TERM!(particle)) as XmlSchemaTreeItemPtr;
particle = (*particle).next as XmlSchemaParticlePtr;
}
}
}
#[doc(alias = "xmlSchemaCloneWildcardNsConstraints")]
unsafe fn xml_schema_clone_wildcard_ns_constraints(
ctxt: XmlSchemaParserCtxtPtr,
dest: XmlSchemaWildcardPtr,
source: XmlSchemaWildcardPtr,
) -> i32 {
unsafe {
let mut cur: XmlSchemaWildcardNsPtr;
let mut tmp: XmlSchemaWildcardNsPtr;
let mut last: XmlSchemaWildcardNsPtr;
if source.is_null() || dest.is_null() {
return -1;
}
(*dest).any = (*source).any;
cur = (*source).ns_set;
last = null_mut();
while !cur.is_null() {
tmp = xml_schema_new_wildcard_ns_constraint(ctxt);
if tmp.is_null() {
return -1;
}
(*tmp).value = (*cur).value;
if last.is_null() {
(*dest).ns_set = tmp;
} else {
(*last).next = tmp;
}
last = tmp;
cur = (*cur).next;
}
if !(*dest).neg_ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*dest).neg_ns_set);
}
if !(*source).neg_ns_set.is_null() {
(*dest).neg_ns_set = xml_schema_new_wildcard_ns_constraint(ctxt);
if (*dest).neg_ns_set.is_null() {
return -1;
}
(*(*dest).neg_ns_set).value = (*(*source).neg_ns_set).value;
} else {
(*dest).neg_ns_set = null_mut();
}
0
}
}
#[doc(alias = "xmlSchemaIntersectWildcards")]
unsafe fn xml_schema_intersect_wildcards(
ctxt: XmlSchemaParserCtxtPtr,
complete_wild: XmlSchemaWildcardPtr,
cur_wild: XmlSchemaWildcardPtr,
) -> i32 {
unsafe {
let mut cur: XmlSchemaWildcardNsPtr;
let mut cur_b: XmlSchemaWildcardNsPtr;
let mut prev: XmlSchemaWildcardNsPtr;
let mut tmp: XmlSchemaWildcardNsPtr;
if (*complete_wild).any == (*cur_wild).any
&& (*complete_wild).ns_set.is_null() == (*cur_wild).ns_set.is_null()
&& (*complete_wild).neg_ns_set.is_null() == (*cur_wild).neg_ns_set.is_null()
&& ((*complete_wild).neg_ns_set.is_null()
|| (*(*complete_wild).neg_ns_set).value == (*(*cur_wild).neg_ns_set).value)
{
if !(*complete_wild).ns_set.is_null() {
let mut found: i32 = 0;
cur = (*complete_wild).ns_set;
while !cur.is_null() {
found = 0;
cur_b = (*cur_wild).ns_set;
while !cur_b.is_null() {
if (*cur).value == (*cur_b).value {
found = 1;
break;
}
cur_b = (*cur_b).next;
}
if found == 0 {
break;
}
cur = (*cur).next;
}
if found != 0 {
return 0;
}
} else {
return 0;
}
}
if (*complete_wild).any != (*cur_wild).any && (*complete_wild).any != 0 {
if xml_schema_clone_wildcard_ns_constraints(ctxt, complete_wild, cur_wild) == -1 {
return -1;
}
return 0;
}
if (!(*complete_wild).neg_ns_set.is_null() && !(*cur_wild).ns_set.is_null())
|| (!(*cur_wild).neg_ns_set.is_null() && !(*complete_wild).ns_set.is_null())
{
let neg: *const XmlChar;
if (*complete_wild).ns_set.is_null() {
neg = (*(*complete_wild).neg_ns_set).value;
if xml_schema_clone_wildcard_ns_constraints(ctxt, complete_wild, cur_wild) == -1 {
return -1;
}
} else {
neg = (*(*cur_wild).neg_ns_set).value;
}
prev = null_mut();
cur = (*complete_wild).ns_set;
while !cur.is_null() {
if (*cur).value.is_null() {
if prev.is_null() {
(*complete_wild).ns_set = (*cur).next;
} else {
(*prev).next = (*cur).next;
}
xml_free(cur as _);
break;
}
prev = cur;
cur = (*cur).next;
}
if !neg.is_null() {
prev = null_mut();
cur = (*complete_wild).ns_set;
while !cur.is_null() {
if (*cur).value == neg {
if prev.is_null() {
(*complete_wild).ns_set = (*cur).next;
} else {
(*prev).next = (*cur).next;
}
xml_free(cur as _);
break;
}
prev = cur;
cur = (*cur).next;
}
}
return 0;
}
if !(*complete_wild).ns_set.is_null() && !(*cur_wild).ns_set.is_null() {
let mut found: i32;
cur = (*complete_wild).ns_set;
prev = null_mut();
while !cur.is_null() {
found = 0;
cur_b = (*cur_wild).ns_set;
while !cur_b.is_null() {
if (*cur).value == (*cur_b).value {
found = 1;
break;
}
cur_b = (*cur_b).next;
}
if found == 0 {
if prev.is_null() {
(*complete_wild).ns_set = (*cur).next;
} else {
(*prev).next = (*cur).next;
}
tmp = (*cur).next;
xml_free(cur as _);
cur = tmp;
continue;
}
prev = cur;
cur = (*cur).next;
}
return 0;
}
if !(*complete_wild).neg_ns_set.is_null()
&& !(*cur_wild).neg_ns_set.is_null()
&& (*(*complete_wild).neg_ns_set).value != (*(*cur_wild).neg_ns_set).value
&& !(*(*complete_wild).neg_ns_set).value.is_null()
&& !(*(*cur_wild).neg_ns_set).value.is_null()
{
xml_schema_perr(
ctxt,
(*complete_wild).node.map(|node| node.into()),
XmlParserErrors::XmlSchemapIntersectionNotExpressible,
"The intersection of the wildcard is not expressible.\n",
None,
None,
);
return XmlParserErrors::XmlSchemapIntersectionNotExpressible as i32;
}
if !(*complete_wild).neg_ns_set.is_null()
&& !(*cur_wild).neg_ns_set.is_null()
&& (*(*complete_wild).neg_ns_set).value != (*(*cur_wild).neg_ns_set).value
&& (*(*complete_wild).neg_ns_set).value.is_null()
{
(*(*complete_wild).neg_ns_set).value = (*(*cur_wild).neg_ns_set).value;
}
0
}
}
#[doc(alias = "xmlSchemaExpandAttributeGroupRefs")]
unsafe fn xml_schema_expand_attribute_group_refs(
pctxt: XmlSchemaParserCtxtPtr,
item: XmlSchemaBasicItemPtr,
complete_wild: *mut XmlSchemaWildcardPtr,
list: XmlSchemaItemListPtr<*mut c_void>,
prohibs: XmlSchemaItemListPtr<XmlSchemaAttributeUseProhibPtr>,
) -> i32 {
unsafe {
let mut gr: XmlSchemaAttributeGroupPtr;
let mut sublist: XmlSchemaItemListPtr<*mut c_void>;
let mut created: i32 = (!(*complete_wild).is_null()) as i32;
if !prohibs.is_null() {
(*prohibs).items.clear();
}
let mut i = 0;
'main: while i < (*list).items.len() {
let using = (*list).items[i] as XmlSchemaAttributeUsePtr;
if (*using).typ == XmlSchemaTypeType::XmlSchemaExtraAttrUseProhib {
if prohibs.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaExpandAttributeGroupRefs",
"unexpected attr prohibition found"
);
return -1;
}
if (*list).remove(i) == -1 {
return -1;
}
(*prohibs).push(using as _);
continue 'main;
}
if (*using).typ == XmlSchemaTypeType::XmlSchemaExtraQNameRef
&& (*(using as XmlSchemaQNameRefPtr)).item_type
== XmlSchemaTypeType::XmlSchemaTypeAttributeGroup
{
if (*(using as XmlSchemaQNameRefPtr)).item.is_null() {
return -1;
}
gr = (*(using as XmlSchemaQNameRefPtr)).item as XmlSchemaAttributeGroupPtr;
if (*gr).flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED == 0
&& xml_schema_attribute_group_expand_refs(pctxt, gr) == -1
{
return -1;
}
if !(*gr).attribute_wildcard.is_null() {
if (*complete_wild).is_null() {
*complete_wild = (*gr).attribute_wildcard;
} else {
if created == 0 {
let tmp_wild: XmlSchemaWildcardPtr = xml_schema_add_wildcard(
pctxt,
(*pctxt).schema,
XmlSchemaTypeType::XmlSchemaTypeAnyAttribute,
xml_schema_get_component_node(item as _),
);
if tmp_wild.is_null() {
return -1;
}
if xml_schema_clone_wildcard_ns_constraints(
pctxt,
tmp_wild,
*complete_wild,
) == -1
{
return -1;
}
(*tmp_wild).process_contents = (*(*complete_wild)).process_contents;
*complete_wild = tmp_wild;
created = 1;
}
if xml_schema_intersect_wildcards(
pctxt,
*complete_wild,
(*gr).attribute_wildcard,
) == -1
{
return -1;
}
}
}
sublist = (*gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>;
if sublist.is_null() || (*sublist).items.is_empty() {
if (*list).remove(i) == -1 {
return -1;
}
continue 'main;
}
(*list).items[i] = (*sublist).items[0];
if (*sublist).items.len() != 1 {
for j in 1..(*sublist).items.len() {
i += 1;
if (*list).insert((*sublist).items[j], i) == -1 {
return -1;
}
}
}
}
i += 1;
}
if !prohibs.is_null() && !(*prohibs).items.is_empty() && !(*list).items.is_empty() {
for &prohib in (*prohibs).items.iter().rev() {
for using in (*list)
.items
.iter()
.map(|&using| using as XmlSchemaAttributeUsePtr)
{
if (*prohib).name == WXS_ATTRUSE_DECL_NAME!(using)
&& (*prohib).target_namespace == WXS_ATTRUSE_DECL_TNS!(using)
{
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*prohib).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*prohib).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_warning(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapWarnAttrPointlessProh,
(*prohib).node.map(|node| node.into()),
None,
format!("Skipping pointless attribute use prohibition '{qname}', since a corresponding attribute use exists already in the type definition").as_str(),
Some(&qname),
None,
None
);
if (*prohibs).remove(i) == -1 {
return -1;
}
break;
}
}
}
}
0
}
}
#[doc(alias = "xmlSchemaAttributeGroupExpandRefs")]
unsafe fn xml_schema_attribute_group_expand_refs(
pctxt: XmlSchemaParserCtxtPtr,
attr_gr: XmlSchemaAttributeGroupPtr,
) -> i32 {
unsafe {
if (*attr_gr).attr_uses.is_null()
|| (*attr_gr).flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED != 0
{
return 0;
}
(*attr_gr).flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
if xml_schema_expand_attribute_group_refs(
pctxt,
attr_gr as XmlSchemaBasicItemPtr,
&raw mut (*attr_gr).attribute_wildcard,
(*attr_gr).attr_uses as _,
null_mut(),
) == -1
{
return -1;
}
0
}
}
unsafe fn xml_schema_fixup_simple_type_stage_one(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
if (*typ).typ != XmlSchemaTypeType::XmlSchemaTypeSimple {
return 0;
}
if !WXS_IS_TYPE_NOT_FIXED_1!(typ) {
return 0;
}
(*typ).flags |= XML_SCHEMAS_TYPE_FIXUP_1;
if (*typ).wxs_is_list() {
if (*typ).subtypes.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaFixupSimpleTypeStageOne",
"list type has no item-type assigned"
);
return -1;
}
} else if (*typ).wxs_is_union() {
if (*typ).member_types.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaFixupSimpleTypeStageOne",
"union type has no member-types assigned"
);
return -1;
}
} else {
if (*typ).base_type.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaFixupSimpleTypeStageOne",
"type has no base-type assigned"
);
return -1;
}
if WXS_IS_TYPE_NOT_FIXED_1!((*typ).base_type)
&& xml_schema_fixup_simple_type_stage_one(pctxt, (*typ).base_type) == -1
{
return -1;
}
if (*(*typ).base_type).wxs_is_atomic() {
(*typ).flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
} else if (*(*typ).base_type).wxs_is_list() {
(*typ).flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
(*typ).subtypes = (*(*typ).base_type).subtypes;
} else if (*(*typ).base_type).wxs_is_union() {
(*typ).flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
}
}
0
}
}
unsafe fn xml_schema_check_union_type_def_circular_recur(
pctxt: XmlSchemaParserCtxtPtr,
ctx_type: XmlSchemaTypePtr,
members: XmlSchemaTypeLinkPtr,
) -> i32 {
unsafe {
let mut member: XmlSchemaTypeLinkPtr;
let mut member_type: XmlSchemaTypePtr;
member = members;
while !member.is_null() {
member_type = (*member).typ;
while !member_type.is_null()
&& (*member_type).typ != XmlSchemaTypeType::XmlSchemaTypeBasic
{
if member_type == ctx_type {
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapSrcSimpleType4,
ctx_type as XmlSchemaBasicItemPtr,
None,
"The union type definition is circular",
None,
);
return XmlParserErrors::XmlSchemapSrcSimpleType4 as i32;
}
if (*member_type).wxs_is_union()
&& (*member_type).flags & XML_SCHEMAS_TYPE_MARKED == 0
{
(*member_type).flags |= XML_SCHEMAS_TYPE_MARKED;
let res: i32 = xml_schema_check_union_type_def_circular_recur(
pctxt,
ctx_type,
xml_schema_get_union_simple_type_member_types(member_type),
);
(*member_type).flags ^= XML_SCHEMAS_TYPE_MARKED;
if res != 0 {
return res;
}
}
member_type = (*member_type).base_type;
}
member = (*member).next;
}
0
}
}
unsafe fn xml_schema_check_union_type_def_circular(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
if !(*typ).wxs_is_union() {
return 0;
}
xml_schema_check_union_type_def_circular_recur(pctxt, typ, (*typ).member_types)
}
}
#[doc(alias = "xmlSchemaUnionWildcards")]
unsafe fn xml_schema_union_wildcards(
ctxt: XmlSchemaParserCtxtPtr,
complete_wild: XmlSchemaWildcardPtr,
cur_wild: XmlSchemaWildcardPtr,
) -> i32 {
unsafe {
let mut cur: XmlSchemaWildcardNsPtr;
let mut cur_b: XmlSchemaWildcardNsPtr;
let mut tmp: XmlSchemaWildcardNsPtr;
if ((*complete_wild).any == (*cur_wild).any
&& (*complete_wild).ns_set.is_null() == (*cur_wild).ns_set.is_null()
&& (*complete_wild).neg_ns_set.is_null() == (*cur_wild).neg_ns_set.is_null())
&& ((*complete_wild).neg_ns_set.is_null()
|| (*(*complete_wild).neg_ns_set).value == (*(*cur_wild).neg_ns_set).value)
{
if !(*complete_wild).ns_set.is_null() {
let mut found: i32 = 0;
cur = (*complete_wild).ns_set;
while !cur.is_null() {
found = 0;
cur_b = (*cur_wild).ns_set;
while !cur_b.is_null() {
if (*cur).value == (*cur_b).value {
found = 1;
break;
}
cur_b = (*cur_b).next;
}
if found == 0 {
break;
}
cur = (*cur).next;
}
if found != 0 {
return 0;
}
} else {
return 0;
}
}
if (*complete_wild).any != (*cur_wild).any {
if (*complete_wild).any == 0 {
(*complete_wild).any = 1;
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
if !(*complete_wild).neg_ns_set.is_null() {
xml_free((*complete_wild).neg_ns_set as _);
(*complete_wild).neg_ns_set = null_mut();
}
}
return 0;
}
if !(*complete_wild).ns_set.is_null() && !(*cur_wild).ns_set.is_null() {
let mut found: i32;
cur = (*cur_wild).ns_set;
let start: XmlSchemaWildcardNsPtr = (*complete_wild).ns_set;
while !cur.is_null() {
found = 0;
cur_b = start;
while !cur_b.is_null() {
if (*cur).value == (*cur_b).value {
found = 1;
break;
}
cur_b = (*cur_b).next;
}
if found == 0 {
tmp = xml_schema_new_wildcard_ns_constraint(ctxt);
if tmp.is_null() {
return -1;
}
(*tmp).value = (*cur).value;
(*tmp).next = (*complete_wild).ns_set;
(*complete_wild).ns_set = tmp;
}
cur = (*cur).next;
}
return 0;
}
if !(*complete_wild).neg_ns_set.is_null()
&& !(*cur_wild).neg_ns_set.is_null()
&& (*(*complete_wild).neg_ns_set).value != (*(*cur_wild).neg_ns_set).value
{
(*(*complete_wild).neg_ns_set).value = null_mut();
return 0;
}
if (!(*complete_wild).neg_ns_set.is_null()
&& !(*(*complete_wild).neg_ns_set).value.is_null()
&& !(*cur_wild).ns_set.is_null())
|| (!(*cur_wild).neg_ns_set.is_null()
&& !(*(*cur_wild).neg_ns_set).value.is_null()
&& !(*complete_wild).ns_set.is_null())
{
let mut ns_found: i32;
let mut absent_found: i32 = 0;
if !(*complete_wild).ns_set.is_null() {
cur = (*complete_wild).ns_set;
cur_b = (*cur_wild).neg_ns_set;
} else {
cur = (*cur_wild).ns_set;
cur_b = (*complete_wild).neg_ns_set;
}
ns_found = 0;
while !cur.is_null() {
if (*cur).value.is_null() {
absent_found = 1;
} else if (*cur).value == (*cur_b).value {
ns_found = 1;
}
if ns_found != 0 && absent_found != 0 {
break;
}
cur = (*cur).next;
}
if ns_found != 0 && absent_found != 0 {
(*complete_wild).any = 1;
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
if !(*complete_wild).neg_ns_set.is_null() {
xml_free((*complete_wild).neg_ns_set as _);
(*complete_wild).neg_ns_set = null_mut();
}
} else if ns_found != 0 && absent_found == 0 {
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
if (*complete_wild).neg_ns_set.is_null() {
(*complete_wild).neg_ns_set = xml_schema_new_wildcard_ns_constraint(ctxt);
if (*complete_wild).neg_ns_set.is_null() {
return -1;
}
}
(*(*complete_wild).neg_ns_set).value = null_mut();
} else if ns_found == 0 && absent_found != 0 {
xml_schema_perr(
ctxt,
(*complete_wild).node.map(|node| node.into()),
XmlParserErrors::XmlSchemapUnionNotExpressible,
"The union of the wildcard is not expressible.\n",
None,
None,
);
return XmlParserErrors::XmlSchemapUnionNotExpressible as i32;
} else if ns_found == 0 && absent_found == 0 {
if (*complete_wild).neg_ns_set.is_null() {
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
(*complete_wild).neg_ns_set = xml_schema_new_wildcard_ns_constraint(ctxt);
if (*complete_wild).neg_ns_set.is_null() {
return -1;
}
(*(*complete_wild).neg_ns_set).value = (*(*cur_wild).neg_ns_set).value;
}
}
return 0;
}
if (!(*complete_wild).neg_ns_set.is_null()
&& (*(*complete_wild).neg_ns_set).value.is_null()
&& !(*cur_wild).ns_set.is_null())
|| (!(*cur_wild).neg_ns_set.is_null()
&& (*(*cur_wild).neg_ns_set).value.is_null()
&& !(*complete_wild).ns_set.is_null())
{
if !(*complete_wild).ns_set.is_null() {
cur = (*complete_wild).ns_set;
} else {
cur = (*cur_wild).ns_set;
}
while !cur.is_null() {
if (*cur).value.is_null() {
(*complete_wild).any = 1;
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
if !(*complete_wild).neg_ns_set.is_null() {
xml_free((*complete_wild).neg_ns_set as _);
(*complete_wild).neg_ns_set = null_mut();
}
return 0;
}
cur = (*cur).next;
}
if (*complete_wild).neg_ns_set.is_null() {
if !(*complete_wild).ns_set.is_null() {
xml_schema_free_wildcard_ns_set((*complete_wild).ns_set);
(*complete_wild).ns_set = null_mut();
}
(*complete_wild).neg_ns_set = xml_schema_new_wildcard_ns_constraint(ctxt);
if (*complete_wild).neg_ns_set.is_null() {
return -1;
}
(*(*complete_wild).neg_ns_set).value = null_mut();
}
return 0;
}
0
}
}
#[doc(alias = "xmlSchemaGetParticleEmptiable")]
unsafe fn xml_schema_get_particle_emptiable(particle: XmlSchemaParticlePtr) -> i32 {
unsafe {
let mut part: XmlSchemaParticlePtr;
let mut emptiable: i32;
if (*particle).children.is_null() || (*particle).min_occurs == 0 {
return 1;
}
part = (*(*particle).children).children as XmlSchemaParticlePtr;
if part.is_null() {
return 1;
}
while !part.is_null() {
if (*(*part).children).typ == XmlSchemaTypeType::XmlSchemaTypeElement
|| (*(*part).children).typ == XmlSchemaTypeType::XmlSchemaTypeAny
{
emptiable = ((*part).min_occurs == 0) as i32;
} else {
emptiable = xml_schema_get_particle_emptiable(part);
}
if (*(*particle).children).typ == XmlSchemaTypeType::XmlSchemaTypeChoice {
if emptiable != 0 {
return 1;
}
} else {
if emptiable == 0 {
return 0;
}
}
part = (*part).next as XmlSchemaParticlePtr;
}
if (*(*particle).children).typ == XmlSchemaTypeType::XmlSchemaTypeChoice {
0
} else {
1
}
}
}
unsafe fn xml_schema_is_particle_emptiable(particle: XmlSchemaParticlePtr) -> i32 {
unsafe {
if particle.is_null() || (*particle).min_occurs == 0 || (*particle).children.is_null() {
return 1;
}
if WXS_IS_MODEL_GROUP!((*particle).children) {
return xml_schema_get_particle_emptiable(particle);
}
0
}
}
#[doc(alias = "xmlSchemaCheckSRCCT")]
unsafe fn xml_schema_check_srcct(ctxt: XmlSchemaParserCtxtPtr, typ: XmlSchemaTypePtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
let base: XmlSchemaTypePtr = (*typ).base_type;
if !WXS_HAS_SIMPLE_CONTENT!(typ) {
if !wxs_is_complex(base) {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*base).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*base).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcCt1,
typ as XmlSchemaBasicItemPtr,
(*typ).node.map(|node| node.into()),
format!("If using <complexContent>, the base type is expected to be a complex type. The base type '{qname}' is a simple type").as_str(),
Some(&qname)
);
return XmlParserErrors::XmlSchemapSrcCt1 as i32;
}
} else {
if wxs_is_simple(base) {
if !(*typ).wxs_is_extension() {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*base).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*base).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcCt1,
typ as XmlSchemaBasicItemPtr,
None,
format!("If using <simpleContent> and <restriction>, the base type must be a complex type. The base type '{qname}' is a simple type").as_str(),
Some(&qname)
);
return XmlParserErrors::XmlSchemapSrcCt1 as i32;
}
} else {
if (*base).content_type == XmlSchemaContentType::XmlSchemaContentSimple
|| (*base).content_type == XmlSchemaContentType::XmlSchemaContentBasic
{
if (*base).content_type_def.is_null() {
let name = CStr::from_ptr((*typ).name as *const i8).to_string_lossy();
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapInternal,
typ as XmlSchemaBasicItemPtr,
None,
format!("Internal error: xmlSchemaCheckSRCCT, '{name}', base type has no content type").as_str(),
Some(&name),
);
return -1;
}
} else if (*base).content_type == XmlSchemaContentType::XmlSchemaContentMixed
&& (*typ).wxs_is_restriction()
{
if xml_schema_is_particle_emptiable((*base).subtypes as XmlSchemaParticlePtr)
== 0
{
ret = XmlParserErrors::XmlSchemapSrcCt1 as i32;
} else if (*typ).content_type_def.is_null() {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*base).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*base).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcCt1,
typ as XmlSchemaBasicItemPtr,
None,
format!("A <simpleType> is expected among the children of <restriction>, if <simpleContent> is used and the base type '{qname}' is a complex type").as_str(),
Some(&qname)
);
return XmlParserErrors::XmlSchemapSrcCt1 as i32;
}
} else {
ret = XmlParserErrors::XmlSchemapSrcCt1 as i32;
}
}
if ret > 0 {
if (*typ).wxs_is_restriction() {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*base).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*base).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcCt1,
typ as XmlSchemaBasicItemPtr,
None,
format!("If <simpleContent> and <restriction> is used, the base type must be a simple type or a complex type with mixed content and particle emptiable. The base type '{qname}' is none of those").as_str(),
Some(&qname)
);
} else {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*base).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*base).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapSrcCt1,
typ as XmlSchemaBasicItemPtr,
None,
format!("If <simpleContent> and <extension> is used, the base type must be a simple type. The base type '{qname}' is a complex type").as_str(),
Some(&qname)
);
}
}
}
ret
}
}
#[doc(alias = "xmlSchemaFixupTypeAttributeUses")]
unsafe fn xml_schema_fixup_type_attribute_uses(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let mut uses: XmlSchemaItemListPtr<*mut c_void>;
let mut prohibs: XmlSchemaItemListPtr<XmlSchemaAttributeUseProhibPtr> = null_mut();
if (*typ).base_type.is_null() {
PERROR_INT!(pctxt, "xmlSchemaFixupTypeAttributeUses", "no base type");
return -1;
}
let base_type: XmlSchemaTypePtr = (*typ).base_type;
if WXS_IS_TYPE_NOT_FIXED!(base_type)
&& xml_schema_type_fixup(base_type, pctxt as XmlSchemaAbstractCtxtPtr) == -1
{
return -1;
}
uses = (*typ).attr_uses as _;
let base_uses: XmlSchemaItemListPtr<*mut c_void> = (*base_type).attr_uses as _;
if !uses.is_null() {
if (*typ).wxs_is_restriction() {
if xml_schema_expand_attribute_group_refs(
pctxt,
typ as XmlSchemaBasicItemPtr,
&raw mut (*typ).attribute_wildcard,
uses,
(*pctxt).attr_prohibs,
) == -1
{
PERROR_INT!(
pctxt,
"xmlSchemaFixupTypeAttributeUses",
"failed to expand attributes"
);
return -1;
}
if !(*(*pctxt).attr_prohibs).items.is_empty() {
prohibs = (*pctxt).attr_prohibs;
}
} else if xml_schema_expand_attribute_group_refs(
pctxt,
typ as XmlSchemaBasicItemPtr,
&raw mut (*typ).attribute_wildcard,
uses,
null_mut(),
) == -1
{
PERROR_INT!(
pctxt,
"xmlSchemaFixupTypeAttributeUses",
"failed to expand attributes"
);
return -1;
}
}
if !base_uses.is_null() {
if (*typ).wxs_is_restriction() {
let uses_count = if !uses.is_null() {
(*uses).items.len()
} else {
0
};
'inherit_next: for using in (*base_uses)
.items
.iter()
.map(|&using| using as XmlSchemaAttributeUsePtr)
{
if !prohibs.is_null() {
for &pro in &(*prohibs).items {
if WXS_ATTRUSE_DECL_NAME!(using) == (*pro).name
&& WXS_ATTRUSE_DECL_TNS!(using) == (*pro).target_namespace
{
continue 'inherit_next;
}
}
}
if uses_count != 0 {
for tmp in (*uses).items[..uses_count]
.iter()
.map(|&tmp| tmp as XmlSchemaAttributeUsePtr)
{
if WXS_ATTRUSE_DECL_NAME!(using) == WXS_ATTRUSE_DECL_NAME!(tmp)
&& WXS_ATTRUSE_DECL_TNS!(using) == WXS_ATTRUSE_DECL_TNS!(tmp)
{
continue 'inherit_next;
}
}
}
if uses.is_null() {
(*typ).attr_uses = xml_schema_item_list_create::<*mut c_void>() as _;
if (*typ).attr_uses.is_null() {
return -1;
}
uses = (*typ).attr_uses as _;
}
(*uses).push(using as _);
}
} else {
for using in (*base_uses)
.items
.iter()
.map(|&using| using as XmlSchemaAttributeUsePtr)
{
if uses.is_null() {
(*typ).attr_uses = xml_schema_item_list_create::<*mut c_void>() as _;
if (*typ).attr_uses.is_null() {
return -1;
}
uses = (*typ).attr_uses as _;
}
(*uses).push(using as _);
}
}
}
if !uses.is_null() && (*uses).items.is_empty() {
xml_schema_item_list_free(uses);
(*typ).attr_uses = null_mut();
}
if (*typ).wxs_is_extension() {
if !(*base_type).attribute_wildcard.is_null() {
if !(*typ).attribute_wildcard.is_null() {
if xml_schema_union_wildcards(
pctxt,
(*typ).attribute_wildcard,
(*base_type).attribute_wildcard,
) == -1
{
return -1;
}
} else {
(*typ).attribute_wildcard = (*base_type).attribute_wildcard;
}
} else {
}
} else {
}
0
}
}
#[doc(alias = "xmlSchemaIsDerivedFromBuiltInType")]
unsafe fn xml_schema_is_derived_from_built_in_type(
typ: XmlSchemaTypePtr,
val_type: XmlSchemaValType,
) -> i32 {
unsafe {
if typ.is_null() {
return 0;
}
if wxs_is_complex(typ) {
return 0;
}
if (*typ).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
if (*typ).built_in_type == val_type {
return 1;
}
if (*typ).built_in_type == XmlSchemaValType::XmlSchemasAnySimpletype
|| (*typ).built_in_type == XmlSchemaValType::XmlSchemasAnytype
{
return 0;
}
return xml_schema_is_derived_from_built_in_type((*typ).subtypes, val_type);
}
xml_schema_is_derived_from_built_in_type((*typ).subtypes, val_type)
}
}
#[doc(alias = "xmlSchemaCheckCTPropsCorrect")]
unsafe fn xml_schema_check_ctprops_correct(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
if !(*typ).base_type.is_null()
&& wxs_is_simple((*typ).base_type)
&& !(*typ).wxs_is_extension()
{
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapSrcCt1,
None,
typ as XmlSchemaBasicItemPtr,
"If the base type is a simple type, the derivation method must be 'extension'",
None,
None,
);
return XmlParserErrors::XmlSchemapSrcCt1 as i32;
}
if !(*typ).attr_uses.is_null()
&& (*((*typ).attr_uses as XmlSchemaItemListPtr<*mut c_void>))
.items
.len()
> 1
{
let uses: XmlSchemaItemListPtr<*mut c_void> =
(*typ).attr_uses as XmlSchemaItemListPtr<*mut c_void>;
let mut has_id: i32 = 0;
'next_use: for (i, using) in (*uses)
.items
.iter()
.map(|&using| using as XmlSchemaAttributeUsePtr)
.enumerate()
.rev()
{
if i > 0 {
for tmp in (*uses)
.items
.iter()
.take(i)
.rev()
.map(|&tmp| tmp as XmlSchemaAttributeUsePtr)
{
if WXS_ATTRUSE_DECL_NAME!(using) == WXS_ATTRUSE_DECL_NAME!(tmp)
&& WXS_ATTRUSE_DECL_TNS!(using) == WXS_ATTRUSE_DECL_TNS!(tmp)
{
let desig = xml_schema_get_component_designation(using as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAgPropsCorrect,
None,
typ as XmlSchemaBasicItemPtr,
format!("Duplicate {desig}").as_str(),
Some(&desig),
None,
);
if (*uses).remove(i) == -1 {
return -1;
}
continue 'next_use;
}
}
}
if !WXS_ATTRUSE_TYPEDEF!(using).is_null()
&& xml_schema_is_derived_from_built_in_type(
WXS_ATTRUSE_TYPEDEF!(using),
XmlSchemaValType::XmlSchemasID,
) != 0
{
if has_id != 0 {
let desig = xml_schema_get_component_designation(using as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAgPropsCorrect,
None,
typ as XmlSchemaBasicItemPtr,
format!("There must not exist more than one attribute declaration of type 'xs:ID' (or derived from 'xs:ID'). The {desig} violates this constraint").as_str(),
Some(&desig),
None
);
if (*uses).remove(i) == -1 {
return -1;
}
}
has_id = 1;
}
}
}
0
}
}
#[doc(alias = "xmlSchemaCheckCOSCTExtends")]
unsafe fn xml_schema_check_cosctextends(
ctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let base: XmlSchemaTypePtr = (*typ).base_type;
if wxs_is_complex(base) {
if (*base).flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION != 0 {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapCosCtExtends1_1,
typ as XmlSchemaBasicItemPtr,
None,
"The 'final' of the base type definition contains 'extension'",
None,
);
return XmlParserErrors::XmlSchemapCosCtExtends1_1 as i32;
}
if !(*typ).content_type_def.is_null()
&& (*typ).content_type_def == (*base).content_type_def
{
} else if (*typ).content_type == XmlSchemaContentType::XmlSchemaContentEmpty
&& (*base).content_type == XmlSchemaContentType::XmlSchemaContentEmpty
{
} else {
if (*typ).subtypes.is_null() {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapCosCtExtends1_1,
typ as XmlSchemaBasicItemPtr,
None,
"The content type must specify a particle",
None,
);
return XmlParserErrors::XmlSchemapCosCtExtends1_1 as i32;
}
if (*base).content_type == XmlSchemaContentType::XmlSchemaContentEmpty {
} else {
if (*typ).content_type != (*base).content_type
|| ((*typ).content_type != XmlSchemaContentType::XmlSchemaContentMixed
&& (*typ).content_type
!= XmlSchemaContentType::XmlSchemaContentElements)
{
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapCosCtExtends1_1,
typ as XmlSchemaBasicItemPtr,
None,
"The content type of both, the type and its base type, must either 'mixed' or 'element-only'",
None,
);
return XmlParserErrors::XmlSchemapCosCtExtends1_1 as i32;
}
}
}
} else {
if (*typ).content_type_def != base {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapCosCtExtends1_1,
typ as XmlSchemaBasicItemPtr,
None,
"The content type must be the simple base type",
None,
);
return XmlParserErrors::XmlSchemapCosCtExtends1_1 as i32;
}
if (*base).flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION != 0 {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapCosCtExtends1_1,
typ as XmlSchemaBasicItemPtr,
None,
"The 'final' of the base type definition contains 'extension'",
None,
);
return XmlParserErrors::XmlSchemapCosCtExtends1_1 as i32;
}
}
0
}
}
const XML_SCHEMA_ACTION_DERIVE: i32 = 0;
const XML_SCHEMA_ACTION_REDEFINE: i32 = 1;
macro_rules! WXS_ACTION_STR {
($a:expr) => {
Some(if $a == XML_SCHEMA_ACTION_DERIVE {
"base"
} else {
"redefined"
})
};
}
#[doc(alias = "xmlSchemaTypeFinalContains")]
unsafe fn xml_schema_type_final_contains(typ: XmlSchemaTypePtr, is_final: i32) -> i32 {
unsafe {
if typ.is_null() {
return 0;
}
if (*typ).flags & is_final != 0 { 1 } else { 0 }
}
}
#[doc(alias = "xmlSchemaCheckCOSSTDerivedOK")]
unsafe fn xml_schema_check_cosstderived_ok(
actxt: XmlSchemaAbstractCtxtPtr,
typ: XmlSchemaTypePtr,
base_type: XmlSchemaTypePtr,
subset: i32,
) -> i32 {
unsafe {
if typ == base_type {
return 0;
}
if WXS_IS_TYPE_NOT_FIXED!(typ) && xml_schema_type_fixup(typ, actxt) == -1 {
return -1;
}
if WXS_IS_TYPE_NOT_FIXED!(base_type) && xml_schema_type_fixup(base_type, actxt) == -1 {
return -1;
}
if subset & SUBSET_RESTRICTION != 0
|| xml_schema_type_final_contains((*typ).base_type, XML_SCHEMAS_TYPE_FINAL_RESTRICTION)
!= 0
{
return XmlParserErrors::XmlSchemapCosStDerivedOk2_1 as i32;
}
if (*typ).base_type == base_type {
return 0;
}
if !wxs_is_anytype((*typ).base_type)
&& xml_schema_check_cosstderived_ok(actxt, (*typ).base_type, base_type, subset) == 0
{
return 0;
}
if wxs_is_any_simple_type(base_type) && ((*typ).wxs_is_list() || (*typ).wxs_is_union()) {
return 0;
}
if (*base_type).wxs_is_union() {
let mut cur: XmlSchemaTypeLinkPtr;
cur = (*base_type).member_types;
while !cur.is_null() {
if WXS_IS_TYPE_NOT_FIXED!((*cur).typ)
&& xml_schema_type_fixup((*cur).typ, actxt) == -1
{
return -1;
}
if xml_schema_check_cosstderived_ok(actxt, typ, (*cur).typ, subset) == 0 {
return 0;
}
cur = (*cur).next;
}
}
XmlParserErrors::XmlSchemapCosStDerivedOk2_2 as i32
}
}
unsafe fn xml_schema_get_effective_value_constraint(
attruse: XmlSchemaAttributeUsePtr,
fixed: *mut i32,
value: *mut *const XmlChar,
val: *mut XmlSchemaValPtr,
) -> i32 {
unsafe {
*fixed = 0;
*value = null_mut();
if !val.is_null() {
*val = null_mut();
}
if !(*attruse).def_value.is_null() {
*value = (*attruse).def_value;
if !val.is_null() {
*val = (*attruse).def_val;
}
if (*attruse).flags & XML_SCHEMA_ATTR_USE_FIXED != 0 {
*fixed = 1;
}
return 1;
} else if !(*attruse).attr_decl.is_null() && !(*(*attruse).attr_decl).def_value.is_null() {
*value = (*(*attruse).attr_decl).def_value;
if !val.is_null() {
*val = (*(*attruse).attr_decl).def_val;
}
if (*(*attruse).attr_decl).flags & XML_SCHEMAS_ATTR_FIXED != 0 {
*fixed = 1;
}
return 1;
}
0
}
}
#[doc(alias = "xmlSchemaCheckCVCWildcardNamespace")]
unsafe fn xml_schema_check_cvcwildcard_namespace(
wild: XmlSchemaWildcardPtr,
ns: Option<&str>,
) -> i32 {
unsafe {
if wild.is_null() {
return -1;
}
if (*wild).any != 0 {
return 0;
} else if !(*wild).ns_set.is_null() {
let mut cur: XmlSchemaWildcardNsPtr;
cur = (*wild).ns_set;
while !cur.is_null() {
if (!(*cur).value.is_null())
.then(|| CStr::from_ptr((*cur).value as *const i8).to_string_lossy())
.as_deref()
== ns
{
return 0;
}
cur = (*cur).next;
}
} else if !(*wild).neg_ns_set.is_null()
&& ns.is_some()
&& (!(*(*wild).neg_ns_set).value.is_null())
.then(|| CStr::from_ptr((*(*wild).neg_ns_set).value as *const i8).to_string_lossy())
.as_deref()
!= ns
{
return 0;
}
1
}
}
#[doc(alias = "xmlSchemaIsWildcardNsConstraintSubset")]
unsafe fn xml_schema_check_cosnssubset(
sub: XmlSchemaWildcardPtr,
sper: XmlSchemaWildcardPtr,
) -> i32 {
unsafe {
if (*sper).any != 0 {
return 0;
}
if !(*sub).neg_ns_set.is_null()
&& !(*sper).neg_ns_set.is_null()
&& (*(*sub).neg_ns_set).value == (*(*sper).neg_ns_set).value
{
return 0;
}
if !(*sub).ns_set.is_null() {
if !(*sper).ns_set.is_null() {
let mut cur: XmlSchemaWildcardNsPtr;
let mut cur_b: XmlSchemaWildcardNsPtr;
let mut found: i32 = 0;
cur = (*sub).ns_set;
while !cur.is_null() {
found = 0;
cur_b = (*sper).ns_set;
while !cur_b.is_null() {
if (*cur).value == (*cur_b).value {
found = 1;
break;
}
cur_b = (*cur_b).next;
}
if found == 0 {
return 1;
}
cur = (*cur).next;
}
if found != 0 {
return 0;
}
} else if !(*sper).neg_ns_set.is_null() {
let mut cur: XmlSchemaWildcardNsPtr;
cur = (*sub).ns_set;
while !cur.is_null() {
if (*cur).value == (*(*sper).neg_ns_set).value {
return 1;
}
cur = (*cur).next;
}
return 0;
}
}
1
}
}
#[allow(clippy::too_many_arguments)]
unsafe fn xml_schema_check_derivation_okrestriction2to4(
pctxt: XmlSchemaParserCtxtPtr,
action: i32,
item: XmlSchemaBasicItemPtr,
base_item: XmlSchemaBasicItemPtr,
uses: XmlSchemaItemListPtr<*mut c_void>,
base_uses: XmlSchemaItemListPtr<*mut c_void>,
wild: XmlSchemaWildcardPtr,
base_wild: XmlSchemaWildcardPtr,
) -> i32 {
unsafe {
let mut found: i32;
let mut b_eff_value: *const XmlChar = null();
let mut eff_fixed: i32 = 0;
if !uses.is_null() {
for cur in (*uses)
.items
.iter()
.map(|&cur| cur as XmlSchemaAttributeUsePtr)
{
found = 0;
if !base_uses.is_null() {
for bcur in (*base_uses)
.items
.iter()
.map(|&bcur| bcur as XmlSchemaAttributeUsePtr)
{
if WXS_ATTRUSE_DECL_NAME!(cur) == WXS_ATTRUSE_DECL_NAME!(bcur)
&& WXS_ATTRUSE_DECL_TNS!(cur) == WXS_ATTRUSE_DECL_TNS!(bcur)
{
found = 1;
if (*cur).occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL
&& (*bcur).occurs == XML_SCHEMAS_ATTR_USE_REQUIRED
{
let action_str = WXS_ACTION_STR!(action);
let desig = xml_schema_get_component_designation(base_item as _);
xml_schema_pattr_use_err4(
pctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction2_1_1,
xml_schema_get_component_node(item as _).map(|node| node.into()),
item,
cur,
format!("The 'optional' attribute use is inconsistent with the corresponding 'required' attribute use of the {} {desig}", action_str.unwrap()).as_str(),
action_str,
Some(&desig),
None,
None
);
} else if xml_schema_check_cosstderived_ok(
pctxt as XmlSchemaAbstractCtxtPtr,
WXS_ATTRUSE_TYPEDEF!(cur),
WXS_ATTRUSE_TYPEDEF!(bcur),
0,
) != 0
{
let desig1 = xml_schema_get_component_designation(
WXS_ATTRUSE_TYPEDEF!(cur) as _,
);
let desig2 = xml_schema_get_component_designation(
WXS_ATTRUSE_TYPEDEF!(bcur) as _,
);
let action_str = WXS_ACTION_STR!(action);
let desig3 = xml_schema_get_component_designation(base_item as _);
xml_schema_pattr_use_err4(
pctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction2_1_2,
xml_schema_get_component_node(item as _).map(|node| node.into()),
item,
cur,
format!("The attribute declaration's {desig1} is not validly derived from the corresponding {desig2} of the attribute declaration in the {} {desig3}", action_str.unwrap()).as_str(),
Some(&desig1),
Some(&desig2),
action_str,
Some(&desig3),
);
} else {
xml_schema_get_effective_value_constraint(
bcur,
&raw mut eff_fixed,
&raw mut b_eff_value,
null_mut(),
);
if !b_eff_value.is_null() && eff_fixed == 1 {
let mut r_eff_value: *const XmlChar = null();
xml_schema_get_effective_value_constraint(
bcur,
&raw mut eff_fixed,
&raw mut r_eff_value,
null_mut(),
);
if eff_fixed == 0
|| !WXS_ARE_DEFAULT_STR_EQUAL!(r_eff_value, b_eff_value)
{
let action_str = WXS_ACTION_STR!(action);
let desig =
xml_schema_get_component_designation(base_item as _);
xml_schema_pattr_use_err4(
pctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction2_1_3,
xml_schema_get_component_node(item as _).map(|node| node.into()),
item,
cur,
format!("The effective value constraint of the attribute use is inconsistent with its correspondent in the {} {desig}", action_str.unwrap()).as_str(),
action_str,
Some(&desig),
None,
None
);
}
}
}
break;
}
}
}
if found == 0 {
if base_wild.is_null()
|| xml_schema_check_cvcwildcard_namespace(
base_wild,
(!(*WXS_ATTRUSE_DECL!(cur)).target_namespace.is_null())
.then(|| {
CStr::from_ptr(
(*WXS_ATTRUSE_DECL!(cur)).target_namespace as *const i8,
)
.to_string_lossy()
})
.as_deref(),
) != 0
{
let action_str = WXS_ACTION_STR!(action);
let desig = xml_schema_get_component_designation(base_item as _);
xml_schema_pattr_use_err4(
pctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction2_2,
xml_schema_get_component_node(item as _).map(|node| node.into()),
item,
cur,
format!("Neither a matching attribute use, nor a matching wildcard exists in the {} {desig}", action_str.unwrap()).as_str(),
action_str,
Some(&desig),
None,
None
);
}
}
}
}
if !base_uses.is_null() {
for bcur in (*base_uses)
.items
.iter()
.map(|&bcur| bcur as XmlSchemaAttributeUsePtr)
{
if (*bcur).occurs != XML_SCHEMAS_ATTR_USE_REQUIRED {
continue;
}
found = 0;
if !uses.is_null() {
for cur in (*uses)
.items
.iter()
.map(|&cur| cur as XmlSchemaAttributeUsePtr)
{
if WXS_ATTRUSE_DECL_NAME!(cur) == WXS_ATTRUSE_DECL_NAME!(bcur)
&& WXS_ATTRUSE_DECL_TNS!(cur) == WXS_ATTRUSE_DECL_TNS!(bcur)
{
found = 1;
break;
}
}
}
if found == 0 {
let desig1 = xml_schema_get_component_designation(bcur as _);
let desig2 = xml_schema_get_component_designation(base_item as _);
xml_schema_custom_err4(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction3,
None,
item,
format!(
"A matching attribute use for the 'required' {desig1} of the {} {desig2} is missing", WXS_ACTION_STR!(action).unwrap()
)
.as_str(),
Some(&desig1),
WXS_ACTION_STR!(action),
Some(&desig2),
None,
);
}
}
}
if !wild.is_null() {
if base_wild.is_null() {
let str1 = xml_schema_get_component_type_str(item as _);
let str2 = WXS_ACTION_STR!(action);
let str3 = xml_schema_get_component_type_str(base_item as _);
let qname = xml_schema_get_component_qname(base_item as _);
xml_schema_custom_err4(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction4_1,
None,
item,
format!(
"The {str1} has an attribute wildcard, but the {} {str3} '{qname}' does not have one",
str2.unwrap()
)
.as_str(),
Some(str1),
str2,
Some(str3),
Some(&qname),
);
return (*pctxt).err;
} else if (*base_wild).any == 0 && xml_schema_check_cosnssubset(wild, base_wild) != 0 {
let str1 = WXS_ACTION_STR!(action);
let str2 = xml_schema_get_component_type_str(base_item as _);
let qname = xml_schema_get_component_qname(base_item as _);
xml_schema_custom_err4(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction4_2,
None,
item,
format!("The attribute wildcard is not a valid subset of the wildcard in the {} {str2} '{qname}'", str1.unwrap()).as_str(),
str1,
Some(str2),
Some(&qname),
None,
);
return (*pctxt).err;
}
if !wxs_is_anytype(base_item as XmlSchemaTypePtr)
&& (*wild).process_contents < (*base_wild).process_contents
{
let str1 = WXS_ACTION_STR!(action);
let str2 = xml_schema_get_component_type_str(base_item as _);
let qname = xml_schema_get_component_qname(base_item as _);
xml_schema_custom_err4(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction4_3,
None,
base_item,
format!("The {{process contents}} of the attribute wildcard is weaker than the one in the {} {str2} '{qname}'", str1.unwrap()).as_str(),
str1,
Some(str2),
Some(&qname),
None,
);
return (*pctxt).err;
}
}
0
}
}
#[doc(alias = "xmlSchemaCheckDerivationOKRestriction")]
unsafe fn xml_schema_check_derivation_okrestriction(
ctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let base: XmlSchemaTypePtr = (*typ).base_type;
if !wxs_is_complex(base) {
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
(*typ).node.map(|node| node.into()),
typ as XmlSchemaBasicItemPtr,
"The base type must be a complex type",
None,
None,
);
return (*ctxt).err;
}
if (*base).flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION != 0 {
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
(*typ).node.map(|node| node.into()),
typ as XmlSchemaBasicItemPtr,
"The 'final' of the base type definition contains 'restriction'",
None,
None,
);
return (*ctxt).err;
}
if xml_schema_check_derivation_okrestriction2to4(
ctxt,
XML_SCHEMA_ACTION_DERIVE,
typ as XmlSchemaBasicItemPtr,
base as XmlSchemaBasicItemPtr,
(*typ).attr_uses as _,
(*base).attr_uses as _,
(*typ).attribute_wildcard,
(*base).attribute_wildcard,
) == -1
{
return -1;
}
if (*base).built_in_type == XmlSchemaValType::XmlSchemasAnytype {
} else if matches!(
(*typ).content_type,
XmlSchemaContentType::XmlSchemaContentSimple
| XmlSchemaContentType::XmlSchemaContentBasic
) {
if matches!(
(*base).content_type,
XmlSchemaContentType::XmlSchemaContentSimple
| XmlSchemaContentType::XmlSchemaContentBasic
) {
let err: i32 = xml_schema_check_cosstderived_ok(
ctxt as XmlSchemaAbstractCtxtPtr,
(*typ).content_type_def,
(*base).content_type_def,
0,
);
if err != 0 {
if err == -1 {
return -1;
}
let str1 = xml_schema_get_component_designation((*typ).content_type_def as _);
let str2 = xml_schema_get_component_designation((*base).content_type_def as _);
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
None,
typ as XmlSchemaBasicItemPtr,
format!("The {{content type}} {str1} is not validly derived from the base type's {{content type}} {str2}").as_str(),
Some(&str1),
Some(&str2)
);
return (*ctxt).err;
}
} else if (*base).content_type == XmlSchemaContentType::XmlSchemaContentMixed
&& xml_schema_is_particle_emptiable((*base).subtypes as XmlSchemaParticlePtr) != 0
{
} else {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
typ as XmlSchemaBasicItemPtr,
None,
"The content type of the base type must be either a simple type or 'mixed' and an emptiable particle",
None,
);
return (*ctxt).err;
}
} else if (*typ).content_type == XmlSchemaContentType::XmlSchemaContentEmpty {
if (*base).content_type == XmlSchemaContentType::XmlSchemaContentEmpty {
} else if matches!(
(*base).content_type,
XmlSchemaContentType::XmlSchemaContentElements
| XmlSchemaContentType::XmlSchemaContentMixed
) && xml_schema_is_particle_emptiable(
(*base).subtypes as XmlSchemaParticlePtr,
) != 0
{
} else {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
typ as XmlSchemaBasicItemPtr,
None,
"The content type of the base type must be either empty or 'mixed' (or 'elements-only') and an emptiable particle",
None,
);
return (*ctxt).err;
}
} else if (*typ).content_type == XmlSchemaContentType::XmlSchemaContentElements
|| WXS_HAS_MIXED_CONTENT!(typ)
{
if WXS_HAS_MIXED_CONTENT!(typ) && !WXS_HAS_MIXED_CONTENT!(base) {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
typ as XmlSchemaBasicItemPtr,
None,
"If the content type is 'mixed', then the content type of the base type must also be 'mixed'",
None,
);
return (*ctxt).err;
}
} else {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapDerivationOkRestriction1,
typ as XmlSchemaBasicItemPtr,
None,
"The type is not a valid restriction of its base type",
None,
);
return (*ctxt).err;
}
0
}
}
#[doc(alias = "xmlSchemaCheckCTComponent")]
unsafe fn xml_schema_check_ctcomponent(ctxt: XmlSchemaParserCtxtPtr, typ: XmlSchemaTypePtr) -> i32 {
unsafe {
let mut ret: i32;
ret = xml_schema_check_ctprops_correct(ctxt, typ);
if ret != 0 {
return ret;
}
if (*typ).wxs_is_extension() {
ret = xml_schema_check_cosctextends(ctxt, typ);
} else {
ret = xml_schema_check_derivation_okrestriction(ctxt, typ);
}
ret
}
}
unsafe fn xml_schema_fixup_complex_type(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let mut res: i32;
let olderrs: i32 = (*pctxt).nberrors;
let base_type: XmlSchemaTypePtr = (*typ).base_type;
if !WXS_IS_TYPE_NOT_FIXED!(typ) {
return 0;
}
(*typ).flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
'exit_failure: {
if base_type.is_null() {
PERROR_INT!(pctxt, "xmlSchemaFixupComplexType", "missing baseType");
break 'exit_failure;
}
if WXS_IS_TYPE_NOT_FIXED!(base_type) {
xml_schema_type_fixup(base_type, pctxt as XmlSchemaAbstractCtxtPtr);
}
if (*base_type).flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID != 0 {
return 0;
}
res = xml_schema_check_srcct(pctxt, typ);
HFAILURE!(res, 'exit_failure);
'exit_error: {
HERROR!(res, 'exit_error);
if (*typ).content_type == XmlSchemaContentType::XmlSchemaContentSimple {
if wxs_is_complex(base_type)
&& !(*base_type).content_type_def.is_null()
&& (*typ).wxs_is_restriction()
{
let content_base: XmlSchemaTypePtr;
if !(*typ).content_type_def.is_null() {
content_base = (*typ).content_type_def;
(*typ).content_type_def = null_mut();
} else {
content_base = (*base_type).content_type_def;
}
let content: XmlSchemaTypePtr = xml_schema_add_type(
pctxt,
(*pctxt).schema,
XmlSchemaTypeType::XmlSchemaTypeSimple,
null_mut(),
(*typ).target_namespace,
(*typ).node,
0,
);
if content.is_null() {
break 'exit_failure;
}
(*content).typ = XmlSchemaTypeType::XmlSchemaTypeSimple;
(*content).base_type = content_base;
(*content).facets = (*typ).facets;
(*typ).facets = null_mut();
(*content).facet_set = (*typ).facet_set;
(*typ).facet_set = null_mut();
(*typ).content_type_def = content;
if WXS_IS_TYPE_NOT_FIXED!(content_base) {
xml_schema_type_fixup(content_base, pctxt as XmlSchemaAbstractCtxtPtr);
}
res = xml_schema_fixup_simple_type_stage_one(pctxt, content);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
res = xml_schema_fixup_simple_type_stage_two(pctxt, content);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
} else if wxs_is_complex(base_type)
&& (*base_type).content_type == XmlSchemaContentType::XmlSchemaContentMixed
&& (*typ).wxs_is_restriction()
{
if (*typ).content_type_def.is_null()
|| (*(*typ).content_type_def).base_type.is_null()
{
let name = CStr::from_ptr((*typ).name as *const i8).to_string_lossy();
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapInternal,
typ as XmlSchemaBasicItemPtr,
None,
format!("Internal error: xmlSchemaTypeFixup, complex type '{name}': the <simpleContent><restriction> is missing a <simpleType> child, but was not caught by xmlSchemaCheckSRCCT()").as_str(),
Some(&name)
);
break 'exit_failure;
}
} else if wxs_is_complex(base_type) && (*typ).wxs_is_extension() {
if (*base_type).content_type_def.is_null() {
let name = CStr::from_ptr((*typ).name as *const i8).to_string_lossy();
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapInternal,
typ as XmlSchemaBasicItemPtr,
None,
format!("Internal error: xmlSchemaTypeFixup, complex type '{name}': the <extension>ed base type is a complex type with no simple content type").as_str(),
Some(&name)
);
break 'exit_failure;
}
(*typ).content_type_def = (*base_type).content_type_def;
} else if wxs_is_simple(base_type) && (*typ).wxs_is_extension() {
(*typ).content_type_def = base_type;
} else {
let name = CStr::from_ptr((*typ).name as *const i8).to_string_lossy();
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapInternal,
typ as XmlSchemaBasicItemPtr,
None,
format!("Internal error: xmlSchemaTypeFixup, complex type '{name}' with <simpleContent>: unhandled derivation case").as_str(),
Some(&name)
);
break 'exit_failure;
}
} else {
let mut dummy_sequence: i32 = 0;
let mut particle: XmlSchemaParticlePtr =
(*typ).subtypes as XmlSchemaParticlePtr;
if particle.is_null()
|| ((*particle).typ == XmlSchemaTypeType::XmlSchemaTypeParticle
&& (matches!(
(*(*particle).children).typ,
XmlSchemaTypeType::XmlSchemaTypeAll
| XmlSchemaTypeType::XmlSchemaTypeSequence
) || ((*(*particle).children).typ
== XmlSchemaTypeType::XmlSchemaTypeChoice
&& (*particle).min_occurs == 0))
&& (*((*particle).children as XmlSchemaTreeItemPtr))
.children
.is_null())
{
if (*typ).flags & XML_SCHEMAS_TYPE_MIXED != 0 {
if particle.is_null()
|| (*(*particle).children).typ
!= XmlSchemaTypeType::XmlSchemaTypeSequence
{
particle = xml_schema_add_particle(pctxt, (*typ).node, 1, 1);
if particle.is_null() {
break 'exit_error;
}
(*particle).children = xml_schema_add_model_group(
pctxt,
(*pctxt).schema,
XmlSchemaTypeType::XmlSchemaTypeSequence,
(*typ).node.unwrap(),
)
as XmlSchemaTreeItemPtr;
if (*particle).children.is_null() {
break 'exit_failure;
}
(*typ).subtypes = particle as XmlSchemaTypePtr;
}
dummy_sequence = 1;
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentElements;
} else {
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentEmpty;
}
} else {
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentElements;
}
if (*typ).wxs_is_restriction() {
if (*typ).content_type != XmlSchemaContentType::XmlSchemaContentEmpty
&& (*typ).flags & XML_SCHEMAS_TYPE_MIXED != 0
{
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentMixed;
}
} else {
if (*typ).content_type == XmlSchemaContentType::XmlSchemaContentEmpty {
(*typ).content_type = (*base_type).content_type;
(*typ).subtypes = (*base_type).subtypes;
(*typ).content_type_def = (*base_type).content_type_def;
} else if (*base_type).content_type
== XmlSchemaContentType::XmlSchemaContentEmpty
{
if (*typ).flags & XML_SCHEMAS_TYPE_MIXED != 0 {
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentMixed;
}
} else {
if (*typ).flags & XML_SCHEMAS_TYPE_MIXED != 0 {
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentMixed;
}
if !WXS_TYPE_PARTICLE!(typ).is_null()
&& !WXS_TYPE_PARTICLE_TERM!(typ).is_null()
&& (*WXS_TYPE_PARTICLE_TERM!(typ)).typ
== XmlSchemaTypeType::XmlSchemaTypeAll
{
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCosAllLimited,
xml_schema_get_component_node(typ as _).map(|node| node.into()),
null_mut(),
"The type has an 'all' model group in its {content type} and thus cannot be derived from a non-empty type, since this would produce a 'sequence' model group containing the 'all' model group; 'all' model groups are not allowed to appear inside other model groups",
None,
None,
);
} else if !WXS_TYPE_PARTICLE!(base_type).is_null()
&& !WXS_TYPE_PARTICLE_TERM!(base_type).is_null()
&& (*WXS_TYPE_PARTICLE_TERM!(base_type)).typ
== XmlSchemaTypeType::XmlSchemaTypeAll
{
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapCosAllLimited,
xml_schema_get_component_node(typ as _).map(|node| node.into()),
null_mut(),
"A type cannot be derived by extension from a type which has an 'all' model group in its {content type}, since this would produce a 'sequence' model group containing the 'all' model group; 'all' model groups are not allowed to appear inside other model groups",
None,
None,
);
} else if dummy_sequence == 0 && !(*base_type).subtypes.is_null() {
let effective_content: XmlSchemaTreeItemPtr =
(*typ).subtypes as XmlSchemaTreeItemPtr;
particle = xml_schema_add_particle(pctxt, (*typ).node, 1, 1);
if particle.is_null() {
break 'exit_failure;
}
(*particle).children = xml_schema_add_model_group(
pctxt,
(*pctxt).schema,
XmlSchemaTypeType::XmlSchemaTypeSequence,
(*typ).node.unwrap(),
)
as XmlSchemaTreeItemPtr;
if (*particle).children.is_null() {
break 'exit_failure;
}
(*typ).subtypes = particle as XmlSchemaTypePtr;
(*(*particle).children).children = xml_schema_add_particle(
pctxt,
(*typ).node,
(*((*base_type).subtypes as XmlSchemaParticlePtr)).min_occurs,
(*((*base_type).subtypes as XmlSchemaParticlePtr)).max_occurs,
)
as XmlSchemaTreeItemPtr;
if (*(*particle).children).children.is_null() {
break 'exit_failure;
}
particle = (*(*particle).children).children as XmlSchemaParticlePtr;
(*particle).children =
(*((*base_type).subtypes as XmlSchemaParticlePtr)).children;
(*particle).next = effective_content;
} else {
(*(*particle).children).children =
(*base_type).subtypes as XmlSchemaTreeItemPtr;
}
}
}
}
res = xml_schema_fixup_type_attribute_uses(pctxt, typ);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
res = xml_schema_check_ctcomponent(pctxt, typ);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
if olderrs != (*pctxt).nberrors {
return (*pctxt).err;
} else {
return 0;
}
}
(*typ).flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
return (*pctxt).err;
}
(*typ).flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
-1
}
}
#[doc(alias = "xmlSchemaTypeFixup")]
unsafe fn xml_schema_type_fixup(typ: XmlSchemaTypePtr, actxt: XmlSchemaAbstractCtxtPtr) -> i32 {
unsafe {
if typ.is_null() {
return 0;
}
if (*actxt).typ != XML_SCHEMA_CTXT_PARSER {
AERROR_INT!(
actxt,
"xmlSchemaTypeFixup",
"this function needs a parser context"
);
return -1;
}
if !WXS_IS_TYPE_NOT_FIXED!(typ) {
return 0;
}
if (*typ).typ == XmlSchemaTypeType::XmlSchemaTypeComplex {
return xml_schema_fixup_complex_type(actxt as XmlSchemaParserCtxtPtr, typ);
} else if (*typ).typ == XmlSchemaTypeType::XmlSchemaTypeSimple {
return xml_schema_fixup_simple_type_stage_two(actxt as XmlSchemaParserCtxtPtr, typ);
}
0
}
}
unsafe fn xml_schema_finish_member_type_definitions_property(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let mut link: XmlSchemaTypeLinkPtr;
let mut last_link: XmlSchemaTypeLinkPtr;
let mut prev_link: XmlSchemaTypeLinkPtr;
let mut sub_link: XmlSchemaTypeLinkPtr;
let mut new_link: XmlSchemaTypeLinkPtr;
link = (*typ).member_types;
while !link.is_null() {
if WXS_IS_TYPE_NOT_FIXED!((*link).typ) {
xml_schema_type_fixup((*link).typ, pctxt as XmlSchemaAbstractCtxtPtr);
}
if (*(*link).typ).wxs_is_union() {
sub_link = xml_schema_get_union_simple_type_member_types((*link).typ);
if !sub_link.is_null() {
(*link).typ = (*sub_link).typ;
if !(*sub_link).next.is_null() {
last_link = (*link).next;
sub_link = (*sub_link).next;
prev_link = link;
while !sub_link.is_null() {
new_link =
xml_malloc(size_of::<XmlSchemaTypeLink>()) as XmlSchemaTypeLinkPtr;
if new_link.is_null() {
xml_schema_perr_memory(pctxt, "allocating a type link", None);
return -1;
}
(*new_link).typ = (*sub_link).typ;
(*prev_link).next = new_link;
prev_link = new_link;
(*new_link).next = last_link;
sub_link = (*sub_link).next;
}
}
}
}
link = (*link).next;
}
0
}
}
#[doc(alias = "xmlSchemaCheckSTPropsCorrect")]
unsafe fn xml_schema_check_st_props_correct(
ctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let base_type: XmlSchemaTypePtr = (*typ).base_type;
if base_type.is_null() {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapStPropsCorrect1,
typ as XmlSchemaBasicItemPtr,
None,
"No base type existent",
None,
);
return XmlParserErrors::XmlSchemapStPropsCorrect1 as i32;
}
if !wxs_is_simple(base_type) {
let qname = xml_schema_get_component_qname(base_type as _);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapStPropsCorrect1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The base type '{qname}' is not a simple type").as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapStPropsCorrect1 as i32;
}
if ((*typ).wxs_is_list() || (*typ).wxs_is_union())
&& !(*typ).wxs_is_restriction()
&& (!wxs_is_any_simple_type(base_type)
&& (*base_type).typ != XmlSchemaTypeType::XmlSchemaTypeSimple)
{
let qname = xml_schema_get_component_qname(base_type as _);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapStPropsCorrect1,
typ as XmlSchemaBasicItemPtr,
None,
format!("A type, derived by list or union, must have the simple ur-type definition as base type, not '{qname}'").as_str(),
Some(&qname)
);
return XmlParserErrors::XmlSchemapStPropsCorrect1 as i32;
}
if !(*typ).wxs_is_atomic() && !(*typ).wxs_is_union() && !(*typ).wxs_is_list() {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapStPropsCorrect1,
typ as XmlSchemaBasicItemPtr,
None,
"The variety is absent",
None,
);
return XmlParserErrors::XmlSchemapStPropsCorrect1 as i32;
}
if xml_schema_type_final_contains(base_type, XML_SCHEMAS_TYPE_FINAL_RESTRICTION) != 0 {
let qname = xml_schema_get_component_qname(base_type as _);
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapStPropsCorrect3,
typ as XmlSchemaBasicItemPtr,
None,
format!("The 'final' of its base type '{qname}' must not contain 'restriction'")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapStPropsCorrect3 as i32;
}
0
}
}
#[doc(alias = "xmlSchemaCheckCOSSTRestricts")]
unsafe fn xml_schema_check_cosstrestricts(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
if (*typ).typ != XmlSchemaTypeType::XmlSchemaTypeSimple {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"given type is not a user-derived simpleType"
);
return -1;
}
if (*typ).wxs_is_atomic() {
let primitive: XmlSchemaTypePtr;
if !(*(*typ).base_type).wxs_is_atomic() {
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts1_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The base type '{qname}' is not an atomic simple type").as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts1_1 as i32;
}
if xml_schema_type_final_contains((*typ).base_type, XML_SCHEMAS_TYPE_FINAL_RESTRICTION)
!= 0
{
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts1_2,
typ as XmlSchemaBasicItemPtr,
None,
format!("The final of its base type '{qname}' must not contain 'restriction'")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts1_2 as i32;
}
if !(*typ).facets.is_null() {
let mut facet: XmlSchemaFacetPtr;
let mut ok: i32 = 1;
primitive = xml_schema_get_primitive_type(typ);
if primitive.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"failed to get primitive type"
);
return -1;
}
facet = (*typ).facets;
while {
if xml_schema_is_built_in_type_facet(primitive, (*facet).typ as _) == 0 {
ok = 0;
xml_schema_pillegal_facet_atomic_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts1_3_1,
typ,
primitive,
facet,
);
}
facet = (*facet).next;
!facet.is_null()
} {}
if ok == 0 {
return XmlParserErrors::XmlSchemapCosStRestricts1_3_1 as i32;
}
}
} else if (*typ).wxs_is_list() {
let item_type: XmlSchemaTypePtr = (*typ).subtypes;
if item_type.is_null() || !wxs_is_simple(item_type) {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"failed to evaluate the item type"
);
return -1;
}
if WXS_IS_TYPE_NOT_FIXED!(item_type) {
xml_schema_type_fixup(item_type, pctxt as XmlSchemaAbstractCtxtPtr);
}
if !(*item_type).wxs_is_atomic() && !(*item_type).wxs_is_union() {
let qname = xml_schema_get_component_qname(item_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The item type '{qname}' does not have a variety of atomic or union")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts2_1 as i32;
} else if (*item_type).wxs_is_union() {
let mut member: XmlSchemaTypeLinkPtr;
member = (*item_type).member_types;
while !member.is_null() {
if !(*(*member).typ).wxs_is_atomic() {
let qname = xml_schema_get_component_qname((*member).typ as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The item type is a union type, but the member type '{qname}' of this item type is not atomic").as_str(),
Some(&qname)
);
return XmlParserErrors::XmlSchemapCosStRestricts2_1 as i32;
}
member = (*member).next;
}
}
if wxs_is_any_simple_type((*typ).base_type) {
let mut facet: XmlSchemaFacetPtr;
if xml_schema_type_final_contains(item_type, XML_SCHEMAS_TYPE_FINAL_LIST) != 0 {
let qname = xml_schema_get_component_qname(item_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_1_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The final of its item type '{qname}' must not contain 'list'")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts2_3_1_1 as i32;
}
if !(*typ).facets.is_null() {
facet = (*typ).facets;
while {
if (*facet).typ != XmlSchemaTypeType::XmlSchemaFacetWhitespace {
xml_schema_pillegal_facet_list_union_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_1_2,
typ,
facet,
);
return XmlParserErrors::XmlSchemapCosStRestricts2_3_1_2 as i32;
}
facet = (*facet).next;
!facet.is_null()
} {}
}
} else {
if !(*(*typ).base_type).wxs_is_list() {
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_2_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The base type '{qname}' must be a list type").as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts2_3_2_1 as i32;
}
if xml_schema_type_final_contains(
(*typ).base_type,
XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
) != 0
{
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_2_2,
typ as XmlSchemaBasicItemPtr,
None,
format!(
"The 'final' of the base type '{qname}' must not contain 'restriction'"
)
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts2_3_2_2 as i32;
}
{
let base_item_type = (*(*typ).base_type).subtypes;
if base_item_type.is_null() || !wxs_is_simple(base_item_type) {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"failed to eval the item type of a base type"
);
return -1;
}
if item_type != base_item_type
&& xml_schema_check_cosstderived_ok(
pctxt as XmlSchemaAbstractCtxtPtr,
item_type,
base_item_type,
0,
) != 0
{
let q1 = xml_schema_get_component_qname(item_type as _);
let q2 = xml_schema_get_component_qname(base_item_type as _);
let q3 = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err_ext(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_2_3,
typ as XmlSchemaBasicItemPtr,
None,
format!("The item type '{q1}' is not validly derived from the item type '{q2}' of the base type '{q3}'").as_str(),
Some(&q1),
Some(&q2),
Some(&q3)
);
return XmlParserErrors::XmlSchemapCosStRestricts2_3_2_3 as i32;
}
}
if !(*typ).facets.is_null() {
let mut facet: XmlSchemaFacetPtr;
let mut ok: i32 = 1;
facet = (*typ).facets;
while {
match (*facet).typ {
XmlSchemaTypeType::XmlSchemaFacetLength
| XmlSchemaTypeType::XmlSchemaFacetMinLength
| XmlSchemaTypeType::XmlSchemaFacetMaxLength
| XmlSchemaTypeType::XmlSchemaFacetWhitespace
| XmlSchemaTypeType::XmlSchemaFacetPattern
| XmlSchemaTypeType::XmlSchemaFacetEnumeration => {}
_ => {
xml_schema_pillegal_facet_list_union_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts2_3_2_4,
typ,
facet,
);
ok = 0;
}
}
facet = (*facet).next;
!facet.is_null()
} {}
if ok == 0 {
return XmlParserErrors::XmlSchemapCosStRestricts2_3_2_4 as i32;
}
}
}
} else if (*typ).wxs_is_union() {
let mut member: XmlSchemaTypeLinkPtr;
member = (*typ).member_types;
while !member.is_null() {
if WXS_IS_TYPE_NOT_FIXED!((*member).typ) {
xml_schema_type_fixup((*member).typ, pctxt as XmlSchemaAbstractCtxtPtr);
}
if !(*(*member).typ).wxs_is_atomic() && !(*(*member).typ).wxs_is_list() {
let qname = xml_schema_get_component_qname((*member).typ as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The member type '{qname}' is neither an atomic, nor a list type")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts3_1 as i32;
}
member = (*member).next;
}
if (*(*typ).base_type).built_in_type == XmlSchemaValType::XmlSchemasAnySimpletype {
member = (*typ).member_types;
while !member.is_null() {
if xml_schema_type_final_contains((*member).typ, XML_SCHEMAS_TYPE_FINAL_UNION)
!= 0
{
let qname = xml_schema_get_component_qname((*member).typ as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The 'final' of member type '{qname}' contains 'union'")
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts3_3_1 as i32;
}
member = (*member).next;
}
if !(*typ).facet_set.is_null() {
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_1_2,
typ as XmlSchemaBasicItemPtr,
None,
"No facets allowed",
None,
);
return XmlParserErrors::XmlSchemapCosStRestricts3_3_1_2 as i32;
}
} else {
if !(*(*typ).base_type).wxs_is_union() {
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_2_1,
typ as XmlSchemaBasicItemPtr,
None,
format!("The base type '{qname}' is not a union type").as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts3_3_2_1 as i32;
}
if xml_schema_type_final_contains(
(*typ).base_type,
XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
) != 0
{
let qname = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_2_2,
typ as XmlSchemaBasicItemPtr,
None,
format!(
"The 'final' of its base type '{qname}' must not contain 'restriction'"
)
.as_str(),
Some(&qname),
);
return XmlParserErrors::XmlSchemapCosStRestricts3_3_2_2 as i32;
}
{
let mut base_member: XmlSchemaTypeLinkPtr;
if !(*typ).member_types.is_null() {
member = (*typ).member_types;
base_member =
xml_schema_get_union_simple_type_member_types((*typ).base_type);
if member.is_null() && !base_member.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"different number of member types in base"
);
}
while !member.is_null() {
if base_member.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaCheckCOSSTRestricts",
"different number of member types in base"
);
} else if (*member).typ != (*base_member).typ
&& xml_schema_check_cosstderived_ok(
pctxt as XmlSchemaAbstractCtxtPtr,
(*member).typ,
(*base_member).typ,
0,
) != 0
{
let q1 = xml_schema_get_component_qname((*member).typ as _);
let q2 = xml_schema_get_component_qname((*base_member).typ as _);
let q3 = xml_schema_get_component_qname((*typ).base_type as _);
xml_schema_pcustom_err_ext(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_2_3,
typ as XmlSchemaBasicItemPtr,
None,
format!("The member type {q1} is not validly derived from its corresponding member type {q2} of the base type {q3}").as_str(),
Some(&q1),
Some(&q2),
Some(&q3)
);
return XmlParserErrors::XmlSchemapCosStRestricts3_3_2_3 as i32;
}
member = (*member).next;
if !base_member.is_null() {
base_member = (*base_member).next;
}
}
}
}
if !(*typ).facets.is_null() {
let mut facet: XmlSchemaFacetPtr;
let mut ok: i32 = 1;
facet = (*typ).facets;
while {
if !matches!(
(*facet).typ,
XmlSchemaTypeType::XmlSchemaFacetPattern
| XmlSchemaTypeType::XmlSchemaFacetEnumeration
) {
xml_schema_pillegal_facet_list_union_err(
pctxt,
XmlParserErrors::XmlSchemapCosStRestricts3_3_2_4,
typ,
facet,
);
ok = 0;
}
facet = (*facet).next;
!facet.is_null()
} {}
if ok == 0 {
return XmlParserErrors::XmlSchemapCosStRestricts3_3_2_4 as i32;
}
}
}
}
0
}
}
unsafe fn xml_schema_create_vctxt_on_pctxt(ctxt: XmlSchemaParserCtxtPtr) -> i32 {
unsafe {
if (*ctxt).vctxt.is_null() {
(*ctxt).vctxt = xml_schema_new_valid_ctxt(null_mut());
if (*ctxt).vctxt.is_null() {
xml_schema_perr(
ctxt,
None,
XmlParserErrors::XmlSchemapInternal,
"Internal error: xmlSchemaCreateVCtxtOnPCtxt, failed to create a temp. validation context.\n",
None,
None,
);
return -1;
}
(*(*ctxt).vctxt).set_errors((*ctxt).error, (*ctxt).warning, (*ctxt).err_ctxt.clone());
(*(*ctxt).vctxt).set_structured_errors((*ctxt).serror, (*ctxt).err_ctxt.clone());
}
0
}
}
#[doc(alias = "xmlSchemaCheckFacetValues")]
unsafe fn xml_schema_check_facet_values(
type_decl: XmlSchemaTypePtr,
pctxt: XmlSchemaParserCtxtPtr,
) -> i32 {
unsafe {
let mut res: i32;
let olderrs: i32 = (*pctxt).nberrors;
let name: *const XmlChar = (*type_decl).name;
'exit_failure: {
if !(*type_decl).facets.is_null() {
let mut facet: XmlSchemaFacetPtr = (*type_decl).facets;
if (*pctxt).vctxt.is_null() && xml_schema_create_vctxt_on_pctxt(pctxt) == -1 {
return -1;
}
(*(*pctxt).vctxt).schema = (*pctxt).schema;
while !facet.is_null() {
res = xml_schema_check_facet(facet, type_decl, pctxt, name);
HFAILURE!(res, 'exit_failure);
facet = (*facet).next;
}
(*(*pctxt).vctxt).schema = null_mut();
}
if olderrs != (*pctxt).nberrors {
return (*pctxt).err;
}
return 0;
}
-1
}
}
unsafe fn xml_schema_type_fixup_whitespace(typ: XmlSchemaTypePtr) -> i32 {
unsafe {
if (*typ).wxs_is_list() {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
return 0;
} else if (*typ).wxs_is_union() {
return 0;
}
if !(*typ).facet_set.is_null() {
let mut lin: XmlSchemaFacetLinkPtr;
lin = (*typ).facet_set;
while !lin.is_null() {
if (*(*lin).facet).typ == XmlSchemaTypeType::XmlSchemaFacetWhitespace {
match (*(*lin).facet).whitespace {
w if XML_SCHEMAS_FACET_PRESERVE == w => {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
}
w if XML_SCHEMAS_FACET_REPLACE == w => {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
}
w if XML_SCHEMAS_FACET_COLLAPSE == w => {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
}
_ => {
return -1;
}
}
return 0;
}
lin = (*lin).next;
}
}
{
let mut anc: XmlSchemaTypePtr;
anc = (*typ).base_type;
while !anc.is_null() && (*anc).built_in_type != XmlSchemaValType::XmlSchemasAnytype {
if (*anc).typ == XmlSchemaTypeType::XmlSchemaTypeBasic {
if (*anc).built_in_type == XmlSchemaValType::XmlSchemasNormString {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
} else if (*anc).built_in_type == XmlSchemaValType::XmlSchemasString
|| (*anc).built_in_type == XmlSchemaValType::XmlSchemasAnySimpletype
{
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
} else {
(*typ).flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
}
break;
}
anc = (*anc).base_type;
}
}
0
}
}
macro_rules! FACET_RESTR_MUTUAL_ERR {
($pctxt:expr, $fac1:expr, $fac2:expr) => {{
let ft1 = xml_schema_facet_type_to_string((*$fac1).typ);
let ft2 = xml_schema_facet_type_to_string((*$fac2).typ);
xml_schema_pcustom_err_ext(
$pctxt,
XmlParserErrors::XmlSchemapInvalidFacetValue,
$fac1 as XmlSchemaBasicItemPtr,
(*$fac1).node.map(|node| node.into()),
format!("It is an error for both '{ft1}' and '{ft2}' to be specified on the same type definition").as_str(),
Some(ft1),
Some(ft2),
None,
)
}};
}
macro_rules! FACET_RESTR_ERR {
($pctxt:expr, $fac1:expr, $msg:expr) => {
xml_schema_pcustom_err(
$pctxt,
XmlParserErrors::XmlSchemapInvalidFacetValue,
$fac1 as XmlSchemaBasicItemPtr,
(*$fac1).node.map(|node| node.into()),
$msg,
None,
);
};
}
macro_rules! FACET_RESTR_FIXED_ERR {
($pctxt:expr, $fac:expr) => {
xml_schema_pcustom_err(
$pctxt,
XmlParserErrors::XmlSchemapInvalidFacetValue,
$fac as XmlSchemaBasicItemPtr,
(*$fac).node.map(|node| node.into()),
"The base type's facet is 'fixed', thus the value must not differ",
None,
)
};
}
#[doc(alias = "xmlSchemaDeriveAndValidateFacets")]
unsafe fn xml_schema_derive_and_validate_facets(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let base: XmlSchemaTypePtr = (*typ).base_type;
let mut link: XmlSchemaFacetLinkPtr;
let mut cur: XmlSchemaFacetLinkPtr;
let mut last: XmlSchemaFacetLinkPtr;
let mut facet: XmlSchemaFacetPtr;
let mut bfacet: XmlSchemaFacetPtr;
let mut flength: XmlSchemaFacetPtr = null_mut();
let mut ftotdig: XmlSchemaFacetPtr = null_mut();
let mut ffracdig: XmlSchemaFacetPtr = null_mut();
let mut fmaxlen: XmlSchemaFacetPtr = null_mut();
let mut fminlen: XmlSchemaFacetPtr = null_mut();
let mut fmininc: XmlSchemaFacetPtr = null_mut();
let mut fmaxinc: XmlSchemaFacetPtr = null_mut();
let mut fminexc: XmlSchemaFacetPtr = null_mut();
let mut fmaxexc: XmlSchemaFacetPtr = null_mut();
let mut bflength: XmlSchemaFacetPtr = null_mut();
let mut bftotdig: XmlSchemaFacetPtr = null_mut();
let mut bffracdig: XmlSchemaFacetPtr = null_mut();
let mut bfmaxlen: XmlSchemaFacetPtr = null_mut();
let mut bfminlen: XmlSchemaFacetPtr = null_mut();
let mut bfmininc: XmlSchemaFacetPtr = null_mut();
let mut bfmaxinc: XmlSchemaFacetPtr = null_mut();
let mut bfminexc: XmlSchemaFacetPtr = null_mut();
let mut bfmaxexc: XmlSchemaFacetPtr = null_mut();
let mut res: i32;
if (*typ).facet_set.is_null() && (*base).facet_set.is_null() {
return 0;
}
last = (*typ).facet_set;
if !last.is_null() {
while !(*last).next.is_null() {
last = (*last).next;
}
}
cur = (*typ).facet_set;
while !cur.is_null() {
facet = (*cur).facet;
match (*facet).typ {
XmlSchemaTypeType::XmlSchemaFacetLength => {
flength = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinLength => {
fminlen = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinInclusive => {
fmininc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinExclusive => {
fminexc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxLength => {
fmaxlen = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxInclusive => {
fmaxinc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxExclusive => {
fmaxexc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetTotalDigits => {
ftotdig = facet;
}
XmlSchemaTypeType::XmlSchemaFacetFractionDigits => {
ffracdig = facet;
}
_ => {}
}
cur = (*cur).next;
}
cur = (*base).facet_set;
while !cur.is_null() {
facet = (*cur).facet;
match (*facet).typ {
XmlSchemaTypeType::XmlSchemaFacetLength => {
bflength = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinLength => {
bfminlen = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinInclusive => {
bfmininc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMinExclusive => {
bfminexc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxLength => {
bfmaxlen = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxInclusive => {
bfmaxinc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetMaxExclusive => {
bfmaxexc = facet;
}
XmlSchemaTypeType::XmlSchemaFacetTotalDigits => {
bftotdig = facet;
}
XmlSchemaTypeType::XmlSchemaFacetFractionDigits => {
bffracdig = facet;
}
_ => {}
}
cur = (*cur).next;
}
if !flength.is_null() && (!fminlen.is_null() || !fmaxlen.is_null()) {
FACET_RESTR_ERR!(
pctxt,
flength,
"It is an error for both 'length' and either of 'minLength' or 'maxLength' to be specified on the same type definition"
);
}
if !fmaxinc.is_null() && !fmaxexc.is_null() {
FACET_RESTR_MUTUAL_ERR!(pctxt, fmaxinc, fmaxexc);
}
if !fmininc.is_null() && !fminexc.is_null() {
FACET_RESTR_MUTUAL_ERR!(pctxt, fmininc, fminexc)
}
'internal_error: {
if !flength.is_null() && !bflength.is_null() {
res = xml_schema_compare_values((*flength).val, (*bflength).val);
if res == -2 {
break 'internal_error;
}
if res != 0 {
xml_schema_derive_facet_err(pctxt, flength, bflength, 0, 0, 1);
}
if res != 0 && (*bflength).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, flength)
}
}
if !fminlen.is_null() && !bfminlen.is_null() {
res = xml_schema_compare_values((*fminlen).val, (*bfminlen).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fminlen, bfminlen, 1, 1, 1);
}
if res != 0 && (*bfminlen).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fminlen)
}
}
if !fmaxlen.is_null() && !bfmaxlen.is_null() {
res = xml_schema_compare_values((*fmaxlen).val, (*bfmaxlen).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
}
if res != 0 && (*bfmaxlen).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fmaxlen)
}
}
if flength.is_null() {
flength = bflength;
}
if !flength.is_null() {
if fminlen.is_null() {
fminlen = bfminlen;
}
if !fminlen.is_null() {
res = xml_schema_compare_values((*flength).val, (*fminlen).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, flength, fminlen, 1, 1, 0);
}
}
if fmaxlen.is_null() {
fmaxlen = bfmaxlen;
}
if !fmaxlen.is_null() {
res = xml_schema_compare_values((*flength).val, (*fmaxlen).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, flength, fmaxlen, -1, 1, 0);
}
}
}
if !fmaxinc.is_null() {
if !fmininc.is_null() {
res = xml_schema_compare_values((*fmaxinc).val, (*fmininc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fmaxinc, fmininc, 1, 1, 0);
}
}
if !bfmaxinc.is_null() {
res = xml_schema_compare_values((*fmaxinc).val, (*bfmaxinc).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
}
if res != 0 && (*bfmaxinc).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fmaxinc);
}
}
if !bfmaxexc.is_null() {
res = xml_schema_compare_values((*fmaxinc).val, (*bfmaxexc).val);
if res == -2 {
break 'internal_error;
}
if res != -1 {
xml_schema_derive_facet_err(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
}
}
if !bfmininc.is_null() {
res = xml_schema_compare_values((*fmaxinc).val, (*bfmininc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fmaxinc, bfmininc, 1, 1, 1);
}
}
if !bfminexc.is_null() {
res = xml_schema_compare_values((*fmaxinc).val, (*bfminexc).val);
if res == -2 {
break 'internal_error;
}
if res != 1 {
xml_schema_derive_facet_err(pctxt, fmaxinc, bfminexc, 1, 0, 1);
}
}
}
if !fmaxexc.is_null() {
if !fminexc.is_null() {
res = xml_schema_compare_values((*fmaxexc).val, (*fminexc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fmaxexc, fminexc, 1, 1, 0);
}
}
if !bfmaxexc.is_null() {
res = xml_schema_compare_values((*fmaxexc).val, (*bfmaxexc).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
}
if res != 0 && (*bfmaxexc).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fmaxexc);
}
}
if !bfmaxinc.is_null() {
res = xml_schema_compare_values((*fmaxexc).val, (*bfmaxinc).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
}
}
if !bfmininc.is_null() {
res = xml_schema_compare_values((*fmaxexc).val, (*bfmininc).val);
if res == -2 {
break 'internal_error;
}
if res != 1 {
xml_schema_derive_facet_err(pctxt, fmaxexc, bfmininc, 1, 0, 1);
}
}
if !bfminexc.is_null() {
res = xml_schema_compare_values((*fmaxexc).val, (*bfminexc).val);
if res == -2 {
break 'internal_error;
}
if res != 1 {
xml_schema_derive_facet_err(pctxt, fmaxexc, bfminexc, 1, 0, 1);
}
}
}
if !fminexc.is_null() {
if !fmaxinc.is_null() {
res = xml_schema_compare_values((*fminexc).val, (*fmaxinc).val);
if res == -2 {
break 'internal_error;
}
if res != -1 {
xml_schema_derive_facet_err(pctxt, fminexc, fmaxinc, -1, 0, 0);
}
}
if !bfminexc.is_null() {
res = xml_schema_compare_values((*fminexc).val, (*bfminexc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fminexc, bfminexc, 1, 1, 1);
}
if res != 0 && (*bfminexc).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fminexc)
}
}
if !bfmaxinc.is_null() {
res = xml_schema_compare_values((*fminexc).val, (*bfmaxinc).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fminexc, bfmaxinc, -1, 1, 1);
}
}
if !bfmininc.is_null() {
res = xml_schema_compare_values((*fminexc).val, (*bfmininc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fminexc, bfmininc, 1, 1, 1);
}
}
if !bfmaxexc.is_null() {
res = xml_schema_compare_values((*fminexc).val, (*bfmaxexc).val);
if res == -2 {
break 'internal_error;
}
if res != -1 {
xml_schema_derive_facet_err(pctxt, fminexc, bfmaxexc, -1, 0, 1);
}
}
}
if !fmininc.is_null() {
if !fmaxexc.is_null() {
res = xml_schema_compare_values((*fmininc).val, (*fmaxexc).val);
if res == -2 {
break 'internal_error;
}
if res != -1 {
xml_schema_derive_facet_err(pctxt, fmininc, fmaxexc, -1, 0, 0);
}
}
if !bfmininc.is_null() {
res = xml_schema_compare_values((*fmininc).val, (*bfmininc).val);
if res == -2 {
break 'internal_error;
}
if res == -1 {
xml_schema_derive_facet_err(pctxt, fmininc, bfmininc, 1, 1, 1);
}
if res != 0 && (*bfmininc).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, fmininc)
}
}
if !bfmaxinc.is_null() {
res = xml_schema_compare_values((*fmininc).val, (*bfmaxinc).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, fmininc, bfmaxinc, -1, 1, 1);
}
}
if !bfminexc.is_null() {
res = xml_schema_compare_values((*fmininc).val, (*bfminexc).val);
if res == -2 {
break 'internal_error;
}
if res != 1 {
xml_schema_derive_facet_err(pctxt, fmininc, bfminexc, 1, 0, 1);
}
}
if !bfmaxexc.is_null() {
res = xml_schema_compare_values((*fmininc).val, (*bfmaxexc).val);
if res == -2 {
break 'internal_error;
}
if res != -1 {
xml_schema_derive_facet_err(pctxt, fmininc, bfmaxexc, -1, 0, 1);
}
}
}
if !ftotdig.is_null() && !bftotdig.is_null() {
res = xml_schema_compare_values((*ftotdig).val, (*bftotdig).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, ftotdig, bftotdig, -1, 1, 1);
}
if res != 0 && (*bftotdig).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, ftotdig)
}
}
if !ffracdig.is_null() && !bffracdig.is_null() {
res = xml_schema_compare_values((*ffracdig).val, (*bffracdig).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, ffracdig, bffracdig, -1, 1, 1);
}
if res != 0 && (*bffracdig).fixed != 0 {
FACET_RESTR_FIXED_ERR!(pctxt, ffracdig);
}
}
if ftotdig.is_null() {
ftotdig = bftotdig;
}
if ffracdig.is_null() {
ffracdig = bffracdig;
}
if !ftotdig.is_null() && !ffracdig.is_null() {
res = xml_schema_compare_values((*ffracdig).val, (*ftotdig).val);
if res == -2 {
break 'internal_error;
}
if res == 1 {
xml_schema_derive_facet_err(pctxt, ffracdig, ftotdig, -1, 1, 0);
}
}
cur = (*base).facet_set;
while !cur.is_null() {
'to_continue: {
bfacet = (*cur).facet;
if matches!(
(*bfacet).typ,
XmlSchemaTypeType::XmlSchemaFacetPattern
| XmlSchemaTypeType::XmlSchemaFacetEnumeration
) {
break 'to_continue;
}
link = (*typ).facet_set;
while !link.is_null() {
facet = (*link).facet;
if (*facet).typ == (*bfacet).typ {
if (*facet).typ == XmlSchemaTypeType::XmlSchemaFacetWhitespace {
if (*facet).whitespace < (*bfacet).whitespace {
FACET_RESTR_ERR!(
pctxt,
facet,
"The 'whitespace' value has to be equal to or stronger than the 'whitespace' value of the base type"
);
}
if (*bfacet).fixed != 0
&& (*facet).whitespace != (*bfacet).whitespace
{
FACET_RESTR_FIXED_ERR!(pctxt, facet);
}
}
break;
}
link = (*link).next;
}
if link.is_null() {
link = xml_malloc(size_of::<XmlSchemaFacetLink>()) as XmlSchemaFacetLinkPtr;
if link.is_null() {
xml_schema_perr_memory(
pctxt,
"deriving facets, creating a facet link",
None,
);
return -1;
}
(*link).facet = (*cur).facet;
(*link).next = null_mut();
if last.is_null() {
(*typ).facet_set = link;
} else {
(*last).next = link;
}
last = link;
}
}
cur = (*cur).next;
}
return 0;
}
PERROR_INT!(
pctxt,
"xmlSchemaDeriveAndValidateFacets",
"an error occurred"
);
-1
}
}
unsafe fn xml_schema_type_fixup_optim_facets(typ: XmlSchemaTypePtr) {
unsafe {
let mut has: i32;
let mut need_val: i32 = 0;
let mut norm_val: i32 = 0;
has = ((*(*typ).base_type).flags & XML_SCHEMAS_TYPE_HAS_FACETS != 0) as i32;
if has != 0 {
need_val = ((*(*typ).base_type).flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE != 0) as i32;
norm_val = ((*(*typ).base_type).flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED != 0) as i32;
}
if !(*typ).facets.is_null() {
let mut fac: XmlSchemaFacetPtr;
fac = (*typ).facets;
while !fac.is_null() {
match (*fac).typ {
XmlSchemaTypeType::XmlSchemaFacetWhitespace => {}
XmlSchemaTypeType::XmlSchemaFacetPattern => {
norm_val = 1;
has = 1;
}
XmlSchemaTypeType::XmlSchemaFacetEnumeration => {
need_val = 1;
norm_val = 1;
has = 1;
}
_ => {
has = 1;
}
}
fac = (*fac).next;
}
}
if norm_val != 0 {
(*typ).flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
}
if need_val != 0 {
(*typ).flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
}
if has != 0 {
(*typ).flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
}
if has != 0 && need_val == 0 && (*typ).wxs_is_atomic() {
let prim: XmlSchemaTypePtr = xml_schema_get_primitive_type(typ);
if (*prim).built_in_type != XmlSchemaValType::XmlSchemasAnySimpletype
&& (*prim).built_in_type != XmlSchemaValType::XmlSchemasString
{
(*typ).flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
}
}
}
}
unsafe fn xml_schema_fixup_simple_type_stage_two(
pctxt: XmlSchemaParserCtxtPtr,
typ: XmlSchemaTypePtr,
) -> i32 {
unsafe {
let mut res: i32;
let olderrs: i32 = (*pctxt).nberrors;
if (*typ).typ != XmlSchemaTypeType::XmlSchemaTypeSimple {
return -1;
}
if !WXS_IS_TYPE_NOT_FIXED!(typ) {
return 0;
}
(*typ).flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
(*typ).content_type = XmlSchemaContentType::XmlSchemaContentSimple;
'exit_failure: {
if (*typ).base_type.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaFixupSimpleTypeStageTwo",
"missing baseType"
);
break 'exit_failure;
}
if WXS_IS_TYPE_NOT_FIXED!((*typ).base_type) {
xml_schema_type_fixup((*typ).base_type, pctxt as XmlSchemaAbstractCtxtPtr);
}
if !(*typ).member_types.is_null()
&& xml_schema_finish_member_type_definitions_property(pctxt, typ) == -1
{
return -1;
}
res = xml_schema_check_st_props_correct(pctxt, typ);
'exit_error: {
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
res = xml_schema_check_cosstrestricts(pctxt, typ);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
res = xml_schema_check_facet_values(typ, pctxt);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
if !(*typ).facet_set.is_null() || !(*(*typ).base_type).facet_set.is_null() {
res = xml_schema_derive_and_validate_facets(pctxt, typ);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
}
res = xml_schema_type_fixup_whitespace(typ);
HFAILURE!(res, 'exit_failure);
HERROR!(res, 'exit_error);
xml_schema_type_fixup_optim_facets(typ);
}
if olderrs != (*pctxt).nberrors {
return (*pctxt).err;
}
return 0;
}
-1
}
}
#[doc(alias = "xmlSchemaCheckAttrPropsCorrect")]
unsafe fn xml_schema_check_attr_props_correct(
pctxt: XmlSchemaParserCtxtPtr,
attr: XmlSchemaAttributePtr,
) -> i32 {
unsafe {
if (*attr).subtypes.is_null() {
return 0;
}
if !(*attr).def_value.is_null() {
if xml_schema_is_derived_from_built_in_type(
(*attr).subtypes,
XmlSchemaValType::XmlSchemasID,
) != 0
{
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAPropsCorrect3,
None,
attr as XmlSchemaBasicItemPtr,
"Value constraints are not allowed if the type definition is or is derived from xs:ID",
None,
None,
);
return (*pctxt).err;
}
let ret: i32 = xml_schema_vcheck_cvc_simple_type(
pctxt as XmlSchemaAbstractCtxtPtr,
(*attr).node.map(|node| node.into()),
(*attr).subtypes,
(*attr).def_value,
&raw mut (*attr).def_val,
1,
1,
0,
);
if ret != 0 {
if ret < 0 {
PERROR_INT!(
pctxt,
"xmlSchemaCheckAttrPropsCorrect",
"calling xmlSchemaVCheckCVCSimpleType()"
);
return -1;
}
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAPropsCorrect2,
None,
attr as XmlSchemaBasicItemPtr,
"The value of the value constraint is not valid",
None,
None,
);
return (*pctxt).err;
}
}
0
}
}
#[doc(alias = "xmlSchemaCheckAttrUsePropsCorrect")]
unsafe fn xml_schema_check_attr_use_props_correct(
ctxt: XmlSchemaParserCtxtPtr,
using: XmlSchemaAttributeUsePtr,
) -> i32 {
unsafe {
if ctxt.is_null() || using.is_null() {
return -1;
}
if (*using).def_value.is_null()
|| WXS_ATTRUSE_DECL!(using).is_null()
|| (*WXS_ATTRUSE_DECL!(using)).typ != XmlSchemaTypeType::XmlSchemaTypeAttribute
{
return 0;
}
if !(*WXS_ATTRUSE_DECL!(using)).def_value.is_null()
&& (*WXS_ATTRUSE_DECL!(using)).flags & XML_SCHEMAS_ATTR_FIXED != 0
&& (*using).flags & XML_SCHEMA_ATTR_USE_FIXED == 0
{
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapAuPropsCorrect2,
using as XmlSchemaBasicItemPtr,
None,
"The attribute declaration has a 'fixed' value constraint , thus the attribute use must also have a 'fixed' value constraint",
None,
);
return (*ctxt).err;
}
if !(*using).def_val.is_null() && !WXS_ATTRUSE_TYPEDEF!(using).is_null() {
if xml_schema_is_derived_from_built_in_type(
WXS_ATTRUSE_TYPEDEF!(using),
XmlSchemaValType::XmlSchemasID,
) != 0
{
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAuPropsCorrect,
None,
using as XmlSchemaBasicItemPtr,
"Value constraints are not allowed if the type definition is or is derived from xs:ID",
None,
None,
);
return (*ctxt).err;
}
let ret: i32 = xml_schema_vcheck_cvc_simple_type(
ctxt as XmlSchemaAbstractCtxtPtr,
Some(XmlGenericNodePtr::from((*using).node)),
WXS_ATTRUSE_TYPEDEF!(using),
(*using).def_value,
&raw mut (*using).def_val,
1,
1,
0,
);
if ret != 0 {
if ret < 0 {
PERROR_INT2!(
ctxt,
"xmlSchemaCheckAttrUsePropsCorrect",
"calling xmlSchemaVCheckCVCSimpleType()"
);
return -1;
}
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAuPropsCorrect,
None,
using as XmlSchemaBasicItemPtr,
"The value of the value constraint is not valid",
None,
None,
);
return (*ctxt).err;
}
}
if !(*WXS_ATTRUSE_DECL!(using)).def_val.is_null()
&& (*WXS_ATTRUSE_DECL!(using)).flags & XML_SCHEMA_ATTR_USE_FIXED == 0
{
if xml_schema_are_values_equal((*using).def_val, (*WXS_ATTRUSE_DECL!(using)).def_val)
== 0
{
let def_value = CStr::from_ptr((*WXS_ATTRUSE_DECL!(using)).def_value as *const i8)
.to_string_lossy();
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapAuPropsCorrect2,
using as XmlSchemaBasicItemPtr,
None,
format!("The 'fixed' value constraint of the attribute use must match the attribute declaration's value constraint '{def_value}'").as_str(),
Some(&def_value)
);
}
return (*ctxt).err;
}
0
}
}
#[doc(alias = "xmlSchemaAttributeGroupExpandRefs")]
unsafe fn xml_schema_check_agprops_correct(
pctxt: XmlSchemaParserCtxtPtr,
attr_gr: XmlSchemaAttributeGroupPtr,
) -> i32 {
unsafe {
if !(*attr_gr).attr_uses.is_null()
&& (*((*attr_gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>))
.items
.len()
> 1
{
let uses: XmlSchemaItemListPtr<*mut c_void> =
(*attr_gr).attr_uses as XmlSchemaItemListPtr<*mut c_void>;
let mut has_id: i32 = 0;
'next_use: for (i, using) in (*uses)
.items
.iter()
.map(|&using| using as XmlSchemaAttributeUsePtr)
.enumerate()
.rev()
{
if i > 0 {
for tmp in (*uses)
.items
.iter()
.take(i)
.rev()
.map(|&tmp| tmp as XmlSchemaAttributeUsePtr)
{
if WXS_ATTRUSE_DECL_NAME!(using) == WXS_ATTRUSE_DECL_NAME!(tmp)
&& WXS_ATTRUSE_DECL_TNS!(using) == WXS_ATTRUSE_DECL_TNS!(tmp)
{
let str1 = xml_schema_get_component_designation(using as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAgPropsCorrect,
(*attr_gr).node.map(|node| node.into()),
attr_gr as XmlSchemaBasicItemPtr,
format!("Duplicate {str1}").as_str(),
Some(&str1),
None,
);
if (*uses).remove(i) == -1 {
return -1;
}
continue 'next_use;
}
}
}
if !WXS_ATTRUSE_TYPEDEF!(using).is_null()
&& xml_schema_is_derived_from_built_in_type(
WXS_ATTRUSE_TYPEDEF!(using),
XmlSchemaValType::XmlSchemasID,
) != 0
{
if has_id != 0 {
let str1 = xml_schema_get_component_designation(using as _);
xml_schema_custom_err(
pctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemapAgPropsCorrect,
(*attr_gr).node.map(|node| node.into() ),
attr_gr as XmlSchemaBasicItemPtr,
format!("There must not exist more than one attribute declaration of type 'xs:ID' (or derived from 'xs:ID'). The {str1} violates this constraint").as_str(),
Some(&str1),
None
);
if (*uses).remove(i) == -1 {
return -1;
}
}
has_id = 1;
}
}
}
0
}
}
unsafe fn xml_schema_check_src_redefine_second(pctxt: XmlSchemaParserCtxtPtr) -> i32 {
unsafe {
let mut err: i32;
let mut redef: XmlSchemaRedefPtr = (*WXS_CONSTRUCTOR!(pctxt)).redefs;
let mut item: XmlSchemaBasicItemPtr;
if redef.is_null() {
return 0;
}
while {
'to_continue: {
if (*redef).target.is_null() {
redef = (*redef).next;
break 'to_continue;
}
item = (*redef).item;
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeSimple
| XmlSchemaTypeType::XmlSchemaTypeComplex => {
(*((*redef).target as XmlSchemaTypePtr)).name = null_mut();
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
err = xml_schema_check_derivation_okrestriction2to4(
pctxt,
XML_SCHEMA_ACTION_REDEFINE,
item,
(*redef).target,
(*(item as XmlSchemaAttributeGroupPtr)).attr_uses as _,
(*((*redef).target as XmlSchemaAttributeGroupPtr)).attr_uses as _,
(*(item as XmlSchemaAttributeGroupPtr)).attribute_wildcard,
(*((*redef).target as XmlSchemaAttributeGroupPtr)).attribute_wildcard,
);
if err == -1 {
return -1;
}
}
_ => {}
}
redef = (*redef).next;
}
!redef.is_null()
} {}
0
}
}
unsafe fn xml_schema_check_subst_group_circular(
elem_decl: XmlSchemaElementPtr,
ancestor: XmlSchemaElementPtr,
) -> XmlSchemaElementPtr {
unsafe {
if (*ancestor).ref_decl.is_null() {
return null_mut();
}
if (*ancestor).ref_decl == elem_decl {
return ancestor;
}
if (*(*ancestor).ref_decl).flags & XML_SCHEMAS_ELEM_CIRCULAR != 0 {
return null_mut();
}
(*(*ancestor).ref_decl).flags |= XML_SCHEMAS_ELEM_CIRCULAR;
let ret: XmlSchemaElementPtr =
xml_schema_check_subst_group_circular(elem_decl, (*ancestor).ref_decl);
(*(*ancestor).ref_decl).flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
ret
}
}
fn xml_schema_are_equal_types(type_a: XmlSchemaTypePtr, type_b: XmlSchemaTypePtr) -> i32 {
if type_a.is_null() || type_b.is_null() {
return 0;
}
(type_a == type_b) as i32
}
#[doc(alias = "xmlSchemaCheckCOSCTDerivedOK")]
unsafe fn xml_schema_check_cos_ct_derived_ok(
actxt: XmlSchemaAbstractCtxtPtr,
typ: XmlSchemaTypePtr,
base_type: XmlSchemaTypePtr,
set: i32,
) -> i32 {
unsafe {
let equal: i32 = xml_schema_are_equal_types(typ, base_type);
if equal == 0 {
if (set & SUBSET_EXTENSION != 0 && (*typ).wxs_is_extension())
|| (set & SUBSET_RESTRICTION != 0 && (*typ).wxs_is_restriction())
{
return 1;
}
} else {
return 0;
}
if (*typ).base_type == base_type {
return 0;
}
if wxs_is_anytype((*typ).base_type) {
return 1;
}
if wxs_is_complex((*typ).base_type) {
xml_schema_check_cos_ct_derived_ok(actxt, (*typ).base_type, base_type, set)
} else {
xml_schema_check_cosstderived_ok(actxt, (*typ).base_type, base_type, set)
}
}
}
#[doc(alias = "xmlSchemaCheckCOSDerivedOK")]
unsafe fn xml_schema_check_cos_derived_ok(
actxt: XmlSchemaAbstractCtxtPtr,
typ: XmlSchemaTypePtr,
base_type: XmlSchemaTypePtr,
set: i32,
) -> i32 {
unsafe {
if wxs_is_simple(typ) {
xml_schema_check_cosstderived_ok(actxt, typ, base_type, set)
} else {
xml_schema_check_cos_ct_derived_ok(actxt, typ, base_type, set)
}
}
}
#[doc(alias = "xmlSchemaParseCheckCOSValidDefault")]
unsafe fn xml_schema_parse_check_cos_valid_default(
pctxt: XmlSchemaParserCtxtPtr,
node: Option<XmlGenericNodePtr>,
typ: XmlSchemaTypePtr,
value: *const XmlChar,
val: *mut XmlSchemaValPtr,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
if wxs_is_complex(typ) {
if !WXS_HAS_SIMPLE_CONTENT!(typ)
&& (!WXS_HAS_MIXED_CONTENT!(typ) || !WXS_EMPTIABLE!(typ))
{
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapCosValidDefault2_1,
typ as XmlSchemaBasicItemPtr,
(*typ).node.map(|node| node.into()),
"For a string to be a valid default, the type definition must be a simple type or a complex type with mixed content and a particle emptiable",
None,
);
return XmlParserErrors::XmlSchemapCosValidDefault2_1 as i32;
}
}
if wxs_is_simple(typ) {
ret = xml_schema_vcheck_cvc_simple_type(
pctxt as XmlSchemaAbstractCtxtPtr,
node,
typ,
value,
val,
1,
1,
0,
);
} else if WXS_HAS_SIMPLE_CONTENT!(typ) {
ret = xml_schema_vcheck_cvc_simple_type(
pctxt as XmlSchemaAbstractCtxtPtr,
node,
(*typ).content_type_def,
value,
val,
1,
1,
0,
);
} else {
return ret;
}
if ret < 0 {
PERROR_INT!(
pctxt,
"xmlSchemaParseCheckCOSValidDefault",
"calling xmlSchemaVCheckCVCSimpleType()"
);
}
ret
}
}
#[doc(alias = "xmlSchemaCheckElemPropsCorrect")]
unsafe fn xml_schema_check_elem_props_correct(
pctxt: XmlSchemaParserCtxtPtr,
elem_decl: XmlSchemaElementPtr,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let type_def: XmlSchemaTypePtr = (*elem_decl).subtypes;
if !(*elem_decl).ref_decl.is_null() {
let head: XmlSchemaElementPtr = (*elem_decl).ref_decl;
let circ: XmlSchemaElementPtr;
xml_schema_check_element_decl_component(head, pctxt);
if (*elem_decl).flags & XML_SCHEMAS_ELEM_GLOBAL == 0 {
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapEPropsCorrect3,
elem_decl as XmlSchemaBasicItemPtr,
None,
"Only global element declarations can have a substitution group affiliation",
None,
);
ret = XmlParserErrors::XmlSchemapEPropsCorrect3 as i32;
}
if head == elem_decl {
circ = head;
} else if !(*head).ref_decl.is_null() {
circ = xml_schema_check_subst_group_circular(head, head);
} else {
circ = null_mut();
}
if !circ.is_null() {
let q1 = xml_schema_get_component_qname(circ as _);
let q2 = xml_schema_get_component_qname(head as _);
xml_schema_pcustom_err_ext(
pctxt,
XmlParserErrors::XmlSchemapEPropsCorrect6,
circ as XmlSchemaBasicItemPtr,
None,
format!("The element declaration '{q1}' defines a circular substitution group to element declaration '{q2}'").as_str(),
Some(&q1),
Some(&q2),
None
);
ret = XmlParserErrors::XmlSchemapEPropsCorrect6 as i32;
}
if type_def != (*((*elem_decl).ref_decl)).subtypes {
let mut set: i32 = 0;
if (*head).flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION != 0 {
set |= SUBSET_EXTENSION;
}
if (*head).flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION != 0 {
set |= SUBSET_RESTRICTION;
}
if xml_schema_check_cos_derived_ok(
pctxt as XmlSchemaAbstractCtxtPtr,
type_def,
(*head).subtypes,
set,
) != 0
{
let q1 = xml_schema_get_component_qname(type_def as _);
let q2 = xml_schema_get_component_qname(head as _);
let q3 = xml_schema_get_component_qname((*head).subtypes as _);
ret = XmlParserErrors::XmlSchemapEPropsCorrect4 as i32;
xml_schema_pcustom_err_ext(
pctxt,
XmlParserErrors::XmlSchemapEPropsCorrect4,
elem_decl as XmlSchemaBasicItemPtr,
None,
format!("The type definition '{q1}' was either rejected by the substitution group affiliation '{q2}', or not validly derived from its type definition '{q3}'").as_str(),
Some(&q1),
Some(&q2),
Some(&q3)
);
}
}
}
if !(*elem_decl).value.is_null()
&& ((wxs_is_simple(type_def)
&& xml_schema_is_derived_from_built_in_type(
type_def,
XmlSchemaValType::XmlSchemasID,
) != 0)
|| (wxs_is_complex(type_def)
&& WXS_HAS_SIMPLE_CONTENT!(type_def)
&& xml_schema_is_derived_from_built_in_type(
(*type_def).content_type_def,
XmlSchemaValType::XmlSchemasID,
) != 0))
{
ret = XmlParserErrors::XmlSchemapEPropsCorrect5 as i32;
xml_schema_pcustom_err(
pctxt,
XmlParserErrors::XmlSchemapEPropsCorrect5,
elem_decl as XmlSchemaBasicItemPtr,
None,
"The type definition (or type definition's content type) is or is derived from ID; value constraints are not allowed in conjunction with such a type definition",
None,
);
} else if !(*elem_decl).value.is_null() {
if type_def.is_null() {
xml_schema_perr(
pctxt,
(*elem_decl).node.map(|node| node.into()),
XmlParserErrors::XmlSchemapInternal,
"Internal error: xmlSchemaCheckElemPropsCorrect, type is missing... skipping validation of the value constraint",
None,
None,
);
return -1;
}
let node = if let Some(node) = (*elem_decl).node {
let attr = if (*elem_decl).flags & XML_SCHEMAS_ELEM_FIXED != 0 {
node.has_prop("fixed")
} else {
node.has_prop("default")
};
match attr {
Some(Ok(attr)) => Some(XmlGenericNodePtr::from(attr)),
Some(Err(attr)) => Some(XmlGenericNodePtr::from(attr)),
_ => None,
}
} else {
None
};
let vcret: i32 = xml_schema_parse_check_cos_valid_default(
pctxt,
node,
type_def,
(*elem_decl).value,
&raw mut (*elem_decl).def_val,
);
if vcret != 0 {
if vcret < 0 {
PERROR_INT!(
pctxt,
"xmlSchemaElemCheckValConstr",
"failed to validate the value constraint of an element declaration"
);
return -1;
}
return vcret;
}
}
ret
}
}
unsafe fn xml_schema_subst_group_get(
pctxt: XmlSchemaParserCtxtPtr,
head: XmlSchemaElementPtr,
) -> XmlSchemaSubstGroupPtr {
unsafe {
if WXS_SUBST_GROUPS!(pctxt).is_null() {
return null_mut();
}
xml_hash_lookup2(
WXS_SUBST_GROUPS!(pctxt),
(*head).name,
(*head).target_namespace,
) as _
}
}
unsafe fn xml_schema_subst_group_add(
pctxt: XmlSchemaParserCtxtPtr,
head: XmlSchemaElementPtr,
) -> XmlSchemaSubstGroupPtr {
unsafe {
if WXS_SUBST_GROUPS!(pctxt).is_null() {
WXS_SUBST_GROUPS!(pctxt) = xml_hash_create(10);
if WXS_SUBST_GROUPS!(pctxt).is_null() {
return null_mut();
}
}
let ret: XmlSchemaSubstGroupPtr =
xml_malloc(size_of::<XmlSchemaSubstGroup>()) as XmlSchemaSubstGroupPtr;
if ret.is_null() {
xml_schema_perr_memory(
null_mut(),
"allocating a substitution group container",
None,
);
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaSubstGroup>());
(*ret).head = head;
(*ret).members = xml_schema_item_list_create::<*mut c_void>();
if (*ret).members.is_null() {
xml_schema_subst_group_free(ret);
return null_mut();
}
if xml_hash_add_entry2(
WXS_SUBST_GROUPS!(pctxt),
(*head).name,
(*head).target_namespace,
ret as _,
) != 0
{
PERROR_INT!(
pctxt,
"xmlSchemaSubstGroupAdd",
"failed to add a new substitution container"
);
xml_schema_subst_group_free(ret);
return null_mut();
}
ret
}
}
#[doc(alias = "xmlSchemaAddElementSubstitutionMember")]
unsafe fn xml_schema_add_element_substitution_member(
pctxt: XmlSchemaParserCtxtPtr,
head: XmlSchemaElementPtr,
member: XmlSchemaElementPtr,
) -> i32 {
unsafe {
let mut subst_group: XmlSchemaSubstGroupPtr;
if pctxt.is_null() || head.is_null() || member.is_null() {
return -1;
}
subst_group = xml_schema_subst_group_get(pctxt, head);
if subst_group.is_null() {
subst_group = xml_schema_subst_group_add(pctxt, head);
}
if subst_group.is_null() {
return -1;
}
if (*(*subst_group).members).push(member as _) == -1 {
return -1;
}
0
}
}
#[doc(alias = "xmlSchemaCheckElemSubstGroup")]
unsafe fn xml_schema_check_elem_subst_group(
ctxt: XmlSchemaParserCtxtPtr,
elem_decl: XmlSchemaElementPtr,
) {
unsafe {
if (*elem_decl).ref_decl.is_null() || (*elem_decl).flags & XML_SCHEMAS_ELEM_ABSTRACT != 0 {
return;
}
{
let mut head: XmlSchemaElementPtr;
let mut head_type: XmlSchemaTypePtr;
let mut typ: XmlSchemaTypePtr;
let mut set: i32;
let mut meth_set: i32;
head = (*elem_decl).ref_decl;
while !head.is_null() {
'to_continue: {
set = 0;
meth_set = 0;
if (*head).flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION != 0 {
break 'to_continue;
}
head_type = (*head).subtypes;
typ = (*elem_decl).subtypes;
if head_type == typ {
} else {
if (*head).flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION != 0 {
set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
}
if (*head).flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION != 0 {
set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
}
while !typ.is_null() && typ != head_type && typ != (*typ).base_type {
if (*typ).wxs_is_extension()
&& meth_set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION == 0
{
meth_set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
}
if (*typ).wxs_is_restriction()
&& meth_set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION == 0
{
meth_set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
}
typ = (*typ).base_type;
}
typ = (*(*elem_decl).subtypes).base_type;
while !typ.is_null() {
if wxs_is_complex(typ) {
if (*typ).flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION != 0
&& set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION == 0
{
set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
}
if (*typ).flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION != 0
&& set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION == 0
{
set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
}
} else {
break;
}
if typ == head_type {
break;
}
typ = (*typ).base_type;
}
if set != 0
&& ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION != 0
&& meth_set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION != 0)
|| (set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION != 0
&& meth_set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION != 0))
{
break 'to_continue;
}
}
xml_schema_add_element_substitution_member(ctxt, head, elem_decl);
if (*head).flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD == 0 {
(*head).flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
}
}
head = (*head).ref_decl;
}
}
}
}
#[doc(alias = "xmlSchemaCheckElementDeclComponent")]
unsafe fn xml_schema_check_element_decl_component(
elem_decl: XmlSchemaElementPtr,
ctxt: XmlSchemaParserCtxtPtr,
) {
unsafe {
if elem_decl.is_null() {
return;
}
if (*elem_decl).flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED != 0 {
return;
}
(*elem_decl).flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
if xml_schema_check_elem_props_correct(ctxt, elem_decl) == 0 {
xml_schema_check_elem_subst_group(ctxt, elem_decl);
}
}
}
#[doc(alias = "xmlSchemaBuildContentModelForSubstGroup")]
unsafe fn xml_schema_build_content_model_for_subst_group(
pctxt: XmlSchemaParserCtxtPtr,
particle: XmlSchemaParticlePtr,
mut counter: i32,
mut end: usize,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let elem_decl: XmlSchemaElementPtr = (*particle).children as XmlSchemaElementPtr;
let start = (*pctxt).state;
if end == usize::MAX {
end = (*pctxt).am.as_mut().unwrap().new_state();
}
let subst_group: XmlSchemaSubstGroupPtr = xml_schema_subst_group_get(pctxt, elem_decl);
if subst_group.is_null() {
let name = CStr::from_ptr((*elem_decl).name as *const i8).to_string_lossy();
xml_schema_perr(
pctxt,
xml_schema_get_component_node(particle as _).map(|node| node.into()),
XmlParserErrors::XmlSchemapInternal,
"Internal error: xmlSchemaBuildContentModelForSubstGroup, declaration is marked having a subst. group but none available.\n",
Some(&name),
None,
);
return 0;
}
if counter >= 0 {
let tmp = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(start, usize::MAX, counter);
(*pctxt).am.as_mut().unwrap().new_transition2(
tmp,
end,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8).to_string_lossy()
})
.as_deref(),
elem_decl as _,
);
for member in (*(*subst_group).members)
.items
.iter()
.map(|&member| member as XmlSchemaElementPtr)
{
(*pctxt).am.as_mut().unwrap().new_transition2(
tmp,
end,
CStr::from_ptr((*member).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*member).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*member).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
member as _,
);
}
} else if (*particle).max_occurs == 1 {
(*pctxt).am.as_mut().unwrap().new_epsilon(
(*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
),
end,
);
for member in (*(*subst_group).members)
.items
.iter()
.map(|&member| member as XmlSchemaElementPtr)
{
let tmp = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*member).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*member).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*member).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
member as _,
);
(*pctxt).am.as_mut().unwrap().new_epsilon(tmp, end);
}
} else {
let max_occurs: i32 = if (*particle).max_occurs == UNBOUNDED as i32 {
UNBOUNDED as i32
} else {
(*particle).max_occurs - 1
};
let min_occurs: i32 = if (*particle).min_occurs < 1 {
0
} else {
(*particle).min_occurs - 1
};
counter = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter(min_occurs, max_occurs);
let hop = (*pctxt).am.as_mut().unwrap().new_state();
(*pctxt).am.as_mut().unwrap().new_epsilon(
(*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
),
hop,
);
for member in (*(*subst_group).members)
.items
.iter()
.map(|&member| member as XmlSchemaElementPtr)
{
(*pctxt).am.as_mut().unwrap().new_epsilon(
(*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*member).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*member).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*member).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
member as _,
),
hop,
);
}
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(hop, start, counter);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counter_trans(hop, end, counter);
}
if (*particle).min_occurs == 0 {
(*pctxt).am.as_mut().unwrap().new_epsilon(start, end);
ret = 1;
}
(*pctxt).state = end;
ret
}
}
#[doc(alias = "xmlSchemaBuildContentModelForElement")]
unsafe fn xml_schema_build_content_model_for_element(
ctxt: XmlSchemaParserCtxtPtr,
particle: XmlSchemaParticlePtr,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
if (*((*particle).children as XmlSchemaElementPtr)).flags
& XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD
!= 0
{
ret = xml_schema_build_content_model_for_subst_group(ctxt, particle, -1, usize::MAX);
} else {
let start;
let elem_decl: XmlSchemaElementPtr = (*particle).children as XmlSchemaElementPtr;
if (*elem_decl).flags & XML_SCHEMAS_ELEM_ABSTRACT != 0 {
return 0;
}
if (*particle).max_occurs == 1 {
start = (*ctxt).state;
(*ctxt).state = (*ctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
);
} else if (*particle).max_occurs >= UNBOUNDED as i32 && (*particle).min_occurs < 2 {
start = (*ctxt).state;
(*ctxt).state = (*ctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
);
(*ctxt).state = (*ctxt).am.as_mut().unwrap().new_transition2(
(*ctxt).state,
(*ctxt).state,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
);
} else {
let max_occurs: i32 = if (*particle).max_occurs == UNBOUNDED as i32 {
UNBOUNDED as i32
} else {
(*particle).max_occurs - 1
};
let min_occurs: i32 = if (*particle).min_occurs < 1 {
0
} else {
(*particle).min_occurs - 1
};
start = (*ctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*ctxt).state, usize::MAX);
let counter: i32 = (*ctxt)
.am
.as_mut()
.unwrap()
.new_counter(min_occurs, max_occurs);
(*ctxt).state = (*ctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
elem_decl as _,
);
(*ctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans((*ctxt).state, start, counter);
(*ctxt).state = (*ctxt).am.as_mut().unwrap().new_counter_trans(
(*ctxt).state,
usize::MAX,
counter,
);
}
if (*particle).min_occurs == 0 {
(*ctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(start, (*ctxt).state);
ret = 1;
}
}
ret
}
}
#[doc(alias = "xmlSchemaBuildAContentModel")]
unsafe fn xml_schema_build_acontent_model(
pctxt: XmlSchemaParserCtxtPtr,
particle: XmlSchemaParticlePtr,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let mut tmp2: i32;
if particle.is_null() {
PERROR_INT!(pctxt, "xmlSchemaBuildAContentModel", "particle is NULL");
return 1;
}
if (*particle).children.is_null() {
return 1;
}
match (*(*particle).children).typ {
XmlSchemaTypeType::XmlSchemaTypeAny => {
let mut ns: XmlSchemaWildcardNsPtr;
let wild: XmlSchemaWildcardPtr = (*particle).children as XmlSchemaWildcardPtr;
let start = (*pctxt).state;
let end = (*pctxt).am.as_mut().unwrap().new_state();
if (*particle).max_occurs == 1 {
if (*wild).any == 1 {
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
"*",
Some("*"),
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, end);
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
"*",
None,
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, end);
} else if !(*wild).ns_set.is_null() {
ns = (*wild).ns_set;
while {
(*pctxt).state = start;
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
(*pctxt).state,
usize::MAX,
"*",
(!(*ns).value.is_null())
.then(|| {
CStr::from_ptr((*ns).value as *const i8).to_string_lossy()
})
.as_deref(),
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, end);
ns = (*ns).next;
!ns.is_null()
} {}
} else if !(*wild).neg_ns_set.is_null() {
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_neg_trans(
start,
end,
"*",
(!(*(*wild).neg_ns_set).value.is_null())
.then(|| {
CStr::from_ptr((*(*wild).neg_ns_set).value as *const i8)
.to_string_lossy()
})
.as_deref(),
wild as _,
);
}
} else {
let max_occurs: i32 = if (*particle).max_occurs == UNBOUNDED as i32 {
UNBOUNDED as i32
} else {
(*particle).max_occurs - 1
};
let min_occurs: i32 = if (*particle).min_occurs < 1 {
0
} else {
(*particle).min_occurs - 1
};
let counter: i32 = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter(min_occurs, max_occurs);
let hop = (*pctxt).am.as_mut().unwrap().new_state();
if (*wild).any == 1 {
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
"*",
Some("*"),
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, hop);
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
"*",
None,
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, hop);
} else if !(*wild).ns_set.is_null() {
ns = (*wild).ns_set;
while {
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_transition2(
start,
usize::MAX,
"*",
(!(*ns).value.is_null())
.then(|| {
CStr::from_ptr((*ns).value as *const i8).to_string_lossy()
})
.as_deref(),
wild as _,
);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, hop);
ns = (*ns).next;
!ns.is_null()
} {}
} else if !(*wild).neg_ns_set.is_null() {
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_neg_trans(
start,
hop,
"*",
(!(*(*wild).neg_ns_set).value.is_null())
.then(|| {
CStr::from_ptr((*(*wild).neg_ns_set).value as *const i8)
.to_string_lossy()
})
.as_deref(),
wild as _,
);
}
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(hop, start, counter);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counter_trans(hop, end, counter);
}
if (*particle).min_occurs == 0 {
(*pctxt).am.as_mut().unwrap().new_epsilon(start, end);
ret = 1;
}
(*pctxt).state = end;
}
XmlSchemaTypeType::XmlSchemaTypeElement => {
ret = xml_schema_build_content_model_for_element(pctxt, particle);
}
XmlSchemaTypeType::XmlSchemaTypeSequence => {
let mut sub: XmlSchemaTreeItemPtr;
ret = 1;
if (*particle).min_occurs == 1 && (*particle).max_occurs == 1 {
sub = (*(*particle).children).children;
while !sub.is_null() {
tmp2 = xml_schema_build_acontent_model(pctxt, sub as XmlSchemaParticlePtr);
if tmp2 != 1 {
ret = 0;
}
sub = (*sub).next;
}
} else {
let mut oldstate = (*pctxt).state;
if (*particle).max_occurs >= UNBOUNDED as i32 {
if (*particle).min_occurs > 1 {
(*pctxt).state = (*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, usize::MAX);
oldstate = (*pctxt).state;
let counter: i32 = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter((*particle).min_occurs - 1, UNBOUNDED as _);
sub = (*(*particle).children).children;
while !sub.is_null() {
tmp2 = xml_schema_build_acontent_model(
pctxt,
sub as XmlSchemaParticlePtr,
);
if tmp2 != 1 {
ret = 0;
}
sub = (*sub).next;
}
let tmp = (*pctxt).state;
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(tmp, oldstate, counter);
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_counter_trans(
tmp,
usize::MAX,
counter,
);
if ret == 1 {
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, (*pctxt).state);
}
} else {
(*pctxt).state = (*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, usize::MAX);
oldstate = (*pctxt).state;
sub = (*(*particle).children).children;
while !sub.is_null() {
tmp2 = xml_schema_build_acontent_model(
pctxt,
sub as XmlSchemaParticlePtr,
);
if tmp2 != 1 {
ret = 0;
}
sub = (*sub).next;
}
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, oldstate);
(*pctxt).state = (*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, usize::MAX);
if (*particle).min_occurs == 0 {
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, (*pctxt).state);
ret = 1;
}
}
} else if (*particle).max_occurs > 1 || (*particle).min_occurs > 1 {
(*pctxt).state = (*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, usize::MAX);
oldstate = (*pctxt).state;
let counter: i32 = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter((*particle).min_occurs - 1, (*particle).max_occurs - 1);
sub = (*(*particle).children).children;
while !sub.is_null() {
tmp2 =
xml_schema_build_acontent_model(pctxt, sub as XmlSchemaParticlePtr);
if tmp2 != 1 {
ret = 0;
}
sub = (*sub).next;
}
let tmp = (*pctxt).state;
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(tmp, oldstate, counter);
(*pctxt).state = (*pctxt).am.as_mut().unwrap().new_counter_trans(
tmp,
usize::MAX,
counter,
);
if (*particle).min_occurs == 0 || ret == 1 {
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, (*pctxt).state);
ret = 1;
}
} else {
sub = (*(*particle).children).children;
while !sub.is_null() {
tmp2 =
xml_schema_build_acontent_model(pctxt, sub as XmlSchemaParticlePtr);
if tmp2 != 1 {
ret = 0;
}
sub = (*sub).next;
}
(*pctxt).state = (*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, usize::MAX);
if (*particle).min_occurs == 0 {
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(oldstate, (*pctxt).state);
ret = 1;
}
}
}
}
XmlSchemaTypeType::XmlSchemaTypeChoice => {
let mut sub: XmlSchemaTreeItemPtr;
ret = 0;
let start = (*pctxt).state;
let end = (*pctxt).am.as_mut().unwrap().new_state();
if (*particle).max_occurs == 1 {
sub = (*(*particle).children).children;
while !sub.is_null() {
(*pctxt).state = start;
tmp2 = xml_schema_build_acontent_model(pctxt, sub as XmlSchemaParticlePtr);
if tmp2 == 1 {
ret = 1
}
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, end);
sub = (*sub).next;
}
} else {
let max_occurs: i32 = if (*particle).max_occurs == UNBOUNDED as i32 {
UNBOUNDED as i32
} else {
(*particle).max_occurs - 1
};
let min_occurs: i32 = if (*particle).min_occurs < 1 {
0
} else {
(*particle).min_occurs - 1
};
let counter: i32 = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter(min_occurs, max_occurs);
let hop = (*pctxt).am.as_mut().unwrap().new_state();
let base = (*pctxt).am.as_mut().unwrap().new_state();
sub = (*(*particle).children).children;
while !sub.is_null() {
(*pctxt).state = base;
tmp2 = xml_schema_build_acontent_model(pctxt, sub as XmlSchemaParticlePtr);
if tmp2 == 1 {
ret = 1
}
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, hop);
sub = (*sub).next;
}
(*pctxt).am.as_mut().unwrap().new_epsilon(start, base);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counted_trans(hop, base, counter);
(*pctxt)
.am
.as_mut()
.unwrap()
.new_counter_trans(hop, end, counter);
if ret == 1 {
(*pctxt).am.as_mut().unwrap().new_epsilon(base, end);
}
}
if (*particle).min_occurs == 0 {
(*pctxt).am.as_mut().unwrap().new_epsilon(start, end);
ret = 1;
}
(*pctxt).state = end;
}
XmlSchemaTypeType::XmlSchemaTypeAll => {
let mut sub: XmlSchemaParticlePtr;
let mut elem_decl: XmlSchemaElementPtr;
ret = 1;
sub = (*(*particle).children).children as XmlSchemaParticlePtr;
if sub.is_null() {
} else {
ret = 0;
let start = (*pctxt).state;
let tmp = (*pctxt).am.as_mut().unwrap().new_state();
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon((*pctxt).state, tmp);
(*pctxt).state = tmp;
while !sub.is_null() {
(*pctxt).state = tmp;
elem_decl = (*sub).children as XmlSchemaElementPtr;
if elem_decl.is_null() {
PERROR_INT!(
pctxt,
"xmlSchemaBuildAContentModel",
"<element> particle has no term"
);
return ret;
};
if (*elem_decl).flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD != 0 {
let counter: i32 = (*pctxt)
.am
.as_mut()
.unwrap()
.new_counter((*sub).min_occurs, (*sub).max_occurs);
xml_schema_build_content_model_for_subst_group(
pctxt,
sub,
counter,
(*pctxt).state,
);
} else if (*sub).min_occurs == 1 && (*sub).max_occurs == 1 {
(*pctxt).am.as_mut().unwrap().new_once_trans2(
(*pctxt).state,
(*pctxt).state,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
1,
1,
elem_decl as _,
);
} else if (*sub).min_occurs == 0 && (*sub).max_occurs == 1 {
(*pctxt).am.as_mut().unwrap().new_count_trans2(
(*pctxt).state,
(*pctxt).state,
CStr::from_ptr((*elem_decl).name as *const i8)
.to_string_lossy()
.as_ref(),
(!(*elem_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*elem_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref(),
0,
1,
elem_decl as _,
);
}
sub = (*sub).next as XmlSchemaParticlePtr;
}
(*pctxt).state =
(*pctxt)
.am
.as_mut()
.unwrap()
.new_all_trans((*pctxt).state, usize::MAX, 0);
if (*particle).min_occurs == 0 {
(*pctxt)
.am
.as_mut()
.unwrap()
.new_epsilon(start, (*pctxt).state);
ret = 1;
}
}
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
ret = 1;
}
_ => {
let typename = xml_schema_get_component_type_str(((*particle).children) as _);
xml_schema_internal_err2(
pctxt as XmlSchemaAbstractCtxtPtr,
"xmlSchemaBuildAContentModel",
format!("found unexpected term of type '{typename}' in content model").as_str(),
Some(typename),
None,
);
return ret;
}
}
ret
}
}
#[doc(alias = "xmlSchemaBuildContentModel")]
unsafe fn xml_schema_build_content_model(typ: XmlSchemaTypePtr, ctxt: XmlSchemaParserCtxtPtr) {
unsafe {
if (*typ).typ != XmlSchemaTypeType::XmlSchemaTypeComplex
|| (*typ).cont_model.is_some()
|| !matches!(
(*typ).content_type,
XmlSchemaContentType::XmlSchemaContentElements
| XmlSchemaContentType::XmlSchemaContentMixed
)
{
return;
}
(*ctxt).am = XmlAutomata::new();
if (*ctxt).am.is_none() {
generic_error!(
"Cannot create automata for complex type {}\n",
CStr::from_ptr((*typ).name as *const i8).to_string_lossy()
);
return;
}
(*ctxt).state = (*ctxt).am.as_mut().unwrap().get_init_state();
xml_schema_build_acontent_model(ctxt, WXS_TYPE_PARTICLE!(typ));
(*ctxt)
.am
.as_mut()
.unwrap()
.get_state_mut((*ctxt).state)
.unwrap()
.set_final_state();
let mut cont_model = (*ctxt).am.as_mut().unwrap().compile();
if let Some(cont_model) = cont_model.as_mut() {
if cont_model.is_determinist() != 1 {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapNotDeterministic,
typ as XmlSchemaBasicItemPtr,
(*typ).node.map(|node| node.into()),
"The content model is not determinist",
None,
);
} else {
}
} else {
xml_schema_pcustom_err(
ctxt,
XmlParserErrors::XmlSchemapInternal,
typ as XmlSchemaBasicItemPtr,
(*typ).node.map(|node| node.into()),
"Failed to compile the content model",
None,
);
}
(*typ).cont_model = cont_model.map(Rc::new);
(*ctxt).state = usize::MAX;
(*ctxt).am.take();
}
}
macro_rules! FIXHFAILURE {
($pctxt:expr, $label:tt) => {
if (*$pctxt).err == XmlParserErrors::XmlSchemapInternal as i32 {
break $label;
}
};
}
pub(crate) unsafe fn xml_schema_fixup_components(
pctxt: XmlSchemaParserCtxtPtr,
root_bucket: XmlSchemaBucketPtr,
) -> i32 {
unsafe {
let con: XmlSchemaConstructionCtxtPtr = (*pctxt).constructor;
let mut ret: i32 = 0;
let oldbucket: XmlSchemaBucketPtr = (*con).bucket;
let mut elem_decl: XmlSchemaElementPtr;
if (*con).pending.is_null() || (*(*con).pending).items.is_empty() {
return 0;
}
if (*con).bucket.is_null() {
(*con).bucket = root_bucket;
}
xml_schema_check_srcredefine_first(pctxt);
xml_schema_add_components(pctxt, root_bucket);
(*pctxt).ctxt_type = null_mut();
let mut nb_items = (*(*con).pending).items.len();
'exit: {
'exit_failure: {
'exit_error: {
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeElement => {
xml_schema_resolve_element_references(
item as XmlSchemaElementPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaTypeComplex
| XmlSchemaTypeType::XmlSchemaTypeSimple => {
xml_schema_resolve_type_references(item as XmlSchemaTypePtr, pctxt);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaTypeAttribute => {
xml_schema_resolve_attr_type_references(
item as XmlSchemaAttributePtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaTypeAttributeUse => {
xml_schema_resolve_attr_use_references(
item as XmlSchemaAttributeUsePtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaExtraQNameRef => {
if (*(item as XmlSchemaQNameRefPtr)).item_type
== XmlSchemaTypeType::XmlSchemaTypeAttributeGroup
{
xml_schema_resolve_attr_group_references(
item as XmlSchemaQNameRefPtr,
pctxt,
);
}
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice
| XmlSchemaTypeType::XmlSchemaTypeAll => {
xml_schema_resolve_model_group_particle_references(
pctxt,
item as XmlSchemaModelGroupPtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaTypeIDCKey
| XmlSchemaTypeType::XmlSchemaTypeIDCUnique
| XmlSchemaTypeType::XmlSchemaTypeIDCKeyref => {
xml_schema_resolve_idckey_references(
item as XmlSchemaIDCPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
XmlSchemaTypeType::XmlSchemaExtraAttrUseProhib => {
xml_schema_resolve_attr_use_prohib_references(
item as XmlSchemaAttributeUseProhibPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
_ => {}
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeComplex
| XmlSchemaTypeType::XmlSchemaTypeSimple => {
xml_schema_check_type_def_circular(item as XmlSchemaTypePtr, pctxt);
FIXHFAILURE!(pctxt, 'exit_failure);
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
}
XmlSchemaTypeType::XmlSchemaTypeGroup => {
xml_schema_check_group_def_circular(
item as XmlSchemaModelGroupDefPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
}
XmlSchemaTypeType::XmlSchemaTypeAttributeGroup => {
xml_schema_check_attr_group_circular(
item as XmlSchemaAttributeGroupPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
}
_ => {}
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
match (*item).typ {
XmlSchemaTypeType::XmlSchemaTypeSequence
| XmlSchemaTypeType::XmlSchemaTypeChoice => {
xml_schema_model_group_to_model_group_def_fixup(
pctxt,
item as XmlSchemaModelGroupPtr,
);
}
_ => {}
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeAttributeGroup
&& !WXS_ATTR_GROUP_EXPANDED!(item)
&& WXS_ATTR_GROUP_HAS_REFS!(item)
{
xml_schema_attribute_group_expand_refs(
pctxt,
item as XmlSchemaAttributeGroupPtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeSimple
&& WXS_IS_TYPE_NOT_FIXED_1!(item as XmlSchemaTypePtr)
{
xml_schema_fixup_simple_type_stage_one(pctxt, item as XmlSchemaTypePtr);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeSimple
&& !(*(item as XmlSchemaTypePtr)).member_types.is_null()
{
xml_schema_check_union_type_def_circular(
pctxt,
item as XmlSchemaTypePtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeSimple
&& WXS_IS_TYPE_NOT_FIXED!(item as XmlSchemaTypePtr)
{
xml_schema_fixup_simple_type_stage_two(pctxt, item as XmlSchemaTypePtr);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeAttribute {
xml_schema_check_attr_props_correct(
pctxt,
item as XmlSchemaAttributePtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeAttributeUse
&& !(*(item as XmlSchemaAttributeUsePtr)).def_value.is_null()
{
xml_schema_check_attr_use_props_correct(
pctxt,
item as XmlSchemaAttributeUsePtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeAttributeGroup
&& !(*(item as XmlSchemaAttributeGroupPtr)).attr_uses.is_null()
&& (*((*(item as XmlSchemaAttributeGroupPtr)).attr_uses
as XmlSchemaItemListPtr<*mut c_void>))
.items
.len()
> 1
{
xml_schema_check_agprops_correct(
pctxt,
item as XmlSchemaAttributeGroupPtr,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
if !(*WXS_CONSTRUCTOR!(pctxt)).redefs.is_null() {
xml_schema_check_src_redefine_second(pctxt);
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeComplex
&& WXS_IS_TYPE_NOT_FIXED!(item as XmlSchemaTypePtr)
{
xml_schema_fixup_complex_type(pctxt, item as XmlSchemaTypePtr);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
nb_items = (*(*con).pending).items.len();
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeElement {
elem_decl = item as XmlSchemaElementPtr;
if (*elem_decl).flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED == 0 {
xml_schema_check_element_decl_component(
elem_decl as XmlSchemaElementPtr,
pctxt,
);
FIXHFAILURE!(pctxt, 'exit_failure);
}
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
for item in (*(*con).pending)
.items
.iter()
.take(nb_items)
.map(|&item| item as XmlSchemaTreeItemPtr)
{
if (*item).typ == XmlSchemaTypeType::XmlSchemaTypeComplex {
xml_schema_build_content_model(item as XmlSchemaTypePtr, pctxt);
}
}
if (*pctxt).nberrors != 0 {
break 'exit_error;
}
break 'exit;
}
ret = (*pctxt).err;
break 'exit;
}
ret = -1;
}
(*con).bucket = oldbucket;
(*(*con).pending).items.clear();
if !(*con).subst_groups.is_null() {
xml_hash_free((*con).subst_groups, Some(xml_schema_subst_group_free_entry));
(*con).subst_groups = null_mut();
}
if !(*con).redefs.is_null() {
xml_schema_redef_list_free((*con).redefs);
(*con).redefs = null_mut();
}
ret
}
}
#[doc(alias = "xmlSchemaIDCFreeKey")]
pub(crate) unsafe fn xml_schema_idc_free_key(key: XmlSchemaPSVIIDCKeyPtr) {
unsafe {
if !(*key).val.is_null() {
xml_schema_free_value((*key).val);
}
xml_free(key as _);
}
}
pub(crate) unsafe fn xml_schema_free_idc_state_obj_list(mut sto: XmlSchemaIDCStateObjPtr) {
unsafe {
let mut next: XmlSchemaIDCStateObjPtr;
while !sto.is_null() {
next = (*sto).next;
if !(*sto).history.is_null() {
xml_free((*sto).history as _);
}
(*sto).xpath_ctxt.take();
xml_free(sto as _);
sto = next;
}
}
}
extern "C" fn xml_free_idc_hash_entry(payload: *mut c_void, _name: *const XmlChar) {
let mut e: XmlIDCHashEntryPtr = payload as _;
let mut n: XmlIDCHashEntryPtr;
while !e.is_null() {
unsafe {
n = (*e).next;
xml_free(e as _);
e = n;
}
}
}
#[doc(alias = "xmlSchemaIDCReleaseMatcherList")]
pub(crate) unsafe fn xml_schema_idc_release_matcher_list(
vctxt: XmlSchemaValidCtxtPtr,
mut matcher: XmlSchemaIDCMatcherPtr,
) {
unsafe {
let mut next: XmlSchemaIDCMatcherPtr;
while !matcher.is_null() {
next = (*matcher).next;
if !(*matcher).key_seqs.is_null() {
for i in 0..(*matcher).size_key_seqs {
if !(*(*matcher).key_seqs.add(i as usize)).is_null() {
xml_free(*(*matcher).key_seqs.add(i as usize) as _);
*(*matcher).key_seqs.add(i as usize) = null_mut();
}
}
}
if !(*matcher).targets.is_null() {
if (*matcher).idc_type == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref as i32 {
for idc_node in (*(*matcher).targets)
.items
.iter()
.map(|&idc_node| idc_node as XmlSchemaPSVIIDCNodePtr)
{
xml_free((*idc_node).keys as _);
xml_free(idc_node as _);
}
}
xml_schema_item_list_free((*matcher).targets);
(*matcher).targets = null_mut();
}
if !(*matcher).htab.is_null() {
xml_hash_free((*matcher).htab, Some(xml_free_idc_hash_entry));
(*matcher).htab = null_mut();
}
(*matcher).next = null_mut();
if !(*vctxt).idc_matcher_cache.is_null() {
(*matcher).next_cached = (*vctxt).idc_matcher_cache;
}
(*vctxt).idc_matcher_cache = matcher;
matcher = next;
}
}
}
#[doc(alias = "xmlSchemaIDCFreeBinding")]
unsafe fn xml_schema_idc_free_binding(bind: XmlSchemaPSVIIDCBindingPtr) {
unsafe {
if !(*bind).dupls.is_null() {
xml_schema_item_list_free((*bind).dupls);
}
drop_in_place(bind);
xml_free(bind as _);
}
}
#[doc(alias = "xmlSchemaIDCFreeIDCTable")]
pub(crate) unsafe fn xml_schema_idcfree_idc_table(mut bind: XmlSchemaPSVIIDCBindingPtr) {
unsafe {
let mut prev: XmlSchemaPSVIIDCBindingPtr;
while !bind.is_null() {
prev = bind;
bind = (*bind).next;
xml_schema_idc_free_binding(prev);
}
}
}
#[doc(alias = "xmlSchemaAugmentImportedIDC")]
unsafe fn xml_schema_augment_imported_idc(
imported: XmlSchemaImportPtr,
vctxt: XmlSchemaValidCtxtPtr,
) {
unsafe {
for &idc_def in (*(*imported).schema).idc_def.values() {
let aidc: XmlSchemaIDCAugPtr =
xml_malloc(size_of::<XmlSchemaIDCAug>()) as XmlSchemaIDCAugPtr;
if aidc.is_null() {
xml_schema_verr_memory(
vctxt,
"xmlSchemaAugmentIDC: allocating an augmented IDC definition",
None,
);
continue;
}
(*aidc).keyref_depth = -1;
(*aidc).def = idc_def;
(*aidc).next = null_mut();
if (*vctxt).aidcs.is_null() {
(*vctxt).aidcs = aidc;
} else {
(*aidc).next = (*vctxt).aidcs;
(*vctxt).aidcs = aidc;
}
if (*vctxt).has_keyrefs == 0
&& (*idc_def).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref
{
(*vctxt).has_keyrefs = 1;
}
}
}
}
unsafe fn xml_schema_create_pctxt_on_vctxt(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
if (*vctxt).pctxt.is_null() {
if !(*vctxt).schema.is_null() {
(*vctxt).pctxt =
xml_schema_new_parser_ctxt_use_dict(Some("*"), (*(*vctxt).schema).dict);
} else {
(*vctxt).pctxt = xml_schema_new_parser_ctxt("*");
}
if (*vctxt).pctxt.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaCreatePCtxtOnVCtxt",
"failed to create a temp. parser context"
);
return -1;
}
(*(*vctxt).pctxt).set_errors(
(*vctxt).error,
(*vctxt).warning,
(*vctxt).err_ctxt.clone(),
);
(*(*vctxt).pctxt).set_structured_errors((*vctxt).serror, (*vctxt).err_ctxt.clone());
}
0
}
}
unsafe fn xml_schema_pre_run(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
(*vctxt).err = 0;
(*vctxt).nberrors = 0;
(*vctxt).depth = -1;
(*vctxt).skip_depth = -1;
(*vctxt).has_keyrefs = 0;
(*vctxt).create_idcnode_tables = 0;
if (*vctxt).schema.is_null() {
(*vctxt).xsi_assemble = 1;
if (*vctxt).pctxt.is_null() && xml_schema_create_pctxt_on_vctxt(vctxt) == -1 {
return -1;
}
let pctxt: XmlSchemaParserCtxtPtr = (*vctxt).pctxt;
(*pctxt).xsi_assemble = 1;
(*vctxt).schema = (*pctxt).new_schema();
if (*vctxt).schema.is_null() {
return -1;
}
(*pctxt).constructor = xml_schema_construction_ctxt_create((*pctxt).dict);
if (*pctxt).constructor.is_null() {
return -1;
}
(*(*pctxt).constructor).main_schema = (*vctxt).schema;
(*pctxt).owns_constructor = 1;
}
for &imported in (*(*vctxt).schema).schemas_imports.values() {
if !imported.is_null() {
xml_schema_augment_imported_idc(imported, vctxt);
}
}
0
}
}
#[doc(alias = "xmlSchemaGetFreshElemInfo")]
unsafe fn xml_schema_get_fresh_elem_info(vctxt: XmlSchemaValidCtxtPtr) -> XmlSchemaNodeInfoPtr {
unsafe {
let mut info: XmlSchemaNodeInfoPtr = null_mut();
if (*vctxt).depth > (*vctxt).size_elem_infos {
VERROR_INT!(
vctxt,
"xmlSchemaGetFreshElemInfo",
"inconsistent depth encountered"
);
return null_mut();
}
if (*vctxt).elem_infos.is_null() {
(*vctxt).elem_infos =
xml_malloc(10 * size_of::<XmlSchemaNodeInfoPtr>()) as *mut XmlSchemaNodeInfoPtr;
if (*vctxt).elem_infos.is_null() {
xml_schema_verr_memory(vctxt, "allocating the element info array", None);
return null_mut();
}
memset(
(*vctxt).elem_infos as _,
0,
10 * size_of::<XmlSchemaNodeInfoPtr>(),
);
(*vctxt).size_elem_infos = 10;
} else if (*vctxt).size_elem_infos <= (*vctxt).depth {
let i: i32 = (*vctxt).size_elem_infos;
(*vctxt).size_elem_infos *= 2;
(*vctxt).elem_infos = xml_realloc(
(*vctxt).elem_infos as _,
(*vctxt).size_elem_infos as usize * size_of::<XmlSchemaNodeInfoPtr>(),
) as *mut XmlSchemaNodeInfoPtr;
if (*vctxt).elem_infos.is_null() {
xml_schema_verr_memory(vctxt, "re-allocating the element info array", None);
return null_mut();
}
for i in i..(*vctxt).size_elem_infos {
*(*vctxt).elem_infos.add(i as usize) = null_mut();
}
} else {
info = *(*vctxt).elem_infos.add((*vctxt).depth as usize);
}
if info.is_null() {
info = xml_malloc(size_of::<XmlSchemaNodeInfo>()) as XmlSchemaNodeInfoPtr;
if info.is_null() {
xml_schema_verr_memory(vctxt, "allocating an element info", None);
return null_mut();
}
*(*vctxt).elem_infos.add((*vctxt).depth as usize) = info;
} else if (*info).local_name.is_some() {
VERROR_INT!(
vctxt,
"xmlSchemaGetFreshElemInfo",
"elem info has not been cleared"
);
return null_mut();
}
std::ptr::write(&mut *info, XmlSchemaNodeInfo::default());
(*info).node_type = XmlElementType::XmlElementNode as i32;
(*info).depth = (*vctxt).depth;
info
}
}
unsafe fn xml_schema_validator_push_elem(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
(*vctxt).inode = xml_schema_get_fresh_elem_info(vctxt);
if (*vctxt).inode.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPushElem",
"calling xmlSchemaGetFreshElemInfo()"
);
return -1;
}
(*vctxt).nb_attr_infos = 0;
0
}
}
unsafe fn xml_schema_get_fresh_attr_info(vctxt: XmlSchemaValidCtxtPtr) -> XmlSchemaAttrInfoPtr {
unsafe {
let iattr: XmlSchemaAttrInfoPtr;
if (*vctxt).attr_infos.is_null() {
(*vctxt).attr_infos =
xml_malloc(size_of::<XmlSchemaAttrInfoPtr>()) as *mut XmlSchemaAttrInfoPtr;
(*vctxt).size_attr_infos = 1;
if (*vctxt).attr_infos.is_null() {
xml_schema_verr_memory(vctxt, "allocating attribute info list", None);
return null_mut();
}
} else if (*vctxt).size_attr_infos <= (*vctxt).nb_attr_infos {
(*vctxt).size_attr_infos += 1;
(*vctxt).attr_infos = xml_realloc(
(*vctxt).attr_infos as _,
(*vctxt).size_attr_infos as usize * size_of::<XmlSchemaAttrInfoPtr>(),
) as *mut XmlSchemaAttrInfoPtr;
if (*vctxt).attr_infos.is_null() {
xml_schema_verr_memory(vctxt, "re-allocating attribute info list", None);
return null_mut();
}
} else {
iattr = *(*vctxt).attr_infos.add((*vctxt).nb_attr_infos as usize);
(*vctxt).nb_attr_infos += 1;
if (*iattr).local_name.is_some() {
VERROR_INT!(vctxt, "xmlSchemaGetFreshAttrInfo", "attr info not cleared");
return null_mut();
}
(*iattr).node_type = XmlElementType::XmlAttributeNode as i32;
return iattr;
}
iattr = xml_malloc(size_of::<XmlSchemaAttrInfo>()) as XmlSchemaAttrInfoPtr;
if iattr.is_null() {
xml_schema_verr_memory(vctxt, "creating new attribute info", None);
return null_mut();
}
std::ptr::write(&mut *iattr, XmlSchemaAttrInfo::default());
(*iattr).node_type = XmlElementType::XmlAttributeNode as i32;
*(*vctxt).attr_infos.add((*vctxt).nb_attr_infos as usize) = iattr;
(*vctxt).nb_attr_infos += 1;
iattr
}
}
#[allow(clippy::too_many_arguments)]
unsafe fn xml_schema_validator_push_attribute(
vctxt: XmlSchemaValidCtxtPtr,
attr_node: Option<XmlAttrPtr>,
node_line: i32,
local_name: &str,
ns_name: Option<&str>,
owned_names: i32,
value: *mut XmlChar,
owned_value: i32,
) -> i32 {
unsafe {
let attr: XmlSchemaAttrInfoPtr = xml_schema_get_fresh_attr_info(vctxt);
if attr.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaPushAttribute",
"calling xmlSchemaGetFreshAttrInfo()"
);
return -1;
}
(*attr).node = attr_node;
(*attr).node_line = node_line;
(*attr).state = XML_SCHEMAS_ATTR_UNKNOWN;
(*attr).local_name = Some(local_name.to_owned());
(*attr).ns_name = ns_name.map(|ns_name| ns_name.to_owned());
if owned_names != 0 {
(*attr).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
}
if let Some(ns_name) = ns_name {
if local_name == "nil" {
if ns_name == XML_SCHEMA_INSTANCE_NS.to_str().unwrap() {
(*attr).meta_type = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
}
} else if local_name == "type" {
if ns_name == XML_SCHEMA_INSTANCE_NS.to_str().unwrap() {
(*attr).meta_type = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
}
} else if local_name == "schemaLocation" {
if ns_name == XML_SCHEMA_INSTANCE_NS.to_str().unwrap() {
(*attr).meta_type = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
}
} else if local_name == "noNamespaceSchemaLocation" {
if ns_name == XML_SCHEMA_INSTANCE_NS.to_str().unwrap() {
(*attr).meta_type = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
}
} else if ns_name == XML_NAMESPACE_NS.to_str().unwrap() {
(*attr).meta_type = XML_SCHEMA_ATTR_INFO_META_XMLNS;
}
}
(*attr).value = value;
if owned_value != 0 {
(*attr).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
}
if (*attr).meta_type != 0 {
(*attr).state = XML_SCHEMAS_ATTR_META;
}
0
}
}
unsafe fn xml_schema_get_meta_attr_info(
vctxt: XmlSchemaValidCtxtPtr,
meta_type: i32,
) -> XmlSchemaAttrInfoPtr {
unsafe {
if (*vctxt).nb_attr_infos == 0 {
return null_mut();
}
{
let mut iattr: XmlSchemaAttrInfoPtr;
for i in 0..(*vctxt).nb_attr_infos {
iattr = *(*vctxt).attr_infos.add(i as usize) as _;
if (*iattr).meta_type == meta_type {
return iattr;
}
}
}
null_mut()
}
}
#[doc(alias = "xmlSchemaAssembleByLocation")]
unsafe fn xml_schema_assemble_by_location(
vctxt: XmlSchemaValidCtxtPtr,
schema: XmlSchemaPtr,
node: Option<XmlGenericNodePtr>,
ns_name: *const XmlChar,
mut location: *const XmlChar,
) -> i32 {
unsafe {
let mut ret: i32;
let mut bucket: XmlSchemaBucketPtr = null_mut();
if vctxt.is_null() || schema.is_null() {
return -1;
}
if (*vctxt).pctxt.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaAssembleByLocation",
"no parser context available"
);
return -1;
}
let pctxt: XmlSchemaParserCtxtPtr = (*vctxt).pctxt;
if (*pctxt).constructor.is_null() {
PERROR_INT!(pctxt, "xmlSchemaAssembleByLocation", "no constructor");
return -1;
}
location = xml_schema_build_absolute_uri((*pctxt).dict, location, node);
ret = xml_schema_add_schema_doc(
pctxt,
XML_SCHEMA_SCHEMA_IMPORT,
location,
None,
null_mut(),
0,
node,
null_mut(),
ns_name,
&raw mut bucket,
);
if ret != 0 {
return ret;
}
if bucket.is_null() {
let location = CStr::from_ptr(location as *const i8).to_string_lossy();
xml_schema_custom_warning(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavMisc,
node,
None,
format!(
"The document at location '{}' could not be acquired",
location
)
.as_str(),
Some(&location),
None,
None,
);
return ret;
}
if !bucket.is_null() && (*WXS_CONSTRUCTOR!(pctxt)).bucket.is_null() {
(*WXS_CONSTRUCTOR!(pctxt)).bucket = bucket;
}
if bucket.is_null() || !can_parse_schema(bucket) {
return 0;
}
(*pctxt).nberrors = 0;
(*pctxt).err = 0;
(*pctxt).doc = (*bucket).doc;
ret = (*pctxt).parse_new_doc_with_context(schema, bucket);
if ret == -1 {
(*pctxt).doc = None;
return -1;
}
if ret == 0 && (*pctxt).nberrors != 0 {
ret = (*pctxt).err;
}
if (*pctxt).nberrors == 0 {
xml_schema_fixup_components(pctxt, bucket);
ret = (*pctxt).err;
if ret != 0 && (*vctxt).err == 0 {
(*vctxt).err = ret;
}
(*vctxt).nberrors += (*pctxt).nberrors;
} else {
(*vctxt).nberrors += (*pctxt).nberrors;
}
(*pctxt).doc = None;
ret
}
}
#[doc(alias = "xmlSchemaAssembleByXSI")]
unsafe fn xml_schema_assemble_by_xsi(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut cur: *const XmlChar;
let mut end: *const XmlChar;
let mut nsname: *const XmlChar = null();
let mut location: *const XmlChar;
let mut ret: i32 = 0;
let mut iattr: XmlSchemaAttrInfoPtr;
iattr = xml_schema_get_meta_attr_info(vctxt, XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
if iattr.is_null() {
iattr = xml_schema_get_meta_attr_info(
vctxt,
XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC,
);
}
if iattr.is_null() {
return 0;
}
cur = (*iattr).value;
loop {
if (*iattr).meta_type == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC {
while (*cur).is_xml_blank_char() {
cur = cur.add(1);
}
end = cur;
while *end != 0 && !(*end).is_xml_blank_char() {
end = end.add(1);
}
if end == cur {
break;
}
nsname = xml_dict_lookup((*(*vctxt).schema).dict, cur, end.offset_from(cur) as _);
cur = end;
}
while (*cur).is_xml_blank_char() {
cur = cur.add(1);
}
end = cur;
while *end != 0 && !(*end).is_xml_blank_char() {
end = end.add(1);
}
if end == cur {
if (*iattr).meta_type == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC {
xml_schema_custom_warning(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavMisc,
(*iattr).node.map(|attr| attr.into()),
None,
"The value must consist of tuples: the target namespace name and the document's URI",
None,
None,
None,
);
}
break;
}
location = xml_dict_lookup((*(*vctxt).schema).dict, cur, end.offset_from(cur) as _);
cur = end;
ret = xml_schema_assemble_by_location(
vctxt,
(*vctxt).schema,
(*iattr).node.map(|attr| attr.into()),
nsname,
location,
);
if ret == -1 {
VERROR_INT!(vctxt, "xmlSchemaAssembleByXSI", "assembling schemata");
return -1;
}
if *cur == 0 {
break;
}
}
ret
}
}
unsafe fn xml_schema_vexpand_qname(
vctxt: XmlSchemaValidCtxtPtr,
value: *const XmlChar,
ns_name: *mut *const XmlChar,
local_name: *mut *const XmlChar,
) -> i32 {
unsafe {
if ns_name.is_null() || local_name.is_null() {
return -1;
}
*ns_name = null_mut();
*local_name = null_mut();
if validate_qname::<true>(
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
)
.is_err()
{
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
xml_schema_simple_type_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1,
None,
&value,
&*xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasQName),
1,
);
return 1;
}
let value = CStr::from_ptr(value as *const i8).to_string_lossy();
let mut prefix = None;
if let Some((pre, local)) = split_qname2(&value) {
prefix = Some(pre);
*local_name = xml_dict_lookup((*vctxt).dict, local.as_ptr(), local.len() as i32);
} else {
*local_name = xml_dict_lookup((*vctxt).dict, value.as_ptr(), value.len() as i32);
}
if let Some(href) = (*vctxt).lookup_namespace(prefix) {
*ns_name = xml_dict_lookup((*vctxt).dict, href.as_ptr(), href.len() as i32);
}
if prefix.is_some() {
if (*ns_name).is_null() {
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcDatatypeValid1_2_1,
None,
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasQName)
as XmlSchemaBasicItemPtr,
format!(
"The QName value '{}' has no corresponding namespace declaration in scope",
value
)
.as_str(),
Some(&value),
None,
);
return 2;
}
}
0
}
}
unsafe fn xml_schema_process_xsi_type(
vctxt: XmlSchemaValidCtxtPtr,
iattr: XmlSchemaAttrInfoPtr,
local_type: *mut XmlSchemaTypePtr,
elem_decl: XmlSchemaElementPtr,
) -> i32 {
unsafe {
let mut ret: i32;
if local_type.is_null() {
return -1;
}
*local_type = null_mut();
if iattr.is_null() {
return 0;
} else {
let mut ns_name: *const XmlChar = null();
let mut local: *const XmlChar = null();
ACTIVATE_ATTRIBUTE!(vctxt, iattr);
ret = xml_schema_vexpand_qname(vctxt, (*iattr).value, &raw mut ns_name, &raw mut local);
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElementByDeclaration",
"calling xmlSchemaQNameExpand() to validate the attribute 'xsi:type'"
);
ACTIVATE_ELEM!(vctxt);
return -1;
}
ACTIVATE_ELEM!(vctxt);
return ret;
}
*local_type = (*(*vctxt).schema).get_type(
CStr::from_ptr(local as *const i8)
.to_string_lossy()
.as_ref(),
(!ns_name.is_null())
.then(|| CStr::from_ptr(ns_name as *const i8).to_string_lossy())
.as_deref(),
);
if (*local_type).is_null() {
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr(ns_name as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr(local as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcElt4_2,
None,
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasQName) as XmlSchemaBasicItemPtr,
format!("The QName value '{qname}' of the xsi:type attribute does not resolve to a type definition").as_str(),
Some(&qname),
None
);
ret = (*vctxt).err;
ACTIVATE_ELEM!(vctxt);
return ret;
}
if !elem_decl.is_null() {
let mut set: i32 = 0;
if (*elem_decl).flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION != 0
|| (*(*elem_decl).subtypes).flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION != 0
{
set |= SUBSET_EXTENSION;
}
if (*elem_decl).flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION != 0
|| (*(*elem_decl).subtypes).flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION != 0
{
set |= SUBSET_RESTRICTION;
}
if xml_schema_check_cos_derived_ok(
vctxt as XmlSchemaAbstractCtxtPtr,
*local_type,
(*elem_decl).subtypes,
set,
) != 0
{
let qname = xml_schema_format_qname(
Some(
CStr::from_ptr((*(*local_type)).target_namespace as *const i8)
.to_string_lossy()
.as_ref(),
),
Some(
CStr::from_ptr((*(*local_type)).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcElt4_3,
None,
null_mut(),
format!("The type definition '{qname}', specified by xsi:type, is blocked or not validly derived from the type definition of the element declaration").as_str(),
Some(&qname),
None
);
ret = (*vctxt).err;
*local_type = null_mut();
}
}
}
ACTIVATE_ELEM!(vctxt);
ret
}
}
fn xml_schema_vcontent_model_callback(
_exec: XmlRegExecCtxtPtr,
_name: &str,
transdata: *mut c_void,
inputdata: *mut c_void,
) {
unsafe {
let item: XmlSchemaElementPtr = transdata as XmlSchemaElementPtr;
let inode: XmlSchemaNodeInfoPtr = inputdata as XmlSchemaNodeInfoPtr;
(*inode).decl = item;
}
}
unsafe fn xml_schema_validate_child_elem(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
if (*vctxt).depth <= 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateChildElem",
"not intended for the validation root"
);
return -1;
}
let pielem: XmlSchemaNodeInfoPtr = *(*vctxt).elem_infos.add((*vctxt).depth as usize - 1);
if (*pielem).flags & XML_SCHEMA_ELEM_INFO_EMPTY != 0 {
(*pielem).flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
}
'unexpected_elem: {
if INODE_NILLED!(pielem) {
ACTIVATE_PARENT_ELEM!(vctxt);
ret = XmlParserErrors::XmlSchemavCvcElt3_2_1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"Neither character nor element content is allowed, because the element was 'nilled'"
);
ACTIVATE_ELEM!(vctxt);
break 'unexpected_elem;
}
let ptype: XmlSchemaTypePtr = (*pielem).type_def;
if (*ptype).built_in_type == XmlSchemaValType::XmlSchemasAnytype {
(*(*vctxt).inode).decl = (*(*vctxt).schema).get_elem(
(*(*vctxt).inode).local_name.as_deref().unwrap(),
(*(*vctxt).inode).ns_name.as_deref(),
);
if (*(*vctxt).inode).decl.is_null() {
let iattr: XmlSchemaAttrInfoPtr =
xml_schema_get_meta_attr_info(vctxt, XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
if !iattr.is_null() {
ret = xml_schema_process_xsi_type(
vctxt,
iattr,
&raw mut (*(*vctxt).inode).type_def,
null_mut(),
);
if ret != 0 {
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateChildElem",
"calling xmlSchemaProcessXSIType() to process the attribute 'xsi:nil'"
);
return -1;
}
return ret;
}
} else {
(*(*vctxt).inode).type_def =
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasAnytype);
}
}
return 0;
}
match (*ptype).content_type {
XmlSchemaContentType::XmlSchemaContentEmpty => {
ACTIVATE_PARENT_ELEM!(vctxt);
ret = XmlParserErrors::XmlSchemavCvcComplexType2_1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"Element content is not allowed, because the content type is empty"
);
ACTIVATE_ELEM!(vctxt);
break 'unexpected_elem;
}
XmlSchemaContentType::XmlSchemaContentMixed
| XmlSchemaContentType::XmlSchemaContentElements => {
let mut values = [const { Cow::Borrowed("") }; 10];
let mut terminal: i32 = 0;
let Some(cont_model) = (*ptype).cont_model.clone() else {
VERROR_INT!(
vctxt,
"xmlSchemaValidateChildElem",
"type has elem content but no content model"
);
return -1;
};
if (*pielem).flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT != 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateChildElem",
"validating elem, but elem content is already invalid"
);
return -1;
}
let regex_ctxt = (*pielem).regex_ctxt.get_or_insert_with(|| {
Box::new(XmlRegExecCtxt::new(
cont_model,
Some(xml_schema_vcontent_model_callback),
vctxt as _,
))
});
ret = regex_ctxt.push_string2(
(*(*vctxt).inode).local_name.as_deref().unwrap(),
(*(*vctxt).inode).ns_name.as_deref(),
(*vctxt).inode as _,
);
if (*vctxt).err == XmlParserErrors::XmlSchemavInternal as i32 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateChildElem",
"calling xmlRegExecPushString2()"
);
return -1;
}
if ret < 0 {
if let Some((nbval, nbneg, values)) =
regex_ctxt.err_info(None, &mut values, &mut terminal)
{
xml_schema_complex_type_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavElementContent,
None,
None,
"This element is not expected",
nbval,
nbneg,
values,
);
}
ret = (*vctxt).err;
break 'unexpected_elem;
} else {
ret = 0;
}
}
XmlSchemaContentType::XmlSchemaContentSimple
| XmlSchemaContentType::XmlSchemaContentBasic => {
ACTIVATE_PARENT_ELEM!(vctxt);
if wxs_is_complex(ptype) {
ret = XmlParserErrors::XmlSchemavCvcComplexType2_2 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"Element content is not allowed, because the content type is a simple type definition"
);
} else {
ret = XmlParserErrors::XmlSchemavCvcType3_1_2 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"Element content is not allowed, because the type definition is simple"
);
}
ACTIVATE_ELEM!(vctxt);
ret = (*vctxt).err;
break 'unexpected_elem;
}
_ => {}
}
return ret;
}
(*vctxt).skip_depth = (*vctxt).depth;
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
(*pielem).flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
ret
}
}
unsafe fn xml_schema_validate_elem_wildcard(vctxt: XmlSchemaValidCtxtPtr, skip: *mut i32) -> i32 {
unsafe {
let wild: XmlSchemaWildcardPtr = (*(*vctxt).inode).decl as XmlSchemaWildcardPtr;
if skip.is_null() || wild.is_null() || (*wild).typ != XmlSchemaTypeType::XmlSchemaTypeAny {
VERROR_INT!(vctxt, "xmlSchemaValidateElemWildcard", "bad arguments");
return -1;
}
*skip = 0;
if (*wild).process_contents == XML_SCHEMAS_ANY_SKIP {
*skip = 1;
return 0;
}
{
let decl: XmlSchemaElementPtr = (*(*vctxt).schema).get_elem(
(*(*vctxt).inode).local_name.as_deref().unwrap(),
(*(*vctxt).inode).ns_name.as_deref(),
);
if !decl.is_null() {
(*(*vctxt).inode).decl = decl;
return 0;
}
}
if (*wild).process_contents == XML_SCHEMAS_ANY_STRICT {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt1,
null_mut(),
"No matching global element declaration available, but demanded by the strict wildcard"
);
return (*vctxt).err;
}
if (*vctxt).nb_attr_infos != 0 {
let iattr: XmlSchemaAttrInfoPtr =
xml_schema_get_meta_attr_info(vctxt, XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
if !iattr.is_null() {
if xml_schema_process_xsi_type(
vctxt,
iattr,
&raw mut (*(*vctxt).inode).type_def,
null_mut(),
) == -1
{
VERROR_INT!(
vctxt,
"xmlSchemaValidateElemWildcard",
"calling xmlSchemaProcessXSIType() to process the attribute 'xsi:nil'"
);
return -1;
}
return 0;
}
}
(*(*vctxt).inode).type_def =
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasAnytype);
0
}
}
#[doc(alias = "xmlSchemaIDCAddStateObject")]
unsafe fn xml_schema_idc_add_state_object(
vctxt: XmlSchemaValidCtxtPtr,
matcher: XmlSchemaIDCMatcherPtr,
sel: XmlSchemaIdcselectPtr,
typ: i32,
) -> i32 {
unsafe {
let sto: XmlSchemaIDCStateObjPtr;
if !(*vctxt).xpath_state_pool.is_null() {
sto = (*vctxt).xpath_state_pool;
(*vctxt).xpath_state_pool = (*sto).next;
(*sto).next = null_mut();
} else {
sto = xml_malloc(size_of::<XmlSchemaIDCStateObj>()) as XmlSchemaIDCStateObjPtr;
if sto.is_null() {
xml_schema_verr_memory(null_mut(), "allocating an IDC state object", None);
return -1;
}
memset(sto as _, 0, size_of::<XmlSchemaIDCStateObj>());
}
if !(*vctxt).xpath_states.is_null() {
(*sto).next = (*vctxt).xpath_states;
}
(*vctxt).xpath_states = sto;
(*sto).xpath_ctxt.take();
(*sto).xpath_ctxt = (*sel).xpath_comp.as_ref().unwrap().get_stream_context();
if (*sto).xpath_ctxt.is_none() {
VERROR_INT!(
vctxt,
"xmlSchemaIDCAddStateObject",
"failed to create an XPath validation context"
);
return -1;
}
(*sto).typ = typ;
(*sto).depth = (*vctxt).depth;
(*sto).matcher = matcher;
(*sto).sel = sel;
(*sto).nb_history = 0;
0
}
}
#[doc(alias = "xmlSchemaIDCRegisterMatchers")]
unsafe fn xml_schema_idc_register_matchers(
vctxt: XmlSchemaValidCtxtPtr,
elem_decl: XmlSchemaElementPtr,
) -> i32 {
unsafe {
let mut matcher: XmlSchemaIDCMatcherPtr;
let mut last: XmlSchemaIDCMatcherPtr = null_mut();
let mut idc: XmlSchemaIDCPtr;
let mut ref_idc: XmlSchemaIDCPtr;
let mut aidc: XmlSchemaIDCAugPtr;
idc = (*elem_decl).idcs as XmlSchemaIDCPtr;
if idc.is_null() {
return 0;
}
if !(*(*vctxt).inode).idc_matchers.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaIDCRegisterMatchers",
"The chain of IDC matchers is expected to be empty"
);
return -1;
}
while {
if (*idc).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
ref_idc = (*(*idc).refe).item as XmlSchemaIDCPtr;
if !ref_idc.is_null() {
(*(*vctxt).inode).has_keyrefs = 1;
aidc = (*vctxt).aidcs;
while !aidc.is_null() {
if (*aidc).def == ref_idc {
break;
}
aidc = (*aidc).next;
}
if aidc.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaIDCRegisterMatchers",
"Could not find an augmented IDC item for an IDC definition"
);
return -1;
}
if (*aidc).keyref_depth == -1 || (*vctxt).depth < (*aidc).keyref_depth {
(*aidc).keyref_depth = (*vctxt).depth;
}
}
}
aidc = (*vctxt).aidcs;
while !aidc.is_null() {
if (*aidc).def == idc {
break;
}
aidc = (*aidc).next;
}
if aidc.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaIDCRegisterMatchers",
"Could not find an augmented IDC item for an IDC definition"
);
return -1;
}
if !(*vctxt).idc_matcher_cache.is_null() {
matcher = (*vctxt).idc_matcher_cache;
(*vctxt).idc_matcher_cache = (*matcher).next_cached;
(*matcher).next_cached = null_mut();
} else {
matcher = xml_malloc(size_of::<XmlSchemaIDCMatcher>()) as XmlSchemaIDCMatcherPtr;
if matcher.is_null() {
xml_schema_verr_memory(vctxt, "allocating an IDC matcher", None);
return -1;
}
memset(matcher as _, 0, size_of::<XmlSchemaIDCMatcher>());
}
if last.is_null() {
(*(*vctxt).inode).idc_matchers = matcher;
} else {
(*last).next = matcher;
}
last = matcher;
(*matcher).typ = IDC_MATCHER;
(*matcher).depth = (*vctxt).depth;
(*matcher).aidc = aidc;
(*matcher).idc_type = (*(*aidc).def).typ as _;
if xml_schema_idc_add_state_object(
vctxt,
matcher,
(*idc).selector,
XPATH_STATE_OBJ_TYPE_IDC_SELECTOR,
) == -1
{
return -1;
}
idc = (*idc).next;
!idc.is_null()
} {}
0
}
}
unsafe fn xml_schema_validate_elem_decl(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let elem_decl: XmlSchemaElementPtr = (*(*vctxt).inode).decl;
let mut actual_type: XmlSchemaTypePtr;
if elem_decl.is_null() {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt1,
null_mut(),
"No matching declaration available"
);
return (*vctxt).err;
}
actual_type = (*elem_decl).subtypes;
if (*elem_decl).flags & XML_SCHEMAS_ELEM_ABSTRACT != 0 {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt2,
null_mut(),
"The element declaration is abstract"
);
return (*vctxt).err;
}
if actual_type.is_null() {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcType1,
null_mut(),
"The type definition is absent"
);
return XmlParserErrors::XmlSchemavCvcType1 as i32;
}
if (*vctxt).nb_attr_infos != 0 {
let mut ret: i32;
let mut iattr: XmlSchemaAttrInfoPtr;
iattr = xml_schema_get_meta_attr_info(vctxt, XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
if !iattr.is_null() {
ACTIVATE_ATTRIBUTE!(vctxt, iattr);
ret = xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
None,
xml_schema_get_built_in_type(XmlSchemaValType::XmlSchemasBoolean),
(*iattr).value,
&raw mut (*iattr).val,
1,
0,
0,
);
ACTIVATE_ELEM!(vctxt);
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElemDecl",
"calling xmlSchemaVCheckCVCSimpleType() to validate the attribute 'xsi:nil'"
);
return -1;
}
if ret == 0 {
if (*elem_decl).flags & XML_SCHEMAS_ELEM_NILLABLE == 0 {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt3_1,
null_mut(),
"The element is not 'nillable'"
);
} else if xml_schema_value_get_as_boolean((*iattr).val) != 0 {
if (*elem_decl).flags & XML_SCHEMAS_ELEM_FIXED != 0
&& !(*elem_decl).value.is_null()
{
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt3_2_2,
null_mut(),
"The element cannot be 'nilled' because there is a fixed value constraint defined for it"
);
} else {
(*(*vctxt).inode).flags |= XML_SCHEMA_ELEM_INFO_NILLED;
}
}
}
}
iattr = xml_schema_get_meta_attr_info(vctxt, XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
if !iattr.is_null() {
let mut local_type: XmlSchemaTypePtr = null_mut();
ret = xml_schema_process_xsi_type(vctxt, iattr, &raw mut local_type, elem_decl);
if ret != 0 && ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElemDecl",
"calling xmlSchemaProcessXSIType() to process the attribute 'xsi:type'"
);
return -1;
}
if !local_type.is_null() {
(*(*vctxt).inode).flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
actual_type = local_type;
}
}
}
if !(*elem_decl).idcs.is_null() && xml_schema_idc_register_matchers(vctxt, elem_decl) == -1
{
return -1;
}
if actual_type.is_null() {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcType1,
null_mut(),
"The type definition is absent"
);
return XmlParserErrors::XmlSchemavCvcType1 as i32;
}
(*(*vctxt).inode).type_def = actual_type;
0
}
}
#[doc(alias = "xmlSchemaXPathEvaluate")]
unsafe fn xml_schema_xpath_evaluate(
vctxt: XmlSchemaValidCtxtPtr,
node_type: XmlElementType,
) -> i32 {
unsafe {
let mut sto: XmlSchemaIDCStateObjPtr;
let mut head: XmlSchemaIDCStateObjPtr = null_mut();
let mut res: i32;
let mut resolved: i32 = 0;
let mut depth: i32 = (*vctxt).depth;
if (*vctxt).xpath_states.is_null() {
return 0;
}
if node_type == XmlElementType::XmlAttributeNode {
depth += 1;
}
let first: XmlSchemaIDCStateObjPtr = (*vctxt).xpath_states;
sto = first;
while sto != head {
if node_type == XmlElementType::XmlElementNode {
res = (*sto).xpath_ctxt.as_mut().unwrap().push(
(*(*vctxt).inode).local_name.as_deref(),
(*(*vctxt).inode).ns_name.as_deref(),
);
} else {
res = (*sto).xpath_ctxt.as_mut().unwrap().push_attr(
(*(*vctxt).inode).local_name.as_deref(),
(*(*vctxt).inode).ns_name.as_deref(),
);
}
if res == -1 {
VERROR_INT!(vctxt, "xmlSchemaXPathEvaluate", "calling xmlStreamPush()");
return -1;
}
if res == 0 {
} else {
if (*sto).history.is_null() {
(*sto).history = xml_malloc(5 * size_of::<i32>()) as *mut i32;
if (*sto).history.is_null() {
xml_schema_verr_memory(
null_mut(),
"allocating the state object history",
None,
);
return -1;
}
(*sto).size_history = 5;
} else if (*sto).size_history <= (*sto).nb_history {
(*sto).size_history *= 2;
(*sto).history = xml_realloc(
(*sto).history as _,
(*sto).size_history as usize * size_of::<i32>(),
) as *mut i32;
if (*sto).history.is_null() {
xml_schema_verr_memory(
null_mut(),
"re-allocating the state object history",
None,
);
return -1;
}
}
*(*sto).history.add((*sto).nb_history as usize) = depth;
(*sto).nb_history += 1;
if (*sto).typ == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR {
let mut sel: XmlSchemaIdcselectPtr;
sel = (*(*(*(*sto).matcher).aidc).def).fields;
while !sel.is_null() {
if xml_schema_idc_add_state_object(
vctxt,
(*sto).matcher,
sel,
XPATH_STATE_OBJ_TYPE_IDC_FIELD,
) == -1
{
return -1;
}
sel = (*sel).next;
}
} else if (*sto).typ == XPATH_STATE_OBJ_TYPE_IDC_FIELD {
if resolved == 0
&& (*(*vctxt).inode).flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED == 0
{
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
}
resolved += 1;
}
}
if (*sto).next.is_null() {
head = first;
sto = (*vctxt).xpath_states;
} else {
sto = (*sto).next;
}
}
resolved
}
}
unsafe fn xml_schema_get_idc_designation(idc: XmlSchemaIDCPtr) -> String {
unsafe { xml_schema_get_component_designation(idc as _) }
}
#[doc(alias = "xmlSchemaIDCStoreKey")]
unsafe fn xml_schema_idc_store_key(
vctxt: XmlSchemaValidCtxtPtr,
key: XmlSchemaPSVIIDCKeyPtr,
) -> i32 {
unsafe {
if (*vctxt).idc_keys.is_null() {
(*vctxt).idc_keys =
xml_malloc(40 * size_of::<XmlSchemaPSVIIDCKeyPtr>()) as *mut XmlSchemaPSVIIDCKeyPtr;
if (*vctxt).idc_keys.is_null() {
xml_schema_verr_memory(vctxt, "allocating the IDC key storage list", None);
return -1;
}
(*vctxt).size_idc_keys = 40;
} else if (*vctxt).size_idc_keys <= (*vctxt).nb_idc_keys {
(*vctxt).size_idc_keys *= 2;
(*vctxt).idc_keys = xml_realloc(
(*vctxt).idc_keys as _,
(*vctxt).size_idc_keys as usize * size_of::<XmlSchemaPSVIIDCKeyPtr>(),
) as *mut XmlSchemaPSVIIDCKeyPtr;
if (*vctxt).idc_keys.is_null() {
xml_schema_verr_memory(vctxt, "re-allocating the IDC key storage list", None);
return -1;
}
}
*(*vctxt).idc_keys.add((*vctxt).nb_idc_keys as usize) = key;
(*vctxt).nb_idc_keys += 1;
0
}
}
unsafe fn xml_schema_idc_acquire_target_list(
_vctxt: XmlSchemaValidCtxtPtr,
matcher: XmlSchemaIDCMatcherPtr,
) -> XmlSchemaItemListPtr<*mut c_void> {
unsafe {
if (*matcher).targets.is_null() {
(*matcher).targets = xml_schema_item_list_create::<*mut c_void>();
}
(*matcher).targets
}
}
unsafe fn xml_schema_get_canon_value_hash(
val: XmlSchemaValPtr,
ret_value: *mut *mut XmlChar,
) -> i32 {
unsafe {
xml_schema_get_canon_value_whtsp_ext_1(
val,
XmlSchemaWhitespaceValueType::XmlSchemaWhitespaceCollapse,
ret_value,
1,
)
}
}
unsafe fn xml_schema_format_idc_key_sequence_1(
vctxt: XmlSchemaValidCtxtPtr,
seq: *mut XmlSchemaPSVIIDCKeyPtr,
count: i32,
for_hash: i32,
) -> String {
unsafe {
let mut res: i32;
let mut value: *mut XmlChar = null_mut();
let mut buf = "[".to_owned();
for i in 0..count {
buf.push('\'');
if for_hash == 0 {
res = xml_schema_get_canon_value_whtsp_ext(
(*(*seq.add(i as usize))).val,
(*(*(*seq.add(i as usize))).typ)
.white_space_facet_value()
.unwrap(),
&raw mut value,
);
} else {
res =
xml_schema_get_canon_value_hash((*(*seq.add(i as usize))).val, &raw mut value);
}
if res == 0 {
buf.push_str(
CStr::from_ptr(value as *const i8)
.to_string_lossy()
.as_ref(),
);
} else {
VERROR_INT!(
vctxt,
"xmlSchemaFormatIDCKeySequence",
"failed to compute a canonical value"
);
buf.push_str("???");
}
if i < count - 1 {
buf.push_str("', ");
} else {
buf.push('\'');
}
if !value.is_null() {
xml_free(value as _);
value = null_mut();
}
}
buf.push(']');
buf
}
}
unsafe fn xml_schema_hash_key_sequence(
vctxt: XmlSchemaValidCtxtPtr,
seq: *mut XmlSchemaPSVIIDCKeyPtr,
count: i32,
) -> String {
unsafe { xml_schema_format_idc_key_sequence_1(vctxt, seq, count, 1) }
}
unsafe fn xml_schema_format_idc_key_sequence(
vctxt: XmlSchemaValidCtxtPtr,
seq: *mut XmlSchemaPSVIIDCKeyPtr,
count: i32,
) -> String {
unsafe { xml_schema_format_idc_key_sequence_1(vctxt, seq, count, 0) }
}
#[doc(alias = "xmlSchemaIDCStoreNodeTableItem")]
unsafe fn xml_schema_idc_store_node_table_item(
vctxt: XmlSchemaValidCtxtPtr,
item: XmlSchemaPSVIIDCNodePtr,
) -> i32 {
unsafe {
if (*vctxt).idc_nodes.is_null() {
(*vctxt).idc_nodes = xml_malloc(20 * size_of::<XmlSchemaPSVIIDCNodePtr>())
as *mut XmlSchemaPSVIIDCNodePtr;
if (*vctxt).idc_nodes.is_null() {
xml_schema_verr_memory(vctxt, "allocating the IDC node table item list", None);
return -1;
}
(*vctxt).size_idc_nodes = 20;
} else if (*vctxt).size_idc_nodes <= (*vctxt).nb_idc_nodes {
(*vctxt).size_idc_nodes *= 2;
(*vctxt).idc_nodes = xml_realloc(
(*vctxt).idc_nodes as _,
(*vctxt).size_idc_nodes as usize * size_of::<XmlSchemaPSVIIDCNodePtr>(),
) as *mut XmlSchemaPSVIIDCNodePtr;
if (*vctxt).idc_nodes.is_null() {
xml_schema_verr_memory(vctxt, "re-allocating the IDC node table item list", None);
return -1;
}
}
*(*vctxt).idc_nodes.add((*vctxt).nb_idc_nodes as usize) = item;
(*vctxt).nb_idc_nodes += 1;
0
}
}
unsafe fn xml_schema_vadd_node_qname(
vctxt: XmlSchemaValidCtxtPtr,
lname: &str,
nsname: Option<&str>,
) -> i32 {
unsafe {
let lname = xml_dict_lookup((*vctxt).dict, lname.as_ptr(), lname.len() as i32);
if lname.is_null() {
return -1;
}
let nsname = if let Some(nsname) = nsname {
xml_dict_lookup((*vctxt).dict, nsname.as_ptr(), nsname.len() as i32)
} else {
null_mut()
};
for i in (0..(*(*vctxt).node_qnames).items.len()).step_by(2) {
if (*(*vctxt).node_qnames).items[i] == lname as _
&& (*(*vctxt).node_qnames).items[i] == nsname as _
{
return i as i32;
}
}
let i: i32 = (*(*vctxt).node_qnames).items.len() as i32;
(*(*vctxt).node_qnames).push(lname as _);
(*(*vctxt).node_qnames).push(nsname as _);
i
}
}
#[doc(alias = "xmlSchemaXPathProcessHistory")]
unsafe fn xml_schema_xpath_process_history(vctxt: XmlSchemaValidCtxtPtr, depth: i32) -> i32 {
unsafe {
let mut sto: XmlSchemaIDCStateObjPtr;
let mut nextsto: XmlSchemaIDCStateObjPtr;
let mut res: i32;
let mut match_depth: i32;
let mut key: XmlSchemaPSVIIDCKeyPtr = null_mut();
let typ: XmlSchemaTypePtr = (*(*vctxt).inode).type_def;
let mut simple_type: XmlSchemaTypePtr;
if (*vctxt).xpath_states.is_null() {
return 0;
}
sto = (*vctxt).xpath_states;
'main: while !sto.is_null() {
res = (*sto).xpath_ctxt.as_mut().unwrap().pop();
if res == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaXPathProcessHistory",
"calling xmlStreamPop()"
);
return -1;
}
'deregister_check: {
if (*sto).nb_history == 0 {
break 'deregister_check;
}
match_depth = *(*sto).history.add((*sto).nb_history as usize - 1);
if match_depth != depth {
sto = (*sto).next;
continue 'main;
}
if (*sto).typ == XPATH_STATE_OBJ_TYPE_IDC_FIELD {
if wxs_is_complex(typ) {
if WXS_HAS_SIMPLE_CONTENT!(typ) {
simple_type = (*typ).content_type_def;
if simple_type.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaXPathProcessHistory",
"field resolves to a CT with simple content but the CT is missing the ST definition"
);
return -1;
}
} else {
simple_type = null_mut();
}
} else {
simple_type = typ;
}
if simple_type.is_null() {
let xpath =
CStr::from_ptr((*(*sto).sel).xpath as *const i8).to_string_lossy();
let desig = xml_schema_get_idc_designation((*(*(*sto).matcher).aidc).def);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcIdc,
None,
(*(*(*sto).matcher).aidc).def as XmlSchemaBasicItemPtr,
format!("The XPath '{xpath}' of a field of {desig} does evaluate to a node of non-simple type").as_str(),
Some(&xpath),
Some(&desig)
);
(*sto).nb_history -= 1;
break 'deregister_check;
}
if key.is_null() && (*(*vctxt).inode).val.is_null() {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcIdc,
(*(*(*sto).matcher).aidc).def as XmlSchemaBasicItemPtr,
"Warning: No precomputed value available, the value was either invalid or something strange happened"
);
(*sto).nb_history -= 1;
break 'deregister_check;
} else {
let matcher: XmlSchemaIDCMatcherPtr = (*sto).matcher;
let mut key_seq: *mut XmlSchemaPSVIIDCKeyPtr;
let pos: i32 = (*sto).depth - (*matcher).depth;
let idx: i32 = (*(*sto).sel).index;
if (*matcher).key_seqs.is_null() {
if pos > 9 {
(*matcher).size_key_seqs = pos * 2;
} else {
(*matcher).size_key_seqs = 10;
}
(*matcher).key_seqs = xml_malloc(
(*matcher).size_key_seqs as usize
* size_of::<*mut XmlSchemaPSVIIDCKeyPtr>(),
)
as *mut *mut XmlSchemaPSVIIDCKeyPtr;
if (*matcher).key_seqs.is_null() {
xml_schema_verr_memory(
null_mut(),
"allocating an array of key-sequences",
None,
);
return -1;
}
memset(
(*matcher).key_seqs as _,
0,
(*matcher).size_key_seqs as usize
* size_of::<*mut XmlSchemaPSVIIDCKeyPtr>(),
);
} else if pos >= (*matcher).size_key_seqs {
let i: i32 = (*matcher).size_key_seqs;
(*matcher).size_key_seqs = pos * 2;
(*matcher).key_seqs = xml_realloc(
(*matcher).key_seqs as _,
(*matcher).size_key_seqs as usize
* size_of::<*mut XmlSchemaPSVIIDCKeyPtr>(),
)
as *mut *mut XmlSchemaPSVIIDCKeyPtr;
if (*matcher).key_seqs.is_null() {
xml_schema_verr_memory(
null_mut(),
"reallocating an array of key-sequences",
None,
);
return -1;
}
for i in i..(*matcher).size_key_seqs {
*(*matcher).key_seqs.add(i as usize) = null_mut();
}
}
'create_key: {
'create_sequence: {
key_seq = *(*matcher).key_seqs.add(pos as usize);
if key_seq.is_null() {
break 'create_sequence;
} else if !(*key_seq.add(idx as usize)).is_null() {
let xpath = CStr::from_ptr((*(*sto).sel).xpath as *const i8)
.to_string_lossy();
let desig =
xml_schema_get_idc_designation((*(*matcher).aidc).def);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcIdc,
None,
(*(*matcher).aidc).def as XmlSchemaBasicItemPtr,
format!("The XPath '{xpath}' of a field of {desig} evaluates to a node-set with more than one member").as_str(),
Some(&xpath),
Some(&desig)
);
(*sto).nb_history -= 1;
break 'deregister_check;
} else {
break 'create_key;
}
}
key_seq = xml_malloc(
(*(*(*matcher).aidc).def).nb_fields as usize
* size_of::<XmlSchemaPSVIIDCKeyPtr>(),
) as *mut XmlSchemaPSVIIDCKeyPtr;
if key_seq.is_null() {
xml_schema_verr_memory(
null_mut(),
"allocating an IDC key-sequence",
None,
);
return -1;
}
memset(
key_seq as _,
0,
(*(*(*matcher).aidc).def).nb_fields as usize
* size_of::<XmlSchemaPSVIIDCKeyPtr>(),
);
*(*matcher).key_seqs.add(pos as usize) = key_seq;
}
if key.is_null() {
key = xml_malloc(size_of::<XmlSchemaPSVIIDCKey>())
as XmlSchemaPSVIIDCKeyPtr;
if key.is_null() {
xml_schema_verr_memory(null_mut(), "allocating a IDC key", None);
xml_free(key_seq as _);
*(*matcher).key_seqs.add(pos as usize) = null_mut();
return -1;
}
(*key).typ = simple_type;
(*key).val = (*(*vctxt).inode).val;
(*(*vctxt).inode).val = null_mut();
if xml_schema_idc_store_key(vctxt, key) == -1 {
xml_schema_idc_free_key(key);
return -1;
}
}
*key_seq.add(idx as usize) = key;
}
} else if (*sto).typ == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR {
let mut key_seq: *mut *mut XmlSchemaPSVIIDCKeyPtr = null_mut();
let nt_item: XmlSchemaPSVIIDCNodePtr;
let targets: XmlSchemaItemListPtr<*mut c_void>;
let matcher: XmlSchemaIDCMatcherPtr = (*sto).matcher;
let idc: XmlSchemaIDCPtr = (*(*matcher).aidc).def;
let nb_keys: i32 = (*idc).nb_fields;
let pos: i32 = depth - (*matcher).depth;
'selector_leave: {
'selector_key_error: {
if (*matcher).key_seqs.is_null() || (*matcher).size_key_seqs <= pos {
if (*idc).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKey {
break 'selector_key_error;
} else {
break 'selector_leave;
}
}
key_seq = (*matcher).key_seqs.add(pos as usize);
if (*key_seq).is_null() {
if (*idc).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKey {
break 'selector_key_error;
} else {
break 'selector_leave;
}
}
for i in 0..nb_keys {
if (*(*key_seq).add(i as usize)).is_null() {
if (*idc).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKey {
break 'selector_key_error;
}
break 'selector_leave;
}
}
targets = xml_schema_idc_acquire_target_list(vctxt, matcher);
if (*idc).typ != XmlSchemaTypeType::XmlSchemaTypeIDCKeyref
&& !(*targets).items.is_empty()
{
let mut ckey: XmlSchemaPSVIIDCKeyPtr;
let mut bkey: XmlSchemaPSVIIDCKeyPtr;
let mut bkey_seq: *mut XmlSchemaPSVIIDCKeyPtr;
let mut e: XmlIDCHashEntryPtr;
res = 0;
if (*matcher).htab.is_null() {
e = null_mut();
} else {
let value = CString::new(xml_schema_hash_key_sequence(
vctxt, *key_seq, nb_keys,
))
.unwrap();
e = xml_hash_lookup(
(*matcher).htab,
value.as_ptr() as *const u8,
) as _;
}
while !e.is_null() {
bkey_seq = (*(((*targets).items[(*e).index as usize])
as XmlSchemaPSVIIDCNodePtr))
.keys;
for j in 0..nb_keys {
ckey = *(*key_seq).add(j as usize);
bkey = *bkey_seq.add(j as usize);
res = xml_schema_are_values_equal((*ckey).val, (*bkey).val);
if res == -1 {
return -1;
} else if res == 0 {
break;
}
}
if res == 1 {
break;
}
e = (*e).next;
}
if !e.is_null() {
let seq = xml_schema_format_idc_key_sequence(
vctxt, *key_seq, nb_keys,
);
let desig = xml_schema_get_idc_designation(idc);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcIdc,
None,
idc as XmlSchemaBasicItemPtr,
format!("Duplicate key-sequence {seq} in {desig}").as_str(),
Some(&seq),
Some(&desig),
);
break 'selector_leave;
}
}
nt_item = xml_malloc(size_of::<XmlSchemaPSVIIDCNode>())
as XmlSchemaPSVIIDCNodePtr;
if nt_item.is_null() {
xml_schema_verr_memory(
null_mut(),
"allocating an IDC node-table item",
None,
);
xml_free(*key_seq as _);
*key_seq = null_mut();
return -1;
}
memset(nt_item as _, 0, size_of::<XmlSchemaPSVIIDCNode>());
if (*idc).typ != XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
if xml_schema_idc_store_node_table_item(vctxt, nt_item) == -1 {
xml_free(nt_item as _);
xml_free(*key_seq as _);
*key_seq = null_mut();
return -1;
}
(*nt_item).node_qname_id = -1;
} else {
(*nt_item).node_qname_id = xml_schema_vadd_node_qname(
vctxt,
(*(*vctxt).inode).local_name.as_deref().unwrap(),
(*(*vctxt).inode).ns_name.as_deref(),
);
if (*nt_item).node_qname_id == -1 {
xml_free(nt_item as _);
xml_free(*key_seq as _);
*key_seq = null_mut();
return -1;
}
}
(*nt_item).node = (*vctxt).node;
(*nt_item).node_line = (*(*vctxt).inode).node_line;
(*nt_item).keys = *key_seq;
*key_seq = null_mut();
if (*targets).push(nt_item as _) == -1 {
if (*idc).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
xml_free((*nt_item).keys as _);
xml_free(nt_item as _);
}
return -1;
}
if (*idc).typ != XmlSchemaTypeType::XmlSchemaTypeIDCKeyref {
if (*matcher).htab.is_null() {
(*matcher).htab = xml_hash_create(4);
}
let value = CString::new(xml_schema_hash_key_sequence(
vctxt,
(*nt_item).keys,
nb_keys,
))
.unwrap();
let e: XmlIDCHashEntryPtr =
xml_malloc(size_of::<XmlIDCHashEntry>()) as _;
(*e).index = (*targets).items.len() as i32 - 1;
let r: XmlIDCHashEntryPtr =
xml_hash_lookup((*matcher).htab, value.as_ptr() as *const u8)
as _;
if !r.is_null() {
(*e).next = (*r).next;
(*r).next = e;
} else {
(*e).next = null_mut();
xml_hash_add_entry(
(*matcher).htab,
value.as_ptr() as *const u8,
e as _,
);
}
}
break 'selector_leave;
}
{
let desig = xml_schema_get_idc_designation(idc);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcIdc,
None,
idc as XmlSchemaBasicItemPtr,
format!("Not all fields of {desig} evaluate to a node").as_str(),
Some(&desig),
None,
);
}
}
if !key_seq.is_null() && !(*key_seq).is_null() {
xml_free(*key_seq as _);
*key_seq = null_mut();
}
}
(*sto).nb_history -= 1;
}
if (*sto).nb_history == 0 && (*sto).depth == depth {
if (*vctxt).xpath_states != sto {
VERROR_INT!(
vctxt,
"xmlSchemaXPathProcessHistory",
"The state object to be removed is not the first in the list"
);
}
nextsto = (*sto).next;
(*vctxt).xpath_states = (*sto).next;
(*sto).next = (*vctxt).xpath_state_pool;
(*vctxt).xpath_state_pool = sto;
sto = nextsto;
} else {
sto = (*sto).next;
}
}
0
}
}
#[doc(alias = "xmlSchemaXPathPop")]
unsafe fn xml_schema_xpath_pop(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut sto: XmlSchemaIDCStateObjPtr;
let mut res: i32;
if (*vctxt).xpath_states.is_null() {
return 0;
}
sto = (*vctxt).xpath_states;
while {
res = (*sto).xpath_ctxt.as_mut().unwrap().pop();
if res == -1 {
return -1;
}
sto = (*sto).next;
!sto.is_null()
} {}
0
}
}
unsafe fn xml_schema_vattributes_complex(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let typ: XmlSchemaTypePtr = (*(*vctxt).inode).type_def;
let mut attr_use: XmlSchemaAttributeUsePtr;
let mut attr_decl: XmlSchemaAttributePtr;
let mut iattr: XmlSchemaAttrInfoPtr;
let mut tmpiattr: XmlSchemaAttrInfoPtr;
let mut found: i32;
let mut xpath_res: i32;
let mut res: i32;
let mut wild_ids = 0;
let mut fixed: i32;
let attr_use_list: XmlSchemaItemListPtr<*mut c_void> =
(*typ).attr_uses as XmlSchemaItemListPtr<*mut c_void>;
let nb_attrs: i32 = (*vctxt).nb_attr_infos;
let nb_uses = if !attr_use_list.is_null() {
(*attr_use_list).items.len()
} else {
0
};
for i in 0..nb_uses {
found = 0;
attr_use = (*attr_use_list).items[i] as _;
attr_decl = WXS_ATTRUSE_DECL!(attr_use);
for j in 0..nb_attrs {
iattr = *(*vctxt).attr_infos.add(j as usize);
if (*iattr).meta_type != 0 {
continue;
}
let local_name = (*iattr).local_name.as_deref().unwrap();
if local_name != CStr::from_ptr((*attr_decl).name as *const i8).to_string_lossy() {
continue;
}
if (*iattr).ns_name.as_deref()
!= (!(*attr_decl).target_namespace.is_null())
.then(|| {
CStr::from_ptr((*attr_decl).target_namespace as *const i8)
.to_string_lossy()
})
.as_deref()
{
continue;
}
found = 1;
(*iattr).state = XML_SCHEMAS_ATTR_ASSESSED;
(*iattr).using = attr_use;
(*iattr).decl = attr_decl;
(*iattr).type_def = (*attr_decl).subtypes;
break;
}
if found != 0 {
continue;
}
if (*attr_use).occurs == XML_SCHEMAS_ATTR_USE_REQUIRED {
tmpiattr = xml_schema_get_fresh_attr_info(vctxt);
if tmpiattr.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaGetFreshAttrInfo()"
);
return -1;
}
(*tmpiattr).state = XML_SCHEMAS_ATTR_ERR_MISSING;
(*tmpiattr).using = attr_use;
(*tmpiattr).decl = attr_decl;
} else if (*attr_use).occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL
&& (!(*attr_use).def_value.is_null() || !(*attr_decl).def_value.is_null())
{
tmpiattr = xml_schema_get_fresh_attr_info(vctxt);
if tmpiattr.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaGetFreshAttrInfo()"
);
return -1;
}
(*tmpiattr).state = XML_SCHEMAS_ATTR_DEFAULT;
(*tmpiattr).using = attr_use;
(*tmpiattr).decl = attr_decl;
(*tmpiattr).type_def = (*attr_decl).subtypes;
(*tmpiattr).local_name = (!(*attr_decl).name.is_null()).then(|| {
CStr::from_ptr((*attr_decl).name as *const i8)
.to_string_lossy()
.into_owned()
});
(*tmpiattr).ns_name = (!(*attr_decl).target_namespace.is_null()).then(|| {
CStr::from_ptr((*attr_decl).target_namespace as *const i8)
.to_string_lossy()
.into_owned()
});
}
}
if (*vctxt).nb_attr_infos == 0 {
return 0;
}
if !(*typ).attribute_wildcard.is_null() {
for i in 0..nb_attrs {
iattr = *(*vctxt).attr_infos.add(i as usize);
if (*iattr).state != XML_SCHEMAS_ATTR_UNKNOWN {
continue;
}
if xml_schema_check_cvcwildcard_namespace(
(*typ).attribute_wildcard,
(*iattr).ns_name.as_deref(),
) == 0
{
if (*(*typ).attribute_wildcard).process_contents == XML_SCHEMAS_ANY_SKIP {
(*iattr).state = XML_SCHEMAS_ATTR_WILD_SKIP;
continue;
}
(*iattr).decl = (*(*vctxt).schema).get_attribute_decl(
(*iattr).local_name.as_deref().unwrap(),
(*iattr).ns_name.as_deref(),
);
if !(*iattr).decl.is_null() {
(*iattr).state = XML_SCHEMAS_ATTR_ASSESSED;
(*iattr).type_def = (*((*iattr).decl)).subtypes;
if xml_schema_is_derived_from_built_in_type(
(*iattr).type_def,
XmlSchemaValType::XmlSchemasID,
) != 0
{
if wild_ids != 0 {
(*iattr).state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
continue;
}
wild_ids += 1;
if !attr_use_list.is_null() {
for j in 0..(*attr_use_list).items.len() {
if xml_schema_is_derived_from_built_in_type(
WXS_ATTRUSE_TYPEDEF!((*attr_use_list).items[j]),
XmlSchemaValType::XmlSchemasID,
) != 0
{
(*iattr).state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
break;
}
}
}
}
} else if (*(*typ).attribute_wildcard).process_contents == XML_SCHEMAS_ANY_LAX {
(*iattr).state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
} else {
(*iattr).state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
}
}
}
}
if (*vctxt).nb_attr_infos == 0 {
return 0;
}
let mut def_attr_owner_elem = None;
if (*vctxt).options & XmlSchemaValidOption::XmlSchemaValVcICreate as i32 != 0 {
let ielem: XmlSchemaNodeInfoPtr = *(*vctxt).elem_infos.add((*vctxt).depth as usize);
if !ielem.is_null() && (*ielem).node.is_some_and(|node| node.doc.is_some()) {
def_attr_owner_elem = (*ielem).node;
}
}
'internal_error: {
for i in 0..(*vctxt).nb_attr_infos {
iattr = *(*vctxt).attr_infos.add(i as usize);
if (*iattr).state != XML_SCHEMAS_ATTR_ASSESSED
&& (*iattr).state != XML_SCHEMAS_ATTR_DEFAULT
{
continue;
}
if (*iattr).type_def.is_null() {
(*iattr).state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
continue;
}
ACTIVATE_ATTRIBUTE!(vctxt, iattr);
xpath_res = 0;
if !(*vctxt).xpath_states.is_null() {
xpath_res = xml_schema_xpath_evaluate(vctxt, XmlElementType::XmlAttributeNode);
if xpath_res == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaXPathEvaluate()"
);
break 'internal_error;
}
}
'eval_idcs: {
if (*iattr).state == XML_SCHEMAS_ATTR_DEFAULT {
if xpath_res != 0 || def_attr_owner_elem.is_some() {
if !(*(*iattr).using).def_value.is_null() {
(*iattr).value = (*(*iattr).using).def_value;
(*iattr).val = (*(*iattr).using).def_val;
} else {
(*iattr).value = (*(*iattr).decl).def_value;
(*iattr).val = (*(*iattr).decl).def_val;
}
if (*iattr).val.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"default/fixed value on an attribute use was not precomputed"
);
break 'internal_error;
}
(*iattr).val = xml_schema_copy_value((*iattr).val);
if (*iattr).val.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaCopyValue()"
);
break 'internal_error;
}
}
if let Some(mut def_attr_owner_elem) = def_attr_owner_elem {
let mut value: *const XmlChar;
value = (*iattr).value;
let norm_value = (*(*iattr).type_def)
.normalize_value(
CStr::from_ptr((*iattr).value as *const i8)
.to_string_lossy()
.as_ref(),
)
.map_or(null_mut(), |res| {
xml_strndup(res.as_ptr(), res.len() as i32)
});
if !norm_value.is_null() {
value = norm_value;
}
if let Some(ns_name) = (*iattr).ns_name.as_deref() {
let doc = def_attr_owner_elem.doc;
let mut ns = def_attr_owner_elem.search_ns_by_href(doc, ns_name);
if ns.is_none() {
let mut counter: i32 = 0;
let mut prefix;
while {
prefix = format!("p{counter}");
counter += 1;
let doc = def_attr_owner_elem.doc;
ns = def_attr_owner_elem
.search_ns(doc, Some(prefix.as_str()));
if counter > 1000 {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"could not compute a ns prefix for a default/fixed attribute"
);
if !norm_value.is_null() {
xml_free(norm_value as _);
}
break 'internal_error;
}
ns.is_some()
} {}
ns = xml_new_ns(
(*vctxt).validation_root,
Some(ns_name),
Some(&prefix),
);
}
xml_new_ns_prop(
Some(def_attr_owner_elem),
ns,
(*iattr).local_name.as_deref().unwrap(),
Some(&CStr::from_ptr(value as *const i8).to_string_lossy()),
);
} else if xml_new_prop(
Some(def_attr_owner_elem),
(*iattr).local_name.as_deref().unwrap(),
Some(&CStr::from_ptr(value as *const i8).to_string_lossy()),
)
.is_none()
{
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlNewProp()"
);
if !norm_value.is_null() {
xml_free(norm_value as _);
}
break 'internal_error;
}
if !norm_value.is_null() {
xml_free(norm_value as _);
}
}
break 'eval_idcs;
}
if !(*vctxt).value.is_null() {
xml_schema_free_value((*vctxt).value);
(*vctxt).value = null_mut();
}
if (*(*iattr).decl).flags & XML_SCHEMAS_ATTR_FIXED != 0
|| (!(*iattr).using.is_null()
&& (*(*iattr).using).flags & XML_SCHEMAS_ATTR_FIXED != 0)
{
fixed = 1;
} else {
fixed = 0;
}
if xpath_res != 0 || fixed != 0 {
(*iattr).flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
res = xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
(*iattr).node.map(|attr| attr.into()),
(*iattr).type_def,
(*iattr).value,
&raw mut (*iattr).val,
1,
1,
0,
);
} else {
res = xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
(*iattr).node.map(|attr| attr.into()),
(*iattr).type_def,
(*iattr).value,
null_mut(),
1,
0,
0,
);
}
if res != 0 {
if res == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaStreamValidateSimpleTypeValue()"
);
break 'internal_error;
}
(*iattr).state = XML_SCHEMAS_ATTR_INVALID_VALUE;
break 'eval_idcs;
}
if fixed != 0 {
if (*iattr).val.is_null() {
break 'eval_idcs;
}
if !(*iattr).using.is_null() && !(*(*iattr).using).def_value.is_null() {
if (*(*iattr).using).def_val.is_null() {
break 'eval_idcs;
}
(*iattr).vc_value = (*(*iattr).using).def_value;
if xml_schema_are_values_equal((*iattr).val, (*(*iattr).using).def_val)
== 0
{
(*iattr).state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
}
} else {
if (*(*iattr).decl).def_val.is_null() {
break 'eval_idcs;
}
(*iattr).vc_value = (*(*iattr).decl).def_value;
if xml_schema_are_values_equal((*iattr).val, (*(*iattr).decl).def_val)
== 0
{
(*iattr).state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
}
}
}
}
if xpath_res != 0 {
if xml_schema_xpath_process_history(vctxt, (*vctxt).depth + 1) == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaVAttributesComplex",
"calling xmlSchemaXPathEvaluate()"
);
break 'internal_error;
}
} else if !(*vctxt).xpath_states.is_null() {
xml_schema_xpath_pop(vctxt);
}
}
for i in 0..(*vctxt).nb_attr_infos {
iattr = *(*vctxt).attr_infos.add(i as usize);
if (*iattr).state == XML_SCHEMAS_ATTR_META
|| (*iattr).state == XML_SCHEMAS_ATTR_ASSESSED
|| (*iattr).state == XML_SCHEMAS_ATTR_WILD_SKIP
|| (*iattr).state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL
{
continue;
}
ACTIVATE_ATTRIBUTE!(vctxt, iattr);
match (*iattr).state {
w if XML_SCHEMAS_ATTR_ERR_MISSING == w => {
ACTIVATE_ELEM!(vctxt);
let namespace_name = (*(*iattr).decl).target_namespace as *const i8;
let qname = xml_schema_format_qname(
(!namespace_name.is_null())
.then(|| CStr::from_ptr(namespace_name).to_string_lossy())
.as_deref(),
Some(
CStr::from_ptr((*(*iattr).decl).name as *const i8)
.to_string_lossy()
.as_ref(),
),
);
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcComplexType4,
None,
null_mut(),
format!("The attribute '{qname}' is required but missing").as_str(),
Some(&qname),
None,
);
}
w if XML_SCHEMAS_ATTR_ERR_NO_TYPE == w => {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcAttribute2,
null_mut(),
"The type definition is absent"
);
}
w if XML_SCHEMAS_ATTR_ERR_FIXED_VALUE == w => {
let value = CStr::from_ptr((*iattr).value as *const i8).to_string_lossy();
let vc_value =
CStr::from_ptr((*iattr).vc_value as *const i8).to_string_lossy();
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcAu,
None,
null_mut(),
format!(
"The value '{value}' does not match the fixed value constraint '{vc_value}'"
)
.as_str(),
Some(&value),
Some(&vc_value),
);
}
w if XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL == w => {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcWildcard,
null_mut(),
"No matching global attribute declaration available, but demanded by the strict wildcard"
);
}
w if XML_SCHEMAS_ATTR_UNKNOWN == w => {
if (*iattr).meta_type != 0 {
} else {
if (*typ).attribute_wildcard.is_null() {
xml_schema_illegal_attr_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcComplexType3_2_1,
Some(&*iattr),
None,
);
} else {
xml_schema_illegal_attr_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcComplexType3_2_2,
Some(&*iattr),
None,
);
}
}
}
_ => {}
}
}
ACTIVATE_ELEM!(vctxt);
return 0;
}
ACTIVATE_ELEM!(vctxt);
-1
}
}
unsafe fn xml_schema_vattributes_simple(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut iattr: XmlSchemaAttrInfoPtr;
let mut ret: i32 = 0;
if (*vctxt).nb_attr_infos == 0 {
return 0;
}
for i in 0..(*vctxt).nb_attr_infos {
iattr = *(*vctxt).attr_infos.add(i as usize) as _;
if (*iattr).meta_type == 0 {
ACTIVATE_ATTRIBUTE!(vctxt, iattr);
xml_schema_illegal_attr_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavCvcType3_1_1,
Some(&*iattr),
None,
);
ret = XmlParserErrors::XmlSchemavCvcType3_1_1 as i32;
}
}
ACTIVATE_ELEM!(vctxt);
ret
}
}
unsafe fn xml_schema_validate_elem(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
VERROR_INT!(vctxt, "xmlSchemaValidateElem", "in skip-state");
return -1;
}
if (*vctxt).xsi_assemble != 0 {
ret = xml_schema_assemble_by_xsi(vctxt);
if ret != 0 {
if ret == -1 {
return -1;
}
(*vctxt).skip_depth = 0;
return ret;
}
for &imported in (*(*vctxt).schema).schemas_imports.values() {
if !imported.is_null() {
xml_schema_augment_imported_idc(imported, vctxt);
}
}
}
'goto_exit: {
if (*vctxt).depth > 0 {
ret = xml_schema_validate_child_elem(vctxt);
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"calling xmlSchemaStreamValidateChildElement()"
);
return -1;
}
break 'goto_exit;
}
if (*vctxt).depth == (*vctxt).skip_depth {
break 'goto_exit;
}
if (*(*vctxt).inode).decl.is_null() && (*(*vctxt).inode).type_def.is_null() {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"the child element was valid but neither the declaration nor the type was set"
);
return -1;
}
} else {
(*(*vctxt).inode).decl = (*(*vctxt).schema).get_elem(
(*(*vctxt).inode).local_name.as_deref().unwrap(),
(*(*vctxt).inode).ns_name.as_deref(),
);
if (*(*vctxt).inode).decl.is_null() {
ret = XmlParserErrors::XmlSchemavCvcElt1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"No matching global declaration available for the validation root"
);
break 'goto_exit;
}
}
'type_validation: {
if (*(*vctxt).inode).decl.is_null() {
break 'type_validation;
}
if (*(*(*vctxt).inode).decl).typ == XmlSchemaTypeType::XmlSchemaTypeAny {
let mut skip: i32 = 0;
ret = xml_schema_validate_elem_wildcard(vctxt, &raw mut skip);
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"calling xmlSchemaValidateElemWildcard()"
);
return -1;
}
break 'goto_exit;
}
if skip != 0 {
(*vctxt).skip_depth = (*vctxt).depth;
break 'goto_exit;
}
if (*(*(*vctxt).inode).decl).typ != XmlSchemaTypeType::XmlSchemaTypeElement {
(*(*vctxt).inode).decl = null_mut();
break 'type_validation;
}
}
ret = xml_schema_validate_elem_decl(vctxt);
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"calling xmlSchemaValidateElemDecl()"
);
return -1;
}
break 'goto_exit;
}
}
if (*(*vctxt).inode).type_def.is_null() {
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
ret = XmlParserErrors::XmlSchemavCvcType1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"The type definition is absent"
);
break 'goto_exit;
}
if (*(*(*vctxt).inode).type_def).flags & XML_SCHEMAS_TYPE_ABSTRACT != 0 {
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
ret = XmlParserErrors::XmlSchemavCvcType2 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"The type definition is abstract"
);
break 'goto_exit;
}
if !(*vctxt).xpath_states.is_null() {
ret = xml_schema_xpath_evaluate(vctxt, XmlElementType::XmlElementNode);
(*(*vctxt).inode).applied_xpath = 1;
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"calling xmlSchemaXPathEvaluate()"
);
return -1;
}
}
if wxs_is_complex((*(*vctxt).inode).type_def) {
if (*vctxt).nb_attr_infos != 0 || !(*(*(*vctxt).inode).type_def).attr_uses.is_null()
{
ret = xml_schema_vattributes_complex(vctxt);
}
} else if (*vctxt).nb_attr_infos != 0 {
ret = xml_schema_vattributes_simple(vctxt);
}
if (*vctxt).nb_attr_infos != 0 {
(*vctxt).clear_attr_infos();
}
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaValidateElem",
"calling attributes validation"
);
return -1;
}
ret = 0;
}
if ret != 0 {
(*vctxt).skip_depth = (*vctxt).depth;
}
ret
}
}
const XML_SCHEMA_PUSH_TEXT_PERSIST: i32 = 1;
const XML_SCHEMA_PUSH_TEXT_CREATED: i32 = 2;
const XML_SCHEMA_PUSH_TEXT_VOLATILE: i32 = 3;
unsafe fn xml_schema_vpush_text(
vctxt: XmlSchemaValidCtxtPtr,
node_type: i32,
value: Option<&str>,
mode: i32,
consumed: *mut i32,
) -> i32 {
unsafe {
if !consumed.is_null() {
*consumed = 0;
}
if INODE_NILLED!((*vctxt).inode) {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcElt3_2_1,
null_mut(),
"Neither character nor element content is allowed because the element is 'nilled'"
);
return (*vctxt).err;
}
if (*(*(*vctxt).inode).type_def).content_type == XmlSchemaContentType::XmlSchemaContentEmpty
{
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcComplexType2_1,
null_mut(),
"Character content is not allowed, because the content type is empty"
);
return (*vctxt).err;
}
if (*(*(*vctxt).inode).type_def).content_type
== XmlSchemaContentType::XmlSchemaContentElements
{
if node_type != XmlElementType::XmlTextNode as i32 || !xml_schema_is_blank(value) {
VERROR!(
vctxt,
XmlParserErrors::XmlSchemavCvcComplexType2_3,
null_mut(),
"Character content other than whitespace is not allowed because the content type is 'element-only'"
);
return (*vctxt).err;
}
return 0;
}
let Some(value) = value.filter(|value| !value.is_empty()) else {
return 0;
};
if (*(*(*vctxt).inode).type_def).content_type == XmlSchemaContentType::XmlSchemaContentMixed
&& ((*(*vctxt).inode).decl.is_null() || (*(*(*vctxt).inode).decl).value.is_null())
{
return 0;
}
if (*(*vctxt).inode).value.is_null() {
match mode {
_ if mode == XML_SCHEMA_PUSH_TEXT_PERSIST => {
(*(*vctxt).inode).value = xml_strndup(value.as_ptr(), value.len() as i32);
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
}
_ if mode == XML_SCHEMA_PUSH_TEXT_CREATED => {
(*(*vctxt).inode).value = xml_strndup(value.as_ptr(), value.len() as i32);
if !consumed.is_null() {
*consumed = 1;
}
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
}
_ if mode == XML_SCHEMA_PUSH_TEXT_VOLATILE => {
(*(*vctxt).inode).value = xml_strndup(value.as_ptr(), value.len() as i32);
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
}
_ => {}
}
} else {
if (*(*vctxt).inode).flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES != 0 {
(*(*vctxt).inode).value = xml_strncat(
(*(*vctxt).inode).value as _,
value.as_ptr(),
value.len() as i32,
);
} else {
(*(*vctxt).inode).value =
xml_strncat_new((*(*vctxt).inode).value, value.as_ptr(), value.len() as i32);
(*(*vctxt).inode).flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
}
}
0
}
}
unsafe fn xml_schema_vcheck_inode_data_type(
vctxt: XmlSchemaValidCtxtPtr,
inode: XmlSchemaNodeInfoPtr,
typ: XmlSchemaTypePtr,
value: *const XmlChar,
) -> i32 {
unsafe {
if (*inode).flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED != 0 {
xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
None,
typ,
value,
&raw mut (*inode).val,
1,
1,
0,
)
} else {
xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
None,
typ,
value,
null_mut(),
1,
0,
0,
)
}
}
}
#[doc(alias = "xmlSchemaCheckCOSValidDefault")]
unsafe fn xml_schema_check_cos_valid_default(
vctxt: XmlSchemaValidCtxtPtr,
value: *const XmlChar,
val: *mut XmlSchemaValPtr,
) -> i32 {
unsafe {
let mut ret: i32 = 0;
let inode: XmlSchemaNodeInfoPtr = (*vctxt).inode;
if wxs_is_complex((*inode).type_def) {
if !WXS_HAS_SIMPLE_CONTENT!((*inode).type_def)
&& (!WXS_HAS_MIXED_CONTENT!((*inode).type_def)
|| !WXS_EMPTIABLE!((*inode).type_def))
{
ret = XmlParserErrors::XmlSchemapCosValidDefault2_1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"For a string to be a valid default, the type definition must be a simple type or a complex type with simple content or mixed content and a particle emptiable"
);
return ret;
}
}
if wxs_is_simple((*inode).type_def) {
ret = xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
None,
(*inode).type_def,
value,
val,
1,
1,
0,
);
} else if WXS_HAS_SIMPLE_CONTENT!((*inode).type_def) {
ret = xml_schema_vcheck_cvc_simple_type(
vctxt as XmlSchemaAbstractCtxtPtr,
None,
(*(*inode).type_def).content_type_def,
value,
val,
1,
1,
0,
);
}
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaCheckCOSValidDefault",
"calling xmlSchemaVCheckCVCSimpleType()"
);
}
ret
}
}
#[doc(alias = "xmlSchemaIDCNewBinding")]
unsafe fn xml_schema_idc_new_binding(idc_def: XmlSchemaIDCPtr) -> XmlSchemaPSVIIDCBindingPtr {
unsafe {
let ret: XmlSchemaPSVIIDCBindingPtr =
xml_malloc(size_of::<XmlSchemaPSVIIDCBinding>()) as XmlSchemaPSVIIDCBindingPtr;
if ret.is_null() {
xml_schema_verr_memory(null_mut(), "allocating a PSVI IDC binding item", None);
return null_mut();
}
std::ptr::write(&mut *ret, Default::default());
(*ret).definition = idc_def;
ret
}
}
#[doc(alias = "xmlSchemaIDCAcquireBinding")]
unsafe fn xml_schema_idc_acquire_binding(
vctxt: XmlSchemaValidCtxtPtr,
matcher: XmlSchemaIDCMatcherPtr,
) -> XmlSchemaPSVIIDCBindingPtr {
unsafe {
let ielem: XmlSchemaNodeInfoPtr = *(*vctxt).elem_infos.add((*matcher).depth as usize);
if (*ielem).idc_table.is_null() {
(*ielem).idc_table = xml_schema_idc_new_binding((*(*matcher).aidc).def);
if (*ielem).idc_table.is_null() {
return null_mut();
}
return (*ielem).idc_table;
} else {
let mut bind: XmlSchemaPSVIIDCBindingPtr;
bind = (*ielem).idc_table;
while {
if (*bind).definition == (*(*matcher).aidc).def {
return bind;
}
if (*bind).next.is_null() {
(*bind).next = xml_schema_idc_new_binding((*(*matcher).aidc).def);
if (*bind).next.is_null() {
return null_mut();
}
return (*bind).next;
}
bind = (*bind).next;
!bind.is_null()
} {}
}
null_mut()
}
}
#[doc(alias = "xmlSchemaIDCAppendNodeTableItem")]
unsafe fn xml_schema_idc_append_node_table_item(
bind: XmlSchemaPSVIIDCBindingPtr,
nt_item: XmlSchemaPSVIIDCNodePtr,
) -> i32 {
unsafe {
(*bind).node_table.push(nt_item);
0
}
}
unsafe fn xml_schema_idc_fill_node_tables(
vctxt: XmlSchemaValidCtxtPtr,
ielem: XmlSchemaNodeInfoPtr,
) -> i32 {
unsafe {
let mut bind: XmlSchemaPSVIIDCBindingPtr;
let mut res: i32;
let mut keys: *mut XmlSchemaPSVIIDCKeyPtr;
let mut ntkeys: *mut XmlSchemaPSVIIDCKeyPtr;
let mut matcher: XmlSchemaIDCMatcherPtr = (*ielem).idc_matchers;
while !matcher.is_null() {
if (*(*(*matcher).aidc).def).typ == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref
|| WXS_ILIST_IS_EMPTY!((*matcher).targets)
{
matcher = (*matcher).next;
continue;
}
if (*vctxt).create_idcnode_tables == 0
&& ((*(*matcher).aidc).keyref_depth == -1
|| (*(*matcher).aidc).keyref_depth > (*vctxt).depth)
{
matcher = (*matcher).next;
continue;
}
bind = xml_schema_idc_acquire_binding(vctxt, matcher);
if bind.is_null() {
return -1;
}
let (dupls, nb_dupls) = if !WXS_ILIST_IS_EMPTY!((*bind).dupls) {
(&(*(*bind).dupls).items[..], (*(*bind).dupls).items.len()) } else {
(&[][..], 0)
};
let nb_node_table = (*bind).node_table.len();
if nb_node_table == 0 && nb_dupls == 0 {
(*bind).node_table = (*(*matcher).targets)
.items
.drain(..)
.map(|item| item as XmlSchemaPSVIIDCNodePtr)
.collect();
if !(*matcher).htab.is_null() {
xml_hash_free((*matcher).htab, Some(xml_free_idc_hash_entry));
(*matcher).htab = null_mut();
}
} else {
let nb_targets = (*(*matcher).targets).items.len();
let targets = &(*(*matcher).targets).items[..]; let nb_fields = (*(*(*matcher).aidc).def).nb_fields;
let mut i = 0;
while i < nb_targets {
'next_target: {
keys = (*(targets[i] as XmlSchemaPSVIIDCNodePtr)).keys;
if nb_dupls != 0 {
let mut j = 0;
'lj: while {
if nb_fields == 1 {
res = xml_schema_are_values_equal(
(*(*keys.add(0))).val,
(*(*(*(dupls[j] as XmlSchemaPSVIIDCNodePtr)).keys.add(0)))
.val,
);
if res == -1 {
return -1;
}
if res == 1 {
break 'next_target;
}
} else {
res = 0;
ntkeys = (*(dupls[j] as XmlSchemaPSVIIDCNodePtr)).keys;
for k in 0..nb_fields {
res = xml_schema_are_values_equal(
(*(*keys.add(k as usize))).val,
(*(*ntkeys.add(k as usize))).val,
);
if res == -1 {
return -1;
}
if res == 0 {
break 'lj;
}
}
if res == 1 {
break 'next_target;
}
}
j += 1;
j < nb_dupls
} {}
}
if nb_node_table != 0 {
let mut j = 0;
while {
'next_node_table_entry: {
if nb_fields == 1 {
res = xml_schema_are_values_equal(
(*(*keys.add(0))).val,
(*(*(*(*bind).node_table[j]).keys.add(0))).val,
);
if res == -1 {
return -1;
}
if res == 0 {
break 'next_node_table_entry;
}
} else {
ntkeys = (*(*bind).node_table[j]).keys;
for k in 0..nb_fields {
res = xml_schema_are_values_equal(
(*(*keys.add(k as usize))).val,
(*(*ntkeys.add(k as usize))).val,
);
if res == -1 {
return -1;
}
if res == 0 {
break 'next_node_table_entry;
}
}
}
if (*bind).dupls.is_null() {
(*bind).dupls =
xml_schema_item_list_create::<*mut c_void>();
if (*bind).dupls.is_null() {
return -1;
}
}
if (*(*bind).dupls).push((*bind).node_table[j] as _) == -1 {
return -1;
}
(*bind).node_table[j] = (*bind).node_table.pop().unwrap();
break 'next_target;
}
j += 1;
j < nb_node_table
} {}
}
if xml_schema_idc_append_node_table_item(
bind,
targets[i] as XmlSchemaPSVIIDCNodePtr,
) == -1
{
return -1;
}
}
i += 1;
}
}
matcher = (*matcher).next;
}
0
}
}
#[doc(alias = "xmlSchemaCheckCVCIDCKeyRef")]
unsafe fn xml_schema_check_cvc_idc_key_ref(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut matcher: XmlSchemaIDCMatcherPtr;
let mut bind: XmlSchemaPSVIIDCBindingPtr;
matcher = (*(*vctxt).inode).idc_matchers;
while !matcher.is_null() {
if (*matcher).idc_type == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref as i32
&& !(*matcher).targets.is_null()
&& !(*(*matcher).targets).items.is_empty()
{
let mut res: i32;
let mut ref_keys: *mut XmlSchemaPSVIIDCKeyPtr;
let mut keys: *mut XmlSchemaPSVIIDCKeyPtr;
let mut ref_node: XmlSchemaPSVIIDCNodePtr;
let mut table: XmlHashTablePtr = null_mut();
let nb_fields: i32 = (*(*(*matcher).aidc).def).nb_fields;
bind = (*(*vctxt).inode).idc_table;
while !bind.is_null() {
if (*(*(*(*matcher).aidc).def).refe).item as XmlSchemaIDCPtr
== (*bind).definition
{
break;
}
bind = (*bind).next;
}
let has_dupls: i32 = (!bind.is_null()
&& !(*bind).dupls.is_null()
&& !(*(*bind).dupls).items.is_empty())
as i32;
if !bind.is_null() {
table = xml_hash_create((*bind).node_table.len() as i32 * 2);
for j in 0..(*bind).node_table.len() {
keys = (*(*bind).node_table[j]).keys;
let value =
CString::new(xml_schema_hash_key_sequence(vctxt, keys, nb_fields))
.unwrap();
let e: XmlIDCHashEntryPtr = xml_malloc(size_of::<XmlIDCHashEntry>()) as _;
(*e).index = j as i32;
let r: XmlIDCHashEntryPtr =
xml_hash_lookup(table, value.as_ptr() as *const u8) as _;
if !r.is_null() {
(*e).next = (*r).next;
(*r).next = e;
} else {
(*e).next = null_mut();
xml_hash_add_entry(table, value.as_ptr() as *const u8, e as _);
}
}
}
for i in 0..(*(*matcher).targets).items.len() {
res = 0;
ref_node = (*(*matcher).targets).items[i] as _;
if !bind.is_null() {
let mut e: XmlIDCHashEntryPtr;
ref_keys = (*ref_node).keys;
let value =
CString::new(xml_schema_hash_key_sequence(vctxt, ref_keys, nb_fields))
.unwrap();
e = xml_hash_lookup(table, value.as_ptr() as *const u8) as _;
res = 0;
while !e.is_null() {
keys = (*(*bind).node_table[(*e).index as usize]).keys;
for k in 0..nb_fields {
res = xml_schema_are_values_equal(
(*(*keys.add(k as usize))).val,
(*(*ref_keys.add(k as usize))).val,
);
if res == 0 {
break;
} else if res == -1 {
return -1;
}
}
if res == 1 {
break;
}
e = (*e).next;
}
if res == 0 && has_dupls != 0 {
for j in 0..(*(*bind).dupls).items.len() {
keys = (*(((*(*bind).dupls).items[j]) as XmlSchemaPSVIIDCNodePtr))
.keys;
for k in 0..nb_fields {
res = xml_schema_are_values_equal(
(*(*keys.add(k as usize))).val,
(*(*ref_keys.add(k as usize))).val,
);
if res == 0 {
break;
} else if res == -1 {
return -1;
}
}
if res == 1 {
let seq = xml_schema_format_idc_key_sequence(
vctxt,
(*ref_node).keys,
nb_fields,
);
let qname =
xml_schema_get_component_qname((*(*matcher).aidc).def as _);
xml_schema_keyref_err(
vctxt,
XmlParserErrors::XmlSchemavCvcIdc,
ref_node,
(*(*matcher).aidc).def as XmlSchemaTypePtr,
format!("More than one match found for key-sequence {seq} of keyref '{qname}'").as_str(),
Some(&seq),
Some(&qname),
);
break;
}
}
}
}
if res == 0 {
let seq =
xml_schema_format_idc_key_sequence(vctxt, (*ref_node).keys, nb_fields);
let qname = xml_schema_get_component_qname((*(*matcher).aidc).def as _);
xml_schema_keyref_err(
vctxt,
XmlParserErrors::XmlSchemavCvcIdc,
ref_node,
(*(*matcher).aidc).def as XmlSchemaTypePtr,
format!("No match found for key-sequence {seq} of keyref '{qname}'")
.as_str(),
Some(&seq),
Some(&qname),
);
}
}
if !table.is_null() {
xml_hash_free(table, Some(xml_free_idc_hash_entry));
}
}
matcher = (*matcher).next;
}
0
}
}
#[doc(alias = "xmlSchemaBubbleIDCNodeTables")]
unsafe fn xml_schema_bubble_idc_node_tables(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut bind: XmlSchemaPSVIIDCBindingPtr;
let mut par_bind: XmlSchemaPSVIIDCBindingPtr = null_mut();
let mut node: XmlSchemaPSVIIDCNodePtr;
let mut par_node: XmlSchemaPSVIIDCNodePtr = null_mut();
let mut aidc: XmlSchemaIDCAugPtr;
let mut ret: i32 = 0;
bind = (*(*vctxt).inode).idc_table;
if bind.is_null() {
return 0;
}
let par_table: *mut XmlSchemaPSVIIDCBindingPtr =
&raw mut (*(*(*vctxt).elem_infos.add((*vctxt).depth as usize - 1))).idc_table;
while !bind.is_null() {
'next_binding: {
if (*bind).node_table.is_empty() && WXS_ILIST_IS_EMPTY!((*bind).dupls) {
break 'next_binding;
}
if (*vctxt).create_idcnode_tables == 0 {
aidc = (*vctxt).aidcs;
loop {
if (*aidc).def == (*bind).definition {
if (*aidc).keyref_depth == -1 || (*aidc).keyref_depth >= (*vctxt).depth
{
break 'next_binding;
}
break;
}
aidc = (*aidc).next;
if aidc.is_null() {
break;
}
}
}
if !par_table.is_null() {
par_bind = *par_table;
}
while !par_bind.is_null() {
if (*par_bind).definition == (*bind).definition {
break;
}
par_bind = (*par_bind).next;
}
if !par_bind.is_null() {
let mut old_num = (*par_bind).node_table.len();
let (old_dupls, dupls) = if !WXS_ILIST_IS_EMPTY!((*par_bind).dupls) {
(
(*(*par_bind).dupls).items.len(),
&(*(*par_bind).dupls).items[..],
) } else {
(0, &[][..])
};
let mut par_nodes = &mut (*par_bind).node_table;
let nb_fields = (*(*bind).definition).nb_fields;
for i in 0..(*bind).node_table.len() {
node = (*bind).node_table[i];
if node.is_null() {
continue;
}
if old_dupls != 0 {
let mut j = 0;
while j < old_dupls {
if nb_fields == 1 {
ret = xml_schema_are_values_equal(
(*(*(*node).keys.add(0))).val,
(*(*(*(dupls[j] as XmlSchemaPSVIIDCNodePtr)).keys.add(0)))
.val,
);
if ret == -1 {
return -1;
}
if ret == 0 {
j += 1;
continue;
}
} else {
par_node = dupls[j] as XmlSchemaPSVIIDCNodePtr;
for k in 0..nb_fields {
ret = xml_schema_are_values_equal(
(*(*(*node).keys.add(k as usize))).val,
(*(*(*par_node).keys.add(k as usize))).val,
);
if ret == -1 {
return -1;
}
if ret == 0 {
break;
}
}
}
if ret == 1 {
break;
}
j += 1;
}
if j != old_dupls {
continue;
}
}
if old_num != 0 {
let mut j = 0;
while j < old_num {
par_node = par_nodes[j];
if nb_fields == 1 {
ret = xml_schema_are_values_equal(
(*(*(*node).keys.add(0))).val,
(*(*(*par_node).keys.add(0))).val,
);
if ret == -1 {
return -1;
}
if ret == 0 {
j += 1;
continue;
}
} else {
for k in 0..nb_fields {
ret = xml_schema_are_values_equal(
(*(*(*node).keys.add(k as usize))).val,
(*(*(*par_node).keys.add(k as usize))).val,
);
if ret == -1 {
return -1;
}
if ret == 0 {
break;
}
}
}
if ret == 1 {
break;
}
j += 1;
}
if j != old_num {
old_num -= 1;
par_nodes.swap_remove(j);
if (*par_bind).dupls.is_null() {
(*par_bind).dupls =
xml_schema_item_list_create::<*mut c_void>();
if (*par_bind).dupls.is_null() {
return -1;
}
}
(*(*par_bind).dupls).push(par_node as _);
} else {
par_nodes = &mut (*par_bind).node_table;
par_nodes.push(node);
}
}
}
} else {
par_bind = xml_schema_idc_new_binding((*bind).definition);
if par_bind.is_null() {
return -1;
}
if !(*bind).node_table.is_empty() {
if (*vctxt).psvi_expose_idcnode_tables == 0 {
(*par_bind).node_table = take(&mut (*bind).node_table);
} else {
(*par_bind).node_table = (*bind).node_table.clone();
}
}
if !(*bind).dupls.is_null() {
if !(*par_bind).dupls.is_null() {
xml_schema_item_list_free((*par_bind).dupls);
}
(*par_bind).dupls = (*bind).dupls;
(*bind).dupls = null_mut();
}
if !par_table.is_null() {
if (*par_table).is_null() {
*par_table = par_bind;
} else {
(*par_bind).next = *par_table;
*par_table = par_bind;
}
}
}
}
bind = (*bind).next;
}
0
}
}
unsafe fn xml_schema_validator_pop_elem(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
let inode: XmlSchemaNodeInfoPtr = (*vctxt).inode;
if (*vctxt).nb_attr_infos != 0 {
(*vctxt).clear_attr_infos();
}
'internal_error: {
'end_elem: {
if (*inode).flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED != 0 {
(*vctxt).skip_depth = (*vctxt).depth - 1;
break 'end_elem;
}
if (*inode).type_def.is_null()
|| (*inode).flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE != 0
{
break 'end_elem;
}
'character_content: {
'skip_nilled: {
if matches!(
(*(*inode).type_def).content_type,
XmlSchemaContentType::XmlSchemaContentMixed
| XmlSchemaContentType::XmlSchemaContentElements
) {
if (*(*inode).type_def).built_in_type
== XmlSchemaValType::XmlSchemasAnytype
{
break 'character_content;
}
if (*inode).flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT == 0 {
let mut values = [const { Cow::Borrowed("") }; 10];
let mut terminal: i32 = 0;
let regex_ctxt = (*inode).regex_ctxt.get_or_insert_with(|| {
Box::new(XmlRegExecCtxt::new(
(*(*inode).type_def).cont_model.clone().unwrap(),
Some(xml_schema_vcontent_model_callback),
vctxt as _,
))
});
if INODE_NILLED!(inode) {
ret = 0;
break 'skip_nilled;
}
let values = regex_ctxt.next_values(&mut values, &mut terminal);
ret = regex_ctxt.push_string(None, null_mut());
if ret < 0 || (ret == 0 && !INODE_NILLED!(inode)) {
ret = 1;
(*inode).flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
if let Some((nbval, nbneg, values)) = values {
xml_schema_complex_type_err(
vctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavElementContent,
None,
None,
"Missing child element(s)",
nbval,
nbneg,
values,
);
}
} else {
ret = 0;
}
}
}
}
if (*(*inode).type_def).content_type
== XmlSchemaContentType::XmlSchemaContentElements
{
break 'end_elem;
}
}
if !(*vctxt).value.is_null() {
xml_schema_free_value((*vctxt).value);
(*vctxt).value = null_mut();
}
if (*inode).decl.is_null() {
if wxs_is_simple((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*inode).type_def,
(*inode).value,
);
} else if WXS_HAS_SIMPLE_CONTENT!((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*(*inode).type_def).content_type_def,
(*inode).value,
);
}
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPopElem",
"calling xmlSchemaVCheckCVCSimpleType()"
);
break 'internal_error;
}
break 'end_elem;
}
if !(*(*inode).decl).value.is_null()
&& (*inode).flags & XML_SCHEMA_ELEM_INFO_EMPTY != 0
&& !INODE_NILLED!(inode)
{
'default_psvi: {
if (*inode).flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE != 0 {
ret = xml_schema_check_cos_valid_default(
vctxt,
(*(*inode).decl).value,
&raw mut (*inode).val,
);
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPopElem",
"calling xmlSchemaCheckCOSValidDefault()"
);
break 'internal_error;
}
break 'end_elem;
}
break 'default_psvi;
}
if wxs_is_simple((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*inode).type_def,
(*(*inode).decl).value,
);
} else if WXS_HAS_SIMPLE_CONTENT!((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*(*inode).type_def).content_type_def,
(*(*inode).decl).value,
);
}
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPopElem",
"calling xmlSchemaVCheckCVCSimpleType()"
);
break 'internal_error;
}
break 'end_elem;
}
}
if (*vctxt).options & XmlSchemaValidOption::XmlSchemaValVcICreate as i32 != 0 {
if let Some(mut node) = (*inode).node {
let norm_value = (*(*inode).type_def)
.normalize_value(
CStr::from_ptr((*(*inode).decl).value as *const i8)
.to_string_lossy()
.as_ref(),
)
.map_or(null_mut(), |res| {
xml_strndup(res.as_ptr(), res.len() as i32)
});
let text_child = if !norm_value.is_null() {
let text_child = xml_new_doc_text(
node.doc,
Some(
&CStr::from_ptr(norm_value as *const i8).to_string_lossy(),
),
);
xml_free(norm_value as _);
text_child
} else {
xml_new_doc_text(
node.doc,
Some(
CStr::from_ptr((*(*inode).decl).value as *const i8)
.to_string_lossy()
.as_ref(),
),
)
};
if let Some(text_child) = text_child {
node.add_child(text_child.into());
} else {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPopElem",
"calling xmlNewDocText()"
);
break 'internal_error;
}
}
}
} else if !INODE_NILLED!(inode) {
if wxs_is_simple((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*inode).type_def,
(*inode).value,
);
} else if WXS_HAS_SIMPLE_CONTENT!((*inode).type_def) {
ret = xml_schema_vcheck_inode_data_type(
vctxt,
inode,
(*(*inode).type_def).content_type_def,
(*inode).value,
);
}
if ret != 0 {
if ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaValidatorPopElem",
"calling xmlSchemaVCheckCVCSimpleType()"
);
break 'internal_error;
}
break 'end_elem;
}
if !(*(*inode).decl).value.is_null()
&& (*(*inode).decl).flags & XML_SCHEMAS_ELEM_FIXED != 0
{
if (*inode).flags & XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT != 0 {
ret = XmlParserErrors::XmlSchemavCvcElt5_2_2_1 as i32;
VERROR!(
vctxt,
ret.try_into().unwrap(),
null_mut(),
"The content must not contain element nodes since there is a fixed value constraint"
);
break 'end_elem;
} else {
if WXS_HAS_MIXED_CONTENT!((*inode).type_def) {
if !xml_str_equal((*inode).value, (*(*inode).decl).value) {
let value = CStr::from_ptr((*inode).value as *const i8)
.to_string_lossy();
let vc_value =
CStr::from_ptr((*(*inode).decl).value as *const i8)
.to_string_lossy();
ret = XmlParserErrors::XmlSchemavCvcElt5_2_2_2_1 as i32;
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
ret.try_into().unwrap(),
None,
null_mut(),
format!("The initial value '{value}' does not match the fixed value constraint '{vc_value}'").as_str(),
Some(&value),
Some(&vc_value)
);
break 'end_elem;
}
} else if WXS_HAS_SIMPLE_CONTENT!((*inode).type_def) {
let value =
CStr::from_ptr((*inode).value as *const i8).to_string_lossy();
let vc_value = CStr::from_ptr((*(*inode).decl).value as *const i8)
.to_string_lossy();
if !xml_str_equal((*inode).value, (*(*inode).decl).value) {
ret = XmlParserErrors::XmlSchemavCvcElt5_2_2_2_2 as i32;
xml_schema_custom_err(
vctxt as XmlSchemaAbstractCtxtPtr,
ret.try_into().unwrap(),
None,
null_mut(),
format!("The actual value '{value}' does not match the fixed value constraint '{vc_value}'").as_str(),
Some(&value),
Some(&vc_value)
);
break 'end_elem;
}
}
}
}
}
}
if (*vctxt).depth < 0 {
return 0;
}
if (*vctxt).depth == (*vctxt).skip_depth {
(*vctxt).skip_depth = -1;
}
if (*inode).applied_xpath != 0
&& xml_schema_xpath_process_history(vctxt, (*vctxt).depth) == -1
{
break 'internal_error;
}
if !(*inode).idc_matchers.is_null()
&& ((*vctxt).has_keyrefs != 0 || (*vctxt).create_idcnode_tables != 0)
&& xml_schema_idc_fill_node_tables(vctxt, inode) == -1
{
break 'internal_error;
}
if (*(*vctxt).inode).has_keyrefs != 0 && xml_schema_check_cvc_idc_key_ref(vctxt) == -1 {
break 'internal_error;
}
if !(*inode).idc_table.is_null()
&& (*vctxt).depth > 0
&& ((*vctxt).has_keyrefs != 0 || (*vctxt).create_idcnode_tables != 0)
{
if xml_schema_bubble_idc_node_tables(vctxt) == -1 {
break 'internal_error;
}
}
(*vctxt).clear_elem_info(inode);
if (*vctxt).depth == 0 {
(*vctxt).depth -= 1;
(*vctxt).inode = null_mut();
return 0;
}
if !(*vctxt).aidcs.is_null() {
let mut aidc: XmlSchemaIDCAugPtr = (*vctxt).aidcs;
while {
if (*aidc).keyref_depth == (*vctxt).depth {
(*aidc).keyref_depth = -1;
}
aidc = (*aidc).next;
!aidc.is_null()
} {}
}
(*vctxt).depth -= 1;
(*vctxt).inode = *(*vctxt).elem_infos.add((*vctxt).depth as usize);
return ret;
}
(*vctxt).err = -1;
-1
}
}
unsafe fn xml_schema_vdoc_walk(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
let mut ielem: XmlSchemaNodeInfoPtr = null_mut();
let val_root = if let Some(validation_root) = (*vctxt).validation_root {
Some(validation_root)
} else if let Some(doc) = (*vctxt).doc {
doc.get_root_element()
} else {
None
};
if val_root.is_none() {
VERROR!(
vctxt,
1i32.try_into().unwrap(),
null_mut(),
"The document has no document element"
);
return 1;
}
(*vctxt).depth = -1;
(*vctxt).validation_root = val_root;
let mut node = val_root;
'main: while let Some(cur_node) = node {
'goto_leave_node: {
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
if let Some(next) = cur_node
.next
.map(|node| XmlNodePtr::try_from(node).unwrap())
{
node = Some(next);
continue 'main;
} else {
node = cur_node.parent().map(|p| XmlNodePtr::try_from(p).unwrap());
break 'goto_leave_node;
}
}
if cur_node.element_type() == XmlElementType::XmlElementNode {
(*vctxt).depth += 1;
if xml_schema_validator_push_elem(vctxt) == -1 {
return -1;
}
ielem = (*vctxt).inode;
(*ielem).node = cur_node.into();
(*ielem).node_line = cur_node.line as _;
(*ielem).local_name = cur_node.name().map(|name| name.into_owned());
if let Some(ns) = cur_node.ns {
(*ielem).ns_name = ns.href.as_deref().map(|href| href.to_owned());
}
(*ielem).flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
(*vctxt).nb_attr_infos = 0;
if cur_node.properties.is_some() {
let mut attr = cur_node.properties;
while let Some(cur_attr) = attr {
let ns_name = cur_attr.ns.as_deref().and_then(|ns| ns.href.as_deref());
let value = cur_attr
.children()
.and_then(|c| c.get_string(cur_attr.doc, 1))
.map(|c| CString::new(c).unwrap());
let value = xml_strdup(
value
.as_ref()
.map_or(null_mut(), |v| v.as_ptr() as *const u8),
);
ret = xml_schema_validator_push_attribute(
vctxt,
Some(cur_attr),
(*ielem).node_line,
&cur_attr.name,
ns_name,
0,
value,
1,
);
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaDocWalk",
"calling xmlSchemaValidatorPushAttribute()"
);
return -1;
}
attr = cur_attr.next;
}
}
ret = xml_schema_validate_elem(vctxt);
if ret != 0 {
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaDocWalk",
"calling xmlSchemaValidateElem()"
);
return -1;
}
break 'goto_leave_node;
}
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
break 'goto_leave_node;
}
} else if matches!(
cur_node.element_type(),
XmlElementType::XmlTextNode | XmlElementType::XmlCDATASectionNode
) {
if !ielem.is_null() && (*ielem).flags & XML_SCHEMA_ELEM_INFO_EMPTY != 0 {
(*ielem).flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
}
ret = xml_schema_vpush_text(
vctxt,
cur_node.element_type() as _,
cur_node.content.as_deref(),
XML_SCHEMA_PUSH_TEXT_PERSIST,
null_mut(),
);
if ret < 0 {
VERROR_INT!(vctxt, "xmlSchemaVDocWalk", "calling xmlSchemaVPushText()");
return -1;
}
} else if matches!(
cur_node.element_type(),
XmlElementType::XmlEntityNode | XmlElementType::XmlEntityRefNode
) {
VERROR_INT!(
vctxt,
"xmlSchemaVDocWalk",
"there is at least one entity reference in the node-tree currently being validated. Processing of entities with this XML Schema processor is not supported (yet). Please substitute entities before validation."
);
return -1;
} else {
break 'goto_leave_node;
}
if let Some(children) = cur_node
.children
.map(|children| XmlNodePtr::try_from(children).unwrap())
{
node = Some(children);
continue 'main;
}
}
'leave_node: while let Some(cur_node) = node {
if cur_node.element_type() == XmlElementType::XmlElementNode {
if Some(cur_node) != (*(*vctxt).inode).node {
VERROR_INT!(vctxt, "xmlSchemaVDocWalk", "element position mismatch");
return -1;
}
ret = xml_schema_validator_pop_elem(vctxt);
if ret != 0 && ret < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaVDocWalk",
"calling xmlSchemaValidatorPopElem()"
);
return -1;
}
if Some(cur_node) == val_root {
break 'main;
}
}
if let Some(next) = cur_node
.next
.map(|node| XmlNodePtr::try_from(node).unwrap())
{
node = Some(next);
continue 'main;
} else {
node = cur_node.parent.map(|p| XmlNodePtr::try_from(p).unwrap());
continue 'leave_node;
}
}
}
ret
}
}
#[doc(alias = "xmlSchemaIDCFreeMatcherList")]
pub(crate) unsafe fn xml_schema_idc_free_matcher_list(mut matcher: XmlSchemaIDCMatcherPtr) {
unsafe {
let mut next: XmlSchemaIDCMatcherPtr;
while !matcher.is_null() {
next = (*matcher).next;
if !(*matcher).key_seqs.is_null() {
for i in 0..(*matcher).size_key_seqs {
if !(*(*matcher).key_seqs.add(i as usize)).is_null() {
xml_free(*(*matcher).key_seqs.add(i as usize) as _);
}
}
xml_free((*matcher).key_seqs as _);
}
if !(*matcher).targets.is_null() {
if (*matcher).idc_type == XmlSchemaTypeType::XmlSchemaTypeIDCKeyref as i32 {
let mut idc_node: XmlSchemaPSVIIDCNodePtr;
for i in 0..(*(*matcher).targets).items.len() {
idc_node = (*(*matcher).targets).items[i] as XmlSchemaPSVIIDCNodePtr;
xml_free((*idc_node).keys as _);
xml_free(idc_node as _);
}
}
xml_schema_item_list_free((*matcher).targets);
}
if !(*matcher).htab.is_null() {
xml_hash_free((*matcher).htab, Some(xml_free_idc_hash_entry));
}
xml_free(matcher as _);
matcher = next;
}
}
}
unsafe fn xml_schema_post_run(vctxt: XmlSchemaValidCtxtPtr) {
unsafe {
if (*vctxt).xsi_assemble != 0 && !(*vctxt).schema.is_null() {
xml_schema_free((*vctxt).schema);
(*vctxt).schema = null_mut();
}
(*vctxt).clear();
}
}
unsafe fn xml_schema_vstart(vctxt: XmlSchemaValidCtxtPtr) -> i32 {
unsafe {
let mut ret: i32 = 0;
if xml_schema_pre_run(vctxt) < 0 {
return -1;
}
#[cfg(feature = "libxml_reader")]
let f = !(*vctxt).reader.is_null();
#[cfg(not(feature = "libxml_reader"))]
let f = false;
if (*vctxt).doc.is_some() {
ret = xml_schema_vdoc_walk(vctxt);
} else if f {
} else if let Some(ctxt) = (*vctxt)
.parser_ctxt
.as_deref_mut()
.filter(|ctxt| ctxt.sax.is_some())
{
ret = ctxt.parse_document();
} else {
VERROR_INT!(vctxt, "xmlSchemaVStart", "no instance to validate");
ret = -1;
}
xml_schema_post_run(vctxt);
if ret == 0 {
ret = (*vctxt).err;
}
ret
}
}
#[doc(alias = "xmlSchemaValidateDoc")]
pub unsafe fn xml_schema_validate_doc(ctxt: XmlSchemaValidCtxtPtr, doc: XmlDocPtr) -> i32 {
unsafe {
if ctxt.is_null() {
return -1;
}
(*ctxt).doc = Some(doc);
(*ctxt).node = doc.get_root_element();
if (*ctxt).node.is_none() {
xml_schema_custom_err(
ctxt as XmlSchemaAbstractCtxtPtr,
XmlParserErrors::XmlSchemavDocumentElementMissing,
Some(doc.into()),
null_mut(),
"The document has no document element",
None,
None,
);
return (*ctxt).err;
}
(*ctxt).validation_root = (*ctxt).node;
xml_schema_vstart(ctxt)
}
}
#[doc(alias = "xmlSchemaValidateOneElement")]
pub unsafe fn xml_schema_validate_one_element(
ctxt: XmlSchemaValidCtxtPtr,
elem: XmlNodePtr,
) -> i32 {
unsafe {
if ctxt.is_null() || elem.element_type() != XmlElementType::XmlElementNode {
return -1;
}
if (*ctxt).schema.is_null() {
return -1;
}
(*ctxt).doc = elem.doc;
(*ctxt).node = elem.into();
(*ctxt).validation_root = elem.into();
xml_schema_vstart(ctxt)
}
}
#[doc(alias = "xmlSchemaValidateStreamLocator")]
unsafe fn xml_schema_validate_stream_locator(
ctx: *mut c_void,
file: *mut Option<String>,
line: *mut u64,
) -> i32 {
unsafe {
if ctx.is_null() || (file.is_null() && line.is_null()) {
return -1;
}
if !file.is_null() {
*file = None;
}
if !line.is_null() {
*line = 0;
}
let ctxt: XmlParserCtxtPtr = ctx as XmlParserCtxtPtr;
if let Some(input) = (*ctxt).input() {
if !file.is_null() {
*file = input.filename.clone();
}
if !line.is_null() {
*line = input.line as _;
}
return 0;
}
-1
}
}
#[doc(alias = "xmlSchemaValidateStream")]
pub unsafe fn xml_schema_validate_stream<'a>(
ctxt: XmlSchemaValidCtxtPtr<'a>,
input: XmlParserInputBuffer<'a>,
enc: XmlCharEncoding,
sax: Option<Box<XmlSAXHandler>>,
user_data: Option<GenericErrorContext>,
) -> i32 {
unsafe {
let mut plug: XmlSchemaSAXPlugPtr = null_mut();
let mut ret: i32;
if ctxt.is_null() {
return -1;
}
let mut pctxt = if sax.is_some() {
let Ok(new) = XmlParserCtxt::new_sax_parser(sax, user_data) else {
return -1;
};
new
} else {
let Some(mut new) = XmlParserCtxt::new() else {
return -1;
};
new.sax = None;
new
};
pctxt.linenumbers = 1;
if let Some(input_stream) = XmlParserInput::from_io(&mut pctxt, input, enc) {
pctxt.input_push(input_stream);
plug = xml_schema_sax_plug(ctxt, &mut pctxt.sax, &raw mut pctxt.user_data);
(*ctxt).parser_ctxt = Some(Box::new(pctxt));
xml_schema_validate_set_locator(
ctxt,
Some(xml_schema_validate_stream_locator),
(*ctxt).parser_ctxt.as_deref_mut().unwrap() as XmlParserCtxtPtr as _,
);
if plug.is_null() {
ret = -1;
} else {
(*ctxt).enc = enc;
(*ctxt).flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
ret = xml_schema_vstart(ctxt);
let ctxt = (*ctxt).parser_ctxt.take().unwrap();
if ret == 0 && !ctxt.well_formed {
ret = ctxt.err_no;
if ret == 0 {
ret = 1;
}
}
}
} else {
ret = -1;
}
if !plug.is_null() {
xml_schema_sax_unplug(plug).ok();
}
ret
}
}
const XML_SAX_PLUG_MAGIC: u32 = 0xdc43ba21;
pub type XmlSchemaSAXPlugPtr<'a> = *mut XmlSchemaSAXPlugStruct<'a>;
#[repr(C)]
pub struct XmlSchemaSAXPlugStruct<'a> {
magic: u32,
user_sax: Option<Box<XmlSAXHandler>>,
user_data: Option<GenericErrorContext>,
schemas_sax: XmlSAXHandler,
ctxt: XmlSchemaValidCtxtPtr<'a>,
}
fn xml_schema_sax_handle_start_element_ns(
ctxt: &mut XmlParserCtxt,
localname: &str,
_prefix: Option<&str>,
uri: Option<&str>,
namespaces: &[(Option<String>, String)],
_nb_defaulted: usize,
attributes: &[(String, Option<String>, Option<String>, String)],
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
let vctxt = (*plug).ctxt;
let mut ret: i32;
(*vctxt).depth += 1;
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
return;
}
if xml_schema_validator_push_elem(vctxt) == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleStartElementNs",
"calling xmlSchemaValidatorPushElem()"
);
(*vctxt).err = -1;
ctxt.stop();
return;
}
let ielem: XmlSchemaNodeInfoPtr = (*vctxt).inode;
(*ielem).node_line = xml_sax2_get_line_number(ctxt);
(*ielem).local_name = Some(localname.to_owned());
(*ielem).ns_name = uri.map(|uri| uri.to_owned());
(*ielem).flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
let namespaces = namespaces
.iter()
.map(|(pre, loc)| {
let pre = pre.as_deref().map(|p| CString::new(p).unwrap());
let loc = CString::new(loc.as_str()).unwrap();
(pre, loc)
})
.collect::<Vec<_>>(); for (pre, href) in &namespaces {
if (*ielem).ns_bindings.is_null() {
(*ielem).ns_bindings = xml_malloc(10 * size_of::<*const XmlChar>()) as _;
if (*ielem).ns_bindings.is_null() {
xml_schema_verr_memory(
vctxt,
"allocating namespace bindings for SAX validation",
None,
);
(*vctxt).err = -1;
ctxt.stop();
return;
}
(*ielem).nb_ns_bindings = 0;
(*ielem).size_ns_bindings = 5;
} else if (*ielem).size_ns_bindings <= (*ielem).nb_ns_bindings {
(*ielem).size_ns_bindings *= 2;
(*ielem).ns_bindings = xml_realloc(
(*ielem).ns_bindings as *mut c_void,
(*ielem).size_ns_bindings as usize * 2 * size_of::<*const XmlChar>(),
) as _;
if (*ielem).ns_bindings.is_null() {
xml_schema_verr_memory(
vctxt,
"re-allocating namespace bindings for SAX validation",
None,
);
(*vctxt).err = -1;
ctxt.stop();
return;
}
}
*(*ielem)
.ns_bindings
.add((*ielem).nb_ns_bindings as usize * 2) =
pre.as_deref().map_or(null(), |p| p.as_ptr() as *const u8);
if !href.is_empty() {
*(*ielem)
.ns_bindings
.add((*ielem).nb_ns_bindings as usize * 2 + 1) = null_mut();
} else {
*(*ielem)
.ns_bindings
.add((*ielem).nb_ns_bindings as usize * 2 + 1) = href.as_ptr() as *const u8;
}
(*ielem).nb_ns_bindings += 1;
}
let attributes = attributes
.iter()
.map(|attr| {
let pre = attr.1.as_deref().map(|pre| CString::new(pre).unwrap());
let val = CString::new(attr.3.replace("&", "&").as_str()).unwrap();
(attr.0.clone(), pre, attr.2.clone(), val)
})
.collect::<Vec<_>>();
for attr in &attributes {
ret = xml_schema_validator_push_attribute(
vctxt,
None,
(*ielem).node_line,
attr.0.as_str(),
attr.2.as_deref(),
0,
attr.3.as_ptr() as *mut u8,
1,
);
if ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleStartElementNs",
"calling xmlSchemaValidatorPushAttribute()"
);
(*vctxt).err = -1;
ctxt.stop();
return;
}
}
ret = xml_schema_validate_elem(vctxt);
if ret != 0 && ret == -1 {
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleStartElementNs",
"calling xmlSchemaValidateElem()"
);
(*vctxt).err = -1;
ctxt.stop();
}
drop(namespaces);
drop(attributes);
}
}
fn xml_schema_sax_handle_end_element_ns(
ctxt: &mut XmlParserCtxt,
localname: &str,
_prefix: Option<&str>,
uri: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
let vctxt = (*plug).ctxt;
if (*vctxt).skip_depth != -1 {
if (*vctxt).depth > (*vctxt).skip_depth {
(*vctxt).depth -= 1;
return;
} else {
(*vctxt).skip_depth = -1;
}
}
if (*(*vctxt).inode).local_name.as_deref() != Some(localname)
|| (*(*vctxt).inode).ns_name.as_deref() != uri
{
VERROR_INT!(vctxt, "xmlSchemaSAXHandleEndElementNs", "elem pop mismatch");
}
let res: i32 = xml_schema_validator_pop_elem(vctxt);
if res < 0 {
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleEndElementNs",
"calling xmlSchemaValidatorPopElem()"
);
(*vctxt).err = -1;
ctxt.stop();
}
}
}
fn xml_schema_sax_handle_text(ctxt: &mut XmlParserCtxt, ch: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
let vctxt = (*plug).ctxt;
if (*vctxt).depth < 0 {
return;
}
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
return;
}
if (*(*vctxt).inode).flags & XML_SCHEMA_ELEM_INFO_EMPTY != 0 {
(*(*vctxt).inode).flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
}
if xml_schema_vpush_text(
vctxt,
XmlElementType::XmlTextNode as i32,
Some(ch),
XML_SCHEMA_PUSH_TEXT_VOLATILE,
null_mut(),
) == -1
{
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleCDataSection",
"calling xmlSchemaVPushText()"
);
(*vctxt).err = -1;
ctxt.stop();
}
}
}
fn xml_schema_sax_handle_cdata_section(ctxt: &mut XmlParserCtxt, ch: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
let vctxt = (*plug).ctxt;
if (*vctxt).depth < 0 {
return;
}
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
return;
}
if (*(*vctxt).inode).flags & XML_SCHEMA_ELEM_INFO_EMPTY != 0 {
(*(*vctxt).inode).flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
}
if xml_schema_vpush_text(
vctxt,
XmlElementType::XmlCDATASectionNode as i32,
Some(ch),
XML_SCHEMA_PUSH_TEXT_VOLATILE,
null_mut(),
) == -1
{
VERROR_INT!(
vctxt,
"xmlSchemaSAXHandleCDataSection",
"calling xmlSchemaVPushText()"
);
(*vctxt).err = -1;
ctxt.stop();
}
}
}
fn xml_schema_sax_handle_reference(ctxt: &mut XmlParserCtxt, _name: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
let vctxt = (*plug).ctxt;
if (*vctxt).depth < 0 {
return;
}
if (*vctxt).skip_depth != -1 && (*vctxt).depth >= (*vctxt).skip_depth {
}
}
}
fn internal_subset_split(
ctxt: &mut XmlParserCtxt,
name: Option<&str>,
external_id: Option<&str>,
system_id: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(internal_subset) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.internal_subset)
{
internal_subset(ctxt, name, external_id, system_id);
}
}
}
}
fn is_standalone_split(ctxt: &mut XmlParserCtxt) -> i32 {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(is_standalone) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.is_standalone)
{
return is_standalone(ctxt);
}
}
0
}
}
fn has_internal_subset_split(ctxt: &mut XmlParserCtxt) -> i32 {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(has_internal_subset) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.has_internal_subset)
{
return has_internal_subset(ctxt);
}
}
0
}
}
fn has_external_subset_split(ctxt: &mut XmlParserCtxt) -> i32 {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(has_external_subset) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.has_external_subset)
{
return has_external_subset(ctxt);
}
}
0
}
}
fn external_subset_split(
ctxt: &mut XmlParserCtxt,
name: Option<&str>,
external_id: Option<&str>,
system_id: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(external_subset) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.external_subset)
{
external_subset(ctxt, name, external_id, system_id);
}
}
}
}
fn resolve_entity_split(
ctxt: &mut XmlParserCtxt,
public_id: Option<&str>,
system_id: Option<&str>,
) -> Option<XmlParserInput<'static>> {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(resolve_entity) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.resolve_entity)
{
return resolve_entity(ctxt, public_id, system_id);
}
}
None
}
}
fn get_entity_split(ctxt: &mut XmlParserCtxt, name: &str) -> Option<XmlEntityPtr> {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(get_entity) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.get_entity)
{
return get_entity(ctxt, name);
}
}
None
}
}
fn get_parameter_entity_split(ctxt: &mut XmlParserCtxt, name: &str) -> Option<XmlEntityPtr> {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(get_parameter_entity) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.get_parameter_entity)
{
return get_parameter_entity(ctxt, name);
}
}
None
}
}
fn entity_decl_split(
ctxt: &mut XmlParserCtxt,
name: &str,
typ: XmlEntityType,
public_id: Option<&str>,
system_id: Option<&str>,
content: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(entity_decl) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.entity_decl)
{
entity_decl(ctxt, name, typ, public_id, system_id, content);
}
}
}
}
fn attribute_decl_split(
ctxt: &mut XmlParserCtxt,
elem: &str,
name: &str,
typ: XmlAttributeType,
def: XmlAttributeDefault,
default_value: Option<&str>,
tree: Option<Box<XmlEnumeration>>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(attribute_decl) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.attribute_decl)
{
attribute_decl(ctxt, elem, name, typ, def, default_value, tree);
}
}
}
}
fn element_decl_split(
ctxt: &mut XmlParserCtxt,
name: &str,
typ: Option<XmlElementTypeVal>,
content: Option<Rc<ElementContent>>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(element_decl) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.element_decl)
{
element_decl(ctxt, name, typ, content);
}
}
}
}
fn notation_decl_split(
ctxt: &mut XmlParserCtxt,
name: &str,
public_id: Option<&str>,
system_id: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(notation_decl) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.notation_decl)
{
notation_decl(ctxt, name, public_id, system_id);
}
}
}
}
fn unparsed_entity_decl_split(
ctxt: &mut XmlParserCtxt,
name: &str,
public_id: Option<&str>,
system_id: Option<&str>,
notation_name: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(unparsed_entity_decl) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.unparsed_entity_decl)
{
unparsed_entity_decl(ctxt, name, public_id, system_id, notation_name);
}
}
}
}
fn set_document_locator_split(ctxt: &mut XmlParserCtxt, loc: XmlSAXLocator) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(set_document_locator) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.set_document_locator)
{
set_document_locator(ctxt, loc);
}
}
}
}
fn start_document_split(ctxt: &mut XmlParserCtxt) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(start_document) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.start_document)
{
start_document(ctxt);
}
}
}
}
fn end_document_split(ctxt: &mut XmlParserCtxt) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(end_document) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.end_document)
{
end_document(ctxt);
}
}
}
}
fn processing_instruction_split(ctxt: &mut XmlParserCtxt, target: &str, data: Option<&str>) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(processing_instruction) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.processing_instruction)
{
processing_instruction(ctxt, target, data);
}
}
}
}
fn comment_split(ctxt: &mut XmlParserCtxt, value: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if !plug.is_null() {
if let Some(comment) = (*plug).user_sax.as_deref_mut().and_then(|sax| sax.comment) {
comment(ctxt, value);
}
}
}
}
fn warning_split(_ctx: Option<GenericErrorContext>, _msg: &str) {
}
fn error_split(_ctx: Option<GenericErrorContext>, _msg: &str) {
}
fn fatal_error_split(_ctx: Option<GenericErrorContext>, _msg: &str) {
}
fn characters_split(ctxt: &mut XmlParserCtxt, ch: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(characters) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.characters)
{
characters(ctxt, ch);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_text(ctxt, ch);
}
}
}
fn ignorable_whitespace_split(ctxt: &mut XmlParserCtxt, ch: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(ignorable_whitespace) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.ignorable_whitespace)
{
ignorable_whitespace(ctxt, ch);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_text(ctxt, ch);
}
}
}
fn cdata_block_split(ctxt: &mut XmlParserCtxt, value: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(cdata_block) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.cdata_block)
{
cdata_block(ctxt, value);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_cdata_section(ctxt, value);
}
}
}
fn reference_split(ctxt: &mut XmlParserCtxt, name: &str) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(reference) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.reference)
{
reference(ctxt, name);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_reference(ctxt, name);
}
}
}
fn start_element_ns_split(
ctxt: &mut XmlParserCtxt,
localname: &str,
prefix: Option<&str>,
uri: Option<&str>,
namespaces: &[(Option<String>, String)],
nb_defaulted: usize,
attributes: &[(String, Option<String>, Option<String>, String)],
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(start_element_ns) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.start_element_ns)
{
start_element_ns(
ctxt,
localname,
prefix,
uri,
namespaces,
nb_defaulted,
attributes,
);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_start_element_ns(
ctxt,
localname,
prefix,
uri,
namespaces,
nb_defaulted,
attributes,
);
}
}
}
fn end_element_ns_split(
ctxt: &mut XmlParserCtxt,
localname: &str,
prefix: Option<&str>,
uri: Option<&str>,
) {
unsafe {
let user_data = ctxt.user_data.clone().unwrap();
let lock = user_data.lock();
let plug = *lock.downcast_ref::<XmlSchemaSAXPlugPtr>().unwrap();
if plug.is_null() {
return;
}
if let Some(end_element_ns) = (*plug)
.user_sax
.as_deref_mut()
.and_then(|sax| sax.end_element_ns)
{
end_element_ns(ctxt, localname, prefix, uri);
}
if !(*plug).ctxt.is_null() {
xml_schema_sax_handle_end_element_ns(ctxt, localname, prefix, uri);
}
}
}
#[doc(alias = "xmlSchemaSAXPlug")]
pub unsafe fn xml_schema_sax_plug<'a>(
ctxt: XmlSchemaValidCtxtPtr<'a>,
sax: &mut Option<Box<XmlSAXHandler>>,
user_data: *mut Option<GenericErrorContext>,
) -> XmlSchemaSAXPlugPtr<'a> {
unsafe {
if ctxt.is_null() || user_data.is_null() {
return null_mut();
}
let mut old_sax = sax.take();
if old_sax
.as_deref()
.is_some_and(|sax| sax.initialized != XML_SAX2_MAGIC as u32)
{
return null_mut();
}
if old_sax.as_deref().is_some_and(|sax| {
sax.start_element_ns.is_none()
&& sax.end_element_ns.is_none()
&& (sax.start_element.is_some() || sax.end_element.is_some())
}) {
return null_mut();
}
let ret: XmlSchemaSAXPlugPtr =
xml_malloc(size_of::<XmlSchemaSAXPlugStruct>()) as XmlSchemaSAXPlugPtr;
if ret.is_null() {
return null_mut();
}
memset(ret as _, 0, size_of::<XmlSchemaSAXPlugStruct>());
(*ret).magic = XML_SAX_PLUG_MAGIC as _;
(*ret).schemas_sax.initialized = XML_SAX2_MAGIC as _;
(*ret).ctxt = ctxt;
if let Some(old_sax) = old_sax.as_deref_mut() {
if old_sax.internal_subset.is_some() {
(*ret).schemas_sax.internal_subset = Some(internal_subset_split);
}
if old_sax.is_standalone.is_some() {
(*ret).schemas_sax.is_standalone = Some(is_standalone_split);
}
if old_sax.has_internal_subset.is_some() {
(*ret).schemas_sax.has_internal_subset = Some(has_internal_subset_split);
}
if old_sax.has_external_subset.is_some() {
(*ret).schemas_sax.has_external_subset = Some(has_external_subset_split);
}
if old_sax.resolve_entity.is_some() {
(*ret).schemas_sax.resolve_entity = Some(resolve_entity_split);
}
if old_sax.get_entity.is_some() {
(*ret).schemas_sax.get_entity = Some(get_entity_split);
}
if old_sax.entity_decl.is_some() {
(*ret).schemas_sax.entity_decl = Some(entity_decl_split);
}
if old_sax.notation_decl.is_some() {
(*ret).schemas_sax.notation_decl = Some(notation_decl_split);
}
if old_sax.attribute_decl.is_some() {
(*ret).schemas_sax.attribute_decl = Some(attribute_decl_split);
}
if old_sax.element_decl.is_some() {
(*ret).schemas_sax.element_decl = Some(element_decl_split);
}
if old_sax.unparsed_entity_decl.is_some() {
(*ret).schemas_sax.unparsed_entity_decl = Some(unparsed_entity_decl_split);
}
if old_sax.set_document_locator.is_some() {
(*ret).schemas_sax.set_document_locator = Some(set_document_locator_split);
}
if old_sax.start_document.is_some() {
(*ret).schemas_sax.start_document = Some(start_document_split);
}
if old_sax.end_document.is_some() {
(*ret).schemas_sax.end_document = Some(end_document_split);
}
if old_sax.processing_instruction.is_some() {
(*ret).schemas_sax.processing_instruction = Some(processing_instruction_split);
}
if old_sax.comment.is_some() {
(*ret).schemas_sax.comment = Some(comment_split);
}
if old_sax.warning.is_some() {
(*ret).schemas_sax.warning = Some(warning_split);
}
if old_sax.error.is_some() {
(*ret).schemas_sax.error = Some(error_split);
}
if old_sax.fatal_error.is_some() {
(*ret).schemas_sax.fatal_error = Some(fatal_error_split);
}
if old_sax.get_parameter_entity.is_some() {
(*ret).schemas_sax.get_parameter_entity = Some(get_parameter_entity_split);
}
if old_sax.external_subset.is_some() {
(*ret).schemas_sax.external_subset = Some(external_subset_split);
}
(*ret).schemas_sax.characters = Some(characters_split);
if (old_sax.ignorable_whitespace.is_some() || old_sax.characters.is_some())
&& old_sax
.ignorable_whitespace
.zip(old_sax.characters)
.is_none_or(|(l, r)| !fn_addr_eq(l, r))
{
(*ret).schemas_sax.ignorable_whitespace = Some(ignorable_whitespace_split);
} else {
(*ret).schemas_sax.ignorable_whitespace = Some(characters_split);
}
(*ret).schemas_sax.cdata_block = Some(cdata_block_split);
(*ret).schemas_sax.reference = Some(reference_split);
(*ret).schemas_sax.start_element_ns = Some(start_element_ns_split);
(*ret).schemas_sax.end_element_ns = Some(end_element_ns_split);
(*ret).user_data = (*user_data).clone();
*user_data = Some(GenericErrorContext::new(
ret as XmlSchemaSAXPlugPtr<'static>,
));
} else {
(*ret).schemas_sax.start_element_ns = Some(xml_schema_sax_handle_start_element_ns);
(*ret).schemas_sax.end_element_ns = Some(xml_schema_sax_handle_end_element_ns);
(*ret).schemas_sax.ignorable_whitespace = Some(xml_schema_sax_handle_text);
(*ret).schemas_sax.characters = Some(xml_schema_sax_handle_text);
(*ret).schemas_sax.cdata_block = Some(xml_schema_sax_handle_cdata_section);
(*ret).schemas_sax.reference = Some(xml_schema_sax_handle_reference);
(*ret).user_data = Some(GenericErrorContext::new(
ctxt as XmlSchemaValidCtxtPtr<'static>,
));
*user_data = (*ret).user_data.clone();
}
(*ret).user_sax = old_sax;
*sax = Some(Box::new(take(&mut (*ret).schemas_sax)));
(*ctxt).flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
xml_schema_pre_run(ctxt);
ret
}
}
#[doc(alias = "xmlSchemaSAXUnplug")]
pub unsafe fn xml_schema_sax_unplug(
plug: XmlSchemaSAXPlugPtr,
) -> Result<(Option<Box<XmlSAXHandler>>, Option<GenericErrorContext>), i32> {
unsafe {
if plug.is_null() || (*plug).magic != XML_SAX_PLUG_MAGIC {
return Err(-1);
}
(*plug).magic = 0;
xml_schema_post_run((*plug).ctxt);
let user_sax = (*plug).user_sax.take();
let user_data = (*plug).user_data.clone();
xml_free(plug as _);
Ok((user_sax, user_data))
}
}
#[doc(alias = "xmlSchemaValidateSetLocator")]
pub unsafe fn xml_schema_validate_set_locator(
vctxt: XmlSchemaValidCtxtPtr,
f: Option<XmlSchemaValidityLocatorFunc>,
ctxt: *mut c_void,
) {
unsafe {
if vctxt.is_null() {
return;
}
(*vctxt).loc_func = f;
(*vctxt).loc_ctxt = ctxt;
}
}
#[cfg(test)]
mod tests {
use crate::{
globals::reset_last_error,
libxml::xmlmemory::xml_mem_blocks,
test_util::*,
xmlschemas::{context::xml_schema_new_mem_parser_ctxt, dump::xml_schema_dump},
};
use super::*;
#[test]
fn test_xml_schema_dump() {
#[cfg(all(feature = "schema", feature = "libxml_output"))]
unsafe {
let mut leaks = 0;
for n_output in 0..GEN_NB_FILE_PTR {
for n_schema in 0..GEN_NB_XML_SCHEMA_PTR {
let mem_base = xml_mem_blocks();
let mut output = gen_file_ptr(n_output, 0).unwrap();
let schema = gen_xml_schema_ptr(n_schema, 1);
xml_schema_dump(&mut output, schema);
des_xml_schema_ptr(n_schema, schema, 1);
reset_last_error();
if mem_base != xml_mem_blocks() {
leaks += 1;
eprint!(
"Leak of {} blocks found in xmlSchemaDump",
xml_mem_blocks() - mem_base
);
assert!(leaks == 0, "{leaks} Leaks are found in xmlSchemaDump()");
eprint!(" {}", n_output);
eprintln!(" {}", n_schema);
}
}
}
}
}
#[test]
fn test_xml_schema_is_valid() {
#[cfg(feature = "schema")]
unsafe {
let mut leaks = 0;
for n_ctxt in 0..GEN_NB_XML_SCHEMA_VALID_CTXT_PTR {
let mem_base = xml_mem_blocks();
let ctxt = gen_xml_schema_valid_ctxt_ptr(n_ctxt, 0);
let ret_val = xml_schema_is_valid(ctxt);
desret_int(ret_val);
des_xml_schema_valid_ctxt_ptr(n_ctxt, ctxt, 0);
reset_last_error();
if mem_base != xml_mem_blocks() {
leaks += 1;
eprint!(
"Leak of {} blocks found in xmlSchemaIsValid",
xml_mem_blocks() - mem_base
);
assert!(leaks == 0, "{leaks} Leaks are found in xmlSchemaIsValid()");
eprintln!(" {}", n_ctxt);
}
}
}
}
#[test]
fn test_xml_schema_new_mem_parser_ctxt() {
#[cfg(feature = "schema")]
unsafe {
let mut leaks = 0;
for n_buffer in 0..GEN_NB_CONST_CHAR_PTR {
for n_size in 0..GEN_NB_INT {
let mem_base = xml_mem_blocks();
let buffer = gen_const_char_ptr(n_buffer, 0);
let mut size = gen_int(n_size, 1);
if !buffer.is_null() && size > xml_strlen(buffer as _) {
size = 0;
}
let ret_val = xml_schema_new_mem_parser_ctxt(buffer, size);
desret_xml_schema_parser_ctxt_ptr(ret_val);
des_const_char_ptr(n_buffer, buffer, 0);
des_int(n_size, size, 1);
reset_last_error();
if mem_base != xml_mem_blocks() {
leaks += 1;
eprint!(
"Leak of {} blocks found in xmlSchemaNewMemParserCtxt",
xml_mem_blocks() - mem_base
);
assert!(
leaks == 0,
"{leaks} Leaks are found in xmlSchemaNewMemParserCtxt()"
);
eprint!(" {}", n_buffer);
eprintln!(" {}", n_size);
}
}
}
}
}
}