mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-29 11:41:22 +03:00
merged the current state of XML Schemas implementation, it is not
* Makefile.am TODO_SCHEMAS configure.in genUnicode.py testAutomata.c testRegexp.c testSchemas.c xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c include/libxml/Makefile.am include/libxml/schemasInternals.h include/libxml/xmlautomata.h include/libxml/xmlregexp.h include/libxml/xmlschemas.h include/libxml/xmlschemastypes.h include/libxml/xmlunicode.h include/libxml/xmlversion.h.in : merged the current state of XML Schemas implementation, it is not configured in by default, a specific --schemas configure option has been added. * test/automata test/regexp test/schemas Makefile.am result/automata result/regexp result/schemas: merged automata/regexp/schemas regression tests Daniel
This commit is contained in:
490
xmlschemastypes.c
Normal file
490
xmlschemastypes.c
Normal file
@ -0,0 +1,490 @@
|
||||
/*
|
||||
* schemastypes.c : implementation of the XML Schema Datatypes
|
||||
* definition and validity checking
|
||||
*
|
||||
* See Copyright for the status of this software.
|
||||
*
|
||||
* Daniel Veillard <veillard@redhat.com>
|
||||
*/
|
||||
|
||||
#define IN_LIBXML
|
||||
#include "libxml.h"
|
||||
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
|
||||
#include <string.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/parserInternals.h>
|
||||
#include <libxml/hash.h>
|
||||
#include <libxml/valid.h>
|
||||
|
||||
#include <libxml/xmlschemas.h>
|
||||
#include <libxml/schemasInternals.h>
|
||||
#include <libxml/xmlschemastypes.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#define TODO \
|
||||
xmlGenericError(xmlGenericErrorContext, \
|
||||
"Unimplemented block at %s:%d\n", \
|
||||
__FILE__, __LINE__);
|
||||
|
||||
#define XML_SCHEMAS_NAMESPACE_NAME \
|
||||
(const xmlChar *)"http://www.w3.org/2001/XMLSchema"
|
||||
|
||||
typedef enum {
|
||||
XML_SCHEMAS_UNKNOWN = 0,
|
||||
XML_SCHEMAS_STRING,
|
||||
XML_SCHEMAS_NMTOKEN,
|
||||
XML_SCHEMAS_DECIMAL,
|
||||
XML_SCHEMAS_,
|
||||
XML_SCHEMAS_XXX
|
||||
} xmlSchemaValType;
|
||||
|
||||
unsigned long powten[10] = {
|
||||
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
|
||||
100000000L, 1000000000L
|
||||
};
|
||||
|
||||
typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
|
||||
typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
|
||||
struct _xmlSchemaValDecimal {
|
||||
/* would use long long but not portable */
|
||||
unsigned long base;
|
||||
unsigned int extra;
|
||||
int sign:1;
|
||||
int frac:7;
|
||||
int total:8;
|
||||
};
|
||||
|
||||
struct _xmlSchemaVal {
|
||||
xmlSchemaValType type;
|
||||
union {
|
||||
xmlSchemaValDecimal decimal;
|
||||
} value;
|
||||
};
|
||||
|
||||
static int xmlSchemaTypesInitialized = 0;
|
||||
static xmlHashTablePtr xmlSchemaTypesBank = NULL;
|
||||
|
||||
static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
|
||||
static xmlSchemaTypePtr xmlSchemaTypeNmtoken = NULL;
|
||||
|
||||
/*
|
||||
* xmlSchemaInitBasicType:
|
||||
* @name: the type name
|
||||
*
|
||||
* Initialize one default type
|
||||
*/
|
||||
static xmlSchemaTypePtr
|
||||
xmlSchemaInitBasicType(const char *name) {
|
||||
xmlSchemaTypePtr ret;
|
||||
|
||||
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
|
||||
if (ret == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"Could not initilize type %s: out of memory\n", name);
|
||||
return(NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(xmlSchemaType));
|
||||
ret->name = xmlStrdup((const xmlChar *)name);
|
||||
ret->type = XML_SCHEMA_TYPE_BASIC;
|
||||
ret->contentType = XML_SCHEMA_CONTENT_BASIC;
|
||||
xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
|
||||
XML_SCHEMAS_NAMESPACE_NAME, ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* xmlSchemaInitTypes:
|
||||
*
|
||||
* Initialize the default XML Schemas type library
|
||||
*/
|
||||
void
|
||||
xmlSchemaInitTypes(void) {
|
||||
if (xmlSchemaTypesInitialized != 0)
|
||||
return;
|
||||
xmlSchemaTypesBank = xmlHashCreate(40);
|
||||
|
||||
xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string");
|
||||
xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType");
|
||||
xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType");
|
||||
xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal");
|
||||
xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date");
|
||||
xmlSchemaTypePositiveIntegerDef = xmlSchemaInitBasicType("positiveInteger");
|
||||
xmlSchemaTypeNonNegativeIntegerDef =
|
||||
xmlSchemaInitBasicType("nonNegativeInteger");
|
||||
xmlSchemaTypeNmtoken = xmlSchemaInitBasicType("NMTOKEN");
|
||||
|
||||
xmlSchemaTypesInitialized = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaCleanupTypes:
|
||||
*
|
||||
* Cleanup the default XML Schemas type library
|
||||
*/
|
||||
void
|
||||
xmlSchemaCleanupTypes(void) {
|
||||
if (xmlSchemaTypesInitialized == 0)
|
||||
return;
|
||||
xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
|
||||
xmlSchemaTypesInitialized = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaNewValue:
|
||||
* @type: the value type
|
||||
*
|
||||
* Allocate a new simple type value
|
||||
*
|
||||
* Returns a pointer to the new value or NULL in case of error
|
||||
*/
|
||||
static xmlSchemaValPtr
|
||||
xmlSchemaNewValue(xmlSchemaValType type) {
|
||||
xmlSchemaValPtr value;
|
||||
|
||||
value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
|
||||
if (value == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
memset(value, 0, sizeof(xmlSchemaVal));
|
||||
value->type = type;
|
||||
return(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaFreeValue:
|
||||
* @value: the value to free
|
||||
*
|
||||
* Cleanup the default XML Schemas type library
|
||||
*/
|
||||
void
|
||||
xmlSchemaFreeValue(xmlSchemaValPtr value) {
|
||||
if (value == NULL)
|
||||
return;
|
||||
xmlFree(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaGetPredefinedType:
|
||||
* @name: the type name
|
||||
* @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
|
||||
*
|
||||
* Lookup a type in the default XML Schemas type library
|
||||
*
|
||||
* Returns the type if found, NULL otherwise
|
||||
*/
|
||||
xmlSchemaTypePtr
|
||||
xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
|
||||
if (xmlSchemaTypesInitialized == 0)
|
||||
xmlSchemaInitTypes();
|
||||
if (name == NULL)
|
||||
return(NULL);
|
||||
return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
|
||||
}
|
||||
/**
|
||||
* xmlSchemaValidatePredefinedType:
|
||||
* @type: the predefined type
|
||||
* @value: the value to check
|
||||
* @val: the return computed value
|
||||
*
|
||||
* Check that a value conforms to the lexical space of the predefined type.
|
||||
* if true a value is computed and returned in @val.
|
||||
*
|
||||
* Returns 0 if this validates, a positive error code number otherwise
|
||||
* and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
|
||||
xmlSchemaValPtr *val) {
|
||||
xmlSchemaValPtr v;
|
||||
|
||||
if (xmlSchemaTypesInitialized == 0)
|
||||
return(-1);
|
||||
if (type == NULL)
|
||||
return(-1);
|
||||
if (val != NULL)
|
||||
*val = NULL;
|
||||
if (type == xmlSchemaTypeStringDef) {
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypeAnyTypeDef) {
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypeAnySimpleTypeDef) {
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypeNmtoken) {
|
||||
if (xmlValidateNmtokenValue(value))
|
||||
return(0);
|
||||
return(1);
|
||||
} else if (type == xmlSchemaTypeDecimalDef) {
|
||||
const xmlChar *cur = value, *tmp;
|
||||
int frac = 0, main, neg = 0;
|
||||
unsigned long base = 0;
|
||||
if (cur == NULL)
|
||||
return(1);
|
||||
if (*cur == '+')
|
||||
cur++;
|
||||
else if (*cur == '-') {
|
||||
neg = 1;
|
||||
cur++;
|
||||
}
|
||||
tmp = cur;
|
||||
while ((*cur >= '0') && (*cur <= '9')) {
|
||||
base = base * 10 + (*cur - '0');
|
||||
cur++;
|
||||
}
|
||||
main = cur - tmp;
|
||||
if (*cur == '.') {
|
||||
cur++;
|
||||
tmp = cur;
|
||||
while ((*cur >= '0') && (*cur <= '9')) {
|
||||
base = base * 10 + (*cur - '0');
|
||||
cur++;
|
||||
}
|
||||
frac = cur - tmp;
|
||||
}
|
||||
if (*cur != 0)
|
||||
return(1);
|
||||
if (val != NULL) {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
|
||||
if (v != NULL) {
|
||||
v->value.decimal.base = base;
|
||||
v->value.decimal.sign = neg;
|
||||
v->value.decimal.frac = frac;
|
||||
v->value.decimal.total = frac + main;
|
||||
*val = v;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypeDateDef) {
|
||||
const xmlChar *cur = value;
|
||||
if (cur == NULL)
|
||||
return(1);
|
||||
if (*cur == '-')
|
||||
cur++;
|
||||
if ((*cur < '0') || (*cur > '9'))
|
||||
return(1);
|
||||
if ((*cur < '0') || (*cur > '9'))
|
||||
return(1);
|
||||
if ((*cur < '0') || (*cur > '9'))
|
||||
return(1);
|
||||
if ((*cur < '0') || (*cur > '9'))
|
||||
return(1);
|
||||
while ((*cur >= '0') && (*cur <= '9'))
|
||||
cur++;
|
||||
if (*cur != '-')
|
||||
return(1);
|
||||
cur++;
|
||||
if ((*cur != '0') && (*cur != '1'))
|
||||
return(1);
|
||||
if ((*cur == '0') && (cur[1] == '0'))
|
||||
return(1);
|
||||
if ((*cur == '1') && ((cur[1] < '0') || (cur[1] > '2')))
|
||||
return(1);
|
||||
cur += 2;
|
||||
if (*cur != '-')
|
||||
return(1);
|
||||
cur++;
|
||||
if ((*cur < '0') || (*cur > '3'))
|
||||
return(1);
|
||||
if ((*cur == '0') && (cur[1] == '0'))
|
||||
return(1);
|
||||
if ((*cur == '3') && ((cur[1] < '0') || (cur[1] > '1')))
|
||||
return(1);
|
||||
cur += 2;
|
||||
if (*cur != 0)
|
||||
return(1);
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypePositiveIntegerDef) {
|
||||
const xmlChar *cur = value;
|
||||
unsigned long base = 0;
|
||||
int total = 0;
|
||||
if (cur == NULL)
|
||||
return(1);
|
||||
if (*cur == '+')
|
||||
cur++;
|
||||
while ((*cur >= '0') && (*cur <= '9')) {
|
||||
base = base * 10 + (*cur - '0');
|
||||
total++;
|
||||
cur++;
|
||||
}
|
||||
if (*cur != 0)
|
||||
return(1);
|
||||
if (val != NULL) {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
|
||||
if (v != NULL) {
|
||||
v->value.decimal.base = base;
|
||||
v->value.decimal.sign = 0;
|
||||
v->value.decimal.frac = 0;
|
||||
v->value.decimal.total = total;
|
||||
*val = v;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
} else if (type == xmlSchemaTypeNonNegativeIntegerDef) {
|
||||
const xmlChar *cur = value;
|
||||
unsigned long base = 0;
|
||||
int total = 0;
|
||||
int sign = 0;
|
||||
if (cur == NULL)
|
||||
return(1);
|
||||
if (*cur == '-') {
|
||||
sign = 1;
|
||||
cur++;
|
||||
} else if (*cur == '+')
|
||||
cur++;
|
||||
while ((*cur >= '0') && (*cur <= '9')) {
|
||||
base = base * 10 + (*cur - '0');
|
||||
total++;
|
||||
cur++;
|
||||
}
|
||||
if (*cur != 0)
|
||||
return(1);
|
||||
if ((sign == 1) && (base != 0))
|
||||
return(1);
|
||||
if (val != NULL) {
|
||||
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
|
||||
if (v != NULL) {
|
||||
v->value.decimal.base = base;
|
||||
v->value.decimal.sign = 0;
|
||||
v->value.decimal.frac = 0;
|
||||
v->value.decimal.total = total;
|
||||
*val = v;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
} else {
|
||||
TODO
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaCompareDecimals:
|
||||
* @x: a first decimal value
|
||||
* @y: a second decimal value
|
||||
*
|
||||
* Compare 2 decimals
|
||||
*
|
||||
* Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
|
||||
*/
|
||||
static int
|
||||
xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
|
||||
{
|
||||
xmlSchemaValPtr swp;
|
||||
int order = 1;
|
||||
unsigned long tmp;
|
||||
|
||||
if ((x->value.decimal.sign) && (x->value.decimal.sign))
|
||||
order = -1;
|
||||
else if (x->value.decimal.sign)
|
||||
return (-1);
|
||||
else if (y->value.decimal.sign)
|
||||
return (1);
|
||||
if (x->value.decimal.frac == y->value.decimal.frac) {
|
||||
if (x->value.decimal.base < y->value.decimal.base)
|
||||
return (-1);
|
||||
return (x->value.decimal.base > y->value.decimal.base);
|
||||
}
|
||||
if (y->value.decimal.frac > x->value.decimal.frac) {
|
||||
swp = y;
|
||||
y = x;
|
||||
x = swp;
|
||||
order = -order;
|
||||
}
|
||||
tmp =
|
||||
x->value.decimal.base / powten[x->value.decimal.frac -
|
||||
y->value.decimal.frac];
|
||||
if (tmp > y->value.decimal.base)
|
||||
return (order);
|
||||
if (tmp < y->value.decimal.base)
|
||||
return (-order);
|
||||
tmp =
|
||||
y->value.decimal.base * powten[x->value.decimal.frac -
|
||||
y->value.decimal.frac];
|
||||
if (x->value.decimal.base < tmp)
|
||||
return (-order);
|
||||
if (x->value.decimal.base == tmp)
|
||||
return (0);
|
||||
return (order);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaCompareValues:
|
||||
* @x: a first value
|
||||
* @y: a second value
|
||||
*
|
||||
* Compare 2 values
|
||||
*
|
||||
* Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
|
||||
*/
|
||||
int
|
||||
xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
|
||||
if ((x == NULL) || (y == NULL))
|
||||
return(-2);
|
||||
|
||||
switch (x->type) {
|
||||
case XML_SCHEMAS_STRING:
|
||||
TODO
|
||||
case XML_SCHEMAS_DECIMAL:
|
||||
if (y->type == XML_SCHEMAS_DECIMAL)
|
||||
return(xmlSchemaCompareDecimals(x, y));
|
||||
else
|
||||
return(-2);
|
||||
default:
|
||||
TODO
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlSchemaValidateFacet:
|
||||
* @type: the type declaration
|
||||
* @facet: the facet to check
|
||||
* @value: the lexical repr of the value to validate
|
||||
* @val: the precomputed value
|
||||
*
|
||||
* Check a value against a facet condition
|
||||
*
|
||||
* Returns 0 if the element is schemas valid, a positive error code
|
||||
* number otherwise and -1 in case of internal or API error.
|
||||
*/
|
||||
int
|
||||
xmlSchemaValidateFacet(xmlSchemaTypePtr base, xmlSchemaFacetPtr facet,
|
||||
const xmlChar *value, xmlSchemaValPtr val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (facet->type) {
|
||||
case XML_SCHEMA_FACET_PATTERN:
|
||||
ret = xmlRegexpExec(facet->regexp, value);
|
||||
if (ret == 1)
|
||||
return(0);
|
||||
if (ret == 0) {
|
||||
TODO /* error code */
|
||||
return(1);
|
||||
}
|
||||
return(ret);
|
||||
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
|
||||
ret = xmlSchemaCompareValues(val, facet->val);
|
||||
if (ret == -2) {
|
||||
TODO /* error code */
|
||||
return(-1);
|
||||
}
|
||||
if (ret == -1)
|
||||
return(0);
|
||||
TODO /* error code */
|
||||
return(1);
|
||||
default:
|
||||
TODO
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
Reference in New Issue
Block a user