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