ReactOS  0.4.15-dev-3303-g1ade494
xmlschemastypes.c
Go to the documentation of this file.
1 /*
2  * schemastypes.c : implementation of the XML Schema Datatypes
3  * definition and validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9 
10 /* To avoid EBCDIC trouble when parsing on zOS */
11 #if defined(__MVS__)
12 #pragma convert("ISO8859-1")
13 #endif
14 
15 #define IN_LIBXML
16 #include "libxml.h"
17 
18 #ifdef LIBXML_SCHEMAS_ENABLED
19 
20 #include <string.h>
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <libxml/parserInternals.h>
24 #include <libxml/hash.h>
25 #include <libxml/valid.h>
26 #include <libxml/xpath.h>
27 #include <libxml/uri.h>
28 
29 #include <libxml/xmlschemas.h>
31 #include <libxml/xmlschemastypes.h>
32 
33 #ifdef HAVE_MATH_H
34 #include <math.h>
35 #endif
36 #ifdef HAVE_FLOAT_H
37 #include <float.h>
38 #endif
39 
40 #define DEBUG
41 
42 #ifndef LIBXML_XPATH_ENABLED
43 extern double xmlXPathNAN;
44 extern double xmlXPathPINF;
45 extern double xmlXPathNINF;
46 #endif
47 
48 #define TODO \
49  xmlGenericError(xmlGenericErrorContext, \
50  "Unimplemented block at %s:%d\n", \
51  __FILE__, __LINE__);
52 
53 #define XML_SCHEMAS_NAMESPACE_NAME \
54  (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
55 
56 #define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \
57  ((c) == 0xd))
58 
59 #define IS_WSP_SPACE_CH(c) ((c) == 0x20)
60 
61 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
62 
63 /* Date value */
64 typedef struct _xmlSchemaValDate xmlSchemaValDate;
65 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
66 struct _xmlSchemaValDate {
67  long year;
68  unsigned int mon :4; /* 1 <= mon <= 12 */
69  unsigned int day :5; /* 1 <= day <= 31 */
70  unsigned int hour :5; /* 0 <= hour <= 24 */
71  unsigned int min :6; /* 0 <= min <= 59 */
72  double sec;
73  unsigned int tz_flag :1; /* is tzo explicitly set? */
74  signed int tzo :12; /* -1440 <= tzo <= 1440;
75  currently only -840 to +840 are needed */
76 };
77 
78 /* Duration value */
79 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
80 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
81 struct _xmlSchemaValDuration {
82  long mon; /* mon stores years also */
83  long day;
84  double sec; /* sec stores min and hour also */
85 };
86 
87 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
88 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
89 struct _xmlSchemaValDecimal {
90  /* would use long long but not portable */
91  unsigned long lo;
92  unsigned long mi;
93  unsigned long hi;
94  unsigned int extra;
95  unsigned int sign:1;
96  unsigned int frac:7;
97  unsigned int total:8;
98 };
99 
100 typedef struct _xmlSchemaValQName xmlSchemaValQName;
101 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
102 struct _xmlSchemaValQName {
103  xmlChar *name;
104  xmlChar *uri;
105 };
106 
107 typedef struct _xmlSchemaValHex xmlSchemaValHex;
108 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
109 struct _xmlSchemaValHex {
110  xmlChar *str;
111  unsigned int total;
112 };
113 
114 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
115 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
116 struct _xmlSchemaValBase64 {
117  xmlChar *str;
118  unsigned int total;
119 };
120 
121 struct _xmlSchemaVal {
122  xmlSchemaValType type;
123  struct _xmlSchemaVal *next;
124  union {
125  xmlSchemaValDecimal decimal;
126  xmlSchemaValDate date;
127  xmlSchemaValDuration dur;
128  xmlSchemaValQName qname;
129  xmlSchemaValHex hex;
130  xmlSchemaValBase64 base64;
131  float f;
132  double d;
133  int b;
134  xmlChar *str;
135  } value;
136 };
137 
138 static int xmlSchemaTypesInitialized = 0;
139 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
140 
141 /*
142  * Basic types
143  */
144 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
145 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
146 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
147 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
148 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
149 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
150 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
151 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
152 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
153 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
154 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
155 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
156 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
157 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
158 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
159 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
160 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
161 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
162 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
163 
164 /*
165  * Derived types
166  */
167 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
168 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
169 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
170 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
171 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
172 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
173 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
174 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
175 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
176 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
177 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
178 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
179 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
180 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
181 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
182 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
183 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
184 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
185 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
186 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
187 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
188 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
189 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
190 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
191 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
192 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
193 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
194 
195 /************************************************************************
196  * *
197  * Datatype error handlers *
198  * *
199  ************************************************************************/
206 static void
207 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
208 {
209  __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
210 }
211 
212 /************************************************************************
213  * *
214  * Base types support *
215  * *
216  ************************************************************************/
217 
226 static xmlSchemaValPtr
227 xmlSchemaNewValue(xmlSchemaValType type) {
228  xmlSchemaValPtr value;
229 
230  value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
231  if (value == NULL) {
232  return(NULL);
233  }
234  memset(value, 0, sizeof(xmlSchemaVal));
235  value->type = type;
236  return(value);
237 }
238 
239 static xmlSchemaFacetPtr
240 xmlSchemaNewMinLengthFacet(int value)
241 {
242  xmlSchemaFacetPtr ret;
243 
244  ret = xmlSchemaNewFacet();
245  if (ret == NULL) {
246  return(NULL);
247  }
248  ret->type = XML_SCHEMA_FACET_MINLENGTH;
249  ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
250  if (ret->val == NULL) {
251  xmlFree(ret);
252  return(NULL);
253  }
254  ret->val->value.decimal.lo = value;
255  return (ret);
256 }
257 
258 /*
259  * xmlSchemaInitBasicType:
260  * @name: the type name
261  * @type: the value type associated
262  *
263  * Initialize one primitive built-in type
264  */
265 static xmlSchemaTypePtr
266 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
267  xmlSchemaTypePtr baseType) {
268  xmlSchemaTypePtr ret;
269 
270  ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
271  if (ret == NULL) {
272  xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
273  return(NULL);
274  }
275  memset(ret, 0, sizeof(xmlSchemaType));
276  ret->name = (const xmlChar *)name;
277  ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
278  ret->type = XML_SCHEMA_TYPE_BASIC;
279  ret->baseType = baseType;
280  ret->contentType = XML_SCHEMA_CONTENT_BASIC;
281  /*
282  * Primitive types.
283  */
284  switch (type) {
285  case XML_SCHEMAS_STRING:
286  case XML_SCHEMAS_DECIMAL:
287  case XML_SCHEMAS_DATE:
288  case XML_SCHEMAS_DATETIME:
289  case XML_SCHEMAS_TIME:
290  case XML_SCHEMAS_GYEAR:
291  case XML_SCHEMAS_GYEARMONTH:
292  case XML_SCHEMAS_GMONTH:
293  case XML_SCHEMAS_GMONTHDAY:
294  case XML_SCHEMAS_GDAY:
295  case XML_SCHEMAS_DURATION:
296  case XML_SCHEMAS_FLOAT:
297  case XML_SCHEMAS_DOUBLE:
298  case XML_SCHEMAS_BOOLEAN:
299  case XML_SCHEMAS_ANYURI:
300  case XML_SCHEMAS_HEXBINARY:
301  case XML_SCHEMAS_BASE64BINARY:
302  case XML_SCHEMAS_QNAME:
303  case XML_SCHEMAS_NOTATION:
304  ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
305  break;
306  default:
307  break;
308  }
309  /*
310  * Set variety.
311  */
312  switch (type) {
313  case XML_SCHEMAS_ANYTYPE:
314  case XML_SCHEMAS_ANYSIMPLETYPE:
315  break;
316  case XML_SCHEMAS_IDREFS:
317  case XML_SCHEMAS_NMTOKENS:
318  case XML_SCHEMAS_ENTITIES:
319  ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
320  ret->facets = xmlSchemaNewMinLengthFacet(1);
321  ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
322  break;
323  default:
324  ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
325  break;
326  }
327  xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
328  XML_SCHEMAS_NAMESPACE_NAME, ret);
329  ret->builtInType = type;
330  return(ret);
331 }
332 
333 /*
334 * WARNING: Those type reside normally in xmlschemas.c but are
335 * redefined here locally in oder of being able to use them for xs:anyType-
336 * TODO: Remove those definition if we move the types to a header file.
337 * TODO: Always keep those structs up-to-date with the originals.
338 */
339 #define UNBOUNDED (1 << 30)
340 
341 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
342 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
343 struct _xmlSchemaTreeItem {
344  xmlSchemaTypeType type;
345  xmlSchemaAnnotPtr annot;
346  xmlSchemaTreeItemPtr next;
347  xmlSchemaTreeItemPtr children;
348 };
349 
350 typedef struct _xmlSchemaParticle xmlSchemaParticle;
351 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
352 struct _xmlSchemaParticle {
353  xmlSchemaTypeType type;
354  xmlSchemaAnnotPtr annot;
355  xmlSchemaTreeItemPtr next;
356  xmlSchemaTreeItemPtr children;
357  int minOccurs;
358  int maxOccurs;
360 };
361 
362 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
363 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
364 struct _xmlSchemaModelGroup {
365  xmlSchemaTypeType type;
366  xmlSchemaAnnotPtr annot;
367  xmlSchemaTreeItemPtr next;
368  xmlSchemaTreeItemPtr children;
370 };
371 
372 static xmlSchemaParticlePtr
373 xmlSchemaAddParticle(void)
374 {
375  xmlSchemaParticlePtr ret = NULL;
376 
377  ret = (xmlSchemaParticlePtr)
378  xmlMalloc(sizeof(xmlSchemaParticle));
379  if (ret == NULL) {
380  xmlSchemaTypeErrMemory(NULL, "allocating particle component");
381  return (NULL);
382  }
383  memset(ret, 0, sizeof(xmlSchemaParticle));
384  ret->type = XML_SCHEMA_TYPE_PARTICLE;
385  ret->minOccurs = 1;
386  ret->maxOccurs = 1;
387  return (ret);
388 }
389 
390 /*
391  * xmlSchemaInitTypes:
392  *
393  * Initialize the default XML Schemas type library
394  */
395 void
396 xmlSchemaInitTypes(void)
397 {
398  if (xmlSchemaTypesInitialized != 0)
399  return;
400  xmlSchemaTypesBank = xmlHashCreate(40);
401 
402 
403  /*
404  * 3.4.7 Built-in Complex Type Definition
405  */
406  xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
407  XML_SCHEMAS_ANYTYPE,
408  NULL);
409  xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
410  xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
411  /*
412  * Init the content type.
413  */
414  xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
415  {
416  xmlSchemaParticlePtr particle;
417  xmlSchemaModelGroupPtr sequence;
418  xmlSchemaWildcardPtr wild;
419  /* First particle. */
420  particle = xmlSchemaAddParticle();
421  if (particle == NULL)
422  return;
423  xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
424  /* Sequence model group. */
425  sequence = (xmlSchemaModelGroupPtr)
426  xmlMalloc(sizeof(xmlSchemaModelGroup));
427  if (sequence == NULL) {
428  xmlSchemaTypeErrMemory(NULL, "allocating model group component");
429  return;
430  }
431  memset(sequence, 0, sizeof(xmlSchemaModelGroup));
432  sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
433  particle->children = (xmlSchemaTreeItemPtr) sequence;
434  /* Second particle. */
435  particle = xmlSchemaAddParticle();
436  if (particle == NULL)
437  return;
438  particle->minOccurs = 0;
439  particle->maxOccurs = UNBOUNDED;
440  sequence->children = (xmlSchemaTreeItemPtr) particle;
441  /* The wildcard */
442  wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
443  if (wild == NULL) {
444  xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
445  return;
446  }
447  memset(wild, 0, sizeof(xmlSchemaWildcard));
448  wild->type = XML_SCHEMA_TYPE_ANY;
449  wild->any = 1;
450  wild->processContents = XML_SCHEMAS_ANY_LAX;
451  particle->children = (xmlSchemaTreeItemPtr) wild;
452  /*
453  * Create the attribute wildcard.
454  */
455  wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
456  if (wild == NULL) {
457  xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
458  "wildcard on anyType");
459  return;
460  }
461  memset(wild, 0, sizeof(xmlSchemaWildcard));
462  wild->any = 1;
463  wild->processContents = XML_SCHEMAS_ANY_LAX;
464  xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
465  }
466  xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
467  XML_SCHEMAS_ANYSIMPLETYPE,
468  xmlSchemaTypeAnyTypeDef);
469  /*
470  * primitive datatypes
471  */
472  xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
473  XML_SCHEMAS_STRING,
474  xmlSchemaTypeAnySimpleTypeDef);
475  xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
476  XML_SCHEMAS_DECIMAL,
477  xmlSchemaTypeAnySimpleTypeDef);
478  xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
479  XML_SCHEMAS_DATE,
480  xmlSchemaTypeAnySimpleTypeDef);
481  xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
482  XML_SCHEMAS_DATETIME,
483  xmlSchemaTypeAnySimpleTypeDef);
484  xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
485  XML_SCHEMAS_TIME,
486  xmlSchemaTypeAnySimpleTypeDef);
487  xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
488  XML_SCHEMAS_GYEAR,
489  xmlSchemaTypeAnySimpleTypeDef);
490  xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
491  XML_SCHEMAS_GYEARMONTH,
492  xmlSchemaTypeAnySimpleTypeDef);
493  xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
494  XML_SCHEMAS_GMONTH,
495  xmlSchemaTypeAnySimpleTypeDef);
496  xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
497  XML_SCHEMAS_GMONTHDAY,
498  xmlSchemaTypeAnySimpleTypeDef);
499  xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
500  XML_SCHEMAS_GDAY,
501  xmlSchemaTypeAnySimpleTypeDef);
502  xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
503  XML_SCHEMAS_DURATION,
504  xmlSchemaTypeAnySimpleTypeDef);
505  xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
506  XML_SCHEMAS_FLOAT,
507  xmlSchemaTypeAnySimpleTypeDef);
508  xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
509  XML_SCHEMAS_DOUBLE,
510  xmlSchemaTypeAnySimpleTypeDef);
511  xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
512  XML_SCHEMAS_BOOLEAN,
513  xmlSchemaTypeAnySimpleTypeDef);
514  xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
515  XML_SCHEMAS_ANYURI,
516  xmlSchemaTypeAnySimpleTypeDef);
517  xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
518  XML_SCHEMAS_HEXBINARY,
519  xmlSchemaTypeAnySimpleTypeDef);
520  xmlSchemaTypeBase64BinaryDef
521  = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
522  xmlSchemaTypeAnySimpleTypeDef);
523  xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
524  XML_SCHEMAS_NOTATION,
525  xmlSchemaTypeAnySimpleTypeDef);
526  xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
527  XML_SCHEMAS_QNAME,
528  xmlSchemaTypeAnySimpleTypeDef);
529 
530  /*
531  * derived datatypes
532  */
533  xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
534  XML_SCHEMAS_INTEGER,
535  xmlSchemaTypeDecimalDef);
536  xmlSchemaTypeNonPositiveIntegerDef =
537  xmlSchemaInitBasicType("nonPositiveInteger",
538  XML_SCHEMAS_NPINTEGER,
539  xmlSchemaTypeIntegerDef);
540  xmlSchemaTypeNegativeIntegerDef =
541  xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
542  xmlSchemaTypeNonPositiveIntegerDef);
543  xmlSchemaTypeLongDef =
544  xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
545  xmlSchemaTypeIntegerDef);
546  xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
547  xmlSchemaTypeLongDef);
548  xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
549  XML_SCHEMAS_SHORT,
550  xmlSchemaTypeIntDef);
551  xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
552  XML_SCHEMAS_BYTE,
553  xmlSchemaTypeShortDef);
554  xmlSchemaTypeNonNegativeIntegerDef =
555  xmlSchemaInitBasicType("nonNegativeInteger",
556  XML_SCHEMAS_NNINTEGER,
557  xmlSchemaTypeIntegerDef);
558  xmlSchemaTypeUnsignedLongDef =
559  xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
560  xmlSchemaTypeNonNegativeIntegerDef);
561  xmlSchemaTypeUnsignedIntDef =
562  xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
563  xmlSchemaTypeUnsignedLongDef);
564  xmlSchemaTypeUnsignedShortDef =
565  xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
566  xmlSchemaTypeUnsignedIntDef);
567  xmlSchemaTypeUnsignedByteDef =
568  xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
569  xmlSchemaTypeUnsignedShortDef);
570  xmlSchemaTypePositiveIntegerDef =
571  xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
572  xmlSchemaTypeNonNegativeIntegerDef);
573  xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
574  XML_SCHEMAS_NORMSTRING,
575  xmlSchemaTypeStringDef);
576  xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
577  XML_SCHEMAS_TOKEN,
578  xmlSchemaTypeNormStringDef);
579  xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
580  XML_SCHEMAS_LANGUAGE,
581  xmlSchemaTypeTokenDef);
582  xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
583  XML_SCHEMAS_NAME,
584  xmlSchemaTypeTokenDef);
585  xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
586  XML_SCHEMAS_NMTOKEN,
587  xmlSchemaTypeTokenDef);
588  xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
589  XML_SCHEMAS_NCNAME,
590  xmlSchemaTypeNameDef);
591  xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
592  xmlSchemaTypeNCNameDef);
593  xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
594  XML_SCHEMAS_IDREF,
595  xmlSchemaTypeNCNameDef);
596  xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
597  XML_SCHEMAS_ENTITY,
598  xmlSchemaTypeNCNameDef);
599  /*
600  * Derived list types.
601  */
602  /* ENTITIES */
603  xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
604  XML_SCHEMAS_ENTITIES,
605  xmlSchemaTypeAnySimpleTypeDef);
606  xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
607  /* IDREFS */
608  xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
609  XML_SCHEMAS_IDREFS,
610  xmlSchemaTypeAnySimpleTypeDef);
611  xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
612 
613  /* NMTOKENS */
614  xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
615  XML_SCHEMAS_NMTOKENS,
616  xmlSchemaTypeAnySimpleTypeDef);
617  xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
618 
619  xmlSchemaTypesInitialized = 1;
620 }
621 
622 static void
623 xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
624  xmlSchemaFreeType((xmlSchemaTypePtr) type);
625 }
626 
632 void
633 xmlSchemaCleanupTypes(void) {
634  if (xmlSchemaTypesInitialized == 0)
635  return;
636  /*
637  * Free xs:anyType.
638  */
639  {
640  xmlSchemaParticlePtr particle;
641  /* Attribute wildcard. */
642  xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
643  /* Content type. */
644  particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
645  /* Wildcard. */
646  xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
647  particle->children->children->children);
648  xmlFree((xmlSchemaParticlePtr) particle->children->children);
649  /* Sequence model group. */
650  xmlFree((xmlSchemaModelGroupPtr) particle->children);
651  xmlFree((xmlSchemaParticlePtr) particle);
652  xmlSchemaTypeAnyTypeDef->subtypes = NULL;
653  }
654  xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
655  xmlSchemaTypesInitialized = 0;
656 }
657 
669 int
670 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
671 {
672  if (type == NULL)
673  return (-1);
674  if (type->type != XML_SCHEMA_TYPE_BASIC)
675  return (-1);
676  switch (type->builtInType) {
677  case XML_SCHEMAS_BOOLEAN:
678  if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
679  (facetType == XML_SCHEMA_FACET_WHITESPACE))
680  return (1);
681  else
682  return (0);
683  case XML_SCHEMAS_STRING:
684  case XML_SCHEMAS_NOTATION:
685  case XML_SCHEMAS_QNAME:
686  case XML_SCHEMAS_ANYURI:
687  case XML_SCHEMAS_BASE64BINARY:
688  case XML_SCHEMAS_HEXBINARY:
689  if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
690  (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
691  (facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
692  (facetType == XML_SCHEMA_FACET_PATTERN) ||
693  (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
694  (facetType == XML_SCHEMA_FACET_WHITESPACE))
695  return (1);
696  else
697  return (0);
698  case XML_SCHEMAS_DECIMAL:
699  if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
700  (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
701  (facetType == XML_SCHEMA_FACET_PATTERN) ||
702  (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
703  (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
704  (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
705  (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
706  (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
707  (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
708  return (1);
709  else
710  return (0);
711  case XML_SCHEMAS_TIME:
712  case XML_SCHEMAS_GDAY:
713  case XML_SCHEMAS_GMONTH:
714  case XML_SCHEMAS_GMONTHDAY:
715  case XML_SCHEMAS_GYEAR:
716  case XML_SCHEMAS_GYEARMONTH:
717  case XML_SCHEMAS_DATE:
718  case XML_SCHEMAS_DATETIME:
719  case XML_SCHEMAS_DURATION:
720  case XML_SCHEMAS_FLOAT:
721  case XML_SCHEMAS_DOUBLE:
722  if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
723  (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
724  (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
725  (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
726  (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
727  (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
728  (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
729  return (1);
730  else
731  return (0);
732  default:
733  break;
734  }
735  return (0);
736 }
737 
747 xmlSchemaTypePtr
748 xmlSchemaGetBuiltInType(xmlSchemaValType type)
749 {
750  if (xmlSchemaTypesInitialized == 0)
751  xmlSchemaInitTypes();
752  switch (type) {
753 
754  case XML_SCHEMAS_ANYSIMPLETYPE:
755  return (xmlSchemaTypeAnySimpleTypeDef);
756  case XML_SCHEMAS_STRING:
757  return (xmlSchemaTypeStringDef);
758  case XML_SCHEMAS_NORMSTRING:
759  return (xmlSchemaTypeNormStringDef);
760  case XML_SCHEMAS_DECIMAL:
761  return (xmlSchemaTypeDecimalDef);
762  case XML_SCHEMAS_TIME:
763  return (xmlSchemaTypeTimeDef);
764  case XML_SCHEMAS_GDAY:
765  return (xmlSchemaTypeGDayDef);
766  case XML_SCHEMAS_GMONTH:
767  return (xmlSchemaTypeGMonthDef);
768  case XML_SCHEMAS_GMONTHDAY:
769  return (xmlSchemaTypeGMonthDayDef);
770  case XML_SCHEMAS_GYEAR:
771  return (xmlSchemaTypeGYearDef);
772  case XML_SCHEMAS_GYEARMONTH:
773  return (xmlSchemaTypeGYearMonthDef);
774  case XML_SCHEMAS_DATE:
775  return (xmlSchemaTypeDateDef);
776  case XML_SCHEMAS_DATETIME:
777  return (xmlSchemaTypeDatetimeDef);
778  case XML_SCHEMAS_DURATION:
779  return (xmlSchemaTypeDurationDef);
780  case XML_SCHEMAS_FLOAT:
781  return (xmlSchemaTypeFloatDef);
782  case XML_SCHEMAS_DOUBLE:
783  return (xmlSchemaTypeDoubleDef);
784  case XML_SCHEMAS_BOOLEAN:
785  return (xmlSchemaTypeBooleanDef);
786  case XML_SCHEMAS_TOKEN:
787  return (xmlSchemaTypeTokenDef);
788  case XML_SCHEMAS_LANGUAGE:
789  return (xmlSchemaTypeLanguageDef);
790  case XML_SCHEMAS_NMTOKEN:
791  return (xmlSchemaTypeNmtokenDef);
792  case XML_SCHEMAS_NMTOKENS:
793  return (xmlSchemaTypeNmtokensDef);
794  case XML_SCHEMAS_NAME:
795  return (xmlSchemaTypeNameDef);
796  case XML_SCHEMAS_QNAME:
797  return (xmlSchemaTypeQNameDef);
798  case XML_SCHEMAS_NCNAME:
799  return (xmlSchemaTypeNCNameDef);
800  case XML_SCHEMAS_ID:
801  return (xmlSchemaTypeIdDef);
802  case XML_SCHEMAS_IDREF:
803  return (xmlSchemaTypeIdrefDef);
804  case XML_SCHEMAS_IDREFS:
805  return (xmlSchemaTypeIdrefsDef);
806  case XML_SCHEMAS_ENTITY:
807  return (xmlSchemaTypeEntityDef);
808  case XML_SCHEMAS_ENTITIES:
809  return (xmlSchemaTypeEntitiesDef);
810  case XML_SCHEMAS_NOTATION:
811  return (xmlSchemaTypeNotationDef);
812  case XML_SCHEMAS_ANYURI:
813  return (xmlSchemaTypeAnyURIDef);
814  case XML_SCHEMAS_INTEGER:
815  return (xmlSchemaTypeIntegerDef);
816  case XML_SCHEMAS_NPINTEGER:
817  return (xmlSchemaTypeNonPositiveIntegerDef);
818  case XML_SCHEMAS_NINTEGER:
819  return (xmlSchemaTypeNegativeIntegerDef);
820  case XML_SCHEMAS_NNINTEGER:
821  return (xmlSchemaTypeNonNegativeIntegerDef);
822  case XML_SCHEMAS_PINTEGER:
823  return (xmlSchemaTypePositiveIntegerDef);
824  case XML_SCHEMAS_INT:
825  return (xmlSchemaTypeIntDef);
826  case XML_SCHEMAS_UINT:
827  return (xmlSchemaTypeUnsignedIntDef);
828  case XML_SCHEMAS_LONG:
829  return (xmlSchemaTypeLongDef);
830  case XML_SCHEMAS_ULONG:
831  return (xmlSchemaTypeUnsignedLongDef);
832  case XML_SCHEMAS_SHORT:
833  return (xmlSchemaTypeShortDef);
834  case XML_SCHEMAS_USHORT:
835  return (xmlSchemaTypeUnsignedShortDef);
836  case XML_SCHEMAS_BYTE:
837  return (xmlSchemaTypeByteDef);
838  case XML_SCHEMAS_UBYTE:
839  return (xmlSchemaTypeUnsignedByteDef);
840  case XML_SCHEMAS_HEXBINARY:
841  return (xmlSchemaTypeHexBinaryDef);
842  case XML_SCHEMAS_BASE64BINARY:
843  return (xmlSchemaTypeBase64BinaryDef);
844  case XML_SCHEMAS_ANYTYPE:
845  return (xmlSchemaTypeAnyTypeDef);
846  default:
847  return (NULL);
848  }
849 }
850 
860 int
861 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
862 
863  if ((prev == NULL) || (cur == NULL))
864  return (-1);
865  prev->next = cur;
866  return (0);
867 }
868 
878 xmlSchemaValPtr
879 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
880 
881  if (cur == NULL)
882  return (NULL);
883  return (cur->next);
884 }
885 
895 const xmlChar *
896 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
897 {
898  if (val == NULL)
899  return (NULL);
900  switch (val->type) {
901  case XML_SCHEMAS_STRING:
902  case XML_SCHEMAS_NORMSTRING:
903  case XML_SCHEMAS_ANYSIMPLETYPE:
904  case XML_SCHEMAS_TOKEN:
905  case XML_SCHEMAS_LANGUAGE:
906  case XML_SCHEMAS_NMTOKEN:
907  case XML_SCHEMAS_NAME:
908  case XML_SCHEMAS_NCNAME:
909  case XML_SCHEMAS_ID:
910  case XML_SCHEMAS_IDREF:
911  case XML_SCHEMAS_ENTITY:
912  case XML_SCHEMAS_ANYURI:
913  return (BAD_CAST val->value.str);
914  default:
915  break;
916  }
917  return (NULL);
918 }
919 
928 int
929 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
930 {
931  if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
932  return (0);
933  return (val->value.b);
934 }
935 
949 xmlSchemaValPtr
950 xmlSchemaNewStringValue(xmlSchemaValType type,
951  const xmlChar *value)
952 {
953  xmlSchemaValPtr val;
954 
955  if (type != XML_SCHEMAS_STRING)
956  return(NULL);
957  val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
958  if (val == NULL) {
959  return(NULL);
960  }
961  memset(val, 0, sizeof(xmlSchemaVal));
962  val->type = type;
963  val->value.str = (xmlChar *) value;
964  return(val);
965 }
966 
977 xmlSchemaValPtr
978 xmlSchemaNewNOTATIONValue(const xmlChar *name,
979  const xmlChar *ns)
980 {
981  xmlSchemaValPtr val;
982 
983  val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
984  if (val == NULL)
985  return (NULL);
986 
987  val->value.qname.name = (xmlChar *)name;
988  if (ns != NULL)
989  val->value.qname.uri = (xmlChar *)ns;
990  return(val);
991 }
992 
1003 xmlSchemaValPtr
1004 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
1005  const xmlChar *localName)
1006 {
1007  xmlSchemaValPtr val;
1008 
1009  val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1010  if (val == NULL)
1011  return (NULL);
1012 
1013  val->value.qname.name = (xmlChar *) localName;
1014  val->value.qname.uri = (xmlChar *) namespaceName;
1015  return(val);
1016 }
1017 
1024 void
1025 xmlSchemaFreeValue(xmlSchemaValPtr value) {
1026  xmlSchemaValPtr prev;
1027 
1028  while (value != NULL) {
1029  switch (value->type) {
1030  case XML_SCHEMAS_STRING:
1031  case XML_SCHEMAS_NORMSTRING:
1032  case XML_SCHEMAS_TOKEN:
1033  case XML_SCHEMAS_LANGUAGE:
1034  case XML_SCHEMAS_NMTOKEN:
1035  case XML_SCHEMAS_NMTOKENS:
1036  case XML_SCHEMAS_NAME:
1037  case XML_SCHEMAS_NCNAME:
1038  case XML_SCHEMAS_ID:
1039  case XML_SCHEMAS_IDREF:
1040  case XML_SCHEMAS_IDREFS:
1041  case XML_SCHEMAS_ENTITY:
1042  case XML_SCHEMAS_ENTITIES:
1043  case XML_SCHEMAS_ANYURI:
1044  case XML_SCHEMAS_ANYSIMPLETYPE:
1045  if (value->value.str != NULL)
1046  xmlFree(value->value.str);
1047  break;
1048  case XML_SCHEMAS_NOTATION:
1049  case XML_SCHEMAS_QNAME:
1050  if (value->value.qname.uri != NULL)
1051  xmlFree(value->value.qname.uri);
1052  if (value->value.qname.name != NULL)
1053  xmlFree(value->value.qname.name);
1054  break;
1055  case XML_SCHEMAS_HEXBINARY:
1056  if (value->value.hex.str != NULL)
1057  xmlFree(value->value.hex.str);
1058  break;
1059  case XML_SCHEMAS_BASE64BINARY:
1060  if (value->value.base64.str != NULL)
1061  xmlFree(value->value.base64.str);
1062  break;
1063  default:
1064  break;
1065  }
1066  prev = value;
1067  value = value->next;
1068  xmlFree(prev);
1069  }
1070 }
1071 
1081 xmlSchemaTypePtr
1082 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
1083  if (xmlSchemaTypesInitialized == 0)
1084  xmlSchemaInitTypes();
1085  if (name == NULL)
1086  return(NULL);
1087  return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
1088 }
1089 
1099 xmlSchemaTypePtr
1100 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
1101 {
1102  if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
1103  return (NULL);
1104  switch (type->builtInType) {
1105  case XML_SCHEMAS_NMTOKENS:
1106  return (xmlSchemaTypeNmtokenDef );
1107  case XML_SCHEMAS_IDREFS:
1108  return (xmlSchemaTypeIdrefDef);
1109  case XML_SCHEMAS_ENTITIES:
1110  return (xmlSchemaTypeEntityDef);
1111  default:
1112  return (NULL);
1113  }
1114 }
1115 
1116 /****************************************************************
1117  * *
1118  * Convenience macros and functions *
1119  * *
1120  ****************************************************************/
1121 
1122 #define IS_TZO_CHAR(c) \
1123  ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1124 
1125 #define VALID_YEAR(yr) (yr != 0)
1126 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
1127 /* VALID_DAY should only be used when month is unknown */
1128 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
1129 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
1130 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
1131 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
1132 #define VALID_TZO(tzo) ((tzo >= -840) && (tzo <= 840))
1133 #define IS_LEAP(y) \
1134  (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1135 
1136 static const unsigned int daysInMonth[12] =
1137  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1138 static const unsigned int daysInMonthLeap[12] =
1139  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1140 
1141 #define MAX_DAYINMONTH(yr,mon) \
1142  (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1143 
1144 #define VALID_MDAY(dt) \
1145  (IS_LEAP(dt->year) ? \
1146  (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
1147  (dt->day <= daysInMonth[dt->mon - 1]))
1148 
1149 #define VALID_DATE(dt) \
1150  (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1151 
1152 #define VALID_END_OF_DAY(dt) \
1153  ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1154 
1155 #define VALID_TIME(dt) \
1156  (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
1157  VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \
1158  VALID_TZO(dt->tzo))
1159 
1160 #define VALID_DATETIME(dt) \
1161  (VALID_DATE(dt) && VALID_TIME(dt))
1162 
1163 #define SECS_PER_MIN 60
1164 #define MINS_PER_HOUR 60
1165 #define HOURS_PER_DAY 24
1166 #define SECS_PER_HOUR (MINS_PER_HOUR * SECS_PER_MIN)
1167 #define SECS_PER_DAY (HOURS_PER_DAY * SECS_PER_HOUR)
1168 #define MINS_PER_DAY (HOURS_PER_DAY * MINS_PER_HOUR)
1169 
1170 static const long dayInYearByMonth[12] =
1171  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1172 static const long dayInLeapYearByMonth[12] =
1173  { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1174 
1175 #define DAY_IN_YEAR(day, month, year) \
1176  ((IS_LEAP(year) ? \
1177  dayInLeapYearByMonth[month - 1] : \
1178  dayInYearByMonth[month - 1]) + day)
1179 
1180 #ifdef DEBUG
1181 #define DEBUG_DATE(dt) \
1182  xmlGenericError(xmlGenericErrorContext, \
1183  "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
1184  dt->type,dt->value.date.year,dt->value.date.mon, \
1185  dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
1186  dt->value.date.sec); \
1187  if (dt->value.date.tz_flag) \
1188  if (dt->value.date.tzo != 0) \
1189  xmlGenericError(xmlGenericErrorContext, \
1190  "%+05d\n",dt->value.date.tzo); \
1191  else \
1192  xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1193  else \
1194  xmlGenericError(xmlGenericErrorContext,"\n")
1195 #else
1196 #define DEBUG_DATE(dt)
1197 #endif
1198 
1211 static int
1212 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
1213  const xmlChar *cur = *str, *firstChar;
1214  int isneg = 0, digcnt = 0;
1215 
1216  if (((*cur < '0') || (*cur > '9')) &&
1217  (*cur != '-') && (*cur != '+'))
1218  return -1;
1219 
1220  if (*cur == '-') {
1221  isneg = 1;
1222  cur++;
1223  }
1224 
1225  firstChar = cur;
1226 
1227  while ((*cur >= '0') && (*cur <= '9')) {
1228  int digit = *cur - '0';
1229 
1230  if (dt->year > LONG_MAX / 10)
1231  return 2;
1232  dt->year *= 10;
1233  if (dt->year > LONG_MAX - digit)
1234  return 2;
1235  dt->year += digit;
1236  cur++;
1237  digcnt++;
1238  }
1239 
1240  /* year must be at least 4 digits (CCYY); over 4
1241  * digits cannot have a leading zero. */
1242  if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
1243  return 1;
1244 
1245  if (isneg)
1246  dt->year = - dt->year;
1247 
1248  if (!VALID_YEAR(dt->year))
1249  return 2;
1250 
1251  *str = cur;
1252  return 0;
1253 }
1254 
1266 #define PARSE_2_DIGITS(num, cur, invalid) \
1267  if ((cur[0] < '0') || (cur[0] > '9') || \
1268  (cur[1] < '0') || (cur[1] > '9')) \
1269  invalid = 1; \
1270  else \
1271  num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1272  cur += 2;
1273 
1286 #define PARSE_FLOAT(num, cur, invalid) \
1287  PARSE_2_DIGITS(num, cur, invalid); \
1288  if (!invalid && (*cur == '.')) { \
1289  double mult = 1; \
1290  cur++; \
1291  if ((*cur < '0') || (*cur > '9')) \
1292  invalid = 1; \
1293  while ((*cur >= '0') && (*cur <= '9')) { \
1294  mult /= 10; \
1295  num += (*cur - '0') * mult; \
1296  cur++; \
1297  } \
1298  }
1299 
1311 static int
1312 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
1313  const xmlChar *cur = *str;
1314  int ret = 0;
1315  unsigned int value = 0;
1316 
1317  PARSE_2_DIGITS(value, cur, ret);
1318  if (ret != 0)
1319  return ret;
1320 
1321  if (!VALID_MONTH(value))
1322  return 2;
1323 
1324  dt->mon = value;
1325 
1326  *str = cur;
1327  return 0;
1328 }
1329 
1341 static int
1342 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
1343  const xmlChar *cur = *str;
1344  int ret = 0;
1345  unsigned int value = 0;
1346 
1347  PARSE_2_DIGITS(value, cur, ret);
1348  if (ret != 0)
1349  return ret;
1350 
1351  if (!VALID_DAY(value))
1352  return 2;
1353 
1354  dt->day = value;
1355  *str = cur;
1356  return 0;
1357 }
1358 
1371 static int
1372 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1373  const xmlChar *cur = *str;
1374  int ret = 0;
1375  int value = 0;
1376 
1377  PARSE_2_DIGITS(value, cur, ret);
1378  if (ret != 0)
1379  return ret;
1380  if (*cur != ':')
1381  return 1;
1382  if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
1383  return 2;
1384  cur++;
1385 
1386  /* the ':' insures this string is xs:time */
1387  dt->hour = value;
1388 
1389  PARSE_2_DIGITS(value, cur, ret);
1390  if (ret != 0)
1391  return ret;
1392  if (!VALID_MIN(value))
1393  return 2;
1394  dt->min = value;
1395 
1396  if (*cur != ':')
1397  return 1;
1398  cur++;
1399 
1400  PARSE_FLOAT(dt->sec, cur, ret);
1401  if (ret != 0)
1402  return ret;
1403 
1404  if (!VALID_TIME(dt))
1405  return 2;
1406 
1407  *str = cur;
1408  return 0;
1409 }
1410 
1422 static int
1423 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1424  const xmlChar *cur;
1425  int ret = 0;
1426 
1427  if (str == NULL)
1428  return -1;
1429  cur = *str;
1430 
1431  switch (*cur) {
1432  case 0:
1433  dt->tz_flag = 0;
1434  dt->tzo = 0;
1435  break;
1436 
1437  case 'Z':
1438  dt->tz_flag = 1;
1439  dt->tzo = 0;
1440  cur++;
1441  break;
1442 
1443  case '+':
1444  case '-': {
1445  int isneg = 0, tmp = 0;
1446  isneg = (*cur == '-');
1447 
1448  cur++;
1449 
1450  PARSE_2_DIGITS(tmp, cur, ret);
1451  if (ret != 0)
1452  return ret;
1453  if (!VALID_HOUR(tmp))
1454  return 2;
1455 
1456  if (*cur != ':')
1457  return 1;
1458  cur++;
1459 
1460  dt->tzo = tmp * 60;
1461 
1462  PARSE_2_DIGITS(tmp, cur, ret);
1463  if (ret != 0)
1464  return ret;
1465  if (!VALID_MIN(tmp))
1466  return 2;
1467 
1468  dt->tzo += tmp;
1469  if (isneg)
1470  dt->tzo = - dt->tzo;
1471 
1472  if (!VALID_TZO(dt->tzo))
1473  return 2;
1474 
1475  dt->tz_flag = 1;
1476  break;
1477  }
1478  default:
1479  return 1;
1480  }
1481 
1482  *str = cur;
1483  return 0;
1484 }
1485 
1494 static int
1495 _xmlSchemaBase64Decode (const xmlChar ch) {
1496  if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
1497  if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
1498  if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
1499  if ('+' == ch) return 62;
1500  if ('/' == ch) return 63;
1501  if ('=' == ch) return 64;
1502  return -1;
1503 }
1504 
1505 /****************************************************************
1506  * *
1507  * XML Schema Dates/Times Datatypes Handling *
1508  * *
1509  ****************************************************************/
1510 
1522 #define PARSE_DIGITS(num, cur, num_type) \
1523  if ((*cur < '0') || (*cur > '9')) \
1524  num_type = -1; \
1525  else \
1526  while ((*cur >= '0') && (*cur <= '9')) { \
1527  num = num * 10 + (*cur - '0'); \
1528  cur++; \
1529  }
1530 
1544 #define PARSE_NUM(num, cur, num_type) \
1545  num = 0; \
1546  PARSE_DIGITS(num, cur, num_type); \
1547  if (!num_type && (*cur == '.')) { \
1548  double mult = 1; \
1549  cur++; \
1550  if ((*cur < '0') || (*cur > '9')) \
1551  num_type = -1; \
1552  else \
1553  num_type = 1; \
1554  while ((*cur >= '0') && (*cur <= '9')) { \
1555  mult /= 10; \
1556  num += (*cur - '0') * mult; \
1557  cur++; \
1558  } \
1559  }
1560 
1573 static int
1574 xmlSchemaValidateDates (xmlSchemaValType type,
1575  const xmlChar *dateTime, xmlSchemaValPtr *val,
1576  int collapse) {
1577  xmlSchemaValPtr dt;
1578  int ret;
1579  const xmlChar *cur = dateTime;
1580 
1581 #define RETURN_TYPE_IF_VALID(t) \
1582  if (IS_TZO_CHAR(*cur)) { \
1583  ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1584  if (ret == 0) { \
1585  if (*cur != 0) \
1586  goto error; \
1587  dt->type = t; \
1588  goto done; \
1589  } \
1590  }
1591 
1592  if (dateTime == NULL)
1593  return -1;
1594 
1595  if (collapse)
1596  while IS_WSP_BLANK_CH(*cur) cur++;
1597 
1598  if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1599  return 1;
1600 
1601  dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1602  if (dt == NULL)
1603  return -1;
1604 
1605  if ((cur[0] == '-') && (cur[1] == '-')) {
1606  /*
1607  * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1608  * xs:gDay)
1609  */
1610  cur += 2;
1611 
1612  /* is it an xs:gDay? */
1613  if (*cur == '-') {
1614  if (type == XML_SCHEMAS_GMONTH)
1615  goto error;
1616  ++cur;
1617  ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1618  if (ret != 0)
1619  goto error;
1620 
1621  RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1622 
1623  goto error;
1624  }
1625 
1626  /*
1627  * it should be an xs:gMonthDay or xs:gMonth
1628  */
1629  ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1630  if (ret != 0)
1631  goto error;
1632 
1633  /*
1634  * a '-' char could indicate this type is xs:gMonthDay or
1635  * a negative time zone offset. Check for xs:gMonthDay first.
1636  * Also the first three char's of a negative tzo (-MM:SS) can
1637  * appear to be a valid day; so even if the day portion
1638  * of the xs:gMonthDay verifies, we must insure it was not
1639  * a tzo.
1640  */
1641  if (*cur == '-') {
1642  const xmlChar *rewnd = cur;
1643  cur++;
1644 
1645  ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1646  if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
1647 
1648  /*
1649  * we can use the VALID_MDAY macro to validate the month
1650  * and day because the leap year test will flag year zero
1651  * as a leap year (even though zero is an invalid year).
1652  * FUTURE TODO: Zero will become valid in XML Schema 1.1
1653  * probably.
1654  */
1655  if (VALID_MDAY((&(dt->value.date)))) {
1656 
1657  RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1658 
1659  goto error;
1660  }
1661  }
1662 
1663  /*
1664  * not xs:gMonthDay so rewind and check if just xs:gMonth
1665  * with an optional time zone.
1666  */
1667  cur = rewnd;
1668  }
1669 
1670  RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1671 
1672  goto error;
1673  }
1674 
1675  /*
1676  * It's a right-truncated date or an xs:time.
1677  * Try to parse an xs:time then fallback on right-truncated dates.
1678  */
1679  if ((*cur >= '0') && (*cur <= '9')) {
1680  ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1681  if (ret == 0) {
1682  /* it's an xs:time */
1683  RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1684  }
1685  }
1686 
1687  /* fallback on date parsing */
1688  cur = dateTime;
1689 
1690  ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1691  if (ret != 0)
1692  goto error;
1693 
1694  /* is it an xs:gYear? */
1695  RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1696 
1697  if (*cur != '-')
1698  goto error;
1699  cur++;
1700 
1701  ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1702  if (ret != 0)
1703  goto error;
1704 
1705  /* is it an xs:gYearMonth? */
1706  RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1707 
1708  if (*cur != '-')
1709  goto error;
1710  cur++;
1711 
1712  ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1713  if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1714  goto error;
1715 
1716  /* is it an xs:date? */
1717  RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1718 
1719  if (*cur != 'T')
1720  goto error;
1721  cur++;
1722 
1723  /* it should be an xs:dateTime */
1724  ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1725  if (ret != 0)
1726  goto error;
1727 
1728  ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1729  if (collapse)
1730  while IS_WSP_BLANK_CH(*cur) cur++;
1731  if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
1732  goto error;
1733 
1734 
1735  dt->type = XML_SCHEMAS_DATETIME;
1736 
1737 done:
1738 #if 1
1739  if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1740  goto error;
1741 #else
1742  /*
1743  * insure the parsed type is equal to or less significant (right
1744  * truncated) than the desired type.
1745  */
1746  if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1747 
1748  /* time only matches time */
1749  if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1750  goto error;
1751 
1752  if ((type == XML_SCHEMAS_DATETIME) &&
1753  ((dt->type != XML_SCHEMAS_DATE) ||
1754  (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1755  (dt->type != XML_SCHEMAS_GYEAR)))
1756  goto error;
1757 
1758  if ((type == XML_SCHEMAS_DATE) &&
1759  ((dt->type != XML_SCHEMAS_GYEAR) ||
1760  (dt->type != XML_SCHEMAS_GYEARMONTH)))
1761  goto error;
1762 
1763  if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1764  goto error;
1765 
1766  if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1767  goto error;
1768  }
1769 #endif
1770 
1771  if (val != NULL)
1772  *val = dt;
1773  else
1774  xmlSchemaFreeValue(dt);
1775 
1776  return 0;
1777 
1778 error:
1779  if (dt != NULL)
1780  xmlSchemaFreeValue(dt);
1781  return 1;
1782 }
1783 
1796 static int
1797 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1798  const xmlChar *duration, xmlSchemaValPtr *val,
1799  int collapse) {
1800  const xmlChar *cur = duration;
1801  xmlSchemaValPtr dur;
1802  int isneg = 0;
1803  unsigned int seq = 0;
1804  long days, secs = 0;
1805  double sec_frac = 0.0;
1806 
1807  if (duration == NULL)
1808  return -1;
1809 
1810  if (collapse)
1811  while IS_WSP_BLANK_CH(*cur) cur++;
1812 
1813  if (*cur == '-') {
1814  isneg = 1;
1815  cur++;
1816  }
1817 
1818  /* duration must start with 'P' (after sign) */
1819  if (*cur++ != 'P')
1820  return 1;
1821 
1822  if (*cur == 0)
1823  return 1;
1824 
1825  dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1826  if (dur == NULL)
1827  return -1;
1828 
1829  while (*cur != 0) {
1830  long num = 0;
1831  size_t has_digits = 0;
1832  int has_frac = 0;
1833  const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1834 
1835  /* input string should be empty or invalid date/time item */
1836  if (seq >= sizeof(desig))
1837  goto error;
1838 
1839  /* T designator must be present for time items */
1840  if (*cur == 'T') {
1841  if (seq > 3)
1842  goto error;
1843  cur++;
1844  seq = 3;
1845  } else if (seq == 3)
1846  goto error;
1847 
1848  /* Parse integral part. */
1849  while (*cur >= '0' && *cur <= '9') {
1850  long digit = *cur - '0';
1851 
1852  if (num > LONG_MAX / 10)
1853  goto error;
1854  num *= 10;
1855  if (num > LONG_MAX - digit)
1856  goto error;
1857  num += digit;
1858 
1859  has_digits = 1;
1860  cur++;
1861  }
1862 
1863  if (*cur == '.') {
1864  /* Parse fractional part. */
1865  double mult = 1.0;
1866  cur++;
1867  has_frac = 1;
1868  while (*cur >= '0' && *cur <= '9') {
1869  mult /= 10.0;
1870  sec_frac += (*cur - '0') * mult;
1871  has_digits = 1;
1872  cur++;
1873  }
1874  }
1875 
1876  while (*cur != desig[seq]) {
1877  seq++;
1878  /* No T designator or invalid char. */
1879  if (seq == 3 || seq == sizeof(desig))
1880  goto error;
1881  }
1882  cur++;
1883 
1884  if (!has_digits || (has_frac && (seq != 5)))
1885  goto error;
1886 
1887  switch (seq) {
1888  case 0:
1889  /* Year */
1890  if (num > LONG_MAX / 12)
1891  goto error;
1892  dur->value.dur.mon = num * 12;
1893  break;
1894  case 1:
1895  /* Month */
1896  if (dur->value.dur.mon > LONG_MAX - num)
1897  goto error;
1898  dur->value.dur.mon += num;
1899  break;
1900  case 2:
1901  /* Day */
1902  dur->value.dur.day = num;
1903  break;
1904  case 3:
1905  /* Hour */
1906  days = num / HOURS_PER_DAY;
1907  if (dur->value.dur.day > LONG_MAX - days)
1908  goto error;
1909  dur->value.dur.day += days;
1910  secs = (num % HOURS_PER_DAY) * SECS_PER_HOUR;
1911  break;
1912  case 4:
1913  /* Minute */
1914  days = num / MINS_PER_DAY;
1915  if (dur->value.dur.day > LONG_MAX - days)
1916  goto error;
1917  dur->value.dur.day += days;
1918  secs += (num % MINS_PER_DAY) * SECS_PER_MIN;
1919  break;
1920  case 5:
1921  /* Second */
1922  days = num / SECS_PER_DAY;
1923  if (dur->value.dur.day > LONG_MAX - days)
1924  goto error;
1925  dur->value.dur.day += days;
1926  secs += num % SECS_PER_DAY;
1927  break;
1928  }
1929 
1930  seq++;
1931  }
1932 
1933  days = secs / SECS_PER_DAY;
1934  if (dur->value.dur.day > LONG_MAX - days)
1935  goto error;
1936  dur->value.dur.day += days;
1937  dur->value.dur.sec = (secs % SECS_PER_DAY) + sec_frac;
1938 
1939  if (isneg) {
1940  dur->value.dur.mon = -dur->value.dur.mon;
1941  dur->value.dur.day = -dur->value.dur.day;
1942  dur->value.dur.sec = -dur->value.dur.sec;
1943  }
1944 
1945  if (val != NULL)
1946  *val = dur;
1947  else
1948  xmlSchemaFreeValue(dur);
1949 
1950  return 0;
1951 
1952 error:
1953  if (dur != NULL)
1954  xmlSchemaFreeValue(dur);
1955  return 1;
1956 }
1957 
1966 static xmlChar *
1967 xmlSchemaStrip(const xmlChar *value) {
1968  const xmlChar *start = value, *end, *f;
1969 
1970  if (value == NULL) return(NULL);
1971  while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1972  end = start;
1973  while (*end != 0) end++;
1974  f = end;
1975  end--;
1976  while ((end > start) && (IS_BLANK_CH(*end))) end--;
1977  end++;
1978  if ((start == value) && (f == end)) return(NULL);
1979  return(xmlStrndup(start, end - start));
1980 }
1981 
1990 xmlChar *
1991 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
1992  const xmlChar *cur = value;
1993  xmlChar *ret = NULL, *mcur;
1994 
1995  if (value == NULL)
1996  return(NULL);
1997 
1998  while ((*cur != 0) &&
1999  (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
2000  cur++;
2001  }
2002  if (*cur == 0)
2003  return (NULL);
2004  ret = xmlStrdup(value);
2005  /* TODO FIXME: I guess gcc will bark at this. */
2006  mcur = (xmlChar *) (ret + (cur - value));
2007  do {
2008  if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
2009  *mcur = ' ';
2010  mcur++;
2011  } while (*mcur != 0);
2012  return(ret);
2013 }
2014 
2023 xmlChar *
2024 xmlSchemaCollapseString(const xmlChar *value) {
2025  const xmlChar *start = value, *end, *f;
2026  xmlChar *g;
2027  int col = 0;
2028 
2029  if (value == NULL) return(NULL);
2030  while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
2031  end = start;
2032  while (*end != 0) {
2033  if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
2034  col = end - start;
2035  break;
2036  } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
2037  col = end - start;
2038  break;
2039  }
2040  end++;
2041  }
2042  if (col == 0) {
2043  f = end;
2044  end--;
2045  while ((end > start) && (IS_BLANK_CH(*end))) end--;
2046  end++;
2047  if ((start == value) && (f == end)) return(NULL);
2048  return(xmlStrndup(start, end - start));
2049  }
2050  start = xmlStrdup(start);
2051  if (start == NULL) return(NULL);
2052  g = (xmlChar *) (start + col);
2053  end = g;
2054  while (*end != 0) {
2055  if (IS_BLANK_CH(*end)) {
2056  end++;
2057  while (IS_BLANK_CH(*end)) end++;
2058  if (*end != 0)
2059  *g++ = ' ';
2060  } else
2061  *g++ = *end++;
2062  }
2063  *g = 0;
2064  return((xmlChar *) start);
2065 }
2066 
2080 static int
2081 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
2082  xmlSchemaValPtr *ret, xmlNodePtr node) {
2083  xmlChar *val, *cur, *endval;
2084  int nb_values = 0;
2085  int tmp = 0;
2086 
2087  if (value == NULL) {
2088  return(-1);
2089  }
2090  val = xmlStrdup(value);
2091  if (val == NULL) {
2092  return(-1);
2093  }
2094  if (ret != NULL) {
2095  *ret = NULL;
2096  }
2097  cur = val;
2098  /*
2099  * Split the list
2100  */
2101  while (IS_BLANK_CH(*cur)) *cur++ = 0;
2102  while (*cur != 0) {
2103  if (IS_BLANK_CH(*cur)) {
2104  *cur = 0;
2105  cur++;
2106  while (IS_BLANK_CH(*cur)) *cur++ = 0;
2107  } else {
2108  nb_values++;
2109  cur++;
2110  while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
2111  }
2112  }
2113  if (nb_values == 0) {
2114  xmlFree(val);
2115  return(nb_values);
2116  }
2117  endval = cur;
2118  cur = val;
2119  while ((*cur == 0) && (cur != endval)) cur++;
2120  while (cur != endval) {
2121  tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
2122  if (tmp != 0)
2123  break;
2124  while (*cur != 0) cur++;
2125  while ((*cur == 0) && (cur != endval)) cur++;
2126  }
2127  /* TODO what return value ? c.f. bug #158628
2128  if (ret != NULL) {
2129  TODO
2130  } */
2131  xmlFree(val);
2132  if (tmp == 0)
2133  return(nb_values);
2134  return(-1);
2135 }
2136 
2149 static int
2150 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
2151  unsigned long *lmi, unsigned long *lhi) {
2152  unsigned long lo = 0, mi = 0, hi = 0;
2153  const xmlChar *tmp, *cur = *str;
2154  int ret = 0, i = 0;
2155 
2156  if (!((*cur >= '0') && (*cur <= '9')))
2157  return(-2);
2158 
2159  while (*cur == '0') { /* ignore leading zeroes */
2160  cur++;
2161  }
2162  tmp = cur;
2163  while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
2164  i++;tmp++;ret++;
2165  }
2166  if (i > 24) {
2167  *str = tmp;
2168  return(-1);
2169  }
2170  while (i > 16) {
2171  hi = hi * 10 + (*cur++ - '0');
2172  i--;
2173  }
2174  while (i > 8) {
2175  mi = mi * 10 + (*cur++ - '0');
2176  i--;
2177  }
2178  while (i > 0) {
2179  lo = lo * 10 + (*cur++ - '0');
2180  i--;
2181  }
2182 
2183  *str = cur;
2184  *llo = lo;
2185  *lmi = mi;
2186  *lhi = hi;
2187  return(ret);
2188 }
2189 
2190 /*
2191  * xmlSchemaCheckLanguageType
2192  * @value: the value to check
2193  *
2194  * Check that a value conforms to the lexical space of the language datatype.
2195  * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
2196  *
2197  * Returns 1 if this validates, 0 otherwise.
2198  */
2199 static int
2200 xmlSchemaCheckLanguageType(const xmlChar* value) {
2201  int first = 1, len = 0;
2202  const xmlChar* cur = value;
2203 
2204  if (value == NULL)
2205  return (0);
2206 
2207  while (cur[0] != 0) {
2208  if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
2209  || (cur[0] == '-')
2210  || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
2211  return (0);
2212  if (cur[0] == '-') {
2213  if ((len < 1) || (len > 8))
2214  return (0);
2215  len = 0;
2216  first = 0;
2217  }
2218  else
2219  len++;
2220  cur++;
2221  }
2222  if ((len < 1) || (len > 8))
2223  return (0);
2224 
2225  return (1);
2226 }
2227 
2243 static int
2244 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
2245  xmlSchemaValPtr * val, xmlNodePtr node, int flags,
2246  xmlSchemaWhitespaceValueType ws,
2247  int normOnTheFly, int applyNorm, int createStringValue)
2248 {
2249  xmlSchemaValPtr v;
2250  xmlChar *norm = NULL;
2251  int ret = 0;
2252 
2253  if (xmlSchemaTypesInitialized == 0)
2254  xmlSchemaInitTypes();
2255  if (type == NULL)
2256  return (-1);
2257 
2258  /*
2259  * validating a non existent text node is similar to validating
2260  * an empty one.
2261  */
2262  if (value == NULL)
2263  value = BAD_CAST "";
2264 
2265  if (val != NULL)
2266  *val = NULL;
2267  if ((flags == 0) && (value != NULL)) {
2268 
2269  if ((type->builtInType != XML_SCHEMAS_STRING) &&
2270  (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
2271  (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
2272  if (type->builtInType == XML_SCHEMAS_NORMSTRING)
2273  norm = xmlSchemaWhiteSpaceReplace(value);
2274  else
2275  norm = xmlSchemaCollapseString(value);
2276  if (norm != NULL)
2277  value = norm;
2278  }
2279  }
2280 
2281  switch (type->builtInType) {
2282  case XML_SCHEMAS_UNKNOWN:
2283  goto error;
2284  case XML_SCHEMAS_ANYTYPE:
2285  case XML_SCHEMAS_ANYSIMPLETYPE:
2286  if ((createStringValue) && (val != NULL)) {
2287  v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
2288  if (v != NULL) {
2289  v->value.str = xmlStrdup(value);
2290  *val = v;
2291  } else {
2292  goto error;
2293  }
2294  }
2295  goto return0;
2296  case XML_SCHEMAS_STRING:
2297  if (! normOnTheFly) {
2298  const xmlChar *cur = value;
2299 
2300  if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
2301  while (*cur != 0) {
2302  if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2303  goto return1;
2304  } else {
2305  cur++;
2306  }
2307  }
2308  } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
2309  while (*cur != 0) {
2310  if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2311  goto return1;
2312  } else if IS_WSP_SPACE_CH(*cur) {
2313  cur++;
2314  if IS_WSP_SPACE_CH(*cur)
2315  goto return1;
2316  } else {
2317  cur++;
2318  }
2319  }
2320  }
2321  }
2322  if (createStringValue && (val != NULL)) {
2323  if (applyNorm) {
2324  if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2325  norm = xmlSchemaCollapseString(value);
2326  else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
2327  norm = xmlSchemaWhiteSpaceReplace(value);
2328  if (norm != NULL)
2329  value = norm;
2330  }
2331  v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
2332  if (v != NULL) {
2333  v->value.str = xmlStrdup(value);
2334  *val = v;
2335  } else {
2336  goto error;
2337  }
2338  }
2339  goto return0;
2340  case XML_SCHEMAS_NORMSTRING:{
2341  if (normOnTheFly) {
2342  if (applyNorm) {
2343  if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2344  norm = xmlSchemaCollapseString(value);
2345  else
2346  norm = xmlSchemaWhiteSpaceReplace(value);
2347  if (norm != NULL)
2348  value = norm;
2349  }
2350  } else {
2351  const xmlChar *cur = value;
2352  while (*cur != 0) {
2353  if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2354  goto return1;
2355  } else {
2356  cur++;
2357  }
2358  }
2359  }
2360  if (val != NULL) {
2361  v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
2362  if (v != NULL) {
2363  v->value.str = xmlStrdup(value);
2364  *val = v;
2365  } else {
2366  goto error;
2367  }
2368  }
2369  goto return0;
2370  }
2371  case XML_SCHEMAS_DECIMAL:{
2372  const xmlChar *cur = value;
2373  unsigned int len, neg, integ, hasLeadingZeroes;
2374  xmlChar cval[25];
2375  xmlChar *cptr = cval;
2376 
2377  if ((cur == NULL) || (*cur == 0))
2378  goto return1;
2379 
2380  /*
2381  * xs:decimal has a whitespace-facet value of 'collapse'.
2382  */
2383  if (normOnTheFly)
2384  while IS_WSP_BLANK_CH(*cur) cur++;
2385 
2386  /*
2387  * First we handle an optional sign.
2388  */
2389  neg = 0;
2390  if (*cur == '-') {
2391  neg = 1;
2392  cur++;
2393  } else if (*cur == '+')
2394  cur++;
2395  /*
2396  * Disallow: "", "-", "- "
2397  */
2398  if (*cur == 0)
2399  goto return1;
2400  /*
2401  * Next we "pre-parse" the number, in preparation for calling
2402  * the common routine xmlSchemaParseUInt. We get rid of any
2403  * leading zeroes (because we have reserved only 25 chars),
2404  * and note the position of a decimal point.
2405  */
2406  len = 0;
2407  integ = ~0u;
2408  hasLeadingZeroes = 0;
2409  /*
2410  * Skip leading zeroes.
2411  */
2412  while (*cur == '0') {
2413  cur++;
2414  hasLeadingZeroes = 1;
2415  }
2416  if (*cur != 0) {
2417  do {
2418  if ((*cur >= '0') && (*cur <= '9')) {
2419  *cptr++ = *cur++;
2420  len++;
2421  } else if (*cur == '.') {
2422  cur++;
2423  integ = len;
2424  do {
2425  if ((*cur >= '0') && (*cur <= '9')) {
2426  *cptr++ = *cur++;
2427  len++;
2428  } else
2429  break;
2430  } while (len < 24);
2431  /*
2432  * Disallow "." but allow "00."
2433  */
2434  if ((len == 0) && (!hasLeadingZeroes))
2435  goto return1;
2436  break;
2437  } else
2438  break;
2439  } while (len < 24);
2440  }
2441  if (normOnTheFly)
2442  while IS_WSP_BLANK_CH(*cur) cur++;
2443  if (*cur != 0)
2444  goto return1; /* error if any extraneous chars */
2445  if (val != NULL) {
2446  v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
2447  if (v != NULL) {
2448  /*
2449  * Now evaluate the significant digits of the number
2450  */
2451  if (len != 0) {
2452 
2453  if (integ != ~0u) {
2454  /*
2455  * Get rid of trailing zeroes in the
2456  * fractional part.
2457  */
2458  while ((len != integ) && (*(cptr-1) == '0')) {
2459  cptr--;
2460  len--;
2461  }
2462  }
2463  /*
2464  * Terminate the (preparsed) string.
2465  */
2466  if (len != 0) {
2467  *cptr = 0;
2468  cptr = cval;
2469 
2470  xmlSchemaParseUInt((const xmlChar **)&cptr,
2471  &v->value.decimal.lo,
2472  &v->value.decimal.mi,
2473  &v->value.decimal.hi);
2474  }
2475  }
2476  /*
2477  * Set the total digits to 1 if a zero value.
2478  */
2479  v->value.decimal.sign = neg;
2480  if (len == 0) {
2481  /* Speedup for zero values. */
2482  v->value.decimal.total = 1;
2483  } else {
2484  v->value.decimal.total = len;
2485  if (integ == ~0u)
2486  v->value.decimal.frac = 0;
2487  else
2488  v->value.decimal.frac = len - integ;
2489  }
2490  *val = v;
2491  }
2492  }
2493  goto return0;
2494  }
2495  case XML_SCHEMAS_TIME:
2496  case XML_SCHEMAS_GDAY:
2497  case XML_SCHEMAS_GMONTH:
2498  case XML_SCHEMAS_GMONTHDAY:
2499  case XML_SCHEMAS_GYEAR:
2500  case XML_SCHEMAS_GYEARMONTH:
2501  case XML_SCHEMAS_DATE:
2502  case XML_SCHEMAS_DATETIME:
2503  ret = xmlSchemaValidateDates(type->builtInType, value, val,
2504  normOnTheFly);
2505  break;
2506  case XML_SCHEMAS_DURATION:
2507  ret = xmlSchemaValidateDuration(type, value, val,
2508  normOnTheFly);
2509  break;
2510  case XML_SCHEMAS_FLOAT:
2511  case XML_SCHEMAS_DOUBLE: {
2512  const xmlChar *cur = value;
2513  int neg = 0;
2514  int digits_before = 0;
2515  int digits_after = 0;
2516 
2517  if (normOnTheFly)
2518  while IS_WSP_BLANK_CH(*cur) cur++;
2519 
2520  if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
2521  cur += 3;
2522  if (*cur != 0)
2523  goto return1;
2524  if (val != NULL) {
2525  if (type == xmlSchemaTypeFloatDef) {
2526  v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2527  if (v != NULL) {
2528  v->value.f = (float) xmlXPathNAN;
2529  } else {
2530  xmlSchemaFreeValue(v);
2531  goto error;
2532  }
2533  } else {
2534  v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2535  if (v != NULL) {
2536  v->value.d = xmlXPathNAN;
2537  } else {
2538  xmlSchemaFreeValue(v);
2539  goto error;
2540  }
2541  }
2542  *val = v;
2543  }
2544  goto return0;
2545  }
2546  if (*cur == '-') {
2547  neg = 1;
2548  cur++;
2549  }
2550  if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
2551  cur += 3;
2552  if (*cur != 0)
2553  goto return1;
2554  if (val != NULL) {
2555  if (type == xmlSchemaTypeFloatDef) {
2556  v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2557  if (v != NULL) {
2558  if (neg)
2559  v->value.f = (float) xmlXPathNINF;
2560  else
2561  v->value.f = (float) xmlXPathPINF;
2562  } else {
2563  xmlSchemaFreeValue(v);
2564  goto error;
2565  }
2566  } else {
2567  v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2568  if (v != NULL) {
2569  if (neg)
2570  v->value.d = xmlXPathNINF;
2571  else
2572  v->value.d = xmlXPathPINF;
2573  } else {
2574  xmlSchemaFreeValue(v);
2575  goto error;
2576  }
2577  }
2578  *val = v;
2579  }
2580  goto return0;
2581  }
2582  if ((neg == 0) && (*cur == '+'))
2583  cur++;
2584  if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
2585  goto return1;
2586  while ((*cur >= '0') && (*cur <= '9')) {
2587  cur++;
2588  digits_before++;
2589  }
2590  if (*cur == '.') {
2591  cur++;
2592  while ((*cur >= '0') && (*cur <= '9')) {
2593  cur++;
2594  digits_after++;
2595  }
2596  }
2597  if ((digits_before == 0) && (digits_after == 0))
2598  goto return1;
2599  if ((*cur == 'e') || (*cur == 'E')) {
2600  cur++;
2601  if ((*cur == '-') || (*cur == '+'))
2602  cur++;
2603  while ((*cur >= '0') && (*cur <= '9'))
2604  cur++;
2605  }
2606  if (normOnTheFly)
2607  while IS_WSP_BLANK_CH(*cur) cur++;
2608 
2609  if (*cur != 0)
2610  goto return1;
2611  if (val != NULL) {
2612  if (type == xmlSchemaTypeFloatDef) {
2613  v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2614  if (v != NULL) {
2615  /*
2616  * TODO: sscanf seems not to give the correct
2617  * value for extremely high/low values.
2618  * E.g. "1E-149" results in zero.
2619  */
2620  if (sscanf((const char *) value, "%f",
2621  &(v->value.f)) == 1) {
2622  *val = v;
2623  } else {
2624  xmlSchemaFreeValue(v);
2625  goto return1;
2626  }
2627  } else {
2628  goto error;
2629  }
2630  } else {
2631  v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2632  if (v != NULL) {
2633  /*
2634  * TODO: sscanf seems not to give the correct
2635  * value for extremely high/low values.
2636  */
2637  if (sscanf((const char *) value, "%lf",
2638  &(v->value.d)) == 1) {
2639  *val = v;
2640  } else {
2641  xmlSchemaFreeValue(v);
2642  goto return1;
2643  }
2644  } else {
2645  goto error;
2646  }
2647  }
2648  }
2649  goto return0;
2650  }
2651  case XML_SCHEMAS_BOOLEAN:{
2652  const xmlChar *cur = value;
2653 
2654  if (normOnTheFly) {
2655  while IS_WSP_BLANK_CH(*cur) cur++;
2656  if (*cur == '0') {
2657  ret = 0;
2658  cur++;
2659  } else if (*cur == '1') {
2660  ret = 1;
2661  cur++;
2662  } else if (*cur == 't') {
2663  cur++;
2664  if ((*cur++ == 'r') && (*cur++ == 'u') &&
2665  (*cur++ == 'e')) {
2666  ret = 1;
2667  } else
2668  goto return1;
2669  } else if (*cur == 'f') {
2670  cur++;
2671  if ((*cur++ == 'a') && (*cur++ == 'l') &&
2672  (*cur++ == 's') && (*cur++ == 'e')) {
2673  ret = 0;
2674  } else
2675  goto return1;
2676  } else
2677  goto return1;
2678  if (*cur != 0) {
2679  while IS_WSP_BLANK_CH(*cur) cur++;
2680  if (*cur != 0)
2681  goto return1;
2682  }
2683  } else {
2684  if ((cur[0] == '0') && (cur[1] == 0))
2685  ret = 0;
2686  else if ((cur[0] == '1') && (cur[1] == 0))
2687  ret = 1;
2688  else if ((cur[0] == 't') && (cur[1] == 'r')
2689  && (cur[2] == 'u') && (cur[3] == 'e')
2690  && (cur[4] == 0))
2691  ret = 1;
2692  else if ((cur[0] == 'f') && (cur[1] == 'a')
2693  && (cur[2] == 'l') && (cur[3] == 's')
2694  && (cur[4] == 'e') && (cur[5] == 0))
2695  ret = 0;
2696  else
2697  goto return1;
2698  }
2699  if (val != NULL) {
2700  v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2701  if (v != NULL) {
2702  v->value.b = ret;
2703  *val = v;
2704  } else {
2705  goto error;
2706  }
2707  }
2708  goto return0;
2709  }
2710  case XML_SCHEMAS_TOKEN:{
2711  const xmlChar *cur = value;
2712 
2713  if (! normOnTheFly) {
2714  while (*cur != 0) {
2715  if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2716  goto return1;
2717  } else if (*cur == ' ') {
2718  cur++;
2719  if (*cur == 0)
2720  goto return1;
2721  if (*cur == ' ')
2722  goto return1;
2723  } else {
2724  cur++;
2725  }
2726  }
2727  }
2728  if (val != NULL) {
2729  v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2730  if (v != NULL) {
2731  v->value.str = xmlStrdup(value);
2732  *val = v;
2733  } else {
2734  goto error;
2735  }
2736  }
2737  goto return0;
2738  }
2739  case XML_SCHEMAS_LANGUAGE:
2740  if ((norm == NULL) && (normOnTheFly)) {
2741  norm = xmlSchemaCollapseString(value);
2742  if (norm != NULL)
2743  value = norm;
2744  }
2745 
2746  if (xmlSchemaCheckLanguageType(value) == 1) {
2747  if (val != NULL) {
2748  v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2749  if (v != NULL) {
2750  v->value.str = xmlStrdup(value);
2751  *val = v;
2752  } else {
2753  goto error;
2754  }
2755  }
2756  goto return0;
2757  }
2758  goto return1;
2759  case XML_SCHEMAS_NMTOKEN:
2760  if (xmlValidateNMToken(value, 1) == 0) {
2761  if (val != NULL) {
2762  v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2763  if (v != NULL) {
2764  v->value.str = xmlStrdup(value);
2765  *val = v;
2766  } else {
2767  goto error;
2768  }
2769  }
2770  goto return0;
2771  }
2772  goto return1;
2773  case XML_SCHEMAS_NMTOKENS:
2774  ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2775  value, val, node);
2776  if (ret > 0)
2777  ret = 0;
2778  else
2779  ret = 1;
2780  goto done;
2781  case XML_SCHEMAS_NAME:
2782  ret = xmlValidateName(value, 1);
2783  if ((ret == 0) && (val != NULL) && (value != NULL)) {
2784  v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2785  if (v != NULL) {
2786  const xmlChar *start = value, *end;
2787  while (IS_BLANK_CH(*start)) start++;
2788  end = start;
2789  while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2790  v->value.str = xmlStrndup(start, end - start);
2791  *val = v;
2792  } else {
2793  goto error;
2794  }
2795  }
2796  goto done;
2797  case XML_SCHEMAS_QNAME:{
2798  const xmlChar *uri = NULL;
2799  xmlChar *local = NULL;
2800 
2801  ret = xmlValidateQName(value, 1);
2802  if (ret != 0)
2803  goto done;
2804  if (node != NULL) {
2805  xmlChar *prefix;
2806  xmlNsPtr ns;
2807 
2808  local = xmlSplitQName2(value, &prefix);
2809  ns = xmlSearchNs(node->doc, node, prefix);
2810  if ((ns == NULL) && (prefix != NULL)) {
2811  xmlFree(prefix);
2812  if (local != NULL)
2813  xmlFree(local);
2814  goto return1;
2815  }
2816  if (ns != NULL)
2817  uri = ns->href;
2818  if (prefix != NULL)
2819  xmlFree(prefix);
2820  }
2821  if (val != NULL) {
2822  v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
2823  if (v == NULL) {
2824  if (local != NULL)
2825  xmlFree(local);
2826  goto error;
2827  }
2828  if (local != NULL)
2829  v->value.qname.name = local;
2830  else
2831  v->value.qname.name = xmlStrdup(value);
2832  if (uri != NULL)
2833  v->value.qname.uri = xmlStrdup(uri);
2834  *val = v;
2835  } else
2836  if (local != NULL)
2837  xmlFree(local);
2838  goto done;
2839  }
2840  case XML_SCHEMAS_NCNAME:
2841  ret = xmlValidateNCName(value, 1);
2842  if ((ret == 0) && (val != NULL)) {
2843  v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
2844  if (v != NULL) {
2845  v->value.str = xmlStrdup(value);
2846  *val = v;
2847  } else {
2848  goto error;
2849  }
2850  }
2851  goto done;
2852  case XML_SCHEMAS_ID:
2853  ret = xmlValidateNCName(value, 1);
2854  if ((ret == 0) && (val != NULL)) {
2855  v = xmlSchemaNewValue(XML_SCHEMAS_ID);
2856  if (v != NULL) {
2857  v->value.str = xmlStrdup(value);
2858  *val = v;
2859  } else {
2860  goto error;
2861  }
2862  }
2863  if ((ret == 0) && (node != NULL) &&
2864  (node->type == XML_ATTRIBUTE_NODE)) {
2866 
2867  /*
2868  * NOTE: the IDness might have already be declared in the DTD
2869  */
2870  if (attr->atype != XML_ATTRIBUTE_ID) {
2871  xmlIDPtr res;
2872  xmlChar *strip;
2873 
2874  strip = xmlSchemaStrip(value);
2875  if (strip != NULL) {
2876  res = xmlAddID(NULL, node->doc, strip, attr);
2877  xmlFree(strip);
2878  } else
2879  res = xmlAddID(NULL, node->doc, value, attr);
2880  if (res == NULL) {
2881  ret = 2;
2882  } else {
2883  attr->atype = XML_ATTRIBUTE_ID;
2884  }
2885  }
2886  }
2887  goto done;
2888  case XML_SCHEMAS_IDREF:
2889  ret = xmlValidateNCName(value, 1);
2890  if ((ret == 0) && (val != NULL)) {
2891  v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
2892  if (v == NULL)
2893  goto error;
2894  v->value.str = xmlStrdup(value);
2895  *val = v;
2896  }
2897  if ((ret == 0) && (node != NULL) &&
2898  (node->type == XML_ATTRIBUTE_NODE)) {
2900  xmlChar *strip;
2901 
2902  strip = xmlSchemaStrip(value);
2903  if (strip != NULL) {
2904  xmlAddRef(NULL, node->doc, strip, attr);
2905  xmlFree(strip);
2906  } else
2907  xmlAddRef(NULL, node->doc, value, attr);
2908  attr->atype = XML_ATTRIBUTE_IDREF;
2909  }
2910  goto done;
2911  case XML_SCHEMAS_IDREFS:
2912  ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
2913  value, val, node);
2914  if (ret < 0)
2915  ret = 2;
2916  else
2917  ret = 0;
2918  if ((ret == 0) && (node != NULL) &&
2919  (node->type == XML_ATTRIBUTE_NODE)) {
2921 
2922  attr->atype = XML_ATTRIBUTE_IDREFS;
2923  }
2924  goto done;
2925  case XML_SCHEMAS_ENTITY:{
2926  xmlChar *strip;
2927 
2928  ret = xmlValidateNCName(value, 1);
2929  if ((node == NULL) || (node->doc == NULL))
2930  ret = 3;
2931  if (ret == 0) {
2932  xmlEntityPtr ent;
2933 
2934  strip = xmlSchemaStrip(value);
2935  if (strip != NULL) {
2936  ent = xmlGetDocEntity(node->doc, strip);
2937  xmlFree(strip);
2938  } else {
2939  ent = xmlGetDocEntity(node->doc, value);
2940  }
2941  if ((ent == NULL) ||
2942  (ent->etype !=
2944  ret = 4;
2945  }
2946  if ((ret == 0) && (val != NULL)) {
2947  TODO;
2948  }
2949  if ((ret == 0) && (node != NULL) &&
2950  (node->type == XML_ATTRIBUTE_NODE)) {
2952 
2953  attr->atype = XML_ATTRIBUTE_ENTITY;
2954  }
2955  goto done;
2956  }
2957  case XML_SCHEMAS_ENTITIES:
2958  if ((node == NULL) || (node->doc == NULL))
2959  goto return3;
2960  ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
2961  value, val, node);
2962  if (ret <= 0)
2963  ret = 1;
2964  else
2965  ret = 0;
2966  if ((ret == 0) && (node != NULL) &&
2967  (node->type == XML_ATTRIBUTE_NODE)) {
2969 
2970  attr->atype = XML_ATTRIBUTE_ENTITIES;
2971  }
2972  goto done;
2973  case XML_SCHEMAS_NOTATION:{
2974  xmlChar *uri = NULL;
2975  xmlChar *local = NULL;
2976 
2977  ret = xmlValidateQName(value, 1);
2978  if ((ret == 0) && (node != NULL)) {
2979  xmlChar *prefix;
2980 
2981  local = xmlSplitQName2(value, &prefix);
2982  if (prefix != NULL) {
2983  xmlNsPtr ns;
2984 
2985  ns = xmlSearchNs(node->doc, node, prefix);
2986  if (ns == NULL)
2987  ret = 1;
2988  else if (val != NULL)
2989  uri = xmlStrdup(ns->href);
2990  }
2991  if ((local != NULL) && ((val == NULL) || (ret != 0)))
2992  xmlFree(local);
2993  if (prefix != NULL)
2994  xmlFree(prefix);
2995  }
2996  if ((node == NULL) || (node->doc == NULL))
2997  ret = 3;
2998  if (ret == 0) {
2999  ret = xmlValidateNotationUse(NULL, node->doc, value);
3000  if (ret == 1)
3001  ret = 0;
3002  else
3003  ret = 1;
3004  }
3005  if ((ret == 0) && (val != NULL)) {
3006  v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
3007  if (v != NULL) {
3008  if (local != NULL)
3009  v->value.qname.name = local;
3010  else
3011  v->value.qname.name = xmlStrdup(value);
3012  if (uri != NULL)
3013  v->value.qname.uri = uri;
3014 
3015  *val = v;
3016  } else {
3017  if (local != NULL)
3018  xmlFree(local);
3019  if (uri != NULL)
3020  xmlFree(uri);
3021  goto error;
3022  }
3023  }
3024  goto done;
3025  }
3026  case XML_SCHEMAS_ANYURI:{
3027  if (*value != 0) {
3028  xmlURIPtr uri;
3029  xmlChar *tmpval, *cur;
3030  if ((norm == NULL) && (normOnTheFly)) {
3031  norm = xmlSchemaCollapseString(value);
3032  if (norm != NULL)
3033  value = norm;
3034  }
3035  tmpval = xmlStrdup(value);
3036  for (cur = tmpval; *cur; ++cur) {
3037  if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
3038  *cur == '<' || *cur == '>' || *cur == '"' ||
3039  *cur == '{' || *cur == '}' || *cur == '|' ||
3040  *cur == '\\' || *cur == '^' || *cur == '`' ||
3041  *cur == '\'')
3042  *cur = '_';
3043  }
3044  uri = xmlParseURI((const char *) tmpval);
3045  xmlFree(tmpval);
3046  if (uri == NULL)
3047  goto return1;
3048  xmlFreeURI(uri);
3049  }
3050 
3051  if (val != NULL) {
3052  v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
3053  if (v == NULL)
3054  goto error;
3055  v->value.str = xmlStrdup(value);
3056  *val = v;
3057  }
3058  goto return0;
3059  }
3060  case XML_SCHEMAS_HEXBINARY:{
3061  const xmlChar *cur = value, *start;
3062  xmlChar *base;
3063  int total, i = 0;
3064 
3065  if (cur == NULL)
3066  goto return1;
3067 
3068  if (normOnTheFly)
3069  while IS_WSP_BLANK_CH(*cur) cur++;
3070 
3071  start = cur;
3072  while (((*cur >= '0') && (*cur <= '9')) ||
3073  ((*cur >= 'A') && (*cur <= 'F')) ||
3074  ((*cur >= 'a') && (*cur <= 'f'))) {
3075  i++;
3076  cur++;
3077  }
3078  if (normOnTheFly)
3079  while IS_WSP_BLANK_CH(*cur) cur++;
3080 
3081  if (*cur != 0)
3082  goto return1;
3083  if ((i % 2) != 0)
3084  goto return1;
3085 
3086  if (val != NULL) {
3087 
3088  v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
3089  if (v == NULL)
3090  goto error;
3091  /*
3092  * Copy only the normalized piece.
3093  * CRITICAL TODO: Check this.
3094  */
3095  cur = xmlStrndup(start, i);
3096  if (cur == NULL) {
3097  xmlSchemaTypeErrMemory(node, "allocating hexbin data");
3098  xmlFree(v);
3099  goto return1;
3100  }
3101 
3102  total = i / 2; /* number of octets */
3103 
3104  base = (xmlChar *) cur;
3105  while (i-- > 0) {
3106  if (*base >= 'a')
3107  *base = *base - ('a' - 'A');
3108  base++;
3109  }
3110 
3111  v->value.hex.str = (xmlChar *) cur;
3112  v->value.hex.total = total;
3113  *val = v;
3114  }
3115  goto return0;
3116  }
3117  case XML_SCHEMAS_BASE64BINARY:{
3118  /* ISSUE:
3119  *
3120  * Ignore all stray characters? (yes, currently)
3121  * Worry about long lines? (no, currently)
3122  *
3123  * rfc2045.txt:
3124  *
3125  * "The encoded output stream must be represented in lines of
3126  * no more than 76 characters each. All line breaks or other
3127  * characters not found in Table 1 must be ignored by decoding
3128  * software. In base64 data, characters other than those in
3129  * Table 1, line breaks, and other white space probably
3130  * indicate a transmission error, about which a warning
3131  * message or even a message rejection might be appropriate
3132  * under some circumstances." */
3133  const xmlChar *cur = value;
3134  xmlChar *base;
3135  int total, i = 0, pad = 0;
3136 
3137  if (cur == NULL)
3138  goto return1;
3139 
3140  for (; *cur; ++cur) {
3141  int decc;
3142 
3143  decc = _xmlSchemaBase64Decode(*cur);
3144  if (decc < 0) ;
3145  else if (decc < 64)
3146  i++;
3147  else
3148  break;
3149  }
3150  for (; *cur; ++cur) {
3151  int decc;
3152 
3153  decc = _xmlSchemaBase64Decode(*cur);
3154  if (decc < 0) ;
3155  else if (decc < 64)
3156  goto return1;
3157  if (decc == 64)
3158  pad++;
3159  }
3160 
3161  /* rfc2045.txt: "Special processing is performed if fewer than
3162  * 24 bits are available at the end of the data being encoded.
3163  * A full encoding quantum is always completed at the end of a
3164  * body. When fewer than 24 input bits are available in an
3165  * input group, zero bits are added (on the right) to form an
3166  * integral number of 6-bit groups. Padding at the end of the
3167  * data is performed using the "=" character. Since all
3168  * base64 input is an integral number of octets, only the
3169  * following cases can arise: (1) the final quantum of
3170  * encoding input is an integral multiple of 24 bits; here,
3171  * the final unit of encoded output will be an integral
3172  * multiple of indent: Standard input:701: Warning:old style
3173  * assignment ambiguity in "=*". Assuming "= *" 4 characters
3174  * with no "=" padding, (2) the final
3175  * quantum of encoding input is exactly 8 bits; here, the
3176  * final unit of encoded output will be two characters
3177  * followed by two "=" padding characters, or (3) the final
3178  * quantum of encoding input is exactly 16 bits; here, the
3179  * final unit of encoded output will be three characters
3180  * followed by one "=" padding character." */
3181 
3182  total = 3 * (i / 4);
3183  if (pad == 0) {
3184  if (i % 4 != 0)
3185  goto return1;
3186  } else if (pad == 1) {
3187  int decc;
3188 
3189  if (i % 4 != 3)
3190  goto return1;
3191  for (decc = _xmlSchemaBase64Decode(*cur);
3192  (decc < 0) || (decc > 63);
3193  decc = _xmlSchemaBase64Decode(*cur))
3194  --cur;
3195  /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3196  /* 00111100 -> 0x3c */
3197  if (decc & ~0x3c)
3198  goto return1;
3199  total += 2;
3200  } else if (pad == 2) {
3201  int decc;
3202 
3203  if (i % 4 != 2)
3204  goto return1;
3205  for (decc = _xmlSchemaBase64Decode(*cur);
3206  (decc < 0) || (decc > 63);
3207  decc = _xmlSchemaBase64Decode(*cur))
3208  --cur;
3209  /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3210  /* 00110000 -> 0x30 */
3211  if (decc & ~0x30)
3212  goto return1;
3213  total += 1;
3214  } else
3215  goto return1;
3216 
3217  if (val != NULL) {
3218  v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3219  if (v == NULL)
3220  goto error;
3221  base =
3222  (xmlChar *) xmlMallocAtomic((i + pad + 1) *
3223  sizeof(xmlChar));
3224  if (base == NULL) {
3225  xmlSchemaTypeErrMemory(node, "allocating base64 data");
3226  xmlFree(v);
3227  goto return1;
3228  }
3229  v->value.base64.str = base;
3230  for (cur = value; *cur; ++cur)
3231  if (_xmlSchemaBase64Decode(*cur) >= 0) {
3232  *base = *cur;
3233  ++base;
3234  }
3235  *base = 0;
3236  v->value.base64.total = total;
3237  *val = v;
3238  }
3239  goto return0;
3240  }
3241  case XML_SCHEMAS_INTEGER:
3242  case XML_SCHEMAS_PINTEGER:
3243  case XML_SCHEMAS_NPINTEGER:
3244  case XML_SCHEMAS_NINTEGER:
3245  case XML_SCHEMAS_NNINTEGER:{
3246  const xmlChar *cur = value;
3247  unsigned long lo, mi, hi;
3248  int sign = 0;
3249 
3250  if (cur == NULL)
3251  goto return1;
3252  if (normOnTheFly)
3253  while IS_WSP_BLANK_CH(*cur) cur++;
3254  if (*cur == '-') {
3255  sign = 1;
3256  cur++;
3257  } else if (*cur == '+')
3258  cur++;
3259  ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3260  if (ret < 0)
3261  goto return1;
3262  if (normOnTheFly)
3263  while IS_WSP_BLANK_CH(*cur) cur++;
3264  if (*cur != 0)
3265  goto return1;
3266  if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
3267  if ((sign == 0) &&
3268  ((hi != 0) || (mi != 0) || (lo != 0)))
3269  goto return1;
3270  } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
3271  if (sign == 1)
3272  goto return1;
3273  if ((hi == 0) && (mi == 0) && (lo == 0))
3274  goto return1;
3275  } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
3276  if (sign == 0)
3277  goto return1;
3278  if ((hi == 0) && (mi == 0) && (lo == 0))
3279  goto return1;
3280  } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
3281  if ((sign == 1) &&
3282  ((hi != 0) || (mi != 0) || (lo != 0)))
3283  goto return1;
3284  }
3285  if (val != NULL) {
3286  v = xmlSchemaNewValue(type->builtInType);
3287  if (v != NULL) {
3288  if (ret == 0)
3289  ret++;
3290  v->value.decimal.lo = lo;
3291  v->value.decimal.mi = mi;
3292  v->value.decimal.hi = hi;
3293  v->value.decimal.sign = sign;
3294  v->value.decimal.frac = 0;
3295  v->value.decimal.total = ret;
3296  *val = v;
3297  }
3298  }
3299  goto return0;
3300  }
3301  case XML_SCHEMAS_LONG:
3302  case XML_SCHEMAS_BYTE:
3303  case XML_SCHEMAS_SHORT:
3304  case XML_SCHEMAS_INT:{
3305  const xmlChar *cur = value;
3306  unsigned long lo, mi, hi;
3307  int sign = 0;
3308 
3309  if (cur == NULL)
3310  goto return1;
3311  if (*cur == '-') {
3312  sign = 1;
3313  cur++;
3314  } else if (*cur == '+')
3315  cur++;
3316  ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3317  if (ret < 0)
3318  goto return1;
3319  if (*cur != 0)
3320  goto return1;
3321  if (type->builtInType == XML_SCHEMAS_LONG) {
3322  if (hi >= 922) {
3323  if (hi > 922)
3324  goto return1;
3325  if (mi >= 33720368) {
3326  if (mi > 33720368)
3327  goto return1;
3328  if ((sign == 0) && (lo > 54775807))
3329  goto return1;
3330  if ((sign == 1) && (lo > 54775808))
3331  goto return1;
3332  }
3333  }
3334  } else if (type->builtInType == XML_SCHEMAS_INT) {
3335  if (hi != 0)
3336  goto return1;
3337  if (mi >= 21) {
3338  if (mi > 21)
3339  goto return1;
3340  if ((sign == 0) && (lo > 47483647))
3341  goto return1;
3342  if ((sign == 1) && (lo > 47483648))
3343  goto return1;
3344  }
3345  } else if (type->builtInType == XML_SCHEMAS_SHORT) {
3346  if ((mi != 0) || (hi != 0))
3347  goto return1;
3348  if ((sign == 1) && (lo > 32768))
3349  goto return1;
3350  if ((sign == 0) && (lo > 32767))
3351  goto return1;
3352  } else if (type->builtInType == XML_SCHEMAS_BYTE) {
3353  if ((mi != 0) || (hi != 0))
3354  goto return1;
3355  if ((sign == 1) && (lo > 128))
3356  goto return1;
3357  if ((sign == 0) && (lo > 127))
3358  goto return1;
3359  }
3360  if (val != NULL) {
3361  v = xmlSchemaNewValue(type->builtInType);
3362  if (v != NULL) {
3363  v->value.decimal.lo = lo;
3364  v->value.decimal.mi = mi;
3365  v->value.decimal.hi = hi;
3366  v->value.decimal.sign = sign;
3367  v->value.decimal.frac = 0;
3368  v->value.decimal.total = ret;
3369  *val = v;
3370  }
3371  }
3372  goto return0;
3373  }
3374  case XML_SCHEMAS_UINT:
3375  case XML_SCHEMAS_ULONG:
3376  case XML_SCHEMAS_USHORT:
3377  case XML_SCHEMAS_UBYTE:{
3378  const xmlChar *cur = value;
3379  unsigned long lo, mi, hi;
3380 
3381  if (cur == NULL)
3382  goto return1;
3383  ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3384  if (ret < 0)
3385  goto return1;
3386  if (*cur != 0)
3387  goto return1;
3388  if (type->builtInType == XML_SCHEMAS_ULONG) {
3389  if (hi >= 1844) {
3390  if (hi > 1844)
3391  goto return1;
3392  if (mi >= 67440737) {
3393  if (mi > 67440737)
3394  goto return1;
3395  if (lo > 9551615)
3396  goto return1;
3397  }
3398  }
3399  } else if (type->builtInType == XML_SCHEMAS_UINT) {
3400  if (hi != 0)
3401  goto return1;
3402  if (mi >= 42) {
3403  if (mi > 42)
3404  goto return1;
3405  if (lo > 94967295)
3406  goto return1;
3407  }
3408  } else if (type->builtInType == XML_SCHEMAS_USHORT) {
3409  if ((mi != 0) || (hi != 0))
3410  goto return1;
3411  if (lo > 65535)
3412  goto return1;
3413  } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
3414  if ((mi != 0) || (hi != 0))
3415  goto return1;
3416  if (lo > 255)
3417  goto return1;
3418  }
3419  if (val != NULL) {
3420  v = xmlSchemaNewValue(type->builtInType);
3421  if (v != NULL) {
3422  v->value.decimal.lo = lo;
3423  v->value.decimal.mi = mi;
3424  v->value.decimal.hi = hi;
3425  v->value.decimal.sign = 0;
3426  v->value.decimal.frac = 0;
3427  v->value.decimal.total = ret;
3428  *val = v;
3429  }
3430  }
3431  goto return0;
3432  }
3433  }
3434 
3435  done:
3436  if (norm != NULL)
3437  xmlFree(norm);
3438  return (ret);
3439  return3:
3440  if (norm != NULL)
3441  xmlFree(norm);
3442  return (3);
3443  return1:
3444  if (norm != NULL)
3445  xmlFree(norm);
3446  return (1);
3447  return0:
3448  if (norm != NULL)
3449  xmlFree(norm);
3450  return (0);
3451  error:
3452  if (norm != NULL)
3453  xmlFree(norm);
3454  return (-1);
3455 }
3456 
3470 int
3471 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
3472  xmlSchemaValPtr *val, xmlNodePtr node) {
3473  return(xmlSchemaValAtomicType(type, value, val, node, 0,
3474  XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
3475 }
3476 
3491 int
3492 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
3493  xmlSchemaValPtr *val, xmlNodePtr node) {
3494  return(xmlSchemaValAtomicType(type, value, val, node, 1,
3495  XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
3496 }
3497 
3510 int
3511 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
3512  xmlSchemaValPtr *val) {
3513  return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
3514 }
3515 
3525 static int
3526 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
3527 {
3528  xmlSchemaValPtr swp;
3529  int order = 1, integx, integy, dlen;
3530  unsigned long hi, mi, lo;
3531 
3532  /*
3533  * First test: If x is -ve and not zero
3534  */
3535  if ((x->value.decimal.sign) &&
3536  ((x->value.decimal.lo != 0) ||
3537  (x->value.decimal.mi != 0) ||
3538  (x->value.decimal.hi != 0))) {
3539  /*
3540  * Then if y is -ve and not zero reverse the compare
3541  */
3542  if ((y->value.decimal.sign) &&
3543  ((y->value.decimal.lo != 0) ||
3544  (y->value.decimal.mi != 0) ||
3545  (y->value.decimal.hi != 0)))
3546  order = -1;
3547  /*
3548  * Otherwise (y >= 0) we have the answer
3549  */
3550  else
3551  return (-1);
3552  /*
3553  * If x is not -ve and y is -ve we have the answer
3554  */
3555  } else if ((y->value.decimal.sign) &&
3556  ((y->value.decimal.lo != 0) ||
3557  (y->value.decimal.mi != 0) ||
3558  (y->value.decimal.hi != 0))) {
3559  return (1);
3560  }
3561  /*
3562  * If it's not simply determined by a difference in sign,
3563  * then we need to compare the actual values of the two nums.
3564  * To do this, we start by looking at the integral parts.
3565  * If the number of integral digits differ, then we have our
3566  * answer.
3567  */
3568  integx = x->value.decimal.total - x->value.decimal.frac;
3569  integy = y->value.decimal.total - y->value.decimal.frac;
3570  /*
3571  * NOTE: We changed the "total" for values like "0.1"
3572  * (or "-0.1" or ".1") to be 1, which was 2 previously.
3573  * Therefore the special case, when such values are
3574  * compared with 0, needs to be handled separately;
3575  * otherwise a zero would be recognized incorrectly as
3576  * greater than those values. This has the nice side effect
3577  * that we gain an overall optimized comparison with zeroes.
3578  * Note that a "0" has a "total" of 1 already.
3579  */
3580  if (integx == 1) {
3581  if (x->value.decimal.lo == 0) {
3582  if (integy != 1)
3583  return -order;
3584  else if (y->value.decimal.lo != 0)
3585  return -order;
3586  else
3587  return(0);
3588  }
3589  }
3590  if (integy == 1) {
3591  if (y->value.decimal.lo == 0) {
3592  if (integx != 1)
3593  return order;
3594  else if (x->value.decimal.lo != 0)
3595  return order;
3596  else
3597  return(0);
3598  }
3599  }
3600 
3601  if (integx > integy)
3602  return order;
3603  else if (integy > integx)
3604  return -order;
3605 
3606  /*
3607  * If the number of integral digits is the same for both numbers,
3608  * then things get a little more complicated. We need to "normalize"
3609  * the numbers in order to properly compare them. To do this, we
3610  * look at the total length of each number (length => number of
3611  * significant digits), and divide the "shorter" by 10 (decreasing
3612  * the length) until they are of equal length.
3613  */
3614  dlen = x->value.decimal.total - y->value.decimal.total;
3615  if (dlen < 0) { /* y has more digits than x */
3616  swp = x;
3617  hi = y->value.decimal.hi;
3618  mi = y->value.decimal.mi;
3619  lo = y->value.decimal.lo;
3620  dlen = -dlen;
3621  order = -order;
3622  } else { /* x has more digits than y */
3623  swp = y;
3624  hi = x->value.decimal.hi;
3625  mi = x->value.decimal.mi;
3626  lo = x->value.decimal.lo;
3627  }
3628  while (dlen > 8) { /* in effect, right shift by 10**8 */
3629  lo = mi;
3630  mi = hi;
3631  hi = 0;
3632  dlen -= 8;
3633  }
3634  while (dlen > 0) {
3635  unsigned long rem1, rem2;
3636  rem1 = (hi % 10) * 100000000L;
3637  hi = hi / 10;
3638  rem2 = (mi % 10) * 100000000L;
3639  mi = (mi + rem1) / 10;
3640  lo = (lo + rem2) / 10;
3641  dlen--;
3642  }
3643  if (hi > swp->value.decimal.hi) {
3644  return order;
3645  } else if (hi == swp->value.decimal.hi) {
3646  if (mi > swp->value.decimal.mi) {
3647  return order;
3648  } else if (mi == swp->value.decimal.mi) {
3649  if (lo > swp->value.decimal.lo) {
3650  return order;
3651  } else if (lo == swp->value.decimal.lo) {
3652  if (x->value.decimal.total == y->value.decimal.total) {
3653  return 0;
3654  } else {
3655  return order;
3656  }
3657  }
3658  }
3659  }
3660  return -order;
3661 }
3662 
3673 static int
3674 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3675 {
3676  long carry, mon, day;
3677  double sec;
3678  int invert = 1;
3679  long xmon, xday, myear, minday, maxday;
3680  static const long dayRange [2][12] = {
3681  { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3682  { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3683 
3684  if ((x == NULL) || (y == NULL))
3685  return -2;
3686 
3687  /* months */
3688  mon = x->value.dur.mon - y->value.dur.mon;
3689 
3690  /* seconds */
3691  sec = x->value.dur.sec - y->value.dur.sec;
3692  carry = (long)(sec / SECS_PER_DAY);
3693  sec -= ((double)carry) * SECS_PER_DAY;
3694 
3695  /* days */
3696  day = x->value.dur.day - y->value.dur.day + carry;
3697 
3698  /* easy test */
3699  if (mon == 0) {
3700  if (day == 0)
3701  if (sec == 0.0)
3702  return 0;
3703  else if (sec < 0.0)
3704  return -1;
3705  else
3706  return 1;
3707  else if (day < 0)
3708  return -1;
3709  else
3710  return 1;
3711  }
3712 
3713  if (mon > 0) {
3714  if ((day >= 0) && (sec >= 0.0))
3715  return 1;
3716  else {
3717  xmon = mon;
3718  xday = -day;
3719  }
3720  } else if ((day <= 0) && (sec <= 0.0)) {
3721  return -1;
3722  } else {
3723  invert = -1;
3724  xmon = -mon;
3725  xday = day;
3726  }
3727 
3728  myear = xmon / 12;
3729  if (myear == 0) {
3730  minday = 0;
3731  maxday = 0;
3732  } else {
3733  if (myear > LONG_MAX / 366)
3734  return -2;
3735  /* FIXME: This doesn't take leap year exceptions every 100/400 years
3736  into account. */
3737  maxday = 365 * myear + (myear + 3) / 4;
3738  /* FIXME: Needs to be calculated separately */
3739  minday = maxday - 1;
3740  }
3741 
3742  xmon = xmon % 12;
3743  minday += dayRange[0][xmon];
3744  maxday += dayRange[1][xmon];
3745 
3746  if ((maxday == minday) && (maxday == xday))
3747  return(0); /* can this really happen ? */
3748  if (maxday < xday)
3749  return(-invert);
3750  if (minday > xday)
3751  return(invert);
3752 
3753  /* indeterminate */
3754  return 2;
3755 }
3756 
3757 /*
3758  * macros for adding date/times and durations
3759  */
3760 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
3761 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
3762 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
3763 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
3764 
3774 static xmlSchemaValPtr
3775 xmlSchemaDupVal (xmlSchemaValPtr v)
3776 {
3777  xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3778  if (ret == NULL)
3779  return NULL;
3780 
3781  memcpy(ret, v, sizeof(xmlSchemaVal));
3782  ret->next = NULL;
3783  return ret;
3784 }
3785 
3794 xmlSchemaValPtr
3795 xmlSchemaCopyValue(xmlSchemaValPtr val)
3796 {
3797  xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3798 
3799  /*
3800  * Copy the string values.
3801  */
3802  while (val != NULL) {
3803  switch (val->type) {
3804  case XML_SCHEMAS_ANYTYPE:
3805  case XML_SCHEMAS_IDREFS:
3806  case XML_SCHEMAS_ENTITIES:
3807  case XML_SCHEMAS_NMTOKENS:
3808  xmlSchemaFreeValue(ret);
3809  return (NULL);
3810  case XML_SCHEMAS_ANYSIMPLETYPE:
3811  case XML_SCHEMAS_STRING:
3812  case XML_SCHEMAS_NORMSTRING:
3813  case XML_SCHEMAS_TOKEN:
3814  case XML_SCHEMAS_LANGUAGE:
3815  case XML_SCHEMAS_NAME:
3816  case XML_SCHEMAS_NCNAME:
3817  case XML_SCHEMAS_ID:
3818  case XML_SCHEMAS_IDREF:
3819  case XML_SCHEMAS_ENTITY:
3820  case XML_SCHEMAS_NMTOKEN:
3821  case XML_SCHEMAS_ANYURI:
3822  cur = xmlSchemaDupVal(val);
3823  if (val->value.str != NULL)
3824  cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3825  break;
3826  case XML_SCHEMAS_QNAME:
3827  case XML_SCHEMAS_NOTATION:
3828  cur = xmlSchemaDupVal(val);
3829  if (val->value.qname.name != NULL)
3830  cur->value.qname.name =
3831  xmlStrdup(BAD_CAST val->value.qname.name);
3832  if (val->value.qname.uri != NULL)
3833  cur->value.qname.uri =
3834  xmlStrdup(BAD_CAST val->value.qname.uri);
3835  break;
3836  case XML_SCHEMAS_HEXBINARY:
3837  cur = xmlSchemaDupVal(val);
3838  if (val->value.hex.str != NULL)
3839  cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3840  break;
3841  case XML_SCHEMAS_BASE64BINARY:
3842  cur = xmlSchemaDupVal(val);
3843  if (val->value.base64.str != NULL)
3844  cur->value.base64.str =
3845  xmlStrdup(BAD_CAST val->value.base64.str);
3846  break;
3847  default:
3848  cur = xmlSchemaDupVal(val);
3849  break;
3850  }
3851  if (ret == NULL)
3852  ret = cur;
3853  else
3854  prev->next = cur;
3855  prev = cur;
3856  val = val->next;
3857  }
3858  return (ret);
3859 }
3860 
3873 static xmlSchemaValPtr
3874 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3875 {
3876  xmlSchemaValPtr ret, tmp;
3877  long carry, tempdays, temp;
3878  xmlSchemaValDatePtr r, d;
3879  xmlSchemaValDurationPtr u;
3880 
3881  if ((dt == NULL) || (dur == NULL))
3882  return NULL;
3883 
3884  ret = xmlSchemaNewValue(dt->type);
3885  if (ret == NULL)
3886  return NULL;
3887 
3888  /* make a copy so we don't alter the original value */
3889  tmp = xmlSchemaDupVal(dt);
3890  if (tmp == NULL) {
3891  xmlSchemaFreeValue(ret);
3892  return NULL;
3893  }
3894 
3895  r = &(ret->value.date);
3896  d = &(tmp->value.date);
3897  u = &(dur->value.dur);
3898 
3899  /* normalization */
3900  if (d->mon == 0)
3901  d->mon = 1;
3902 
3903  /* normalize for time zone offset */
3904  u->sec -= (d->tzo * 60);
3905  d->tzo = 0;
3906 
3907  /* normalization */
3908  if (d->day == 0)
3909  d->day = 1;
3910 
3911  /* month */
3912  carry = d->mon + u->mon;
3913  r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3914  carry = (long) FQUOTIENT_RANGE(carry, 1, 13);
3915 
3916  /* year (may be modified later) */
3917  r->year = d->year + carry;
3918  if (r->year == 0) {
3919  if (d->year > 0)
3920  r->year--;
3921  else
3922  r->year++;
3923  }
3924 
3925  /* time zone */
3926  r->tzo = d->tzo;
3927  r->tz_flag = d->tz_flag;
3928 
3929  /* seconds */
3930  r->sec = d->sec + u->sec;
3931  carry = (long) FQUOTIENT((long)r->sec, 60);
3932  if (r->sec != 0.0) {
3933  r->sec = MODULO(r->sec, 60.0);
3934  }
3935 
3936  /* minute */
3937  carry += d->min;
3938  r->min = (unsigned int) MODULO(carry, 60);
3939  carry = (long) FQUOTIENT(carry, 60);
3940 
3941  /* hours */
3942  carry += d->hour;
3943  r->hour = (unsigned int) MODULO(carry, 24);
3944  carry = (long)FQUOTIENT(carry, 24);
3945 
3946  /*
3947  * days
3948  * Note we use tempdays because the temporary values may need more
3949  * than 5 bits
3950  */
3951  if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3952  (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3953  tempdays = MAX_DAYINMONTH(r->year, r->mon);
3954  else if (d->day < 1)
3955  tempdays = 1;
3956  else
3957  tempdays = d->day;
3958 
3959  tempdays += u->day + carry;
3960 
3961  while (1) {
3962  if (tempdays < 1) {
3963  long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
3964  long tyr = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
3965  if (tyr == 0)
3966  tyr--;
3967  /*
3968  * Coverity detected an overrun in daysInMonth
3969  * of size 12 at position 12 with index variable "((r)->mon - 1)"
3970  */
3971  if (tmon < 1)
3972  tmon = 1;
3973  if (tmon > 12)
3974  tmon = 12;
3975  tempdays += MAX_DAYINMONTH(tyr, tmon);
3976  carry = -1;
3977  } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
3978  tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3979  tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3980  carry = 1;
3981  } else
3982  break;
3983 
3984  temp = r->mon + carry;
3985  r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3986  r->year = r->year + (long) FQUOTIENT_RANGE(temp, 1, 13);
3987  if (r->year == 0) {
3988  if (temp < 1)
3989  r->year--;
3990  else
3991  r->year++;
3992  }
3993  }
3994 
3995  r->day = tempdays;
3996 
3997  /*
3998  * adjust the date/time type to the date values
3999  */
4000  if (ret->type != XML_SCHEMAS_DATETIME) {
4001  if ((r->hour) || (r->min) || (r->sec))
4002  ret->type = XML_SCHEMAS_DATETIME;
4003  else if (ret->type != XML_SCHEMAS_DATE) {
4004  if ((r->mon != 1) && (r->day != 1))
4005  ret->type = XML_SCHEMAS_DATE;
4006  else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
4007  ret->type = XML_SCHEMAS_GYEARMONTH;
4008  }
4009  }
4010 
4011  xmlSchemaFreeValue(tmp);
4012 
4013  return ret;
4014 }
4015 
4026 static xmlSchemaValPtr
4027 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
4028 {
4029  xmlSchemaValPtr dur, ret;
4030 
4031  if (dt == NULL)
4032  return NULL;
4033 
4034  if (((dt->type != XML_SCHEMAS_TIME) &&
4035  (dt->type != XML_SCHEMAS_DATETIME) &&
4036  (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
4037  return xmlSchemaDupVal(dt);
4038 
4039  dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
4040  if (dur == NULL)
4041  return NULL;
4042 
4043  dur->value.date.sec -= offset;
4044 
4045  ret = _xmlSchemaDateAdd(dt, dur);
4046  if (ret == NULL)
4047  return NULL;
4048 
4049  xmlSchemaFreeValue(dur);
4050 
4051  /* ret->value.date.tzo = 0; */
4052  return ret;
4053 }
4054 
4066 static long
4067 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
4068 {
4069  long ret;
4070  int mon;
4071 
4072  mon = dt->value.date.mon;
4073  if (mon <= 0) mon = 1; /* normalization */
4074 
4075  if (dt->value.date.year <= 0)
4076  ret = (dt->value.date.year * 365) +
4077  (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
4078  ((dt->value.date.year+1)/400)) +
4079  DAY_IN_YEAR(0, mon, dt->value.date.year);
4080  else
4081  ret = ((dt->value.date.year-1) * 365) +
4082  (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
4083  ((dt->value.date.year-1)/400)) +
4084  DAY_IN_YEAR(0, mon, dt->value.date.year);
4085 
4086  return ret;
4087 }
4088 
4097 #define TIME_TO_NUMBER(dt) \
4098  ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
4099  (dt->value.date.min * SECS_PER_MIN) + \
4100  (dt->value.date.tzo * SECS_PER_MIN)) + \
4101  dt->value.date.sec)
4102 
4113 static int
4114 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
4115 {
4116  unsigned char xmask, ymask, xor_mask, and_mask;
4117  xmlSchemaValPtr p1, p2, q1, q2;
4118  long p1d, p2d, q1d, q2d;
4119 
4120  if ((x == NULL) || (y == NULL))
4121  return -2;
4122 
4123  if ((x->value.date.year > LONG_MAX / 366) ||
4124  (x->value.date.year < LONG_MIN / 366) ||
4125  (y->value.date.year > LONG_MAX / 366) ||
4126  (y->value.date.year < LONG_MIN / 366)) {
4127  /* Possible overflow when converting to days. */
4128  return -2;
4129  }
4130 
4131  if (x->value.date.tz_flag) {
4132 
4133  if (!y->value.date.tz_flag) {
4134  p1 = xmlSchemaDateNormalize(x, 0);
4135  p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4136  /* normalize y + 14:00 */
4137  q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4138 
4139  q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4140  if (p1d < q1d) {
4141  xmlSchemaFreeValue(p1);
4142  xmlSchemaFreeValue(q1);
4143  return -1;
4144  } else if (p1d == q1d) {
4145  double sec;
4146 
4147  sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4148  if (sec < 0.0) {
4149  xmlSchemaFreeValue(p1);
4150  xmlSchemaFreeValue(q1);
4151  return -1;
4152  } else {
4153  int ret = 0;
4154  /* normalize y - 14:00 */
4155  q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4156  q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4157  if (p1d > q2d)
4158  ret = 1;
4159  else if (p1d == q2d) {
4160  sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4161  if (sec > 0.0)
4162  ret = 1;
4163  else
4164  ret = 2; /* indeterminate */
4165  }
4166  xmlSchemaFreeValue(p1);
4167  xmlSchemaFreeValue(q1);
4168  xmlSchemaFreeValue(q2);
4169  if (ret != 0)
4170  return(ret);
4171  }
4172  } else {
4173  xmlSchemaFreeValue(p1);
4174  xmlSchemaFreeValue(q1);
4175  }
4176  }
4177  } else if (y->value.date.tz_flag) {
4178  q1 = xmlSchemaDateNormalize(y, 0);
4179  q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4180 
4181  /* normalize x - 14:00 */
4182  p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4183  p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4184 
4185  if (p1d < q1d) {
4186  xmlSchemaFreeValue(p1);
4187  xmlSchemaFreeValue(q1);
4188  return -1;
4189  } else if (p1d == q1d) {
4190  double sec;
4191 
4192  sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4193  if (sec < 0.0) {
4194  xmlSchemaFreeValue(p1);
4195  xmlSchemaFreeValue(q1);
4196  return -1;
4197  } else {
4198  int ret = 0;
4199  /* normalize x + 14:00 */
4200  p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4201  p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4202 
4203  if (p2d > q1d) {
4204  ret = 1;
4205  } else if (p2d == q1d) {
4206  sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4207  if (sec > 0.0)
4208  ret = 1;
4209  else
4210  ret = 2; /* indeterminate */
4211  }
4212  xmlSchemaFreeValue(p1);
4213  xmlSchemaFreeValue(q1);
4214  xmlSchemaFreeValue(p2);
4215  if (ret != 0)
4216  return(ret);
4217  }
4218  } else {
4219  xmlSchemaFreeValue(p1);
4220  xmlSchemaFreeValue(q1);
4221  }
4222  }
4223 
4224  /*
4225  * if the same type then calculate the difference
4226  */
4227  if (x->type == y->type) {
4228  int ret = 0;
4229  q1 = xmlSchemaDateNormalize(y, 0);
4230  q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4231 
4232  p1 = xmlSchemaDateNormalize(x, 0);
4233  p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4234 
4235  if (p1d < q1d) {
4236  ret = -1;
4237  } else if (p1d > q1d) {
4238  ret = 1;
4239  } else {
4240  double sec;
4241 
4242  sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4243  if (sec < 0.0)
4244  ret = -1;
4245  else if (sec > 0.0)
4246  ret = 1;
4247 
4248  }
4249  xmlSchemaFreeValue(p1);
4250  xmlSchemaFreeValue(q1);
4251  return(ret);
4252  }
4253 
4254  switch (x->type) {
4255  case XML_SCHEMAS_DATETIME:
4256  xmask = 0xf;
4257  break;
4258  case XML_SCHEMAS_DATE:
4259  xmask = 0x7;
4260  break;
4261  case XML_SCHEMAS_GYEAR:
4262  xmask = 0x1;
4263  break;
4264  case XML_SCHEMAS_GMONTH:
4265  xmask = 0x2;
4266  break;
4267  case XML_SCHEMAS_GDAY:
4268  xmask = 0x3;
4269  break;
4270  case XML_SCHEMAS_GYEARMONTH:
4271  xmask = 0x3;
4272  break;
4273  case XML_SCHEMAS_GMONTHDAY:
4274  xmask = 0x6;
4275  break;
4276  case XML_SCHEMAS_TIME:
4277  xmask = 0x8;
4278  break;
4279  default:
4280  xmask = 0;
4281  break;
4282  }
4283 
4284  switch (y->type) {
4285  case XML_SCHEMAS_DATETIME:
4286  ymask = 0xf;
4287  break;
4288  case XML_SCHEMAS_DATE:
4289  ymask = 0x7;
4290  break;
4291  case XML_SCHEMAS_GYEAR:
4292  ymask = 0x1;
4293  break;
4294  case XML_SCHEMAS_GMONTH:
4295  ymask = 0x2;
4296  break;
4297  case XML_SCHEMAS_GDAY:
4298  ymask = 0x3;
4299  break;
4300  case XML_SCHEMAS_GYEARMONTH:
4301  ymask = 0x3;
4302  break;
4303  case XML_SCHEMAS_GMONTHDAY:
4304  ymask = 0x6;
4305  break;
4306  case XML_SCHEMAS_TIME:
4307  ymask = 0x8;
4308  break;
4309  default:
4310  ymask = 0;
4311  break;
4312  }
4313 
4314  xor_mask = xmask ^ ymask; /* mark type differences */
4315  and_mask = xmask & ymask; /* mark field specification */
4316 
4317  /* year */
4318  if (xor_mask & 1)
4319  return 2; /* indeterminate */
4320  else if (and_mask & 1) {
4321  if (x->value.date.year < y->value.date.year)
4322  return -1;
4323  else if (x->value.date.year > y->value.date.year)
4324  return 1;
4325  }
4326 
4327  /* month */
4328  if (xor_mask & 2)
4329  return 2; /* indeterminate */
4330  else if (and_mask & 2) {
4331  if (x->value.date.mon < y->value.date.mon)
4332  return -1;
4333  else if (x->value.date.mon > y->value.date.mon)
4334  return 1;
4335  }
4336 
4337  /* day */
4338  if (xor_mask & 4)
4339  return 2; /* indeterminate */
4340  else if (and_mask & 4) {
4341  if (x->value.date.day < y->value.date.day)
4342  return -1;
4343  else if (x->value.date.day > y->value.date.day)
4344  return 1;
4345  }
4346 
4347  /* time */
4348  if (xor_mask & 8)
4349  return 2; /* indeterminate */
4350  else if (and_mask & 8) {
4351  if (x->value.date.hour < y->value.date.hour)
4352  return -1;
4353  else if (x->value.date.hour > y->value.date.hour)
4354  return 1;
4355  else if (x->value.date.min < y->value.date.min)
4356  return -1;
4357  else if (x->value.date.min > y->value.date.min)
4358  return 1;
4359  else if (x->value.date.sec < y->value.date.sec)
4360  return -1;
4361  else if (x->value.date.sec > y->value.date.sec)
4362  return 1;
4363  }
4364 
4365  return 0;
4366 }
4367 
4382 static int
4383 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4384  const xmlChar *y,
4385  int invert)
4386 {
4387  int tmp;
4388 
4389  while ((*x != 0) && (*y != 0)) {
4390  if (IS_WSP_REPLACE_CH(*y)) {
4391  if (! IS_WSP_SPACE_CH(*x)) {
4392  if ((*x - 0x20) < 0) {
4393  if (invert)
4394  return(1);
4395  else
4396  return(-1);
4397  } else {
4398  if (invert)
4399  return(-1);
4400  else
4401  return(1);
4402  }
4403  }
4404  } else {
4405  tmp = *x - *y;
4406  if (tmp < 0) {
4407  if (invert)
4408  return(1);
4409  else
4410  return(-1);
4411  }
4412  if (tmp > 0) {
4413  if (invert)
4414  return(-1);
4415  else
4416  return(1);
4417  }
4418  }
4419  x++;
4420  y++;
4421  }
4422  if (*x != 0) {
4423  if (invert)
4424  return(-1);
4425  else
4426  return(1);
4427  }
4428  if (*y != 0) {
4429  if (invert)
4430  return(1);
4431  else
4432  return(-1);
4433  }
4434  return(0);
4435 }
4436 
4450 static int
4451 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4452  const xmlChar *y,
4453  int invert)
4454 {
4455  int tmp;
4456 
4457  /*
4458  * Skip leading blank chars of the collapsed string.
4459  */
4460  while IS_WSP_BLANK_CH(*y)
4461  y++;
4462 
4463  while ((*x != 0) && (*y != 0)) {
4464  if IS_WSP_BLANK_CH(*y) {
4465  if (! IS_WSP_SPACE_CH(*x)) {
4466  /*
4467  * The yv character would have been replaced to 0x20.
4468  */
4469  if ((*x - 0x20) < 0) {
4470  if (invert)
4471  return(1);
4472  else
4473  return(-1);
4474  } else {
4475  if (invert)
4476  return(-1);
4477  else
4478  return(1);
4479  }
4480  }
4481  x++;
4482  y++;
4483  /*
4484  * Skip contiguous blank chars of the collapsed string.
4485  */
4486  while IS_WSP_BLANK_CH(*y)
4487  y++;
4488  } else {
4489  tmp = *x++ - *y++;
4490  if (tmp < 0) {
4491  if (invert)
4492  return(1);
4493  else
4494  return(-1);
4495  }
4496  if (tmp > 0) {
4497  if (invert)
4498  return(-1);
4499  else
4500  return(1);
4501  }
4502  }
4503  }
4504  if (*x != 0) {
4505  if (invert)
4506  return(-1);
4507  else
4508  return(1);
4509  }
4510  if (*y != 0) {
4511  /*
4512  * Skip trailing blank chars of the collapsed string.
4513  */
4514  while IS_WSP_BLANK_CH(*y)
4515  y++;
4516  if (*y != 0) {
4517  if (invert)
4518  return(1);
4519  else
4520  return(-1);
4521  }
4522  }
4523  return(0);
4524 }
4525 
4539 static int
4540 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4541  const xmlChar *y,
4542  int invert)
4543 {
4544  int tmp;
4545 
4546  /*
4547  * Skip leading blank chars of the collapsed string.
4548  */
4549  while IS_WSP_BLANK_CH(*y)
4550  y++;
4551 
4552  while ((*x != 0) && (*y != 0)) {
4553  if IS_WSP_BLANK_CH(*y) {
4554  if (! IS_WSP_BLANK_CH(*x)) {
4555  /*
4556  * The yv character would have been replaced to 0x20.
4557  */
4558  if ((*x - 0x20) < 0) {
4559  if (invert)
4560  return(1);
4561  else
4562  return(-1);
4563  } else {
4564  if (invert)
4565  return(-1);
4566  else
4567  return(1);
4568  }
4569  }
4570  x++;
4571  y++;
4572  /*
4573  * Skip contiguous blank chars of the collapsed string.
4574  */
4575  while IS_WSP_BLANK_CH(*y)
4576  y++;
4577  } else {
4578  if IS_WSP_BLANK_CH(*x) {
4579  /*
4580  * The xv character would have been replaced to 0x20.
4581  */
4582  if ((0x20 - *y) < 0) {
4583  if (invert)
4584  return(1);
4585  else
4586  return(-1);
4587  } else {
4588  if (invert)
4589  return(-1);
4590  else
4591  return(1);
4592  }
4593  }
4594  tmp = *x++ - *y++;
4595  if (tmp < 0)
4596  return(-1);
4597  if (tmp > 0)
4598  return(1);
4599  }
4600  }
4601  if (*x != 0) {
4602  if (invert)
4603  return(-1);
4604  else
4605  return(1);
4606  }
4607  if (*y != 0) {
4608  /*
4609  * Skip trailing blank chars of the collapsed string.
4610  */
4611  while IS_WSP_BLANK_CH(*y)
4612  y++;
4613  if (*y != 0) {
4614  if (invert)
4615  return(1);
4616  else
4617  return(-1);
4618  }
4619  }
4620  return(0);
4621 }
4622 
4623 
4634 static int
4635 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4636  const xmlChar *y)
4637 {
4638  int tmp;
4639 
4640  while ((*x != 0) && (*y != 0)) {
4641  if IS_WSP_BLANK_CH(*y) {
4642  if (! IS_WSP_BLANK_CH(*x)) {
4643  if ((*x - 0x20) < 0)
4644  return(-1);
4645  else
4646  return(1);
4647  }
4648  } else {
4649  if IS_WSP_BLANK_CH(*x) {
4650  if ((0x20 - *y) < 0)
4651  return(-1);
4652  else
4653  return(1);
4654  }
4655  tmp = *x - *y;
4656  if (tmp < 0)
4657  return(-1);
4658  if (tmp > 0)
4659  return(1);
4660  }
4661  x++;
4662  y++;
4663  }
4664  if (*x != 0)
4665  return(1);
4666  if (*y != 0)
4667  return(-1);
4668  return(0);
4669 }
4670 
4681 static int
4682 xmlSchemaCompareNormStrings(const xmlChar *x,
4683  const xmlChar *y) {
4684  int tmp;
4685 
4686  while (IS_BLANK_CH(*x)) x++;
4687  while (IS_BLANK_CH(*y)) y++;
4688  while ((*x != 0) && (*y != 0)) {
4689  if (IS_BLANK_CH(*x)) {
4690  if (!IS_BLANK_CH(*y)) {
4691  tmp = *x - *y;
4692  return(tmp);
4693  }
4694  while (IS_BLANK_CH(*x)) x++;
4695  while (IS_BLANK_CH(*y)) y++;
4696  } else {
4697  tmp = *x++ - *y++;
4698  if (tmp < 0)
4699  return(-1);
4700  if (tmp > 0)
4701  return(1);
4702  }
4703  }
4704  if (*x != 0) {
4705  while (IS_BLANK_CH(*x)) x++;
4706  if (*x != 0)
4707  return(1);
4708  }
4709  if (*y != 0) {
4710  while (IS_BLANK_CH(*y)) y++;
4711  if (*y != 0)
4712  return(-1);
4713  }
4714  return(0);
4715 }
4716 
4727 static int
4728 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4729  double d1, d2;
4730 
4731  if ((x == NULL) || (y == NULL))
4732  return(-2);
4733 
4734  /*
4735  * Cast everything to doubles.
4736  */
4737  if (x->type == XML_SCHEMAS_DOUBLE)
4738  d1 = x->value.d;
4739  else if (x->type == XML_SCHEMAS_FLOAT)
4740  d1 = x->value.f;
4741  else
4742  return(-2);
4743 
4744  if (y->type == XML_SCHEMAS_DOUBLE)
4745  d2 = y->value.d;
4746  else if (y->type == XML_SCHEMAS_FLOAT)
4747  d2 = y->value.f;
4748  else
4749  return(-2);
4750 
4751  /*
4752  * Check for special cases.
4753  */
4754  if (xmlXPathIsNaN(d1)) {
4755  if (xmlXPathIsNaN(d2))
4756  return(0);
4757  return(1);
4758  }
4759  if (xmlXPathIsNaN(d2))
4760  return(-1);
4761  if (d1 == xmlXPathPINF) {
4762  if (d2 == xmlXPathPINF)
4763  return(0);
4764  return(1);
4765  }
4766  if (d2 == xmlXPathPINF)
4767  return(-1);
4768  if (d1 == xmlXPathNINF) {
4769  if (d2 == xmlXPathNINF)
4770  return(0);
4771  return(-1);
4772  }
4773  if (d2 == xmlXPathNINF)
4774  return(1);
4775 
4776  /*
4777  * basic tests, the last one we should have equality, but
4778  * portability is more important than speed and handling
4779  * NaN or Inf in a portable way is always a challenge, so ...
4780  */
4781  if (d1 < d2)
4782  return(-1);
4783  if (d1 > d2)
4784  return(1);
4785  if (d1 == d2)
4786  return(0);
4787  return(2);
4788 }
4789 
4804 static int
4805 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4806  xmlSchemaValPtr x,
4807  const xmlChar *xvalue,
4808  xmlSchemaWhitespaceValueType xws,
4809  xmlSchemaValType ytype,
4810  xmlSchemaValPtr y,
4811  const xmlChar *yvalue,
4812  xmlSchemaWhitespaceValueType yws)
4813 {
4814  switch (xtype) {
4815  case XML_SCHEMAS_UNKNOWN:
4816  case XML_SCHEMAS_ANYTYPE:
4817  return(-2);
4818  case XML_SCHEMAS_INTEGER:
4819  case XML_SCHEMAS_NPINTEGER:
4820  case XML_SCHEMAS_NINTEGER:
4821  case XML_SCHEMAS_NNINTEGER:
4822  case XML_SCHEMAS_PINTEGER:
4823  case XML_SCHEMAS_INT:
4824  case XML_SCHEMAS_UINT:
4825  case XML_SCHEMAS_LONG:
4826  case XML_SCHEMAS_ULONG:
4827  case XML_SCHEMAS_SHORT:
4828  case XML_SCHEMAS_USHORT:
4829  case XML_SCHEMAS_BYTE:
4830  case XML_SCHEMAS_UBYTE:
4831  case XML_SCHEMAS_DECIMAL:
4832  if ((x == NULL) || (y == NULL))
4833  return(-2);
4834  if (ytype == xtype)
4835  return(xmlSchemaCompareDecimals(x, y));
4836  if ((ytype == XML_SCHEMAS_DECIMAL) ||
4837  (ytype == XML_SCHEMAS_INTEGER) ||
4838  (ytype == XML_SCHEMAS_NPINTEGER) ||
4839  (ytype == XML_SCHEMAS_NINTEGER) ||
4840  (ytype == XML_SCHEMAS_NNINTEGER) ||
4841  (ytype == XML_SCHEMAS_PINTEGER) ||
4842  (ytype == XML_SCHEMAS_INT) ||
4843  (ytype == XML_SCHEMAS_UINT) ||
4844  (ytype == XML_SCHEMAS_LONG) ||
4845  (ytype == XML_SCHEMAS_ULONG) ||
4846  (ytype == XML_SCHEMAS_SHORT) ||
4847  (ytype == XML_SCHEMAS_USHORT) ||
4848  (ytype == XML_SCHEMAS_BYTE) ||
4849  (ytype == XML_SCHEMAS_UBYTE))
4850  return(xmlSchemaCompareDecimals(x, y));
4851  return(-2);
4852  case XML_SCHEMAS_DURATION:
4853  if ((x == NULL) || (y == NULL))
4854  return(-2);
4855  if (ytype == XML_SCHEMAS_DURATION)
4856  return(xmlSchemaCompareDurations(x, y));
4857  return(-2);
4858  case XML_SCHEMAS_TIME:
4859  case XML_SCHEMAS_GDAY:
4860  case XML_SCHEMAS_GMONTH:
4861  case XML_SCHEMAS_GMONTHDAY:
4862  case XML_SCHEMAS_GYEAR:
4863  case XML_SCHEMAS_GYEARMONTH:
4864  case XML_SCHEMAS_DATE:
4865  case XML_SCHEMAS_DATETIME:
4866  if ((x == NULL) || (y == NULL))
4867  return(-2);
4868  if ((ytype == XML_SCHEMAS_DATETIME) ||
4869  (ytype == XML_SCHEMAS_TIME) ||
4870  (ytype == XML_SCHEMAS_GDAY) ||
4871  (ytype == XML_SCHEMAS_GMONTH) ||
4872  (ytype == XML_SCHEMAS_GMONTHDAY) ||
4873  (ytype == XML_SCHEMAS_GYEAR) ||
4874  (ytype == XML_SCHEMAS_DATE) ||
4875  (ytype == XML_SCHEMAS_GYEARMONTH))
4876  return (xmlSchemaCompareDates(x, y));
4877  return (-2);
4878  /*
4879  * Note that we will support comparison of string types against
4880  * anySimpleType as well.
4881  */
4882  case XML_SCHEMAS_ANYSIMPLETYPE:
4883  case XML_SCHEMAS_STRING:
4884  case XML_SCHEMAS_NORMSTRING:
4885  case XML_SCHEMAS_TOKEN:
4886  case XML_SCHEMAS_LANGUAGE:
4887  case XML_SCHEMAS_NMTOKEN:
4888  case XML_SCHEMAS_NAME:
4889  case XML_SCHEMAS_NCNAME:
4890  case XML_SCHEMAS_ID:
4891  case XML_SCHEMAS_IDREF:
4892  case XML_SCHEMAS_ENTITY:
4893  case XML_SCHEMAS_ANYURI:
4894  {
4895  const xmlChar *xv, *yv;
4896 
4897  if (x == NULL)
4898  xv = xvalue;
4899  else
4900  xv = x->value.str;
4901  if (y == NULL)
4902  yv = yvalue;
4903  else
4904  yv = y->value.str;
4905  /*
4906  * TODO: Compare those against QName.
4907  */
4908  if (ytype == XML_SCHEMAS_QNAME) {
4909  TODO
4910  if (y == NULL)
4911  return(-2);
4912  return (-2);
4913  }
4914  if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4915  (ytype == XML_SCHEMAS_STRING) ||
4916  (ytype == XML_SCHEMAS_NORMSTRING) ||
4917  (ytype == XML_SCHEMAS_TOKEN) ||
4918  (ytype == XML_SCHEMAS_LANGUAGE) ||
4919  (ytype == XML_SCHEMAS_NMTOKEN) ||
4920  (ytype == XML_SCHEMAS_NAME) ||
4921  (ytype == XML_SCHEMAS_NCNAME) ||
4922  (ytype == XML_SCHEMAS_ID) ||
4923  (ytype == XML_SCHEMAS_IDREF) ||
4924  (ytype == XML_SCHEMAS_ENTITY) ||
4925  (ytype == XML_SCHEMAS_ANYURI)) {
4926 
4927  if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4928 
4929  if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4930  /* TODO: What about x < y or x > y. */
4931  if (xmlStrEqual(xv, yv))
4932  return (0);
4933  else
4934  return (2);
4935  } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4936  return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
4937  else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4938  return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
4939 
4940  } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
4941 
4942  if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4943  return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
4944  if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4945  return (xmlSchemaCompareReplacedStrings(xv, yv));
4946  if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4947  return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
4948 
4949  } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
4950 
4951  if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4952  return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
4953  if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4954  return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
4955  if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4956  return (xmlSchemaCompareNormStrings(xv, yv));
4957  } else
4958  return (-2);
4959 
4960  }
4961  return (-2);
4962  }
4963  case XML_SCHEMAS_QNAME:
4964  case XML_SCHEMAS_NOTATION:
4965  if ((x == NULL) || (y == NULL))
4966  return(-2);
4967  if ((ytype == XML_SCHEMAS_QNAME) ||
4968  (ytype == XML_SCHEMAS_NOTATION)) {
4969  if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
4970  (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
4971  return(0);
4972  return(2);
4973  }
4974  return (-2);
4975  case XML_SCHEMAS_FLOAT:
4976  case XML_SCHEMAS_DOUBLE:
4977  if ((x == NULL) || (y == NULL))
4978  return(-2);
4979  if ((ytype == XML_SCHEMAS_FLOAT) ||
4980  (ytype == XML_SCHEMAS_DOUBLE))
4981  return (xmlSchemaCompareFloats(x, y));
4982  return (-2);
4983  case XML_SCHEMAS_BOOLEAN:
4984  if ((x == NULL) || (y == NULL))
4985  return(-2);
4986  if (ytype == XML_SCHEMAS_BOOLEAN) {
4987  if (x->value.b == y->value.b)
4988  return(0);
4989  if (x->value.b == 0)
4990  return(-1);
4991  return(1);
4992  }
4993  return (-2);
4994  case XML_SCHEMAS_HEXBINARY:
4995  if ((x == NULL) || (y == NULL))
4996  return(-2);
4997  if (ytype == XML_SCHEMAS_HEXBINARY) {
4998  if (x->value.hex.total == y->value.hex.total) {
4999  int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
5000  if (ret > 0)
5001  return(1);
5002  else if (ret == 0)
5003  return(0);
5004  }
5005  else if (x->value.hex.total > y->value.hex.total)
5006  return(1);
5007 
5008  return(-1);
5009  }
5010  return (-2);
5011  case XML_SCHEMAS_BASE64BINARY:
5012  if ((x == NULL) || (y == NULL))
5013  return(-2);
5014  if (ytype == XML_SCHEMAS_BASE64BINARY) {
5015  if (x->value.base64.total == y->value.base64.total) {
5016  int ret = xmlStrcmp(x->value.base64.str,
5017  y->value.base64.str);
5018  if (ret > 0)
5019  return(1);
5020  else if (ret == 0)
5021  return(0);
5022  else
5023  return(-1);
5024  }
5025  else if (x->value.base64.total > y->value.base64.total)
5026  return(1);
5027  else
5028  return(-1);
5029  }
5030  return (-2);
5031  case XML_SCHEMAS_IDREFS:
5032  case XML_SCHEMAS_ENTITIES:
5033  case XML_SCHEMAS_NMTOKENS:
5034  TODO
5035  break;
5036  }
5037  return -2;
5038 }
5039 
5050 int
5051 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
5052  xmlSchemaWhitespaceValueType xws, yws;
5053 
5054  if ((x == NULL) || (y == NULL))
5055  return(-2);
5056  if (x->type == XML_SCHEMAS_STRING)
5057  xws = XML_SCHEMA_WHITESPACE_PRESERVE;
5058  else if (x->type == XML_SCHEMAS_NORMSTRING)
5059  xws = XML_SCHEMA_WHITESPACE_REPLACE;
5060  else
5061  xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5062 
5063  if (y->type == XML_SCHEMAS_STRING)
5064  yws = XML_SCHEMA_WHITESPACE_PRESERVE;
5065  else if (y->type == XML_SCHEMAS_NORMSTRING)
5066  yws = XML_SCHEMA_WHITESPACE_REPLACE;
5067  else
5068  yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5069 
5070  return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5071  y, NULL, yws));
5072 }
5073 
5086 int
5087 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
5088  xmlSchemaWhitespaceValueType xws,
5089  xmlSchemaValPtr y,
5090  xmlSchemaWhitespaceValueType yws)
5091 {
5092  if ((x == NULL) || (y == NULL))
5093  return(-2);
5094  return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5095  y, NULL, yws));
5096 }
5097 
5110 static int
5111 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
5112  xmlSchemaValPtr x,
5113  const xmlChar *xvalue,
5114  xmlSchemaWhitespaceValueType xws,
5115  xmlSchemaValType ytype,
5116  xmlSchemaValPtr y,
5117  const xmlChar *yvalue,
5118  xmlSchemaWhitespaceValueType yws)
5119 {
5120  return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5121  yvalue, yws));
5122 }
5123 
5132 static int
5133 xmlSchemaNormLen(const xmlChar *value) {
5134  const xmlChar *utf;
5135  int ret = 0;
5136 
5137  if (value == NULL)
5138  return(-1);
5139  utf = value;
5140  while (IS_BLANK_CH(*utf)) utf++;
5141  while (*utf != 0) {
5142  if (utf[0] & 0x80) {
5143  if ((utf[1] & 0xc0) != 0x80)
5144  return(-1);
5145  if ((utf[0] & 0xe0) == 0xe0) {
5146  if ((utf[2] & 0xc0) != 0x80)
5147  return(-1);
5148  if ((utf[0] & 0xf0) == 0xf0) {
5149  if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5150  return(-1);
5151  utf += 4;
5152  } else {
5153  utf += 3;
5154  }
5155  } else {
5156  utf += 2;
5157  }
5158  } else if (IS_BLANK_CH(*utf)) {
5159  while (IS_BLANK_CH(*utf)) utf++;
5160  if (*utf == 0)
5161  break;
5162  } else {
5163  utf++;
5164  }
5165  ret++;
5166  }
5167  return(ret);
5168 }
5169 
5178 unsigned long
5179 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5180 {
5181  /*
5182  * TODO: Check if this is a decimal.
5183  */
5184  if (facet == NULL || facet->val == NULL)
5185  return 0;
5186  return ((unsigned long) facet->val->value.decimal.lo);
5187 }
5188 
5201 int
5202 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5203  const xmlChar *value,
5204  unsigned long actualLen,
5205  unsigned long *expectedLen)
5206 {
5207  if (facet == NULL)
5208  return(-1);
5209  /*
5210  * TODO: Check if this will work with large numbers.
5211  * (compare value.decimal.mi and value.decimal.hi as well?).
5212  */
5213  if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5214  if (actualLen != facet->val->value.decimal.lo) {
5215  if (expectedLen != NULL)
5216  *expectedLen = facet->val->value.decimal.lo;
5218  }
5219  } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5220  if (actualLen < facet->val->value.decimal.lo) {
5221  if (expectedLen != NULL)
5222  *expectedLen = facet->val->value.decimal.lo;
5224  }
5225  } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5226  if (actualLen > facet->val->value.decimal.lo) {
5227  if (expectedLen != NULL)
5228  *expectedLen = facet->val->value.decimal.lo;
5230  }
5231  } else
5232  /*
5233  * NOTE: That we can pass NULL as xmlSchemaValPtr to
5234  * xmlSchemaValidateFacet, since the remaining facet types
5235  * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5236  */
5237  return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5238  return (0);
5239 }
5240 
5256 static int
5257 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5258  xmlSchemaValType valType,
5259  const xmlChar *value,
5260  xmlSchemaValPtr val,
5261  unsigned long *length,
5262  xmlSchemaWhitespaceValueType ws)
5263 {
5264  unsigned int len = 0;
5265 
5266  if ((length == NULL) || (facet == NULL))
5267  return (-1);
5268  *length = 0;
5269  if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5270  (facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5271  (facet->type != XML_SCHEMA_FACET_MINLENGTH))
5272  return (-1);
5273 
5274  /*
5275  * TODO: length, maxLength and minLength must be of type
5276  * nonNegativeInteger only. Check if decimal is used somehow.
5277  */
5278  if ((facet->val == NULL) ||
5279  ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5280  (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5281  (facet->val->value.decimal.frac != 0)) {
5282  return(-1);
5283  }
5284  if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5285  len = val->value.hex.total;
5286  else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5287  len = val->value.base64.total;
5288  else {
5289  switch (valType) {
5290  case XML_SCHEMAS_STRING:
5291  case XML_SCHEMAS_NORMSTRING:
5292  if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5293  /*
5294  * This is to ensure API compatibility with the old
5295  * xmlSchemaValidateLengthFacet(). Anyway, this was and
5296  * is not the correct handling.
5297  * TODO: Get rid of this case somehow.
5298  */
5299  if (valType == XML_SCHEMAS_STRING)
5300  len = xmlUTF8Strlen(value);
5301  else
5302  len = xmlSchemaNormLen(value);
5303  } else if (value != NULL) {
5304  if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5305  len = xmlSchemaNormLen(value);
5306  else
5307  /*
5308  * Should be OK for "preserve" as well.
5309  */
5310  len = xmlUTF8Strlen(value);
5311  }
5312  break;
5313  case XML_SCHEMAS_IDREF:
5314  case XML_SCHEMAS_TOKEN:
5315  case XML_SCHEMAS_LANGUAGE:
5316  case XML_SCHEMAS_NMTOKEN:
5317  case XML_SCHEMAS_NAME:
5318  case XML_SCHEMAS_NCNAME:
5319  case XML_SCHEMAS_ID:
5320  /*
5321  * FIXME: What exactly to do with anyURI?
5322  */
5323  case XML_SCHEMAS_ANYURI:
5324  if (value != NULL)
5325  len = xmlSchemaNormLen(value);
5326  break;
5327  case XML_SCHEMAS_QNAME:
5328  case XML_SCHEMAS_NOTATION:
5329  /*
5330  * For QName and NOTATION, those facets are
5331  * deprecated and should be ignored.
5332  */
5333  return (0);
5334  default:
5335  TODO
5336  }
5337  }
5338  *length = (unsigned long) len;
5339  /*
5340  * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5341  */
5342  if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5343  if (len != facet->val->value.decimal.lo)
5345  } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5346  if (len < facet->val->value.decimal.lo)
5348  } else {
5349  if (len > facet->val->value.decimal.lo)
5351  }
5352 
5353  return (0);
5354 }
5355 
5370 int
5371 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5372  xmlSchemaFacetPtr facet,
5373  const xmlChar *value,
5374  xmlSchemaValPtr val,
5375  unsigned long *length)
5376 {
5377  if (type == NULL)
5378  return(-1);
5379  return (xmlSchemaValidateLengthFacetInternal(facet,
5380  type->builtInType, value, val, length,
5381  XML_SCHEMA_WHITESPACE_UNKNOWN));
5382 }
5383 
5399 int
5400 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5401  xmlSchemaValType valType,
5402  const xmlChar *value,
5403  xmlSchemaValPtr val,
5404  unsigned long *length,
5405  xmlSchemaWhitespaceValueType ws)
5406 {
5407  return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5408  length, ws));
5409 }
5410 
5425 static int
5426 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5427  xmlSchemaWhitespaceValueType fws,
5428  xmlSchemaValType valType,
5429  const xmlChar *value,
5430  xmlSchemaValPtr val,
5431  xmlSchemaWhitespaceValueType ws)
5432 {
5433  int ret;
5434  int stringType;
5435 
5436  if (facet == NULL)
5437  return(-1);
5438 
5439  switch (facet->type) {
5440  case XML_SCHEMA_FACET_PATTERN:
5441  /*
5442  * NOTE that for patterns, the @value needs to be the normalized
5443  * value, *not* the lexical initial value or the canonical value.
5444  */
5445  if (value == NULL)
5446  return(-1);
5447  /*
5448  * If string-derived type, regexp must be tested on the value space of
5449  * the datatype.
5450  * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5451  */
5452  stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
5453  || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
5454  ret = xmlRegexpExec(facet->regexp,
5455  (stringType && val->value.str) ? val->value.str : value);
5456  if (ret == 1)
5457  return(0);
5458  if (ret == 0)
5460  return(ret);
5461  case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5462  ret = xmlSchemaCompareValues(val, facet->val);
5463  if (ret == -2)
5464  return(-1);
5465  if (ret == -1)
5466  return(0);
5468  case XML_SCHEMA_FACET_MAXINCLUSIVE:
5469  ret = xmlSchemaCompareValues(val, facet->val);
5470  if (ret == -2)
5471  return(-1);
5472  if ((ret == -1) || (ret == 0))
5473  return(0);
5475  case XML_SCHEMA_FACET_MINEXCLUSIVE:
5476  ret = xmlSchemaCompareValues(val, facet->val);
5477  if (ret == -2)
5478  return(-1);
5479  if (ret == 1)
5480  return(0);
5482  case XML_SCHEMA_FACET_MININCLUSIVE:
5483  ret = xmlSchemaCompareValues(val, facet->val);
5484  if (ret == -2)
5485  return(-1);
5486  if ((ret == 1) || (ret == 0))
5487  return(0);
5489  case XML_SCHEMA_FACET_WHITESPACE:
5490  /* TODO whitespaces */
5491  /*
5492  * NOTE: Whitespace should be handled to normalize
5493  * the value to be validated against a the facets;
5494  * not to normalize the value in-between.
5495  */
5496  return(0);
5497  case XML_SCHEMA_FACET_ENUMERATION:
5498  if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5499  /*
5500  * This is to ensure API compatibility with the old
5501  * xmlSchemaValidateFacet().
5502  * TODO: Get rid of this case.
5503  */
5504  if ((facet->value != NULL) &&
5505  (xmlStrEqual(facet->value, value)))
5506  return(0);
5507  } else {
5508  ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5509  facet->val, facet->value, fws, valType, val,
5510  value, ws);
5511  if (ret == -2)
5512  return(-1);
5513  if (ret == 0)
5514  return(0);
5515  }
5517  case XML_SCHEMA_FACET_LENGTH:
5518  /*
5519  * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5520  * then any {value} is facet-valid."
5521  */
5522  if ((valType == XML_SCHEMAS_QNAME) ||
5523  (valType == XML_SCHEMAS_NOTATION))
5524  return (0);
5525  /* Falls through. */
5526  case XML_SCHEMA_FACET_MAXLENGTH:
5527  case XML_SCHEMA_FACET_MINLENGTH: {
5528  unsigned int len = 0;
5529 
5530  if ((valType == XML_SCHEMAS_QNAME) ||
5531  (valType == XML_SCHEMAS_NOTATION))
5532  return (0);
5533  /*
5534  * TODO: length, maxLength and minLength must be of type
5535  * nonNegativeInteger only. Check if decimal is used somehow.
5536  */
5537  if ((facet->val == NULL) ||
5538  ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5539  (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5540  (facet->val->value.decimal.frac != 0)) {
5541  return(-1);
5542  }
5543  if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5544  len = val->value.hex.total;
5545  else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5546  len = val->value.base64.total;
5547  else {
5548  switch (valType) {
5549  case XML_SCHEMAS_STRING:
5550  case XML_SCHEMAS_NORMSTRING:
5551  if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5552  /*
5553  * This is to ensure API compatibility with the old
5554  * xmlSchemaValidateFacet(). Anyway, this was and
5555  * is not the correct handling.
5556  * TODO: Get rid of this case somehow.
5557  */
5558  if (valType == XML_SCHEMAS_STRING)
5559  len = xmlUTF8Strlen(value);
5560  else
5561  len = xmlSchemaNormLen(value);
5562  } else if (value != NULL) {
5563  if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5564  len = xmlSchemaNormLen(value);
5565  else
5566  /*
5567  * Should be OK for "preserve" as well.
5568  */
5569  len = xmlUTF8Strlen(value);
5570  }
5571  break;
5572  case XML_SCHEMAS_IDREF:
5573  case XML_SCHEMAS_TOKEN:
5574  case XML_SCHEMAS_LANGUAGE:
5575  case XML_SCHEMAS_NMTOKEN:
5576  case XML_SCHEMAS_NAME:
5577  case XML_SCHEMAS_NCNAME:
5578  case XML_SCHEMAS_ID:
5579  case XML_SCHEMAS_ANYURI:
5580  if (value != NULL)
5581  len = xmlSchemaNormLen(value);
5582  break;
5583  default:
5584  TODO
5585  }
5586  }
5587  if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5588  if (len != facet->val->value.decimal.lo)
5590  } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5591  if (len < facet->val->value.decimal.lo)
5593  } else {
5594  if (len > facet->val->value.decimal.lo)
5596  }
5597  break;
5598  }
5599  case XML_SCHEMA_FACET_TOTALDIGITS:
5600  case XML_SCHEMA_FACET_FRACTIONDIGITS:
5601 
5602  if ((facet->val == NULL) ||
5603  ((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5604  (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5605  (facet->val->value.decimal.frac != 0)) {
5606  return(-1);
5607  }
5608  if ((val == NULL) ||
5609  ((val->type != XML_SCHEMAS_DECIMAL) &&
5610  (val->type != XML_SCHEMAS_INTEGER) &&
5611  (val->type != XML_SCHEMAS_NPINTEGER) &&
5612  (val->type != XML_SCHEMAS_NINTEGER) &&
5613  (val->type != XML_SCHEMAS_NNINTEGER) &&
5614  (val->type != XML_SCHEMAS_PINTEGER) &&
5615  (val->type != XML_SCHEMAS_INT) &&
5616  (val->type != XML_SCHEMAS_UINT) &&
5617  (val->type != XML_SCHEMAS_LONG) &&
5618  (val->type != XML_SCHEMAS_ULONG) &&
5619  (val->type != XML_SCHEMAS_SHORT) &&
5620  (val->type != XML_SCHEMAS_USHORT) &&
5621  (val->type != XML_SCHEMAS_BYTE) &&
5622  (val->type != XML_SCHEMAS_UBYTE))) {
5623  return(-1);
5624  }
5625  if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5626  if (val->value.decimal.total > facet->val->value.decimal.lo)
5628 
5629  } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5630  if (val->value.decimal.frac > facet->val->value.decimal.lo)
5632  }
5633  break;
5634  default:
5635  TODO
5636  }
5637  return(0);
5638 
5639 }
5640 
5653 int
5654 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5655  xmlSchemaFacetPtr facet,
5656  const xmlChar *value,
5657  xmlSchemaValPtr val)
5658 {
5659  /*
5660  * This tries to ensure API compatibility regarding the old
5661  * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5662  * xmlSchemaValidateFacetWhtsp().
5663  */
5664  if (val != NULL)
5665  return(xmlSchemaValidateFacetInternal(facet,
5666  XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5667  XML_SCHEMA_WHITESPACE_UNKNOWN));
5668  else if (base != NULL)
5669  return(xmlSchemaValidateFacetInternal(facet,
5670  XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5671  XML_SCHEMA_WHITESPACE_UNKNOWN));
5672  return(-1);
5673 }
5674 
5692 int
5693 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5694  xmlSchemaWhitespaceValueType fws,
5695  xmlSchemaValType valType,
5696  const xmlChar *value,
5697  xmlSchemaValPtr val,
5698  xmlSchemaWhitespaceValueType ws)
5699 {
5700  return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5701  value, val, ws));
5702 }
5703 
5704 #if 0
5705 #ifndef DBL_DIG
5706 #define DBL_DIG 16
5707 #endif
5708 #ifndef DBL_EPSILON
5709 #define DBL_EPSILON 1E-9
5710 #endif
5711 
5712 #define INTEGER_DIGITS DBL_DIG
5713 #define FRACTION_DIGITS (DBL_DIG + 1)
5714 #define EXPONENT_DIGITS (3 + 2)
5715 
5724 static void
5725 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5726 {
5727  switch (xmlXPathIsInf(number)) {
5728  case 1:
5729  if (buffersize > (int)sizeof("INF"))
5730  snprintf(buffer, buffersize, "INF");
5731  break;
5732  case -1:
5733  if (buffersize > (int)sizeof("-INF"))
5734  snprintf(buffer, buffersize, "-INF");
5735  break;
5736  default:
5737  if (xmlXPathIsNaN(number)) {
5738  if (buffersize > (int)sizeof("NaN"))
5739  snprintf(buffer, buffersize, "NaN");
5740  } else if (number == 0) {
5741  snprintf(buffer, buffersize, "0.0E0");
5742  } else {
5743  /* 3 is sign, decimal point, and terminating zero */
5744  char work[DBL_DIG + EXPONENT_DIGITS + 3];
5745  int integer_place, fraction_place;
5746  char *ptr;
5747  char *after_fraction;
5748  double absolute_value;
5749  int size;
5750 
5751  absolute_value = fabs(number);
5752 
5753  /*
5754  * Result is in work, and after_fraction points
5755  * just past the fractional part.
5756  * Use scientific notation
5757  */
5758  integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
5759  fraction_place = DBL_DIG - 1;
5760  snprintf(work, sizeof(work),"%*.*e",
5761  integer_place, fraction_place, number);
5762  after_fraction = strchr(work + DBL_DIG, 'e');
5763  /* Remove fractional trailing zeroes */
5764  ptr = after_fraction;
5765  while (*(--ptr) == '0')
5766  ;
5767  if (*ptr != '.')
5768  ptr++;
5769  while ((*ptr++ = *after_fraction++) != 0);
5770 
5771  /* Finally copy result back to caller */
5772  size = strlen(work) + 1;
5773  if (size > buffersize) {
5774  work[buffersize - 1] = 0;
5775  size = buffersize;
5776  }
5777  memmove(buffer, work, size);
5778  }
5779  break;
5780  }
5781 }
5782 #endif
5783 
5803 int
5804 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5805 {
5806  if ((retValue == NULL) || (val == NULL))
5807  return (-1);
5808  *retValue = NULL;
5809  switch (val->type) {
5810  case XML_SCHEMAS_STRING:
5811  if (val->value.str == NULL)
5812  *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5813  else
5814  *retValue =
5815  BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5816  break;
5817  case XML_SCHEMAS_NORMSTRING:
5818  if (val->value.str == NULL)
5819  *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5820  else {
5821  *retValue = xmlSchemaWhiteSpaceReplace(
5822  (const xmlChar *) val->value.str);
5823  if ((*retValue) == NULL)
5824  *retValue = BAD_CAST xmlStrdup(
5825  (const xmlChar *) val->value.str);
5826  }
5827  break;
5828  case XML_SCHEMAS_TOKEN:
5829  case XML_SCHEMAS_LANGUAGE:
5830  case XML_SCHEMAS_NMTOKEN:
5831  case XML_SCHEMAS_NAME:
5832  case XML_SCHEMAS_NCNAME:
5833  case XML_SCHEMAS_ID:
5834  case XML_SCHEMAS_IDREF:
5835  case XML_SCHEMAS_ENTITY:
5836  case XML_SCHEMAS_NOTATION: /* Unclear */
5837  case XML_SCHEMAS_ANYURI: /* Unclear */
5838  if (val->value.str == NULL)
5839  return (-1);
5840  *retValue =
5841  BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5842  if (*retValue == NULL)
5843  *retValue =
5844  BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5845  break;
5846  case XML_SCHEMAS_QNAME:
5847  /* TODO: Unclear in XML Schema 1.0. */
5848  if (val->value.qname.uri == NULL) {
5849  *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5850  return (0);
5851  } else {
5852  *retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5853  *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5854  BAD_CAST val->value.qname.uri);
5855  *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5856  BAD_CAST "}");
5857  *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5858  BAD_CAST val->value.qname.uri);
5859  }
5860  break;
5861  case XML_SCHEMAS_DECIMAL:
5862  /*
5863  * TODO: Lookout for a more simple implementation.
5864  */
5865  if ((val->value.decimal.total == 1) &&
5866  (val->value.decimal.lo == 0)) {
5867  *retValue = xmlStrdup(BAD_CAST "0.0");
5868  } else {
5869  xmlSchemaValDecimal dec = val->value.decimal;
5870  int bufsize;
5871  char *buf = NULL, *offs;
5872 
5873  /* Add room for the decimal point as well. */
5874  bufsize = dec.total + 2;
5875  if (dec.sign)
5876  bufsize++;
5877  /* Add room for leading/trailing zero. */
5878  if ((dec.frac == 0) || (dec.frac == dec.total))
5879  bufsize++;
5880  buf = xmlMalloc(bufsize);
5881  if (buf == NULL)
5882  return(-1);
5883  offs = buf;
5884  if (dec.sign)
5885  *offs++ = '-';
5886  if (dec.frac == dec.total) {
5887  *offs++ = '0';
5888  *offs++ = '.';
5889  }
5890  if (dec.hi != 0)
5891  snprintf(offs, bufsize - (offs - buf),
5892  "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5893  else if (dec.mi != 0)
5894  snprintf(offs, bufsize - (offs - buf),
5895  "%lu%lu", dec.mi, dec.lo);
5896  else
5897  snprintf(offs, bufsize - (offs - buf),
5898  "%lu", dec.lo);
5899 
5900  if (dec.frac != 0) {
5901  if (dec.frac != dec.total) {
5902  int diff = dec.total - dec.frac;
5903  /*
5904  * Insert the decimal point.
5905  */
5906  memmove(offs + diff + 1, offs + diff, dec.frac +1);
5907  offs[diff] = '.';
5908  } else {
5909  unsigned int i = 0;
5910  /*
5911  * Insert missing zeroes behind the decimal point.
5912  */
5913  while (*(offs + i) != 0)
5914  i++;
5915  if (i < dec.total) {
5916  memmove(offs + (dec.total - i), offs, i +1);
5917  memset(offs, '0', dec.total - i);
5918  }
5919  }
5920  } else {
5921  /*
5922  * Append decimal point and zero.
5923  */
5924  offs = buf + bufsize - 1;
5925  *offs-- = 0;
5926  *offs-- = '0';
5927  *offs-- = '.';
5928  }
5929  *retValue = BAD_CAST buf;
5930  }
5931  break;
5932  case XML_SCHEMAS_INTEGER:
5933  case XML_SCHEMAS_PINTEGER:
5934  case XML_SCHEMAS_NPINTEGER:
5935  case XML_SCHEMAS_NINTEGER:
5936  case XML_SCHEMAS_NNINTEGER:
5937  case XML_SCHEMAS_LONG:
5938  case XML_SCHEMAS_BYTE:
5939  case XML_SCHEMAS_SHORT:
5940  case XML_SCHEMAS_INT:
5941  case XML_SCHEMAS_UINT:
5942  case XML_SCHEMAS_ULONG:
5943  case XML_SCHEMAS_USHORT:
5944  case XML_SCHEMAS_UBYTE:
5945  if ((val->value.decimal.total == 1) &&
5946  (val->value.decimal.lo == 0))
5947  *retValue = xmlStrdup(BAD_CAST "0");
5948  else {
5949  xmlSchemaValDecimal dec = val->value.decimal;
5950  int bufsize = dec.total + 1;
5951 
5952  /* Add room for the decimal point as well. */
5953  if (dec.sign)
5954  bufsize++;
5955  *retValue = xmlMalloc(bufsize);
5956  if (*retValue == NULL)
5957  return(-1);
5958  if (dec.hi != 0) {
5959  if (dec.sign)
5960  snprintf((char *) *retValue, bufsize,
5961  "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5962  else
5963  snprintf((char *) *retValue, bufsize,
5964  "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5965  } else if (dec.mi != 0) {
5966  if (dec.sign)
5967  snprintf((char *) *retValue, bufsize,
5968  "-%lu%lu", dec.mi, dec.lo);
5969  else
5970  snprintf((char *) *retValue, bufsize,
5971  "%lu%lu", dec.mi, dec.lo);
5972  } else {
5973  if (dec.sign)
5974  snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5975  else
5976  snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5977  }
5978  }
5979  break;
5980  case XML_SCHEMAS_BOOLEAN:
5981  if (val->value.b)
5982  *retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5983  else
5984  *retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5985  break;
5986  case XML_SCHEMAS_DURATION: {
5987  char buf[100];
5988  unsigned long year;
5989  unsigned long mon, day, hour = 0, min = 0;
5990  double sec = 0, left;
5991 
5992  /* TODO: Unclear in XML Schema 1.0 */
5993  /*
5994  * TODO: This results in a normalized output of the value
5995  * - which is NOT conformant to the spec -
5996  * since the exact values of each property are not
5997  * recoverable. Think about extending the structure to
5998  * provide a field for every property.
5999  */
6000  year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
6001  mon = labs(val->value.dur.mon) - 12 * year;
6002 
6003  day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
6004  left = fabs(val->value.dur.sec) - day * 86400;
6005  if (left > 0) {
6006  hour = (unsigned long) FQUOTIENT(left, 3600);
6007  left = left - (hour * 3600);
6008  if (left > 0) {
6009  min = (unsigned long) FQUOTIENT(left, 60);
6010  sec = left - (min * 60);
6011  }
6012  }
6013  if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
6014  snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
6015  year, mon, day, hour, min, sec);
6016  else
6017  snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
6018  year, mon, day, hour, min, sec);
6019  *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6020  }
6021  break;
6022  case XML_SCHEMAS_GYEAR: {
6023  char buf[30];
6024  /* TODO: Unclear in XML Schema 1.0 */
6025  /* TODO: What to do with the timezone? */
6026  snprintf(buf, 30, "%04ld", val->value.date.year);
6027  *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6028  }
6029  break;
6030  case XML_SCHEMAS_GMONTH: {
6031  /* TODO: Unclear in XML Schema 1.0 */
6032  /* TODO: What to do with the timezone? */
6033  *retValue = xmlMalloc(6);
6034  if (*retValue == NULL)
6035  return(-1);
6036  snprintf((char *) *retValue, 6, "--%02u",
6037  val->value.date.mon);
6038  }
6039  break;
6040  case XML_SCHEMAS_GDAY: {
6041  /* TODO: Unclear in XML Schema 1.0 */
6042  /* TODO: What to do with the timezone? */
6043  *retValue = xmlMalloc(6);
6044  if (*retValue == NULL)
6045  return(-1);
6046  snprintf((char *) *retValue, 6, "---%02u",
6047  val->value.date.day);
6048  }
6049  break;
6050  case XML_SCHEMAS_GMONTHDAY: {
6051  /* TODO: Unclear in XML Schema 1.0 */
6052  /* TODO: What to do with the timezone? */
6053  *retValue = xmlMalloc(8);
6054  if (*retValue == NULL)
6055  return(-1);
6056  snprintf((char *) *retValue, 8, "--%02u-%02u",
6057  val->value.date.mon, val->value.date.day);
6058  }
6059  break;
6060  case XML_SCHEMAS_GYEARMONTH: {
6061  char buf[35];
6062  /* TODO: Unclear in XML Schema 1.0 */
6063  /* TODO: What to do with the timezone? */
6064  if (val->value.date.year < 0)
6065  snprintf(buf, 35, "-%04ld-%02u",
6066  labs(val->value.date.year),
6067  val->value.date.mon);
6068  else
6069  snprintf(buf, 35, "%04ld-%02u",
6070  val->value.date.year, val->value.date.mon);
6071  *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6072  }
6073  break;
6074  case XML_SCHEMAS_TIME:
6075  {
6076  char buf[30];
6077 
6078  if (val->value.date.tz_flag) {
6079  xmlSchemaValPtr norm;
6080 
6081  norm = xmlSchemaDateNormalize(val, 0);
6082  if (norm == NULL)
6083  return (-1);
6084  /*
6085  * TODO: Check if "%.14g" is portable.
6086  */
6087  snprintf(buf, 30,
6088  "%02u:%02u:%02.14gZ",
6089  norm->value.date.hour,
6090  norm->value.date.min,
6091  norm->value.date.sec);
6092  xmlSchemaFreeValue(norm);
6093  } else {
6094  snprintf(buf, 30,
6095  "%02u:%02u:%02.14g",
6096  val->value.date.hour,
6097  val->value.date.min,
6098  val->value.date.sec);
6099  }
6100  *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6101  }
6102  break;
6103  case XML_SCHEMAS_DATE:
6104  {
6105  char buf[30];
6106 
6107  if (val->value.date.tz_flag) {
6108  xmlSchemaValPtr norm;
6109 
6110  norm = xmlSchemaDateNormalize(val, 0);
6111  if (norm == NULL)
6112  return (-1);
6113  /*
6114  * TODO: Append the canonical value of the
6115  * recoverable timezone and not "Z".
6116  */
6117  snprintf(buf, 30,
6118  "%04ld-%02u-%02uZ",
6119  norm->value.date.year, norm->value.date.mon,
6120  norm->value.date.day);
6121  xmlSchemaFreeValue(norm);
6122  } else {
6123  snprintf(buf, 30,
6124  "%04ld-%02u-%02u",
6125  val->value.date.year, val->value.date.mon,
6126  val->value.date.day);
6127  }
6128  *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6129  }
6130  break;
6131  case XML_SCHEMAS_DATETIME:
6132  {