2002-04-16 15:50:10 +00:00
/*
* 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>
2003-02-06 08:22:32 +00:00
# include <libxml/xpath.h>
# include <libxml/uri.h>
2002-04-16 15:50:10 +00:00
# include <libxml/xmlschemas.h>
# include <libxml/schemasInternals.h>
# include <libxml/xmlschemastypes.h>
2002-05-03 07:29:38 +00:00
# ifdef HAVE_MATH_H
# include <math.h>
# endif
2002-04-16 15:50:10 +00:00
# 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 ,
2002-05-03 07:29:38 +00:00
XML_SCHEMAS_TIME ,
XML_SCHEMAS_GDAY ,
XML_SCHEMAS_GMONTH ,
XML_SCHEMAS_GMONTHDAY ,
XML_SCHEMAS_GYEAR ,
XML_SCHEMAS_GYEARMONTH ,
XML_SCHEMAS_DATE ,
XML_SCHEMAS_DATETIME ,
XML_SCHEMAS_DURATION ,
2002-09-16 10:51:38 +00:00
XML_SCHEMAS_FLOAT ,
XML_SCHEMAS_DOUBLE ,
2003-02-06 23:41:59 +00:00
XML_SCHEMAS_BOOLEAN ,
2003-02-06 08:22:32 +00:00
XML_SCHEMAS_INT ,
2002-04-16 15:50:10 +00:00
XML_SCHEMAS_ ,
XML_SCHEMAS_XXX
} xmlSchemaValType ;
unsigned long powten [ 10 ] = {
1 , 10 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000L ,
100000000L , 1000000000L
} ;
2002-05-03 07:29:38 +00:00
/* Date value */
typedef struct _xmlSchemaValDate xmlSchemaValDate ;
typedef xmlSchemaValDate * xmlSchemaValDatePtr ;
struct _xmlSchemaValDate {
long year ;
unsigned int mon : 4 ; /* 1 <= mon <= 12 */
unsigned int day : 5 ; /* 1 <= day <= 31 */
unsigned int hour : 5 ; /* 0 <= hour <= 23 */
unsigned int min : 6 ; /* 0 <= min <= 59 */
double sec ;
int tz_flag : 1 ; /* is tzo explicitely set? */
int tzo : 11 ; /* -1440 <= tzo <= 1440 */
} ;
/* Duration value */
typedef struct _xmlSchemaValDuration xmlSchemaValDuration ;
typedef xmlSchemaValDuration * xmlSchemaValDurationPtr ;
struct _xmlSchemaValDuration {
long mon ; /* mon stores years also */
long day ;
double sec ; /* sec stores min and hour also */
} ;
2002-04-16 15:50:10 +00:00
typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal ;
typedef xmlSchemaValDecimal * xmlSchemaValDecimalPtr ;
struct _xmlSchemaValDecimal {
/* would use long long but not portable */
unsigned long base ;
unsigned int extra ;
2002-05-22 06:40:27 +00:00
unsigned int sign : 1 ;
2002-04-16 15:50:10 +00:00
int frac : 7 ;
int total : 8 ;
} ;
struct _xmlSchemaVal {
xmlSchemaValType type ;
union {
2002-05-22 06:40:27 +00:00
xmlSchemaValDecimal decimal ;
2002-05-03 07:29:38 +00:00
xmlSchemaValDate date ;
xmlSchemaValDuration dur ;
2002-09-16 10:51:38 +00:00
float f ;
double d ;
2003-02-06 23:41:59 +00:00
int b ;
2002-04-16 15:50:10 +00:00
} value ;
} ;
static int xmlSchemaTypesInitialized = 0 ;
static xmlHashTablePtr xmlSchemaTypesBank = NULL ;
2003-01-27 12:35:42 +00:00
/*
* Basic types
*/
2002-04-16 15:50:10 +00:00
static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL ;
2002-05-03 07:29:38 +00:00
static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL ;
2002-04-16 15:50:10 +00:00
static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL ;
2002-05-03 07:29:38 +00:00
static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL ;
2002-04-16 15:50:10 +00:00
static xmlSchemaTypePtr xmlSchemaTypeNmtoken = NULL ;
2002-09-16 10:51:38 +00:00
static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL ;
2003-02-06 23:41:59 +00:00
static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL ;
2002-09-16 10:51:38 +00:00
static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL ;
2003-02-06 08:22:32 +00:00
static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL ;
2003-02-04 14:43:39 +00:00
static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL ;
2002-04-16 15:50:10 +00:00
2003-01-27 12:35:42 +00:00
/*
* Derived types
*/
static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL ;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL ;
2003-02-04 14:43:39 +00:00
static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL ;
2003-01-27 12:35:42 +00:00
2002-04-16 15:50:10 +00:00
/*
* 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 ) ;
2003-01-27 12:35:42 +00:00
/*
* primitive datatypes
*/
2002-04-16 15:50:10 +00:00
xmlSchemaTypeStringDef = xmlSchemaInitBasicType ( " string " ) ;
xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType ( " anyType " ) ;
xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType ( " anySimpleType " ) ;
xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType ( " decimal " ) ;
xmlSchemaTypeDateDef = xmlSchemaInitBasicType ( " date " ) ;
2002-05-03 07:29:38 +00:00
xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType ( " dateTime " ) ;
xmlSchemaTypeTimeDef = xmlSchemaInitBasicType ( " time " ) ;
xmlSchemaTypeGYearDef = xmlSchemaInitBasicType ( " gYear " ) ;
xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType ( " gYearMonth " ) ;
xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType ( " gMonth " ) ;
xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType ( " gMonthDay " ) ;
xmlSchemaTypeGDayDef = xmlSchemaInitBasicType ( " gDay " ) ;
xmlSchemaTypeDurationDef = xmlSchemaInitBasicType ( " duration " ) ;
2002-04-16 15:50:10 +00:00
xmlSchemaTypeNmtoken = xmlSchemaInitBasicType ( " NMTOKEN " ) ;
2002-09-16 10:51:38 +00:00
xmlSchemaTypeFloatDef = xmlSchemaInitBasicType ( " float " ) ;
xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType ( " double " ) ;
2003-02-06 23:41:59 +00:00
xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType ( " boolean " ) ;
2003-02-06 08:22:32 +00:00
xmlSchemaTypeNameDef = xmlSchemaInitBasicType ( " Name " ) ;
2003-02-04 14:43:39 +00:00
xmlSchemaTypeQNameDef = xmlSchemaInitBasicType ( " QName " ) ;
xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType ( " anyURI " ) ;
2002-04-16 15:50:10 +00:00
2003-01-27 12:35:42 +00:00
/*
* derived datatypes
*/
xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType ( " integer " ) ; ;
xmlSchemaTypeNonPositiveIntegerDef = xmlSchemaInitBasicType ( " nonPositiveInteger " ) ; ;
xmlSchemaTypeNegativeIntegerDef = xmlSchemaInitBasicType ( " negativeInteger " ) ; ;
xmlSchemaTypeLongDef = xmlSchemaInitBasicType ( " long " ) ; ;
xmlSchemaTypeIntDef = xmlSchemaInitBasicType ( " int " ) ; ;
xmlSchemaTypeShortDef = xmlSchemaInitBasicType ( " short " ) ; ;
xmlSchemaTypeByteDef = xmlSchemaInitBasicType ( " byte " ) ; ;
xmlSchemaTypeNonNegativeIntegerDef = xmlSchemaInitBasicType ( " nonNegativeInteger " ) ;
xmlSchemaTypeUnsignedLongDef = xmlSchemaInitBasicType ( " unsignedLong " ) ; ;
xmlSchemaTypeUnsignedIntDef = xmlSchemaInitBasicType ( " unsignedInt " ) ; ;
xmlSchemaTypeUnsignedShortDef = xmlSchemaInitBasicType ( " insignedShort " ) ; ;
xmlSchemaTypeUnsignedByteDef = xmlSchemaInitBasicType ( " unsignedByte " ) ; ;
xmlSchemaTypePositiveIntegerDef = xmlSchemaInitBasicType ( " positiveInteger " ) ;
2003-02-04 14:43:39 +00:00
xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType ( " NCName " ) ;
2003-01-27 12:35:42 +00:00
2002-04-16 15:50:10 +00:00
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 ) ) ;
}
2002-05-03 07:29:38 +00:00
/****************************************************************
* *
* Convenience macros and functions *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define IS_TZO_CHAR(c) \
( ( c = = 0 ) | | ( c = = ' Z ' ) | | ( c = = ' + ' ) | | ( c = = ' - ' ) )
# define VALID_YEAR(yr) (yr != 0)
# define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
/* VALID_DAY should only be used when month is unknown */
# define VALID_DAY(day) ((day >= 1) && (day <= 31))
# define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
# define VALID_MIN(min) ((min >= 0) && (min <= 59))
# define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
# define VALID_TZO(tzo) ((tzo > -1440) && (tzo < 1440))
# define IS_LEAP(y) \
( ( ( y % 4 = = 0 ) & & ( y % 100 ! = 0 ) ) | | ( y % 400 = = 0 ) )
static const long daysInMonth [ 12 ] =
{ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 } ;
static const long daysInMonthLeap [ 12 ] =
{ 31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 } ;
2002-05-22 06:40:27 +00:00
# define MAX_DAYINMONTH(yr,mon) \
( IS_LEAP ( yr ) ? daysInMonthLeap [ mon - 1 ] : daysInMonth [ mon - 1 ] )
2002-05-03 07:29:38 +00:00
# define VALID_MDAY(dt) \
( IS_LEAP ( dt - > year ) ? \
( dt - > day < = daysInMonthLeap [ dt - > mon - 1 ] ) : \
( dt - > day < = daysInMonth [ dt - > mon - 1 ] ) )
# define VALID_DATE(dt) \
( VALID_YEAR ( dt - > year ) & & VALID_MONTH ( dt - > mon ) & & VALID_MDAY ( dt ) )
# define VALID_TIME(dt) \
( VALID_HOUR ( dt - > hour ) & & VALID_MIN ( dt - > min ) & & \
VALID_SEC ( dt - > sec ) & & VALID_TZO ( dt - > tzo ) )
# define VALID_DATETIME(dt) \
( VALID_DATE ( dt ) & & VALID_TIME ( dt ) )
# define SECS_PER_MIN (60)
# define SECS_PER_HOUR (60 * SECS_PER_MIN)
# define SECS_PER_DAY (24 * SECS_PER_HOUR)
2002-05-22 06:40:27 +00:00
static const long dayInYearByMonth [ 12 ] =
{ 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 } ;
static const long dayInLeapYearByMonth [ 12 ] =
{ 0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335 } ;
# define DAY_IN_YEAR(day, month, year) \
( ( IS_LEAP ( year ) ? \
dayInLeapYearByMonth [ month - 1 ] : \
dayInYearByMonth [ month - 1 ] ) + day )
# ifdef DEBUG
# define DEBUG_DATE(dt) \
xmlGenericError ( xmlGenericErrorContext , \
" type=%o %04ld-%02u-%02uT%02u:%02u:%03f " , \
dt - > type , dt - > value . date . year , dt - > value . date . mon , \
dt - > value . date . day , dt - > value . date . hour , dt - > value . date . min , \
dt - > value . date . sec ) ; \
if ( dt - > value . date . tz_flag ) \
if ( dt - > value . date . tzo ! = 0 ) \
xmlGenericError ( xmlGenericErrorContext , \
" %+05d \n " , dt - > value . date . tzo ) ; \
else \
xmlGenericError ( xmlGenericErrorContext , " Z \n " ) ; \
else \
xmlGenericError ( xmlGenericErrorContext , " \n " )
# else
# define DEBUG_DATE(dt)
# endif
2002-05-03 07:29:38 +00:00
/**
* _xmlSchemaParseGYear :
* @ dt : pointer to a date structure
* @ str : pointer to the string to analyze
*
* Parses a xs : gYear without time zone and fills in the appropriate
* field of the @ dt structure . @ str is updated to point just after the
* xs : gYear . It is supposed that @ dt - > year is big enough to contain
* the year .
*
* Returns 0 or the error code
*/
static int
_xmlSchemaParseGYear ( xmlSchemaValDatePtr dt , const xmlChar * * str ) {
const xmlChar * cur = * str , * firstChar ;
int isneg = 0 , digcnt = 0 ;
if ( ( ( * cur < ' 0 ' ) | | ( * cur > ' 9 ' ) ) & &
( * cur ! = ' - ' ) & & ( * cur ! = ' + ' ) )
return - 1 ;
if ( * cur = = ' - ' ) {
isneg = 1 ;
cur + + ;
}
firstChar = cur ;
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) {
dt - > year = dt - > year * 10 + ( * cur - ' 0 ' ) ;
cur + + ;
digcnt + + ;
}
/* year must be at least 4 digits (CCYY); over 4
* digits cannot have a leading zero . */
if ( ( digcnt < 4 ) | | ( ( digcnt > 4 ) & & ( * firstChar = = ' 0 ' ) ) )
return 1 ;
if ( isneg )
dt - > year = - dt - > year ;
if ( ! VALID_YEAR ( dt - > year ) )
return 2 ;
* str = cur ;
return 0 ;
}
/**
* PARSE_2_DIGITS :
* @ num : the integer to fill in
* @ cur : an # xmlChar *
* @ invalid : an integer
*
* Parses a 2 - digits integer and updates @ num with the value . @ cur is
* updated to point just after the integer .
* In case of error , @ invalid is set to % TRUE , values of @ num and
* @ cur are undefined .
*/
# define PARSE_2_DIGITS(num, cur, invalid) \
if ( ( cur [ 0 ] < ' 0 ' ) | | ( cur [ 0 ] > ' 9 ' ) | | \
( cur [ 1 ] < ' 0 ' ) | | ( cur [ 1 ] > ' 9 ' ) ) \
invalid = 1 ; \
else \
num = ( cur [ 0 ] - ' 0 ' ) * 10 + ( cur [ 1 ] - ' 0 ' ) ; \
cur + = 2 ;
/**
* PARSE_FLOAT :
* @ num : the double to fill in
* @ cur : an # xmlChar *
* @ invalid : an integer
*
* Parses a float and updates @ num with the value . @ cur is
* updated to point just after the float . The float must have a
* 2 - digits integer part and may or may not have a decimal part .
* In case of error , @ invalid is set to % TRUE , values of @ num and
* @ cur are undefined .
*/
# define PARSE_FLOAT(num, cur, invalid) \
PARSE_2_DIGITS ( num , cur , invalid ) ; \
if ( ! invalid & & ( * cur = = ' . ' ) ) { \
double mult = 1 ; \
cur + + ; \
if ( ( * cur < ' 0 ' ) | | ( * cur > ' 9 ' ) ) \
invalid = 1 ; \
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) { \
mult / = 10 ; \
num + = ( * cur - ' 0 ' ) * mult ; \
cur + + ; \
} \
}
/**
* _xmlSchemaParseGMonth :
* @ dt : pointer to a date structure
* @ str : pointer to the string to analyze
*
* Parses a xs : gMonth without time zone and fills in the appropriate
* field of the @ dt structure . @ str is updated to point just after the
* xs : gMonth .
*
* Returns 0 or the error code
*/
static int
_xmlSchemaParseGMonth ( xmlSchemaValDatePtr dt , const xmlChar * * str ) {
const xmlChar * cur = * str ;
int ret = 0 ;
PARSE_2_DIGITS ( dt - > mon , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( ! VALID_MONTH ( dt - > mon ) )
return 2 ;
* str = cur ;
return 0 ;
}
/**
* _xmlSchemaParseGDay :
* @ dt : pointer to a date structure
* @ str : pointer to the string to analyze
*
* Parses a xs : gDay without time zone and fills in the appropriate
* field of the @ dt structure . @ str is updated to point just after the
* xs : gDay .
*
* Returns 0 or the error code
*/
static int
_xmlSchemaParseGDay ( xmlSchemaValDatePtr dt , const xmlChar * * str ) {
const xmlChar * cur = * str ;
int ret = 0 ;
PARSE_2_DIGITS ( dt - > day , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( ! VALID_DAY ( dt - > day ) )
return 2 ;
* str = cur ;
return 0 ;
}
/**
* _xmlSchemaParseTime :
* @ dt : pointer to a date structure
* @ str : pointer to the string to analyze
*
* Parses a xs : time without time zone and fills in the appropriate
* fields of the @ dt structure . @ str is updated to point just after the
* xs : time .
* In case of error , values of @ dt fields are undefined .
*
* Returns 0 or the error code
*/
static int
_xmlSchemaParseTime ( xmlSchemaValDatePtr dt , const xmlChar * * str ) {
const xmlChar * cur = * str ;
unsigned int hour = 0 ; /* use temp var in case str is not xs:time */
int ret = 0 ;
PARSE_2_DIGITS ( hour , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( * cur ! = ' : ' )
return 1 ;
cur + + ;
/* the ':' insures this string is xs:time */
dt - > hour = hour ;
PARSE_2_DIGITS ( dt - > min , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( * cur ! = ' : ' )
return 1 ;
cur + + ;
PARSE_FLOAT ( dt - > sec , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( ! VALID_TIME ( dt ) )
return 2 ;
* str = cur ;
return 0 ;
}
/**
* _xmlSchemaParseTimeZone :
* @ dt : pointer to a date structure
* @ str : pointer to the string to analyze
*
* Parses a time zone without time zone and fills in the appropriate
* field of the @ dt structure . @ str is updated to point just after the
* time zone .
*
* Returns 0 or the error code
*/
static int
_xmlSchemaParseTimeZone ( xmlSchemaValDatePtr dt , const xmlChar * * str ) {
const xmlChar * cur = * str ;
int ret = 0 ;
if ( str = = NULL )
return - 1 ;
switch ( * cur ) {
case 0 :
dt - > tz_flag = 0 ;
dt - > tzo = 0 ;
break ;
case ' Z ' :
dt - > tz_flag = 1 ;
dt - > tzo = 0 ;
cur + + ;
break ;
case ' + ' :
case ' - ' : {
int isneg = 0 , tmp = 0 ;
isneg = ( * cur = = ' - ' ) ;
cur + + ;
PARSE_2_DIGITS ( tmp , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( ! VALID_HOUR ( tmp ) )
return 2 ;
if ( * cur ! = ' : ' )
return 1 ;
cur + + ;
dt - > tzo = tmp * 60 ;
PARSE_2_DIGITS ( tmp , cur , ret ) ;
if ( ret ! = 0 )
return ret ;
if ( ! VALID_MIN ( tmp ) )
return 2 ;
dt - > tzo + = tmp ;
if ( isneg )
dt - > tzo = - dt - > tzo ;
if ( ! VALID_TZO ( dt - > tzo ) )
return 2 ;
2002-05-22 06:40:27 +00:00
dt - > tz_flag = 1 ;
2002-05-03 07:29:38 +00:00
break ;
}
default :
return 1 ;
}
* str = cur ;
return 0 ;
}
/****************************************************************
* *
* XML Schema Dates / Times Datatypes Handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* PARSE_DIGITS :
* @ num : the integer to fill in
* @ cur : an # xmlChar *
* @ num_type : an integer flag
*
* Parses a digits integer and updates @ num with the value . @ cur is
* updated to point just after the integer .
* In case of error , @ num_type is set to - 1 , values of @ num and
* @ cur are undefined .
*/
# define PARSE_DIGITS(num, cur, num_type) \
if ( ( * cur < ' 0 ' ) | | ( * cur > ' 9 ' ) ) \
num_type = - 1 ; \
else \
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) { \
num = num * 10 + ( * cur - ' 0 ' ) ; \
cur + + ; \
}
/**
* PARSE_NUM :
* @ num : the double to fill in
* @ cur : an # xmlChar *
* @ num_type : an integer flag
*
* Parses a float or integer and updates @ num with the value . @ cur is
* updated to point just after the number . If the number is a float ,
* then it must have an integer part and a decimal part ; @ num_type will
* be set to 1. If there is no decimal part , @ num_type is set to zero .
* In case of error , @ num_type is set to - 1 , values of @ num and
* @ cur are undefined .
*/
# define PARSE_NUM(num, cur, num_type) \
num = 0 ; \
PARSE_DIGITS ( num , cur , num_type ) ; \
if ( ! num_type & & ( * cur = = ' . ' ) ) { \
double mult = 1 ; \
cur + + ; \
if ( ( * cur < ' 0 ' ) | | ( * cur > ' 9 ' ) ) \
num_type = - 1 ; \
else \
num_type = 1 ; \
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) { \
mult / = 10 ; \
num + = ( * cur - ' 0 ' ) * mult ; \
cur + + ; \
} \
}
/**
2002-05-22 06:40:27 +00:00
* xmlSchemaValidateDates :
2002-05-03 07:29:38 +00:00
* @ type : the predefined type
* @ dateTime : string to analyze
* @ val : the return computed value
*
* Check that @ dateTime conforms to the lexical space of one of the date types .
* 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 .
*/
static int
2002-09-26 09:47:36 +00:00
xmlSchemaValidateDates ( xmlSchemaTypePtr type ATTRIBUTE_UNUSED ,
2002-09-24 14:13:13 +00:00
const xmlChar * dateTime , xmlSchemaValPtr * val ) {
2002-05-03 07:29:38 +00:00
xmlSchemaValPtr dt ;
int ret ;
const xmlChar * cur = dateTime ;
# define RETURN_TYPE_IF_VALID(t) \
if ( IS_TZO_CHAR ( * cur ) ) { \
ret = _xmlSchemaParseTimeZone ( & ( dt - > value . date ) , & cur ) ; \
if ( ret = = 0 ) { \
if ( * cur ! = 0 ) \
goto error ; \
dt - > type = t ; \
if ( val ! = NULL ) \
* val = dt ; \
return 0 ; \
} \
}
if ( dateTime = = NULL )
return - 1 ;
if ( ( * cur ! = ' - ' ) & & ( * cur < ' 0 ' ) & & ( * cur > ' 9 ' ) )
return 1 ;
dt = xmlSchemaNewValue ( XML_SCHEMAS_UNKNOWN ) ;
if ( dt = = NULL )
return - 1 ;
if ( ( cur [ 0 ] = = ' - ' ) & & ( cur [ 1 ] = = ' - ' ) ) {
/*
* It ' s an incomplete date ( xs : gMonthDay , xs : gMonth or
* xs : gDay )
*/
cur + = 2 ;
/* is it an xs:gDay? */
if ( * cur = = ' - ' ) {
+ + cur ;
ret = _xmlSchemaParseGDay ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_GDAY ) ;
goto error ;
}
/*
* it should be an xs : gMonthDay or xs : gMonth
*/
ret = _xmlSchemaParseGMonth ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
if ( * cur ! = ' - ' )
goto error ;
cur + + ;
/* is it an xs:gMonth? */
if ( * cur = = ' - ' ) {
cur + + ;
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_GMONTH ) ;
goto error ;
}
/* it should be an xs:gMonthDay */
ret = _xmlSchemaParseGDay ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_GMONTHDAY ) ;
goto error ;
}
/*
* It ' s a right - truncated date or an xs : time .
* Try to parse an xs : time then fallback on right - truncated dates .
*/
if ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) {
ret = _xmlSchemaParseTime ( & ( dt - > value . date ) , & cur ) ;
if ( ret = = 0 ) {
/* it's an xs:time */
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_TIME ) ;
}
}
/* fallback on date parsing */
cur = dateTime ;
ret = _xmlSchemaParseGYear ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
/* is it an xs:gYear? */
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_GYEAR ) ;
if ( * cur ! = ' - ' )
goto error ;
cur + + ;
ret = _xmlSchemaParseGMonth ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
/* is it an xs:gYearMonth? */
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_GYEARMONTH ) ;
if ( * cur ! = ' - ' )
goto error ;
cur + + ;
ret = _xmlSchemaParseGDay ( & ( dt - > value . date ) , & cur ) ;
if ( ( ret ! = 0 ) | | ! VALID_DATE ( ( & ( dt - > value . date ) ) ) )
goto error ;
/* is it an xs:date? */
RETURN_TYPE_IF_VALID ( XML_SCHEMAS_DATE ) ;
if ( * cur ! = ' T ' )
goto error ;
cur + + ;
/* it should be an xs:dateTime */
ret = _xmlSchemaParseTime ( & ( dt - > value . date ) , & cur ) ;
if ( ret ! = 0 )
goto error ;
ret = _xmlSchemaParseTimeZone ( & ( dt - > value . date ) , & cur ) ;
if ( ( ret ! = 0 ) | | ( * cur ! = 0 ) | | ! VALID_DATETIME ( ( & ( dt - > value . date ) ) ) )
goto error ;
dt - > type = XML_SCHEMAS_DATETIME ;
if ( val ! = NULL )
* val = dt ;
return 0 ;
error :
if ( dt ! = NULL )
xmlSchemaFreeValue ( dt ) ;
return 1 ;
}
/**
2002-05-22 06:40:27 +00:00
* xmlSchemaValidateDuration :
2002-05-03 07:29:38 +00:00
* @ type : the predefined type
* @ duration : string to analyze
* @ val : the return computed value
*
* Check that @ duration conforms to the lexical space of the duration 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 .
*/
static int
2002-09-26 09:47:36 +00:00
xmlSchemaValidateDuration ( xmlSchemaTypePtr type ATTRIBUTE_UNUSED ,
2002-09-24 14:13:13 +00:00
const xmlChar * duration , xmlSchemaValPtr * val ) {
2002-05-03 07:29:38 +00:00
const xmlChar * cur = duration ;
xmlSchemaValPtr dur ;
int isneg = 0 ;
unsigned int seq = 0 ;
if ( duration = = NULL )
return - 1 ;
if ( * cur = = ' - ' ) {
isneg = 1 ;
cur + + ;
}
/* duration must start with 'P' (after sign) */
if ( * cur + + ! = ' P ' )
return 1 ;
dur = xmlSchemaNewValue ( XML_SCHEMAS_DURATION ) ;
if ( dur = = NULL )
return - 1 ;
while ( * cur ! = 0 ) {
double num ;
int num_type = 0 ; /* -1 = invalid, 0 = int, 1 = floating */
const xmlChar desig [ ] = { ' Y ' , ' M ' , ' D ' , ' H ' , ' M ' , ' S ' } ;
const double multi [ ] = { 0.0 , 0.0 , 86400.0 , 3600.0 , 60.0 , 1.0 , 0.0 } ;
/* input string should be empty or invalid date/time item */
if ( seq > = sizeof ( desig ) )
goto error ;
/* T designator must be present for time items */
if ( * cur = = ' T ' ) {
if ( seq < = 3 ) {
seq = 3 ;
cur + + ;
} else
return 1 ;
} else if ( seq = = 3 )
goto error ;
/* parse the number portion of the item */
PARSE_NUM ( num , cur , num_type ) ;
if ( ( num_type = = - 1 ) | | ( * cur = = 0 ) )
goto error ;
/* update duration based on item type */
while ( seq < sizeof ( desig ) ) {
if ( * cur = = desig [ seq ] ) {
/* verify numeric type; only seconds can be float */
if ( ( num_type ! = 0 ) & & ( seq < ( sizeof ( desig ) - 1 ) ) )
goto error ;
switch ( seq ) {
case 0 :
dur - > value . dur . mon = ( long ) num * 12 ;
break ;
case 1 :
dur - > value . dur . mon + = ( long ) num ;
break ;
default :
/* convert to seconds using multiplier */
dur - > value . dur . sec + = num * multi [ seq ] ;
seq + + ;
break ;
}
break ; /* exit loop */
}
/* no date designators found? */
if ( + + seq = = 3 )
goto error ;
}
cur + + ;
}
if ( isneg ) {
dur - > value . dur . mon = - dur - > value . dur . mon ;
dur - > value . dur . day = - dur - > value . dur . day ;
dur - > value . dur . sec = - dur - > value . dur . sec ;
}
if ( val ! = NULL )
* val = dur ;
return 0 ;
error :
if ( dur ! = NULL )
xmlSchemaFreeValue ( dur ) ;
return 1 ;
}
2003-02-06 08:22:32 +00:00
2002-04-16 15:50:10 +00:00
/**
* 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 ;
2003-02-06 08:22:32 +00:00
int ret ;
2002-04-16 15:50:10 +00:00
if ( xmlSchemaTypesInitialized = = 0 )
return ( - 1 ) ;
if ( type = = NULL )
return ( - 1 ) ;
2002-05-22 06:40:27 +00:00
2002-04-16 15:50:10 +00:00
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 ;
2002-05-22 06:40:27 +00:00
int frac = 0 , len , neg = 0 ;
2002-04-16 15:50:10 +00:00
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 + + ;
}
2002-05-22 06:40:27 +00:00
len = cur - tmp ;
2002-04-16 15:50:10 +00:00
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 ;
2002-05-22 06:40:27 +00:00
v - > value . decimal . total = frac + len ;
2002-04-16 15:50:10 +00:00
* val = v ;
}
}
return ( 0 ) ;
2002-05-03 07:29:38 +00:00
} else if ( type = = xmlSchemaTypeDurationDef ) {
2002-05-22 06:40:27 +00:00
return xmlSchemaValidateDuration ( type , value , val ) ;
2002-05-03 07:29:38 +00:00
} else if ( ( type = = xmlSchemaTypeDatetimeDef ) | |
( type = = xmlSchemaTypeTimeDef ) | |
( type = = xmlSchemaTypeDateDef ) | |
( type = = xmlSchemaTypeGYearDef ) | |
( type = = xmlSchemaTypeGYearMonthDef ) | |
( type = = xmlSchemaTypeGMonthDef ) | |
( type = = xmlSchemaTypeGMonthDayDef ) | |
( type = = xmlSchemaTypeGDayDef ) ) {
2002-05-22 06:40:27 +00:00
return xmlSchemaValidateDates ( type , value , val ) ;
2002-04-16 15:50:10 +00:00
} 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 ) ;
2003-02-06 08:22:32 +00:00
} else if ( type = = xmlSchemaTypeIntDef ) {
const xmlChar * cur = value ;
2002-09-16 10:51:38 +00:00
unsigned long base = 0 ;
2003-02-06 08:22:32 +00:00
int total = 0 ;
int sign = 0 ;
if ( cur = = NULL )
return ( 1 ) ;
if ( * cur = = ' - ' ) {
sign = 1 ;
cur + + ;
} else if ( * cur = = ' + ' )
cur + + ;
while ( * cur = = ' 0 ' ) {
total + + ;
cur + + ;
}
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) {
base = base * 10 + ( * cur - ' 0 ' ) ;
total + + ;
cur + + ;
}
if ( * cur ! = 0 )
return ( 1 ) ;
if ( ( sign = = 1 ) & & ( total = = 0 ) )
return ( 1 ) ;
if ( val ! = NULL ) {
v = xmlSchemaNewValue ( XML_SCHEMAS_INT ) ;
if ( v ! = NULL ) {
v - > value . decimal . base = base ;
v - > value . decimal . sign = sign ;
v - > value . decimal . frac = 0 ;
v - > value . decimal . total = total ;
* val = v ;
}
}
return ( 0 ) ;
} else if ( ( type = = xmlSchemaTypeFloatDef ) | |
( type = = xmlSchemaTypeDoubleDef ) ) {
const xmlChar * cur = value ;
int neg = 0 ;
2002-09-16 10:51:38 +00:00
if ( cur = = NULL )
return ( 1 ) ;
2003-02-06 08:22:32 +00:00
if ( ( cur [ 0 ] = = ' N ' ) & & ( cur [ 1 ] = = ' a ' ) & & ( cur [ 2 ] = = ' N ' ) ) {
cur + = 3 ;
if ( * cur ! = 0 )
return ( 1 ) ;
if ( val ! = NULL ) {
if ( type = = xmlSchemaTypeFloatDef ) {
v = xmlSchemaNewValue ( XML_SCHEMAS_FLOAT ) ;
if ( v ! = NULL ) {
v - > value . f = ( float ) xmlXPathNAN ;
} else {
xmlSchemaFreeValue ( v ) ;
return ( - 1 ) ;
}
} else {
v = xmlSchemaNewValue ( XML_SCHEMAS_DOUBLE ) ;
if ( v ! = NULL ) {
v - > value . d = xmlXPathNAN ;
} else {
xmlSchemaFreeValue ( v ) ;
return ( - 1 ) ;
}
}
* val = v ;
}
return ( 0 ) ;
}
2002-09-16 10:51:38 +00:00
if ( * cur = = ' + ' )
cur + + ;
else if ( * cur = = ' - ' ) {
neg = 1 ;
cur + + ;
}
2003-02-18 21:12:46 +00:00
if ( cur [ 0 ] = = 0 )
return ( 1 ) ;
2003-02-06 08:22:32 +00:00
if ( ( cur [ 0 ] = = ' I ' ) & & ( cur [ 1 ] = = ' N ' ) & & ( cur [ 2 ] = = ' F ' ) ) {
cur + = 3 ;
if ( * cur ! = 0 )
return ( 1 ) ;
if ( val ! = NULL ) {
if ( type = = xmlSchemaTypeFloatDef ) {
v = xmlSchemaNewValue ( XML_SCHEMAS_FLOAT ) ;
if ( v ! = NULL ) {
if ( neg )
v - > value . f = ( float ) xmlXPathNINF ;
else
v - > value . f = ( float ) xmlXPathPINF ;
} else {
xmlSchemaFreeValue ( v ) ;
return ( - 1 ) ;
}
} else {
v = xmlSchemaNewValue ( XML_SCHEMAS_DOUBLE ) ;
if ( v ! = NULL ) {
if ( neg )
v - > value . d = xmlXPathNINF ;
else
v - > value . d = xmlXPathPINF ;
} else {
xmlSchemaFreeValue ( v ) ;
return ( - 1 ) ;
}
}
* val = v ;
}
return ( 0 ) ;
}
2002-09-16 10:51:38 +00:00
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) {
cur + + ;
}
if ( * cur = = ' . ' ) {
cur + + ;
2003-02-06 08:22:32 +00:00
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) )
cur + + ;
}
if ( ( * cur = = ' e ' ) | | ( * cur = = ' E ' ) ) {
cur + + ;
if ( * cur = = ' - ' )
2002-09-16 10:51:38 +00:00
cur + + ;
2003-02-06 08:22:32 +00:00
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) )
cur + + ;
}
if ( * cur ! = 0 )
return ( 1 ) ;
if ( val ! = NULL ) {
if ( type = = xmlSchemaTypeFloatDef ) {
v = xmlSchemaNewValue ( XML_SCHEMAS_FLOAT ) ;
if ( v ! = NULL ) {
if ( sscanf ( ( const char * ) value , " %f " , & ( v - > value . f ) ) = = 1 ) {
* val = v ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" failed to scanf float %s \n " , value ) ;
xmlSchemaFreeValue ( v ) ;
return ( 1 ) ;
}
} else {
return ( - 1 ) ;
}
} else {
v = xmlSchemaNewValue ( XML_SCHEMAS_DOUBLE ) ;
if ( v ! = NULL ) {
if ( sscanf ( ( const char * ) value , " %lf " , & ( v - > value . d ) ) = = 1 ) {
* val = v ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" failed to scanf double %s \n " , value ) ;
xmlSchemaFreeValue ( v ) ;
return ( 1 ) ;
}
} else {
return ( - 1 ) ;
}
2002-09-16 10:51:38 +00:00
}
}
2002-09-20 13:36:25 +00:00
return ( 0 ) ;
2003-02-06 08:22:32 +00:00
} else if ( type = = xmlSchemaTypeNameDef ) {
2003-02-14 16:54:11 +00:00
ret = xmlValidateName ( value , 1 ) ;
2003-02-06 08:22:32 +00:00
if ( ( ret = = 0 ) & & ( val ! = NULL ) ) {
TODO ;
}
return ( ret ) ;
} else if ( type = = xmlSchemaTypeQNameDef ) {
2003-02-14 16:54:11 +00:00
ret = xmlValidateQName ( value , 1 ) ;
2003-02-06 08:22:32 +00:00
if ( ( ret = = 0 ) & & ( val ! = NULL ) ) {
TODO ;
}
return ( ret ) ;
} else if ( type = = xmlSchemaTypeNCNameDef ) {
2003-02-14 16:54:11 +00:00
ret = xmlValidateNCName ( value , 1 ) ;
2003-02-06 08:22:32 +00:00
if ( ( ret = = 0 ) & & ( val ! = NULL ) ) {
TODO ;
}
return ( ret ) ;
} else if ( type = = xmlSchemaTypeAnyURIDef ) {
xmlURIPtr uri ;
uri = xmlParseURI ( ( const char * ) value ) ;
if ( uri = = NULL )
return ( 1 ) ;
if ( val ! = NULL ) {
TODO ;
}
xmlFreeURI ( uri ) ;
2002-09-20 13:36:25 +00:00
return ( 0 ) ;
2003-02-06 23:41:59 +00:00
} else if ( type = = xmlSchemaTypeBooleanDef ) {
const xmlChar * cur = value ;
if ( ( cur [ 0 ] = = ' 0 ' ) & & ( cur [ 1 ] = = 0 ) )
ret = 0 ;
else if ( ( cur [ 0 ] = = ' 1 ' ) & & ( cur [ 1 ] = = 0 ) )
ret = 1 ;
else if ( ( cur [ 0 ] = = ' t ' ) & & ( cur [ 1 ] = = ' r ' ) & & ( cur [ 2 ] = = ' u ' ) & &
( cur [ 3 ] = = ' e ' ) & & ( cur [ 4 ] = = 0 ) )
ret = 1 ;
else if ( ( cur [ 0 ] = = ' f ' ) & & ( cur [ 1 ] = = ' a ' ) & & ( cur [ 2 ] = = ' l ' ) & &
( cur [ 3 ] = = ' s ' ) & & ( cur [ 4 ] = = ' e ' ) & & ( cur [ 5 ] = = 0 ) )
ret = 0 ;
else
return ( 1 ) ;
if ( val ! = NULL ) {
v = xmlSchemaNewValue ( XML_SCHEMAS_BOOLEAN ) ;
if ( v ! = NULL ) {
v - > value . b = ret ;
* val = v ;
} else {
return ( - 1 ) ;
}
}
return ( 0 ) ;
2002-04-16 15:50:10 +00:00
} else {
TODO
return ( 0 ) ;
}
2003-02-06 08:22:32 +00:00
return ( - 1 ) ;
2002-04-16 15:50:10 +00:00
}
/**
* 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 ) ;
}
2002-05-03 07:29:38 +00:00
/**
* xmlSchemaCompareDurations :
* @ x : a first duration value
* @ y : a second duration value
*
* Compare 2 durations
*
* Returns - 1 if x < y , 0 if x = = y , 1 if x > y , 2 if x < > y , and - 2 in
* case of error
*/
static int
xmlSchemaCompareDurations ( xmlSchemaValPtr x , xmlSchemaValPtr y )
{
long carry , mon , day ;
double sec ;
long xmon , xday , myear , lyear , minday , maxday ;
static const long dayRange [ 2 ] [ 12 ] = {
{ 0 , 28 , 59 , 89 , 120 , 150 , 181 , 212 , 242 , 273 , 303 , 334 , } ,
{ 0 , 31 , 62 , 92 , 123 , 153 , 184 , 215 , 245 , 276 , 306 , 337 } } ;
if ( ( x = = NULL ) | | ( y = = NULL ) )
2002-05-22 06:40:27 +00:00
return - 2 ;
2002-05-03 07:29:38 +00:00
/* months */
mon = x - > value . dur . mon - y - > value . dur . mon ;
/* seconds */
sec = x - > value . dur . sec - y - > value . dur . sec ;
carry = ( long ) sec / SECS_PER_DAY ;
sec - = ( double ) ( carry * SECS_PER_DAY ) ;
/* days */
day = x - > value . dur . day - y - > value . dur . day + carry ;
/* easy test */
if ( mon = = 0 ) {
if ( day = = 0 )
if ( sec = = 0.0 )
return 0 ;
else if ( sec < 0.0 )
return - 1 ;
else
return 1 ;
else if ( day < 0 )
return - 1 ;
else
return 1 ;
}
if ( mon > 0 ) {
if ( ( day > = 0 ) & & ( sec > = 0.0 ) )
return 1 ;
else {
xmon = mon ;
xday = - day ;
}
} else if ( ( day < = 0 ) & & ( sec < = 0.0 ) ) {
return - 1 ;
} else {
xmon = - mon ;
xday = day ;
}
myear = xmon / 12 ;
lyear = myear / 4 ;
minday = ( myear * 365 ) + ( lyear ! = 0 ? lyear - 1 : 0 ) ;
maxday = ( myear * 365 ) + ( lyear ! = 0 ? lyear + 1 : 0 ) ;
xmon = xmon % 12 ;
minday + = dayRange [ 0 ] [ xmon ] ;
maxday + = dayRange [ 1 ] [ xmon ] ;
if ( maxday < xday )
return 1 ;
else if ( minday > xday )
return - 1 ;
/* indeterminate */
2002-05-22 06:40:27 +00:00
return 2 ;
}
/*
* macros for adding date / times and durations
*/
# define FQUOTIENT(a,b) (floor(((double)a / (double)b)))
# define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
# define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
# define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
/**
* _xmlSchemaDateAdd :
* @ dt : an # xmlSchemaValPtr
* @ dur : an # xmlSchemaValPtr of type # XS_DURATION
*
* Compute a new date / time from @ dt and @ dur . This function assumes @ dt
* is either # XML_SCHEMAS_DATETIME , # XML_SCHEMAS_DATE , # XML_SCHEMAS_GYEARMONTH ,
* or # XML_SCHEMAS_GYEAR .
*
* Returns date / time pointer or NULL .
*/
static xmlSchemaValPtr
_xmlSchemaDateAdd ( xmlSchemaValPtr dt , xmlSchemaValPtr dur )
{
xmlSchemaValPtr ret ;
long carry , tempdays , temp ;
xmlSchemaValDatePtr r , d ;
xmlSchemaValDurationPtr u ;
if ( ( dt = = NULL ) | | ( dur = = NULL ) )
return NULL ;
ret = xmlSchemaNewValue ( dt - > type ) ;
if ( ret = = NULL )
return NULL ;
r = & ( ret - > value . date ) ;
d = & ( dt - > value . date ) ;
u = & ( dur - > value . dur ) ;
/* normalization */
if ( d - > mon = = 0 )
d - > mon = 1 ;
/* normalize for time zone offset */
u - > sec - = ( d - > tzo * 60 ) ;
d - > tzo = 0 ;
/* normalization */
if ( d - > day = = 0 )
d - > day = 1 ;
/* month */
carry = d - > mon + u - > mon ;
r - > mon = MODULO_RANGE ( carry , 1 , 13 ) ;
carry = FQUOTIENT_RANGE ( carry , 1 , 13 ) ;
/* year (may be modified later) */
r - > year = d - > year + carry ;
if ( r - > year = = 0 ) {
if ( d - > year > 0 )
r - > year - - ;
else
r - > year + + ;
}
/* time zone */
r - > tzo = d - > tzo ;
r - > tz_flag = d - > tz_flag ;
/* seconds */
r - > sec = d - > sec + u - > sec ;
carry = FQUOTIENT ( ( long ) r - > sec , 60 ) ;
if ( r - > sec ! = 0.0 ) {
r - > sec = MODULO ( r - > sec , 60.0 ) ;
}
/* minute */
carry + = d - > min ;
r - > min = MODULO ( carry , 60 ) ;
carry = FQUOTIENT ( carry , 60 ) ;
/* hours */
carry + = d - > hour ;
r - > hour = MODULO ( carry , 24 ) ;
carry = FQUOTIENT ( carry , 24 ) ;
/*
* days
* Note we use tempdays because the temporary values may need more
* than 5 bits
*/
if ( ( VALID_YEAR ( r - > year ) ) & & ( VALID_MONTH ( r - > mon ) ) & &
( d - > day > MAX_DAYINMONTH ( r - > year , r - > mon ) ) )
tempdays = MAX_DAYINMONTH ( r - > year , r - > mon ) ;
else if ( d - > day < 1 )
tempdays = 1 ;
else
tempdays = d - > day ;
tempdays + = u - > day + carry ;
while ( 1 ) {
if ( tempdays < 1 ) {
long tmon = MODULO_RANGE ( r - > mon - 1 , 1 , 13 ) ;
long tyr = r - > year + FQUOTIENT_RANGE ( r - > mon - 1 , 1 , 13 ) ;
if ( tyr = = 0 )
tyr - - ;
tempdays + = MAX_DAYINMONTH ( tyr , tmon ) ;
carry = - 1 ;
} else if ( tempdays > MAX_DAYINMONTH ( r - > year , r - > mon ) ) {
tempdays = tempdays - MAX_DAYINMONTH ( r - > year , r - > mon ) ;
carry = 1 ;
} else
break ;
temp = r - > mon + carry ;
r - > mon = MODULO_RANGE ( temp , 1 , 13 ) ;
r - > year = r - > year + FQUOTIENT_RANGE ( temp , 1 , 13 ) ;
if ( r - > year = = 0 ) {
if ( temp < 1 )
r - > year - - ;
else
r - > year + + ;
}
}
r - > day = tempdays ;
/*
* adjust the date / time type to the date values
*/
if ( ret - > type ! = XML_SCHEMAS_DATETIME ) {
if ( ( r - > hour ) | | ( r - > min ) | | ( r - > sec ) )
ret - > type = XML_SCHEMAS_DATETIME ;
else if ( ret - > type ! = XML_SCHEMAS_DATE ) {
if ( ( r - > mon ! = 1 ) & & ( r - > day ! = 1 ) )
ret - > type = XML_SCHEMAS_DATE ;
else if ( ( ret - > type ! = XML_SCHEMAS_GYEARMONTH ) & & ( r - > mon ! = 1 ) )
ret - > type = XML_SCHEMAS_GYEARMONTH ;
}
}
return ret ;
}
/**
* xmlSchemaDupVal :
* @ v : value to duplicate
*
* returns a duplicated value .
*/
static xmlSchemaValPtr
xmlSchemaDupVal ( xmlSchemaValPtr v )
{
xmlSchemaValPtr ret = xmlSchemaNewValue ( v - > type ) ;
if ( ret = = NULL )
return ret ;
memcpy ( ret , v , sizeof ( xmlSchemaVal ) ) ;
return ret ;
}
/**
* xmlSchemaDateNormalize :
* @ dt : an # xmlSchemaValPtr
*
* Normalize @ dt to GMT time .
*
*/
static xmlSchemaValPtr
xmlSchemaDateNormalize ( xmlSchemaValPtr dt , double offset )
{
xmlSchemaValPtr dur , ret ;
if ( dt = = NULL )
return NULL ;
if ( ( ( dt - > type ! = XML_SCHEMAS_TIME ) & &
( dt - > type ! = XML_SCHEMAS_DATETIME ) ) | | ( dt - > value . date . tzo = = 0 ) )
return xmlSchemaDupVal ( dt ) ;
dur = xmlSchemaNewValue ( XML_SCHEMAS_DURATION ) ;
if ( dur = = NULL )
return NULL ;
dur - > value . date . sec - = offset ;
ret = _xmlSchemaDateAdd ( dt , dur ) ;
if ( ret = = NULL )
return NULL ;
xmlSchemaFreeValue ( dur ) ;
/* ret->value.date.tzo = 0; */
return ret ;
}
/**
* _xmlSchemaDateCastYMToDays :
* @ dt : an # xmlSchemaValPtr
*
* Convert mon and year of @ dt to total number of days . Take the
* number of years since ( or before ) 1 AD and add the number of leap
* years . This is a function because negative
* years must be handled a little differently and there is no zero year .
*
* Returns number of days .
*/
static long
_xmlSchemaDateCastYMToDays ( const xmlSchemaValPtr dt )
{
long ret ;
if ( dt - > value . date . year < 0 )
ret = ( dt - > value . date . year * 365 ) +
( ( ( dt - > value . date . year + 1 ) / 4 ) - ( ( dt - > value . date . year + 1 ) / 100 ) +
( ( dt - > value . date . year + 1 ) / 400 ) ) +
DAY_IN_YEAR ( 0 , dt - > value . date . mon , dt - > value . date . year ) ;
else
ret = ( ( dt - > value . date . year - 1 ) * 365 ) +
( ( ( dt - > value . date . year - 1 ) / 4 ) - ( ( dt - > value . date . year - 1 ) / 100 ) +
( ( dt - > value . date . year - 1 ) / 400 ) ) +
DAY_IN_YEAR ( 0 , dt - > value . date . mon , dt - > value . date . year ) ;
return ret ;
}
/**
* TIME_TO_NUMBER :
* @ dt : an # xmlSchemaValPtr
*
* Calculates the number of seconds in the time portion of @ dt .
*
* Returns seconds .
*/
# define TIME_TO_NUMBER(dt) \
( ( double ) ( ( dt - > value . date . hour * SECS_PER_HOUR ) + \
( dt - > value . date . min * SECS_PER_MIN ) ) + dt - > value . date . sec )
/**
* xmlSchemaCompareDates :
* @ x : a first date / time value
* @ y : a second date / time value
*
* Compare 2 date / times
*
* Returns - 1 if x < y , 0 if x = = y , 1 if x > y , 2 if x < > y , and - 2 in
* case of error
*/
static int
xmlSchemaCompareDates ( xmlSchemaValPtr x , xmlSchemaValPtr y )
{
unsigned char xmask , ymask , xor_mask , and_mask ;
xmlSchemaValPtr p1 , p2 , q1 , q2 ;
long p1d , p2d , q1d , q2d ;
if ( ( x = = NULL ) | | ( y = = NULL ) )
return - 2 ;
if ( x - > value . date . tz_flag ) {
if ( ! y - > value . date . tz_flag ) {
p1 = xmlSchemaDateNormalize ( x , 0 ) ;
p1d = _xmlSchemaDateCastYMToDays ( p1 ) + p1 - > value . date . day ;
/* normalize y + 14:00 */
q1 = xmlSchemaDateNormalize ( y , ( 14 * SECS_PER_HOUR ) ) ;
q1d = _xmlSchemaDateCastYMToDays ( q1 ) + q1 - > value . date . day ;
2002-07-01 21:52:03 +00:00
if ( p1d < q1d ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return - 1 ;
2002-07-01 21:52:03 +00:00
} else if ( p1d = = q1d ) {
2002-05-22 06:40:27 +00:00
double sec ;
sec = TIME_TO_NUMBER ( p1 ) - TIME_TO_NUMBER ( q1 ) ;
2002-07-01 21:52:03 +00:00
if ( sec < 0.0 ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return - 1 ;
2002-07-01 21:52:03 +00:00
} else {
2002-05-22 06:40:27 +00:00
/* normalize y - 14:00 */
q2 = xmlSchemaDateNormalize ( y , - ( 14 * SECS_PER_HOUR ) ) ;
q2d = _xmlSchemaDateCastYMToDays ( q2 ) + q2 - > value . date . day ;
2002-07-01 21:52:03 +00:00
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
xmlSchemaFreeValue ( q2 ) ;
2002-05-22 06:40:27 +00:00
if ( p1d > q2d )
return 1 ;
else if ( p1d = = q2d ) {
sec = TIME_TO_NUMBER ( p1 ) - TIME_TO_NUMBER ( q2 ) ;
if ( sec > 0.0 )
return 1 ;
else
return 2 ; /* indeterminate */
}
}
2002-07-01 21:52:03 +00:00
} else {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
}
2002-05-22 06:40:27 +00:00
}
} else if ( y - > value . date . tz_flag ) {
q1 = xmlSchemaDateNormalize ( y , 0 ) ;
q1d = _xmlSchemaDateCastYMToDays ( q1 ) + q1 - > value . date . day ;
/* normalize x - 14:00 */
p1 = xmlSchemaDateNormalize ( x , - ( 14 * SECS_PER_HOUR ) ) ;
p1d = _xmlSchemaDateCastYMToDays ( p1 ) + p1 - > value . date . day ;
2002-07-01 21:52:03 +00:00
if ( p1d < q1d ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return - 1 ;
2002-07-01 21:52:03 +00:00
} else if ( p1d = = q1d ) {
2002-05-22 06:40:27 +00:00
double sec ;
sec = TIME_TO_NUMBER ( p1 ) - TIME_TO_NUMBER ( q1 ) ;
2002-07-01 21:52:03 +00:00
if ( sec < 0.0 ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return - 1 ;
2002-07-01 21:52:03 +00:00
} else {
2002-05-22 06:40:27 +00:00
/* normalize x + 14:00 */
p2 = xmlSchemaDateNormalize ( x , ( 14 * SECS_PER_HOUR ) ) ;
p2d = _xmlSchemaDateCastYMToDays ( p2 ) + p2 - > value . date . day ;
2002-07-01 21:52:03 +00:00
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
xmlSchemaFreeValue ( p2 ) ;
2002-05-22 06:40:27 +00:00
if ( p2d > q1d )
return 1 ;
else if ( p2d = = q1d ) {
sec = TIME_TO_NUMBER ( p2 ) - TIME_TO_NUMBER ( q1 ) ;
if ( sec > 0.0 )
return 1 ;
else
return 2 ; /* indeterminate */
}
}
2002-07-01 21:52:03 +00:00
} else {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
}
}
/*
* if the same type then calculate the difference
*/
if ( x - > type = = y - > type ) {
q1 = xmlSchemaDateNormalize ( y , 0 ) ;
q1d = _xmlSchemaDateCastYMToDays ( q1 ) + q1 - > value . date . day ;
p1 = xmlSchemaDateNormalize ( x , 0 ) ;
p1d = _xmlSchemaDateCastYMToDays ( p1 ) + p1 - > value . date . day ;
2002-07-01 21:52:03 +00:00
if ( p1d < q1d ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return - 1 ;
2002-07-01 21:52:03 +00:00
} else if ( p1d > q1d ) {
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
return 1 ;
2002-07-01 21:52:03 +00:00
} else {
2002-05-22 06:40:27 +00:00
double sec ;
sec = TIME_TO_NUMBER ( p1 ) - TIME_TO_NUMBER ( q1 ) ;
2002-07-01 21:52:03 +00:00
xmlSchemaFreeValue ( p1 ) ;
xmlSchemaFreeValue ( q1 ) ;
2002-05-22 06:40:27 +00:00
if ( sec < 0.0 )
return - 1 ;
else if ( sec > 0.0 )
return 1 ;
}
return 0 ;
}
switch ( x - > type ) {
case XML_SCHEMAS_DATETIME :
xmask = 0xf ;
break ;
case XML_SCHEMAS_DATE :
xmask = 0x7 ;
break ;
case XML_SCHEMAS_GYEAR :
xmask = 0x1 ;
break ;
case XML_SCHEMAS_GMONTH :
xmask = 0x2 ;
break ;
case XML_SCHEMAS_GDAY :
xmask = 0x3 ;
break ;
case XML_SCHEMAS_GYEARMONTH :
xmask = 0x3 ;
break ;
case XML_SCHEMAS_GMONTHDAY :
xmask = 0x6 ;
break ;
case XML_SCHEMAS_TIME :
xmask = 0x8 ;
break ;
default :
xmask = 0 ;
break ;
}
switch ( y - > type ) {
case XML_SCHEMAS_DATETIME :
ymask = 0xf ;
break ;
case XML_SCHEMAS_DATE :
ymask = 0x7 ;
break ;
case XML_SCHEMAS_GYEAR :
ymask = 0x1 ;
break ;
case XML_SCHEMAS_GMONTH :
ymask = 0x2 ;
break ;
case XML_SCHEMAS_GDAY :
ymask = 0x3 ;
break ;
case XML_SCHEMAS_GYEARMONTH :
ymask = 0x3 ;
break ;
case XML_SCHEMAS_GMONTHDAY :
ymask = 0x6 ;
break ;
case XML_SCHEMAS_TIME :
ymask = 0x8 ;
break ;
default :
ymask = 0 ;
break ;
}
xor_mask = xmask ^ ymask ; /* mark type differences */
and_mask = xmask & ymask ; /* mark field specification */
/* year */
if ( xor_mask & 1 )
return 2 ; /* indeterminate */
else if ( and_mask & 1 ) {
if ( x - > value . date . year < y - > value . date . year )
return - 1 ;
else if ( x - > value . date . year > y - > value . date . year )
return 1 ;
}
/* month */
if ( xor_mask & 2 )
return 2 ; /* indeterminate */
else if ( and_mask & 2 ) {
if ( x - > value . date . mon < y - > value . date . mon )
return - 1 ;
else if ( x - > value . date . mon > y - > value . date . mon )
return 1 ;
}
/* day */
if ( xor_mask & 4 )
return 2 ; /* indeterminate */
else if ( and_mask & 4 ) {
if ( x - > value . date . day < y - > value . date . day )
return - 1 ;
else if ( x - > value . date . day > y - > value . date . day )
return 1 ;
}
/* time */
if ( xor_mask & 8 )
return 2 ; /* indeterminate */
else if ( and_mask & 8 ) {
if ( x - > value . date . hour < y - > value . date . hour )
return - 1 ;
else if ( x - > value . date . hour > y - > value . date . hour )
return 1 ;
else if ( x - > value . date . min < y - > value . date . min )
return - 1 ;
else if ( x - > value . date . min > y - > value . date . min )
return 1 ;
else if ( x - > value . date . sec < y - > value . date . sec )
return - 1 ;
else if ( x - > value . date . sec > y - > value . date . sec )
return 1 ;
}
2002-05-03 07:29:38 +00:00
return 0 ;
}
2002-04-16 15:50:10 +00:00
/**
* xmlSchemaCompareValues :
* @ x : a first value
* @ y : a second value
*
* Compare 2 values
*
2002-05-22 06:40:27 +00:00
* Returns - 1 if x < y , 0 if x = = y , 1 if x > y , 2 if x < > y , and - 2 in
* case of error
2002-04-16 15:50:10 +00:00
*/
2002-04-22 16:01:24 +00:00
static int
2002-04-16 15:50:10 +00:00
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 ) ) ;
2002-05-22 06:40:27 +00:00
return ( - 2 ) ;
2002-05-03 07:29:38 +00:00
case XML_SCHEMAS_DURATION :
if ( y - > type = = XML_SCHEMAS_DURATION )
return ( xmlSchemaCompareDurations ( x , y ) ) ;
2002-05-22 06:40:27 +00:00
return ( - 2 ) ;
case XML_SCHEMAS_TIME :
case XML_SCHEMAS_GDAY :
case XML_SCHEMAS_GMONTH :
case XML_SCHEMAS_GMONTHDAY :
case XML_SCHEMAS_GYEAR :
case XML_SCHEMAS_GYEARMONTH :
case XML_SCHEMAS_DATE :
case XML_SCHEMAS_DATETIME :
if ( ( y - > type = = XML_SCHEMAS_DATETIME ) | |
( y - > type = = XML_SCHEMAS_TIME ) | |
( y - > type = = XML_SCHEMAS_GDAY ) | |
( y - > type = = XML_SCHEMAS_GMONTH ) | |
( y - > type = = XML_SCHEMAS_GMONTHDAY ) | |
( y - > type = = XML_SCHEMAS_GYEAR ) | |
( y - > type = = XML_SCHEMAS_DATE ) | |
( y - > type = = XML_SCHEMAS_GYEARMONTH ) )
return ( xmlSchemaCompareDates ( x , y ) ) ;
return ( - 2 ) ;
2002-04-16 15:50:10 +00:00
default :
TODO
}
2002-05-22 06:40:27 +00:00
return - 2 ;
2002-04-16 15:50:10 +00:00
}
/**
* xmlSchemaValidateFacet :
2002-12-10 15:19:08 +00:00
* @ base : the base type
2002-04-16 15:50:10 +00:00
* @ 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
2002-09-26 09:47:36 +00:00
xmlSchemaValidateFacet ( xmlSchemaTypePtr base ATTRIBUTE_UNUSED ,
2002-09-24 14:13:13 +00:00
xmlSchemaFacetPtr facet ,
2002-04-16 15:50:10 +00:00
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 ) ;
2002-05-22 06:40:27 +00:00
/* error code */
2002-04-16 15:50:10 +00:00
return ( 1 ) ;
2002-05-03 07:29:38 +00:00
case XML_SCHEMA_FACET_MAXINCLUSIVE :
ret = xmlSchemaCompareValues ( val , facet - > val ) ;
if ( ret = = - 2 ) {
TODO /* error code */
return ( - 1 ) ;
}
if ( ( ret = = - 1 ) | | ( ret = = 0 ) )
return ( 0 ) ;
2002-05-22 06:40:27 +00:00
/* error code */
2002-05-03 07:29:38 +00:00
return ( 1 ) ;
case XML_SCHEMA_FACET_MINEXCLUSIVE :
ret = xmlSchemaCompareValues ( val , facet - > val ) ;
if ( ret = = - 2 ) {
TODO /* error code */
return ( - 1 ) ;
}
if ( ret = = 1 )
return ( 0 ) ;
2002-05-22 06:40:27 +00:00
/* error code */
2002-05-03 07:29:38 +00:00
return ( 1 ) ;
case XML_SCHEMA_FACET_MININCLUSIVE :
ret = xmlSchemaCompareValues ( val , facet - > val ) ;
if ( ret = = - 2 ) {
TODO /* error code */
return ( - 1 ) ;
}
if ( ( ret = = 1 ) | | ( ret = = 0 ) )
return ( 0 ) ;
2002-05-22 06:40:27 +00:00
/* error code */
2002-05-03 07:29:38 +00:00
return ( 1 ) ;
2002-04-17 09:06:27 +00:00
case XML_SCHEMA_FACET_WHITESPACE :
TODO /* whitespaces */
return ( 0 ) ;
2002-04-22 16:01:24 +00:00
case XML_SCHEMA_FACET_MAXLENGTH :
if ( ( facet - > val ! = NULL ) & &
( facet - > val - > type = = XML_SCHEMAS_DECIMAL ) & &
( facet - > val - > value . decimal . frac = = 0 ) ) {
2002-09-24 14:13:13 +00:00
unsigned int len ;
2002-04-22 16:01:24 +00:00
if ( facet - > val - > value . decimal . sign = = 1 )
return ( 1 ) ;
len = xmlUTF8Strlen ( value ) ;
if ( len > facet - > val - > value . decimal . base )
return ( 1 ) ;
return ( 0 ) ;
}
TODO /* error code */
return ( 1 ) ;
2002-04-23 07:12:20 +00:00
case XML_SCHEMA_FACET_ENUMERATION :
if ( ( facet - > value ! = NULL ) & &
( xmlStrEqual ( facet - > value , value ) ) )
return ( 0 ) ;
return ( 1 ) ;
2002-04-16 15:50:10 +00:00
default :
TODO
}
return ( 0 ) ;
}
# endif /* LIBXML_SCHEMAS_ENABLED */