xmlschemastypes.c revision dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3
14255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/*
24255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * schemastypes.c : implementation of the XML Schema Datatypes
34255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *             definition and validity checking
44255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
54255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * See Copyright for the status of this software.
64255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
74255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Daniel Veillard <veillard@redhat.com>
84255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
94255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define IN_LIBXML
114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include "libxml.h"
124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef LIBXML_SCHEMAS_ENABLED
144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <string.h>
164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlmemory.h>
174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/parser.h>
184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/parserInternals.h>
194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/hash.h>
204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/valid.h>
214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlschemas.h>
234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/schemasInternals.h>
244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlschemastypes.h>
254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
26070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#ifdef HAVE_MATH_H
27070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#include <math.h>
28070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#endif
29070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define DEBUG
314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define TODO 								\
334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlGenericError(xmlGenericErrorContext,				\
344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    "Unimplemented block at %s:%d\n",				\
354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            __FILE__, __LINE__);
364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define XML_SCHEMAS_NAMESPACE_NAME \
384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef enum {
414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_UNKNOWN = 0,
424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_STRING,
434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_NMTOKEN,
444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_DECIMAL,
45070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_TIME,
46070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_GDAY,
47070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_GMONTH,
48070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_GMONTHDAY,
49070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_GYEAR,
50070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_GYEARMONTH,
51070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_DATE,
52070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_DATETIME,
53070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    XML_SCHEMAS_DURATION,
5484d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    XML_SCHEMAS_FLOAT,
5584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    XML_SCHEMAS_DOUBLE,
564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_,
574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_SCHEMAS_XXX
584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard} xmlSchemaValType;
594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardunsigned long powten[10] = {
614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    100000000L, 1000000000L
634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
65070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/* Date value */
66070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardtypedef struct _xmlSchemaValDate xmlSchemaValDate;
67070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardtypedef xmlSchemaValDate *xmlSchemaValDatePtr;
68070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstruct _xmlSchemaValDate {
69070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    long		year;
70070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int	mon	:4;	/* 1 <=  mon    <= 12   */
71070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int	day	:5;	/* 1 <=  day    <= 31   */
72070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int	hour	:5;	/* 0 <=  hour   <= 23   */
73070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int	min	:6;	/* 0 <=  min    <= 59	*/
74070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    double		sec;
75070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int			tz_flag	:1;	/* is tzo explicitely set? */
76070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int			tzo	:11;	/* -1440 <= tzo <= 1440 */
77070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard};
78070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
79070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/* Duration value */
80070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardtypedef struct _xmlSchemaValDuration xmlSchemaValDuration;
81070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardtypedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
82070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstruct _xmlSchemaValDuration {
83070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    long	        mon;		/* mon stores years also */
84070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    long        	day;
85070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    double		sec;            /* sec stores min and hour also */
86070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard};
87070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlSchemaValDecimal {
914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* would use long long but not portable */
924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    unsigned long base;
934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    unsigned int extra;
945a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    unsigned int sign:1;
954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int frac:7;
964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int total:8;
974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlSchemaVal {
1004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaValType type;
1014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    union {
1025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	xmlSchemaValDecimal     decimal;
103070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        xmlSchemaValDate        date;
104070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        xmlSchemaValDuration    dur;
10584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	float			f;
10684d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	double			d;
1074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } value;
1084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
1094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int xmlSchemaTypesInitialized = 0;
1114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlHashTablePtr xmlSchemaTypesBank = NULL;
1124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
1144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
1154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
1164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
117070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
1184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
119070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
120070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
121070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
122070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
123070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
124070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
125070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
1264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
1274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
1284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeNmtoken = NULL;
12984d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
13084d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillardstatic xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
1314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/*
1334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaInitBasicType:
1344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @name:  the type name
1354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
1364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Initialize one default type
1374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
1384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaTypePtr
1394255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaInitBasicType(const char *name) {
1404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypePtr ret;
1414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
1434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == NULL) {
1444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlGenericError(xmlGenericErrorContext,
1454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		"Could not initilize type %s: out of memory\n", name);
1464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
1474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
1484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(ret, 0, sizeof(xmlSchemaType));
1494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->name = xmlStrdup((const xmlChar *)name);
1504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->type = XML_SCHEMA_TYPE_BASIC;
1514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->contentType = XML_SCHEMA_CONTENT_BASIC;
1524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
1534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	             XML_SCHEMAS_NAMESPACE_NAME, ret);
1544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
1554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
1564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/*
1584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaInitTypes:
1594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
1604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Initialize the default XML Schemas type library
1614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
1624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
1634255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaInitTypes(void) {
1644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (xmlSchemaTypesInitialized != 0)
1654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
1664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypesBank = xmlHashCreate(40);
1674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string");
1694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType");
1704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType");
1714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal");
1724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date");
173070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime");
174070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time");
175070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear");
176070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth");
177070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth");
178070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay");
179070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay");
180070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration");
1814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypePositiveIntegerDef = xmlSchemaInitBasicType("positiveInteger");
1824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeNonNegativeIntegerDef =
1834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlSchemaInitBasicType("nonNegativeInteger");
1844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypeNmtoken = xmlSchemaInitBasicType("NMTOKEN");
18584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float");
18684d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double");
1874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypesInitialized = 1;
1894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
1904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
1924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaCleanupTypes:
1934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
1944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Cleanup the default XML Schemas type library
1954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
1964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
1974255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaCleanupTypes(void) {
1984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (xmlSchemaTypesInitialized == 0)
1994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
2004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
2014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaTypesInitialized = 0;
2024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
2034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
2054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaNewValue:
2064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @type:  the value type
2074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
2084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Allocate a new simple type value
2094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
2104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns a pointer to the new value or NULL in case of error
2114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
2124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlSchemaValPtr
2134255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaNewValue(xmlSchemaValType type) {
2144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaValPtr value;
2154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
2174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (value == NULL) {
2184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
2194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
2204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(value, 0, sizeof(xmlSchemaVal));
2214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    value->type = type;
2224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(value);
2234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
2244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
2264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaFreeValue:
2274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @value:  the value to free
2284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
2294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Cleanup the default XML Schemas type library
2304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
2314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
2324255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaFreeValue(xmlSchemaValPtr value) {
2334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (value == NULL)
2344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
2354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(value);
2364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
2374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
2394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaGetPredefinedType:
2404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @name: the type name
2414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @ns:  the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
2424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
2434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Lookup a type in the default XML Schemas type library
2444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
2454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the type if found, NULL otherwise
2464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
2474255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaTypePtr
2484255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
2494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (xmlSchemaTypesInitialized == 0)
2504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlSchemaInitTypes();
2514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (name == NULL)
2524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
2534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
2544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
255070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
256070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/****************************************************************
257070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *								*
258070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *		Convenience macros and functions		*
259070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *								*
260070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard ****************************************************************/
261070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
262070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define IS_TZO_CHAR(c)						\
263070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
264070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
265070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_YEAR(yr)          (yr != 0)
266070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
267070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/* VALID_DAY should only be used when month is unknown */
268070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_DAY(day)          ((day >= 1) && (day <= 31))
269070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
270070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_MIN(min)          ((min >= 0) && (min <= 59))
271070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
272070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_TZO(tzo)          ((tzo > -1440) && (tzo < 1440))
273070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define IS_LEAP(y)						\
274070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
275070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
276070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic const long daysInMonth[12] =
277070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
278070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic const long daysInMonthLeap[12] =
279070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
280070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
2815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define MAX_DAYINMONTH(yr,mon)                                  \
2825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
2835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
284070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_MDAY(dt)						\
285070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(IS_LEAP(dt->year) ?				        \
286070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    (dt->day <= daysInMonthLeap[dt->mon - 1]) :	        \
287070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    (dt->day <= daysInMonth[dt->mon - 1]))
288070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
289070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_DATE(dt)						\
290070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
291070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
292070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_TIME(dt)						\
293070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&		\
294070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
295070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
296070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define VALID_DATETIME(dt)					\
297070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(VALID_DATE(dt) && VALID_TIME(dt))
298070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
299070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define SECS_PER_MIN            (60)
300070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define SECS_PER_HOUR           (60 * SECS_PER_MIN)
301070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define SECS_PER_DAY            (24 * SECS_PER_HOUR)
302070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
3035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic const long dayInYearByMonth[12] =
3045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
3055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic const long dayInLeapYearByMonth[12] =
3065a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
3075a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
3085a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define DAY_IN_YEAR(day, month, year)				\
3095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        ((IS_LEAP(year) ?					\
3105a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                dayInLeapYearByMonth[month - 1] :		\
3115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                dayInYearByMonth[month - 1]) + day)
3125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
3135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#ifdef DEBUG
3145a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define DEBUG_DATE(dt)                                                  \
3155a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlGenericError(xmlGenericErrorContext,                             \
3165a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
3175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        dt->type,dt->value.date.year,dt->value.date.mon,                \
3185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
3195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        dt->value.date.sec);                                            \
3205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (dt->value.date.tz_flag)                                         \
3215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (dt->value.date.tzo != 0)                                    \
3225a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmlGenericError(xmlGenericErrorContext,                     \
3235a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                "%+05d\n",dt->value.date.tzo);                          \
3245a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else                                                            \
3255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "Z\n");             \
3265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else                                                                \
3275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        xmlGenericError(xmlGenericErrorContext,"\n")
3285a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#else
3295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define DEBUG_DATE(dt)
3305a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#endif
3315a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
332070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
333070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * _xmlSchemaParseGYear:
334070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dt:  pointer to a date structure
335070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @str: pointer to the string to analyze
336070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
337070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a xs:gYear without time zone and fills in the appropriate
338070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * field of the @dt structure. @str is updated to point just after the
339070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * xs:gYear. It is supposed that @dt->year is big enough to contain
340070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * the year.
341070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
342070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 or the error code
343070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
344070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
345070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard_xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
346070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = *str, *firstChar;
347070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int isneg = 0, digcnt = 0;
348070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
349070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (((*cur < '0') || (*cur > '9')) &&
350070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	(*cur != '-') && (*cur != '+'))
351070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
352070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
353070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur == '-') {
354070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	isneg = 1;
355070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
356070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
357070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
358070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    firstChar = cur;
359070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
360070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    while ((*cur >= '0') && (*cur <= '9')) {
361070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->year = dt->year * 10 + (*cur - '0');
362070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
363070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	digcnt++;
364070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
365070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
366070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* year must be at least 4 digits (CCYY); over 4
367070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard     * digits cannot have a leading zero. */
368070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
369070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
370070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
371070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (isneg)
372070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->year = - dt->year;
373070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
374070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (!VALID_YEAR(dt->year))
375070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 2;
376070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
377070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    *str = cur;
378070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
379070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
380070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
381070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
382070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * PARSE_2_DIGITS:
383070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num:  the integer to fill in
384070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur:  an #xmlChar *
385070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @invalid: an integer
386070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
387070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a 2-digits integer and updates @num with the value. @cur is
388070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * updated to point just after the integer.
389070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * In case of error, @invalid is set to %TRUE, values of @num and
390070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur are undefined.
391070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
392070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define PARSE_2_DIGITS(num, cur, invalid)			\
393070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if ((cur[0] < '0') || (cur[0] > '9') ||			\
394070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    (cur[1] < '0') || (cur[1] > '9'))			\
395070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    invalid = 1;					\
396070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	else							\
397070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    num = (cur[0] - '0') * 10 + (cur[1] - '0');		\
398070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur += 2;
399070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
400070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
401070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * PARSE_FLOAT:
402070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num:  the double to fill in
403070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur:  an #xmlChar *
404070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @invalid: an integer
405070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
406070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a float and updates @num with the value. @cur is
407070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * updated to point just after the float. The float must have a
408070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * 2-digits integer part and may or may not have a decimal part.
409070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * In case of error, @invalid is set to %TRUE, values of @num and
410070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur are undefined.
411070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
412070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define PARSE_FLOAT(num, cur, invalid)				\
413070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	PARSE_2_DIGITS(num, cur, invalid);			\
414070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (!invalid && (*cur == '.')) {			\
415070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    double mult = 1;				        \
416070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    cur++;						\
417070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if ((*cur < '0') || (*cur > '9'))			\
418070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		invalid = 1;					\
419070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    while ((*cur >= '0') && (*cur <= '9')) {		\
420070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		mult /= 10;					\
421070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		num += (*cur - '0') * mult;			\
422070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		cur++;						\
423070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    }							\
424070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}
425070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
426070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
427070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * _xmlSchemaParseGMonth:
428070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dt:  pointer to a date structure
429070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @str: pointer to the string to analyze
430070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
431070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a xs:gMonth without time zone and fills in the appropriate
432070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * field of the @dt structure. @str is updated to point just after the
433070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * xs:gMonth.
434070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
435070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 or the error code
436070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
437070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
438070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard_xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
439070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = *str;
440070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int ret = 0;
441070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
442070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    PARSE_2_DIGITS(dt->mon, cur, ret);
443070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
444070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return ret;
445070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
446070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (!VALID_MONTH(dt->mon))
447070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 2;
448070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
449070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    *str = cur;
450070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
451070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
452070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
453070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
454070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * _xmlSchemaParseGDay:
455070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dt:  pointer to a date structure
456070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @str: pointer to the string to analyze
457070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
458070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a xs:gDay without time zone and fills in the appropriate
459070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * field of the @dt structure. @str is updated to point just after the
460070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * xs:gDay.
461070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
462070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 or the error code
463070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
464070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
465070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard_xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
466070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = *str;
467070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int ret = 0;
468070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
469070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    PARSE_2_DIGITS(dt->day, cur, ret);
470070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
471070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return ret;
472070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
473070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (!VALID_DAY(dt->day))
474070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 2;
475070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
476070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    *str = cur;
477070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
478070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
479070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
480070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
481070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * _xmlSchemaParseTime:
482070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dt:  pointer to a date structure
483070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @str: pointer to the string to analyze
484070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
485070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a xs:time without time zone and fills in the appropriate
486070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * fields of the @dt structure. @str is updated to point just after the
487070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * xs:time.
488070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * In case of error, values of @dt fields are undefined.
489070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
490070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 or the error code
491070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
492070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
493070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard_xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
494070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = *str;
495070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int hour = 0; /* use temp var in case str is not xs:time */
496070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int ret = 0;
497070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
498070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    PARSE_2_DIGITS(hour, cur, ret);
499070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
500070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return ret;
501070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
502070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur != ':')
503070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
504070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur++;
505070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
506070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* the ':' insures this string is xs:time */
507070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    dt->hour = hour;
508070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
509070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    PARSE_2_DIGITS(dt->min, cur, ret);
510070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
511070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return ret;
512070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
513070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur != ':')
514070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
515070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur++;
516070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
517070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    PARSE_FLOAT(dt->sec, cur, ret);
518070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
519070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return ret;
520070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
521070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (!VALID_TIME(dt))
522070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 2;
523070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
524070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    *str = cur;
525070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
526070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
527070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
528070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
529070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * _xmlSchemaParseTimeZone:
530070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dt:  pointer to a date structure
531070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @str: pointer to the string to analyze
532070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
533070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a time zone without time zone and fills in the appropriate
534070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * field of the @dt structure. @str is updated to point just after the
535070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * time zone.
536070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
537070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 or the error code
538070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
539070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
540070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard_xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
541070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = *str;
542070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int ret = 0;
543070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
544070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (str == NULL)
545070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
546070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
547070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    switch (*cur) {
548070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    case 0:
549070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tz_flag = 0;
550070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tzo = 0;
551070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	break;
552070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
553070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    case 'Z':
554070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tz_flag = 1;
555070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tzo = 0;
556070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
557070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	break;
558070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
559070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    case '+':
560070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    case '-': {
561070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	int isneg = 0, tmp = 0;
562070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	isneg = (*cur == '-');
563070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
564070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
565070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
566070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	PARSE_2_DIGITS(tmp, cur, ret);
567070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret != 0)
568070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return ret;
569070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (!VALID_HOUR(tmp))
570070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return 2;
571070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
572070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (*cur != ':')
573070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return 1;
574070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
575070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
576070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tzo = tmp * 60;
577070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
578070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	PARSE_2_DIGITS(tmp, cur, ret);
579070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret != 0)
580070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return ret;
581070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (!VALID_MIN(tmp))
582070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return 2;
583070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
584070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	dt->tzo += tmp;
585070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (isneg)
586070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    dt->tzo = - dt->tzo;
587070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
588070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (!VALID_TZO(dt->tzo))
589070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return 2;
590070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
5915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	dt->tz_flag = 1;
592070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	break;
593070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard      }
594070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    default:
595070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
596070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
597070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
598070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    *str = cur;
599070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
600070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
601070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
602070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/****************************************************************
603070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *								*
604070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *	XML Schema Dates/Times Datatypes Handling		*
605070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *								*
606070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard ****************************************************************/
607070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
608070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
609070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * PARSE_DIGITS:
610070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num:  the integer to fill in
611070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur:  an #xmlChar *
612070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num_type: an integer flag
613070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
614070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a digits integer and updates @num with the value. @cur is
615070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * updated to point just after the integer.
616070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * In case of error, @num_type is set to -1, values of @num and
617070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur are undefined.
618070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
619070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define PARSE_DIGITS(num, cur, num_type)	                \
620070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if ((*cur < '0') || (*cur > '9'))			\
621070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    num_type = -1;					\
622070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        else                                                    \
623070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    while ((*cur >= '0') && (*cur <= '9')) {		\
624070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	        num = num * 10 + (*cur - '0');		        \
625070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	        cur++;                                          \
626070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            }
627070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
628070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
629070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * PARSE_NUM:
630070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num:  the double to fill in
631070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur:  an #xmlChar *
632070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @num_type: an integer flag
633070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
634070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Parses a float or integer and updates @num with the value. @cur is
635070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * updated to point just after the number. If the number is a float,
636070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * then it must have an integer part and a decimal part; @num_type will
637070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * be set to 1. If there is no decimal part, @num_type is set to zero.
638070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * In case of error, @num_type is set to -1, values of @num and
639070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @cur are undefined.
640070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
641070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define PARSE_NUM(num, cur, num_type)				\
642070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        num = 0;                                                \
643070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	PARSE_DIGITS(num, cur, num_type);	                \
644070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (!num_type && (*cur == '.')) {			\
645070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    double mult = 1;				        \
646070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    cur++;						\
647070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if ((*cur < '0') || (*cur > '9'))			\
648070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		num_type = -1;					\
649070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            else                                                \
650070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                num_type = 1;                                   \
651070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    while ((*cur >= '0') && (*cur <= '9')) {		\
652070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		mult /= 10;					\
653070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		num += (*cur - '0') * mult;			\
654070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		cur++;						\
655070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    }							\
656070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}
657070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
658070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
6595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * xmlSchemaValidateDates:
660070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @type: the predefined type
661070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @dateTime:  string to analyze
662070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @val:  the return computed value
663070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
664070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Check that @dateTime conforms to the lexical space of one of the date types.
665070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * if true a value is computed and returned in @val.
666070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
667070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 if this validates, a positive error code number otherwise
668070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *         and -1 in case of internal or API error.
669070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
670070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
671dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3Daniel VeillardxmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
672118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	                const xmlChar *dateTime, xmlSchemaValPtr *val) {
673070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaValPtr dt;
674070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int ret;
675070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar *cur = dateTime;
676070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
677070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard#define RETURN_TYPE_IF_VALID(t)					\
678070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (IS_TZO_CHAR(*cur)) {					\
679070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);	\
680070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret == 0) {						\
681070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (*cur != 0)					\
682070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		goto error;					\
683070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    dt->type = t;					\
684070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            if (val != NULL)                                    \
685070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                *val = dt;                                      \
686070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return 0;						\
687070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}							\
688070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
689070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
690070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (dateTime == NULL)
691070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
692070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
693070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
694070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
695070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
696070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
697070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (dt == NULL)
698070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
699070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
700070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((cur[0] == '-') && (cur[1] == '-')) {
701070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	/*
702070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
703070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 * xs:gDay)
704070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 */
705070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur += 2;
706070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
707070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	/* is it an xs:gDay? */
708070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (*cur == '-') {
709070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	  ++cur;
710070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
711070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (ret != 0)
712070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		goto error;
713070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
714070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
715070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
716070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    goto error;
717070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}
718070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
719070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	/*
720070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 * it should be an xs:gMonthDay or xs:gMonth
721070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	 */
722070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
723070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret != 0)
724070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    goto error;
725070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
726070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (*cur != '-')
727070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    goto error;
728070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	cur++;
729070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
730070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	/* is it an xs:gMonth? */
731070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (*cur == '-') {
732070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    cur++;
733070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
734070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    goto error;
735070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}
736070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
737070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	/* it should be an xs:gMonthDay */
738070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
739070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret != 0)
740070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    goto error;
741070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
742070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
743070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
744070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
745070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
746070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
747070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /*
748070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard     * It's a right-truncated date or an xs:time.
749070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard     * Try to parse an xs:time then fallback on right-truncated dates.
750070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard     */
751070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((*cur >= '0') && (*cur <= '9')) {
752070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
753070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	if (ret == 0) {
754070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    /* it's an xs:time */
755070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
756070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	}
757070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
758070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
759070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* fallback on date parsing */
760070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur = dateTime;
761070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
762070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
763070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
764070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
765070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
766070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* is it an xs:gYear? */
767070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
768070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
769070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur != '-')
770070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
771070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur++;
772070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
773070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
774070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
775070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
776070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
777070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* is it an xs:gYearMonth? */
778070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
779070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
780070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur != '-')
781070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
782070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur++;
783070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
784070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
785070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
786070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
787070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
788070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* is it an xs:date? */
789070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
790070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
791070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur != 'T')
792070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
793070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    cur++;
794070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
795070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* it should be an xs:dateTime */
796070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
797070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (ret != 0)
798070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
799070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
800070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
801070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
802070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	goto error;
803070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
804070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    dt->type = XML_SCHEMAS_DATETIME;
805070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
806070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (val != NULL)
807070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        *val = dt;
808070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
809070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
810070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
811070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillarderror:
812070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (dt != NULL)
813070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	xmlSchemaFreeValue(dt);
814070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 1;
815070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
816070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
817070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
8185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * xmlSchemaValidateDuration:
819070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @type: the predefined type
820070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @duration:  string to analyze
821070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @val:  the return computed value
822070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
823070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Check that @duration conforms to the lexical space of the duration type.
824070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * if true a value is computed and returned in @val.
825070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
826070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns 0 if this validates, a positive error code number otherwise
827070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *         and -1 in case of internal or API error.
828070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
829070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
830dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3Daniel VeillardxmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
831118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	                   const xmlChar *duration, xmlSchemaValPtr *val) {
832070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    const xmlChar  *cur = duration;
833070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmlSchemaValPtr dur;
834070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    int isneg = 0;
835070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    unsigned int seq = 0;
836070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
837070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (duration == NULL)
838070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
839070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
840070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur == '-') {
841070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        isneg = 1;
842070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        cur++;
843070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
844070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
845070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* duration must start with 'P' (after sign) */
846070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (*cur++ != 'P')
847070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return 1;
848070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
849070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
850070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (dur == NULL)
851070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	return -1;
852070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
853070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    while (*cur != 0) {
854070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        double         num;
855070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
856070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
857070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        const double   multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
858070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
859070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        /* input string should be empty or invalid date/time item */
860070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        if (seq >= sizeof(desig))
861070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            goto error;
862070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
863070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        /* T designator must be present for time items */
864070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        if (*cur == 'T') {
865070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            if (seq <= 3) {
866070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                seq = 3;
867070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                cur++;
868070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            } else
869070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                return 1;
870070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        } else if (seq == 3)
871070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            goto error;
872070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
873070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        /* parse the number portion of the item */
874070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        PARSE_NUM(num, cur, num_type);
875070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
876070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        if ((num_type == -1) || (*cur == 0))
877070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            goto error;
878070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
879070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        /* update duration based on item type */
880070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        while (seq < sizeof(desig)) {
881070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            if (*cur == desig[seq]) {
882070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
883070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                /* verify numeric type; only seconds can be float */
884070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                if ((num_type != 0) && (seq < (sizeof(desig)-1)))
885070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                    goto error;
886070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
887070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                switch (seq) {
888070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                    case 0:
889070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        dur->value.dur.mon = (long)num * 12;
890070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        break;
891070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                    case 1:
892070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        dur->value.dur.mon += (long)num;
893070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        break;
894070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                    default:
895070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        /* convert to seconds using multiplier */
896070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        dur->value.dur.sec += num * multi[seq];
897070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        seq++;
898070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                        break;
899070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                }
900070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
901070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                break;          /* exit loop */
902070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            }
903070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            /* no date designators found? */
904070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            if (++seq == 3)
905070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                goto error;
906070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        }
907070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        cur++;
908070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
909070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
910070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (isneg) {
911070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        dur->value.dur.mon = -dur->value.dur.mon;
912070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        dur->value.dur.day = -dur->value.dur.day;
913070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        dur->value.dur.sec = -dur->value.dur.sec;
914070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
915070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
916070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (val != NULL)
917070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        *val = dur;
918070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
919070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
920070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
921070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillarderror:
922070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (dur != NULL)
923070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	xmlSchemaFreeValue(dur);
924070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 1;
925070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
926070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
9274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
9284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaValidatePredefinedType:
9294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @type: the predefined type
9304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @value: the value to check
9314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @val:  the return computed value
9324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
9334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Check that a value conforms to the lexical space of the predefined type.
9344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * if true a value is computed and returned in @val.
9354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
9364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns 0 if this validates, a positive error code number otherwise
9374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *         and -1 in case of internal or API error.
9384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
9394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
9404255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
9414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                        xmlSchemaValPtr *val) {
9424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaValPtr v;
9434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
9444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (xmlSchemaTypesInitialized == 0)
9454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
9464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (type == NULL)
9474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
9485a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
9494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (val != NULL)
9504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	*val = NULL;
9514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (type == xmlSchemaTypeStringDef) {
9524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
9534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypeAnyTypeDef) {
9544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
9554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypeAnySimpleTypeDef) {
9564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
9574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypeNmtoken) {
9584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (xmlValidateNmtokenValue(value))
9594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(0);
9604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
9614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypeDecimalDef) {
9624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	const xmlChar *cur = value, *tmp;
9635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	int frac = 0, len, neg = 0;
9644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	unsigned long base = 0;
9654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == NULL)
9664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
9674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur == '+')
9684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
9694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	else if (*cur == '-') {
9704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = 1;
9714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
9724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
9734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = cur;
9744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	while ((*cur >= '0') && (*cur <= '9')) {
9754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    base = base * 10 + (*cur - '0');
9764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
9774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
9785a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	len = cur - tmp;
9794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur == '.') {
9804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
9814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    tmp = cur;
9824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    while ((*cur >= '0') && (*cur <= '9')) {
9834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		base = base * 10 + (*cur - '0');
9844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		cur++;
9854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
9864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    frac = cur - tmp;
9874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
9884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur != 0)
9894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
9904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (val != NULL) {
9914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
9924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (v != NULL) {
9934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.base = base;
9944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.sign = neg;
9954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.frac = frac;
9965a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard		v->value.decimal.total = frac + len;
9974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		*val = v;
9984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
9994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
10004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
1001070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    } else if (type == xmlSchemaTypeDurationDef) {
10025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return xmlSchemaValidateDuration(type, value, val);
1003070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    } else if ((type == xmlSchemaTypeDatetimeDef) ||
1004070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeTimeDef) ||
1005070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeDateDef) ||
1006070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeGYearDef) ||
1007070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeGYearMonthDef) ||
1008070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeGMonthDef) ||
1009070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeGMonthDayDef) ||
1010070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard               (type == xmlSchemaTypeGDayDef))         {
10115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return xmlSchemaValidateDates(type, value, val);
10124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypePositiveIntegerDef) {
10134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	const xmlChar *cur = value;
10144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	unsigned long base = 0;
10154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int total = 0;
10164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == NULL)
10174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
10184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur == '+')
10194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
10204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	while ((*cur >= '0') && (*cur <= '9')) {
10214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    base = base * 10 + (*cur - '0');
10224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    total++;
10234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
10244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
10254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur != 0)
10264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
10274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (val != NULL) {
10284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
10294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (v != NULL) {
10304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.base = base;
10314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.sign = 0;
10324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.frac = 0;
10334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.total = total;
10344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		*val = v;
10354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
10364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
10374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
10384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (type == xmlSchemaTypeNonNegativeIntegerDef) {
10394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	const xmlChar *cur = value;
10404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	unsigned long base = 0;
10414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int total = 0;
10424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int sign = 0;
10434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == NULL)
10444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
10454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur == '-') {
10464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    sign = 1;
10474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
10484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (*cur == '+')
10494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
10504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	while ((*cur >= '0') && (*cur <= '9')) {
10514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    base = base * 10 + (*cur - '0');
10524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    total++;
10534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur++;
10544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
10554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (*cur != 0)
10564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
10574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((sign == 1) && (base != 0))
10584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
10594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (val != NULL) {
10604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
10614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (v != NULL) {
10624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.base = base;
10634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.sign = 0;
10644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.frac = 0;
10654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		v->value.decimal.total = total;
10664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		*val = v;
10674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
10684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
10694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
107084d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    } else if (type == xmlSchemaTypeFloatDef) {
107184d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	const xmlChar *cur = value, *tmp;
107284d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	int frac = 0, len, neg = 0;
107384d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	unsigned long base = 0;
107484d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	if (cur == NULL)
107584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    return(1);
107684d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	if (*cur == '+')
107784d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    cur++;
107884d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	else if (*cur == '-') {
107984d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    neg = 1;
108084d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    cur++;
108184d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	}
108284d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	tmp = cur;
108384d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	while ((*cur >= '0') && (*cur <= '9')) {
108484d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    base = base * 10 + (*cur - '0');
108584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    cur++;
108684d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	}
108784d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	len = cur - tmp;
108884d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	if (*cur == '.') {
108984d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    cur++;
109084d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    tmp = cur;
109184d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    while ((*cur >= '0') && (*cur <= '9')) {
109284d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard		base = base * 10 + (*cur - '0');
109384d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard		cur++;
109484d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    }
109584d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	    frac = cur - tmp;
109684d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard	}
1097b5c05735785b4d60d0876f2604229f85eb1a9cf1Daniel Veillard	TODO
1098b5c05735785b4d60d0876f2604229f85eb1a9cf1Daniel Veillard	return(0);
109984d70a462ff443b310ca90fdce722f81261dc93bDaniel Veillard    } else if (type == xmlSchemaTypeDoubleDef) {
1100b5c05735785b4d60d0876f2604229f85eb1a9cf1Daniel Veillard	TODO
1101b5c05735785b4d60d0876f2604229f85eb1a9cf1Daniel Veillard	return(0);
11024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
11034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	TODO
11044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
11054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
11074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
11094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaCompareDecimals:
11104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @x:  a first decimal value
11114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @y:  a second decimal value
11124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
11134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Compare 2 decimals
11144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
11154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
11164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
11174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
11184255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
11194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard{
11204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlSchemaValPtr swp;
11214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int order = 1;
11224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    unsigned long tmp;
11234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((x->value.decimal.sign) && (x->value.decimal.sign))
11254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        order = -1;
11264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (x->value.decimal.sign)
11274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (-1);
11284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (y->value.decimal.sign)
11294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (1);
11304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (x->value.decimal.frac == y->value.decimal.frac) {
11314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        if (x->value.decimal.base < y->value.decimal.base)
11324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            return (-1);
11334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (x->value.decimal.base > y->value.decimal.base);
11344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (y->value.decimal.frac > x->value.decimal.frac) {
11364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        swp = y;
11374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        y = x;
11384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        x = swp;
11394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        order = -order;
11404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    tmp =
11424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        x->value.decimal.base / powten[x->value.decimal.frac -
11434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                                       y->value.decimal.frac];
11444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (tmp > y->value.decimal.base)
11454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (order);
11464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (tmp < y->value.decimal.base)
11474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (-order);
11484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    tmp =
11494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        y->value.decimal.base * powten[x->value.decimal.frac -
11504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                                       y->value.decimal.frac];
11514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (x->value.decimal.base < tmp)
11524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (-order);
11534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (x->value.decimal.base == tmp)
11544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return (0);
11554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return (order);
11564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
11574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
1159070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * xmlSchemaCompareDurations:
1160070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @x:  a first duration value
1161070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * @y:  a second duration value
1162070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
1163070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Compare 2 durations
1164070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard *
1165070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
1166070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard * case of error
1167070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard */
1168070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillardstatic int
1169070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel VeillardxmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
1170070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard{
1171070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    long carry, mon, day;
1172070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    double sec;
1173070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    long xmon, xday, myear, lyear, minday, maxday;
1174070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    static const long dayRange [2][12] = {
1175070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
1176070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
1177070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1178070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if ((x == NULL) || (y == NULL))
11795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return -2;
1180070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1181070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* months */
1182070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    mon = x->value.dur.mon - y->value.dur.mon;
1183070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1184070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* seconds */
1185070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    sec = x->value.dur.sec - y->value.dur.sec;
1186070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    carry = (long)sec / SECS_PER_DAY;
1187070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    sec -= (double)(carry * SECS_PER_DAY);
1188070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1189070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* days */
1190070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    day = x->value.dur.day - y->value.dur.day + carry;
1191070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1192070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* easy test */
1193070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (mon == 0) {
1194070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        if (day == 0)
1195070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            if (sec == 0.0)
1196070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                return 0;
1197070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            else if (sec < 0.0)
1198070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                return -1;
1199070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            else
1200070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                return 1;
1201070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        else if (day < 0)
1202070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            return -1;
1203070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        else
1204070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            return 1;
1205070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
1206070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1207070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (mon > 0) {
1208070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        if ((day >= 0) && (sec >= 0.0))
1209070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            return 1;
1210070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        else {
1211070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            xmon = mon;
1212070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard            xday = -day;
1213070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        }
1214070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    } else if ((day <= 0) && (sec <= 0.0)) {
1215070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        return -1;
1216070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    } else {
1217070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        xmon = -mon;
1218070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        xday = day;
1219070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    }
1220070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1221070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    myear = xmon / 12;
1222070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    lyear = myear / 4;
1223070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    minday = (myear * 365) + (lyear != 0 ? lyear - 1 : 0);
1224070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    maxday = (myear * 365) + (lyear != 0 ? lyear + 1 : 0);
1225070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1226070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    xmon = xmon % 12;
1227070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    minday += dayRange[0][xmon];
1228070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    maxday += dayRange[1][xmon];
1229070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1230070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    if (maxday < xday)
1231070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        return 1;
1232070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    else if (minday > xday)
1233070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        return -1;
1234070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1235070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    /* indeterminate */
12365a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return 2;
12375a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard}
12385a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/*
12405a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * macros for adding date/times and durations
12415a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
12425a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
12435a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
12445a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
12455a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
12465a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12475a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
12485a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * _xmlSchemaDateAdd:
12495a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @dt: an #xmlSchemaValPtr
12505a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @dur: an #xmlSchemaValPtr of type #XS_DURATION
12515a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
12525a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Compute a new date/time from @dt and @dur. This function assumes @dt
12535a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
12545a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * or #XML_SCHEMAS_GYEAR.
12555a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
12565a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Returns date/time pointer or NULL.
12575a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
12585a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic xmlSchemaValPtr
12595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard_xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
12605a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard{
12615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValPtr ret;
12625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    long carry, tempdays, temp;
12635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValDatePtr r, d;
12645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValDurationPtr u;
12655a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12665a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if ((dt == NULL) || (dur == NULL))
12675a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return NULL;
12685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    ret = xmlSchemaNewValue(dt->type);
12705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (ret == NULL)
12715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return NULL;
12725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r = &(ret->value.date);
12745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    d = &(dt->value.date);
12755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    u = &(dur->value.dur);
12765a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12775a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* normalization */
12785a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (d->mon == 0)
12795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        d->mon = 1;
12805a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* normalize for time zone offset */
12825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    u->sec -= (d->tzo * 60);
12835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    d->tzo = 0;
12845a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12855a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* normalization */
12865a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (d->day == 0)
12875a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        d->day = 1;
12885a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12895a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* month */
12905a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry  = d->mon + u->mon;
12915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->mon = MODULO_RANGE(carry, 1, 13);
12925a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry  = FQUOTIENT_RANGE(carry, 1, 13);
12935a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
12945a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* year (may be modified later) */
12955a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->year = d->year + carry;
12965a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (r->year == 0) {
12975a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (d->year > 0)
12985a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            r->year--;
12995a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else
13005a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            r->year++;
13015a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
13025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* time zone */
13045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->tzo     = d->tzo;
13055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->tz_flag = d->tz_flag;
13065a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13075a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* seconds */
13085a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->sec = d->sec + u->sec;
13095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry  = FQUOTIENT((long)r->sec, 60);
13105a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (r->sec != 0.0) {
13115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        r->sec = MODULO(r->sec, 60.0);
13125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
13135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13145a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* minute */
13155a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry += d->min;
13165a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->min = MODULO(carry, 60);
13175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry  = FQUOTIENT(carry, 60);
13185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* hours */
13205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry  += d->hour;
13215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->hour = MODULO(carry, 24);
13225a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    carry   = FQUOTIENT(carry, 24);
13235a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13245a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /*
13255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     * days
13265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     * Note we use tempdays because the temporary values may need more
13275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     * than 5 bits
13285a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     */
13295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
13305a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                  (d->day > MAX_DAYINMONTH(r->year, r->mon)))
13315a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        tempdays = MAX_DAYINMONTH(r->year, r->mon);
13325a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else if (d->day < 1)
13335a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        tempdays = 1;
13345a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else
13355a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        tempdays = d->day;
13365a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13375a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    tempdays += u->day + carry;
13385a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    while (1) {
13405a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (tempdays < 1) {
13415a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            long tmon = MODULO_RANGE(r->mon-1, 1, 13);
13425a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            long tyr  = r->year + FQUOTIENT_RANGE(r->mon-1, 1, 13);
13435a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            if (tyr == 0)
13445a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                tyr--;
13455a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            tempdays += MAX_DAYINMONTH(tyr, tmon);
13465a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            carry = -1;
13475a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        } else if (tempdays > MAX_DAYINMONTH(r->year, r->mon)) {
13485a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
13495a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            carry = 1;
13505a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        } else
13515a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
13525a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13535a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        temp = r->mon + carry;
13545a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        r->mon = MODULO_RANGE(temp, 1, 13);
13555a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        r->year = r->year + FQUOTIENT_RANGE(temp, 1, 13);
13565a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (r->year == 0) {
13575a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            if (temp < 1)
13585a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                r->year--;
13595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            else
13605a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                r->year++;
13615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	}
13625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
13635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    r->day = tempdays;
13655a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13665a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /*
13675a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     * adjust the date/time type to the date values
13685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     */
13695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (ret->type != XML_SCHEMAS_DATETIME) {
13705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if ((r->hour) || (r->min) || (r->sec))
13715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ret->type = XML_SCHEMAS_DATETIME;
13725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (ret->type != XML_SCHEMAS_DATE) {
13735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            if ((r->mon != 1) && (r->day != 1))
13745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                ret->type = XML_SCHEMAS_DATE;
13755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
13765a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                ret->type = XML_SCHEMAS_GYEARMONTH;
13775a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        }
13785a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
13795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13805a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return ret;
13815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard}
13825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
13845a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * xmlSchemaDupVal:
13855a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @v: value to duplicate
13865a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
13875a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * returns a duplicated value.
13885a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
13895a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic xmlSchemaValPtr
13905a872413fd58df3095979521d9a03ad03cab73a5Daniel VeillardxmlSchemaDupVal (xmlSchemaValPtr v)
13915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard{
13925a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
13935a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (ret == NULL)
13945a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return ret;
13955a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
13965a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    memcpy(ret, v, sizeof(xmlSchemaVal));
13975a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return ret;
13985a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard}
13995a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14005a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
14015a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * xmlSchemaDateNormalize:
14025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @dt: an #xmlSchemaValPtr
14035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Normalize @dt to GMT time.
14055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14065a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
14075a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic xmlSchemaValPtr
14085a872413fd58df3095979521d9a03ad03cab73a5Daniel VeillardxmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
14095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard{
14105a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValPtr dur, ret;
14115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (dt == NULL)
14135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return NULL;
14145a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14155a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (((dt->type != XML_SCHEMAS_TIME) &&
14165a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard         (dt->type != XML_SCHEMAS_DATETIME)) || (dt->value.date.tzo == 0))
14175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return xmlSchemaDupVal(dt);
14185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
14205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (dur == NULL)
14215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return NULL;
14225a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14235a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    dur->value.date.sec -= offset;
14245a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    ret = _xmlSchemaDateAdd(dt, dur);
14265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (ret == NULL)
14275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return NULL;
14285a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaFreeValue(dur);
14305a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14315a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* ret->value.date.tzo = 0; */
14325a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return ret;
14335a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard}
14345a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14355a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
14365a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * _xmlSchemaDateCastYMToDays:
14375a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @dt: an #xmlSchemaValPtr
14385a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Convert mon and year of @dt to total number of days. Take the
14405a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * number of years since (or before) 1 AD and add the number of leap
14415a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * years. This is a function  because negative
14425a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * years must be handled a little differently and there is no zero year.
14435a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14445a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Returns number of days.
14455a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
14465a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic long
14475a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard_xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
14485a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard{
14495a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    long ret;
14505a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14515a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (dt->value.date.year < 0)
14525a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        ret = (dt->value.date.year * 365) +
14535a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard              (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
14545a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard               ((dt->value.date.year+1)/400)) +
14555a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard              DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
14565a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else
14575a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        ret = ((dt->value.date.year-1) * 365) +
14585a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard              (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
14595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard               ((dt->value.date.year-1)/400)) +
14605a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard              DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
14615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return ret;
14635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard}
14645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14655a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
14665a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * TIME_TO_NUMBER:
14675a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @dt:  an #xmlSchemaValPtr
14685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Calculates the number of seconds in the time portion of @dt.
14705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Returns seconds.
14725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
14735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard#define TIME_TO_NUMBER(dt)                              \
14745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
14755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard              (dt->value.date.min * SECS_PER_MIN)) + dt->value.date.sec)
14765a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14775a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard/**
14785a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * xmlSchemaCompareDates:
14795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @x:  a first date/time value
14805a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * @y:  a second date/time value
14815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Compare 2 date/times
14835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard *
14845a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
14855a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * case of error
14865a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard */
14875a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillardstatic int
14885a872413fd58df3095979521d9a03ad03cab73a5Daniel VeillardxmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
14895a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard{
14905a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    unsigned char xmask, ymask, xor_mask, and_mask;
14915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xmlSchemaValPtr p1, p2, q1, q2;
14925a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    long p1d, p2d, q1d, q2d;
14935a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14945a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if ((x == NULL) || (y == NULL))
14955a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return -2;
14965a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14975a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (x->value.date.tz_flag) {
14985a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
14995a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (!y->value.date.tz_flag) {
15005a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            p1 = xmlSchemaDateNormalize(x, 0);
15015a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
15025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            /* normalize y + 14:00 */
15035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
15045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
1506fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard            if (p1d < q1d) {
1507fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(p1);
1508fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(q1);
15095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                return -1;
1510fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    } else if (p1d == q1d) {
15115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                double sec;
15125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
1514fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard                if (sec < 0.0) {
1515fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		    xmlSchemaFreeValue(p1);
1516fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		    xmlSchemaFreeValue(q1);
15175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    return -1;
1518fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		} else {
15195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    /* normalize y - 14:00 */
15205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
15215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
1522fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		    xmlSchemaFreeValue(p1);
1523fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		    xmlSchemaFreeValue(q1);
1524fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		    xmlSchemaFreeValue(q2);
15255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    if (p1d > q2d)
15265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        return 1;
15275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    else if (p1d == q2d) {
15285a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
15295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        if (sec > 0.0)
15305a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                            return 1;
15315a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        else
15325a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                            return 2; /* indeterminate */
15335a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    }
15345a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                }
1535fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard            } else {
1536fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(p1);
1537fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(q1);
1538fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    }
15395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        }
15405a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    } else if (y->value.date.tz_flag) {
15415a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        q1 = xmlSchemaDateNormalize(y, 0);
15425a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
15435a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15445a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        /* normalize x - 14:00 */
15455a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
15465a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
15475a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
1548fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard        if (p1d < q1d) {
1549fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(p1);
1550fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(q1);
15515a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
1552fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	} else if (p1d == q1d) {
15535a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            double sec;
15545a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15555a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
1556fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard            if (sec < 0.0) {
1557fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(p1);
1558fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(q1);
15595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                return -1;
1560fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    } else {
15615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                /* normalize x + 14:00 */
15625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
15635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
15645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
1565fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(p1);
1566fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(q1);
1567fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		xmlSchemaFreeValue(p2);
15685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                if (p2d > q1d)
15695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    return 1;
15705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                else if (p2d == q1d) {
15715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
15725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    if (sec > 0.0)
15735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        return 1;
15745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                    else
15755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                        return 2; /* indeterminate */
15765a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                }
15775a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            }
1578fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	} else {
1579fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(p1);
1580fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(q1);
15815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        }
15825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
15835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15845a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /*
15855a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     * if the same type then calculate the difference
15865a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard     */
15875a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (x->type == y->type) {
15885a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        q1 = xmlSchemaDateNormalize(y, 0);
15895a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
15905a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
15915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        p1 = xmlSchemaDateNormalize(x, 0);
15925a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
15935a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
1594fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard        if (p1d < q1d) {
1595fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(p1);
1596fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(q1);
15975a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
1598fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	} else if (p1d > q1d) {
1599fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(p1);
1600fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(q1);
16015a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
1602fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	} else {
16035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            double sec;
16045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
1606fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(p1);
1607fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlSchemaFreeValue(q1);
16085a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            if (sec < 0.0)
16095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                return -1;
16105a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            else if (sec > 0.0)
16115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                return 1;
16125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        }
16145a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return 0;
16155a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
16165a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    switch (x->type) {
16185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATETIME:
16195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0xf;
16205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATE:
16225a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x7;
16235a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16245a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEAR:
16255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x1;
16265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTH:
16285a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x2;
16295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16305a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GDAY:
16315a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x3;
16325a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16335a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEARMONTH:
16345a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x3;
16355a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16365a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTHDAY:
16375a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x6;
16385a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_TIME:
16405a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0x8;
16415a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16425a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        default:
16435a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            xmask = 0;
16445a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16455a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
16465a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16475a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    switch (y->type) {
16485a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATETIME:
16495a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0xf;
16505a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16515a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATE:
16525a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x7;
16535a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16545a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEAR:
16555a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x1;
16565a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16575a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTH:
16585a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x2;
16595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16605a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GDAY:
16615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x3;
16625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEARMONTH:
16645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x3;
16655a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16665a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTHDAY:
16675a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x6;
16685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_TIME:
16705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0x8;
16715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        default:
16735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            ymask = 0;
16745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            break;
16755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
16765a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16775a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    xor_mask = xmask ^ ymask;           /* mark type differences */
16785a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    and_mask = xmask & ymask;           /* mark field specification */
16795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16805a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* year */
16815a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (xor_mask & 1)
16825a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return 2; /* indeterminate */
16835a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else if (and_mask & 1) {
16845a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (x->value.date.year < y->value.date.year)
16855a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
16865a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.year > y->value.date.year)
16875a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
16885a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
16895a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
16905a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* month */
16915a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (xor_mask & 2)
16925a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return 2; /* indeterminate */
16935a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else if (and_mask & 2) {
16945a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (x->value.date.mon < y->value.date.mon)
16955a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
16965a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.mon > y->value.date.mon)
16975a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
16985a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
16995a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
17005a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* day */
17015a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (xor_mask & 4)
17025a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return 2; /* indeterminate */
17035a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else if (and_mask & 4) {
17045a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (x->value.date.day < y->value.date.day)
17055a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
17065a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.day > y->value.date.day)
17075a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
17085a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
17095a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
17105a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    /* time */
17115a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    if (xor_mask & 8)
17125a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        return 2; /* indeterminate */
17135a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    else if (and_mask & 8) {
17145a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        if (x->value.date.hour < y->value.date.hour)
17155a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
17165a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.hour > y->value.date.hour)
17175a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
17185a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.min < y->value.date.min)
17195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
17205a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.min > y->value.date.min)
17215a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
17225a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.sec < y->value.date.sec)
17235a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return -1;
17245a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        else if (x->value.date.sec > y->value.date.sec)
17255a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return 1;
17265a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    }
17275a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
1728070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard    return 0;
1729070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard}
1730070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard
1731070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard/**
17324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaCompareValues:
17334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @x:  a first value
17344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @y:  a second value
17354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
17364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Compare 2 values
17374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
17385a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
17395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard * case of error
17404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
1741e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
17424255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
17434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((x == NULL) || (y == NULL))
17444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-2);
17454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
17464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (x->type) {
17474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_SCHEMAS_STRING:
17484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    TODO
17494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_SCHEMAS_DECIMAL:
17504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (y->type == XML_SCHEMAS_DECIMAL)
17514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return(xmlSchemaCompareDecimals(x, y));
17525a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	    return(-2);
1753070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard        case XML_SCHEMAS_DURATION:
1754070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (y->type == XML_SCHEMAS_DURATION)
1755070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard                return(xmlSchemaCompareDurations(x, y));
17565a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return(-2);
17575a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_TIME:
17585a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GDAY:
17595a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTH:
17605a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GMONTHDAY:
17615a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEAR:
17625a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_GYEARMONTH:
17635a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATE:
17645a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard        case XML_SCHEMAS_DATETIME:
17655a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            if ((y->type == XML_SCHEMAS_DATETIME)  ||
17665a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_TIME)      ||
17675a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_GDAY)      ||
17685a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_GMONTH)    ||
17695a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_GMONTHDAY) ||
17705a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_GYEAR)     ||
17715a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_DATE)      ||
17725a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                (y->type == XML_SCHEMAS_GYEARMONTH))
17735a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard                return (xmlSchemaCompareDates(x, y));
17745a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard
17755a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard            return (-2);
17764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	default:
17774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    TODO
17784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
17795a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard    return -2;
17804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
17814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
17824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
17834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlSchemaValidateFacet:
17844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @type:  the type declaration
17854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @facet:  the facet to check
17864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @value:  the lexical repr of the value to validate
17874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @val:  the precomputed value
17884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
17894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Check a value against a facet condition
17904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
17914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns 0 if the element is schemas valid, a positive error code
17924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *     number otherwise and -1 in case of internal or API error.
17934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
17944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
1795dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3Daniel VeillardxmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
1796118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	               xmlSchemaFacetPtr facet,
17974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	               const xmlChar *value, xmlSchemaValPtr val)
17984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard{
17994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
18004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
18014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (facet->type) {
18024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_SCHEMA_FACET_PATTERN:
18034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlRegexpExec(facet->regexp, value);
18044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1)
18054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return(0);
18064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 0) {
18074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		TODO /* error code */
18084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return(1);
18094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
18104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(ret);
18114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlSchemaCompareValues(val, facet->val);
18134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == -2) {
18144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		TODO /* error code */
18154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return(-1);
18164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
18174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == -1)
18184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return(0);
18195a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	    /* error code */
18204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
1821070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1822070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    ret = xmlSchemaCompareValues(val, facet->val);
1823070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (ret == -2) {
1824070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		TODO /* error code */
1825070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(-1);
1826070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    }
1827070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if ((ret == -1) || (ret == 0))
1828070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(0);
18295a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	    /* error code */
1830070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return(1);
1831070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1832070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    ret = xmlSchemaCompareValues(val, facet->val);
1833070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (ret == -2) {
1834070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		TODO /* error code */
1835070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(-1);
1836070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    }
1837070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (ret == 1)
1838070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(0);
18395a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	    /* error code */
1840070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return(1);
1841070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	case XML_SCHEMA_FACET_MININCLUSIVE:
1842070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    ret = xmlSchemaCompareValues(val, facet->val);
1843070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if (ret == -2) {
1844070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		TODO /* error code */
1845070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(-1);
1846070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    }
1847070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    if ((ret == 1) || (ret == 0))
1848070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard		return(0);
18495a872413fd58df3095979521d9a03ad03cab73a5Daniel Veillard	    /* error code */
1850070803b315fa3a5b1167bdda5a2d247bcc526ed2Daniel Veillard	    return(1);
18518651f5365c182ce5c52fe1cdc2b9d72b2ecc34e2Daniel Veillard	case XML_SCHEMA_FACET_WHITESPACE:
18528651f5365c182ce5c52fe1cdc2b9d72b2ecc34e2Daniel Veillard	    TODO /* whitespaces */
18538651f5365c182ce5c52fe1cdc2b9d72b2ecc34e2Daniel Veillard	    return(0);
1854e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	case XML_SCHEMA_FACET_MAXLENGTH:
1855e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    if ((facet->val != NULL) &&
1856e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		(facet->val->type == XML_SCHEMAS_DECIMAL) &&
1857e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		(facet->val->value.decimal.frac == 0)) {
1858118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		unsigned int len;
1859e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
1860e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (facet->val->value.decimal.sign == 1)
1861e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    return(1);
1862e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard                len = xmlUTF8Strlen(value);
1863e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (len > facet->val->value.decimal.base)
1864e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    return(1);
1865e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		return(0);
1866e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    }
1867e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    TODO /* error code */
1868e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    return(1);
186988c5891a25c1151a89f021e915d9efb7e58bfbf7Daniel Veillard	case  XML_SCHEMA_FACET_ENUMERATION:
187088c5891a25c1151a89f021e915d9efb7e58bfbf7Daniel Veillard	    if ((facet->value != NULL) &&
187188c5891a25c1151a89f021e915d9efb7e58bfbf7Daniel Veillard		(xmlStrEqual(facet->value, value)))
187288c5891a25c1151a89f021e915d9efb7e58bfbf7Daniel Veillard		return(0);
187388c5891a25c1151a89f021e915d9efb7e58bfbf7Daniel Veillard	    return(1);
18744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	default:
18754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    TODO
18764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
18774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
18784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
18794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
18804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_SCHEMAS_ENABLED */
1881