ReactOS 0.4.15-dev-7942-gd23573b
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->value.str);
5856 if (*retValue == NULL)
5857 *retValue =
5858 BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5859 break;
5860 case XML_SCHEMAS_QNAME:
5861 /* TODO: Unclear in XML Schema 1.0. */
5862 if (val->value.qname.uri == NULL) {
5863 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5864 return (0);
5865 } else {
5866 *retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5867 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5868 BAD_CAST val->value.qname.uri);
5869 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5870 BAD_CAST "}");
5871 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5872 BAD_CAST val->value.qname.uri);
5873 }
5874 break;
5875 case XML_SCHEMAS_DECIMAL:
5876 /*
5877 * TODO: Lookout for a more simple implementation.
5878 */
5879 if ((val->value.decimal.total == 1) &&
5880 (val->value.decimal.lo == 0)) {
5881 *retValue = xmlStrdup(BAD_CAST "0.0");
5882 } else {
5883 xmlSchemaValDecimal dec = val->value.decimal;
5884 int bufsize;
5885 char *buf = NULL, *offs;
5886
5887 /* Add room for the decimal point as well. */
5888 bufsize = dec.total + 2;
5889 if (dec.sign)
5890 bufsize++;
5891 /* Add room for leading/trailing zero. */
5892 if ((dec.frac == 0) || (dec.frac == dec.total))
5893 bufsize++;
5895 if (buf == NULL)
5896 return(-1);
5897 offs = buf;
5898 if (dec.sign)
5899 *offs++ = '-';
5900 if (dec.frac == dec.total) {
5901 *offs++ = '0';
5902 *offs++ = '.';
5903 }
5904 if (dec.hi != 0)
5905 snprintf(offs, bufsize - (offs - buf),
5906 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5907 else if (dec.mi != 0)
5908 snprintf(offs, bufsize - (offs - buf),
5909 "%lu%lu", dec.mi, dec.lo);
5910 else
5911 snprintf(offs, bufsize - (offs - buf),
5912 "%lu", dec.lo);
5913
5914 if (dec.frac != 0) {
5915 if (dec.frac != dec.total) {
5916 int diff = dec.total - dec.frac;
5917 /*
5918 * Insert the decimal point.
5919 */
5920 memmove(offs + diff + 1, offs + diff, dec.frac +1);
5921 offs[diff] = '.';
5922 } else {
5923 unsigned int i = 0;
5924 /*
5925 * Insert missing zeroes behind the decimal point.
5926 */
5927 while (*(offs + i) != 0)
5928 i++;
5929 if (i < dec.total) {
5930 memmove(offs + (dec.total - i), offs, i +1);
5931 memset(offs, '0', dec.total - i);
5932 }
5933 }
5934 } else {
5935 /*
5936 * Append decimal point and zero.
5937 */
5938 offs = buf + bufsize - 1;
5939 *offs-- = 0;
5940 *offs-- = '0';
5941 *offs-- = '.';
5942 }
5943 *retValue = BAD_CAST buf;
5944 }
5945 break;
5946 case XML_SCHEMAS_INTEGER:
5947 case XML_SCHEMAS_PINTEGER:
5948 case XML_SCHEMAS_NPINTEGER:
5949 case XML_SCHEMAS_NINTEGER:
5950 case XML_SCHEMAS_NNINTEGER:
5951 case XML_SCHEMAS_LONG:
5952 case XML_SCHEMAS_BYTE:
5953 case XML_SCHEMAS_SHORT:
5954 case XML_SCHEMAS_INT:
5955 case XML_SCHEMAS_UINT:
5956 case XML_SCHEMAS_ULONG:
5957 case XML_SCHEMAS_USHORT:
5958 case XML_SCHEMAS_UBYTE:
5959 if ((val->value.decimal.total == 1) &&
5960 (val->value.decimal.lo == 0))
5961 *retValue = xmlStrdup(BAD_CAST "0");
5962 else {
5963 xmlSchemaValDecimal dec = val->value.decimal;
5964 int bufsize = dec.total + 1;
5965
5966 /* Add room for the decimal point as well. */
5967 if (dec.sign)
5968 bufsize++;
5969 *retValue = xmlMalloc(bufsize);
5970 if (*retValue == NULL)
5971 return(-1);
5972 if (dec.hi != 0) {
5973 if (dec.sign)
5974 snprintf((char *) *retValue, bufsize,
5975 "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5976 else
5977 snprintf((char *) *retValue, bufsize,
5978 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5979 } else if (dec.mi != 0) {
5980 if (dec.sign)
5981 snprintf((char *) *retValue, bufsize,
5982 "-%lu%lu", dec.mi, dec.lo);
5983 else
5984 snprintf((char *) *retValue, bufsize,
5985 "%lu%lu", dec.mi, dec.lo);
5986 } else {
5987 if (dec.sign)
5988 snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5989 else
5990 snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5991 }
5992 }
5993 break;
5994 case XML_SCHEMAS_BOOLEAN:
5995 if (val->value.b)
5996 *retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5997 else
5998 *retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5999 break;
6000 case XML_SCHEMAS_DURATION: {
6001 char buf[100];
6002 unsigned long year;
6003 unsigned long mon, day, hour = 0, min = 0;
6004 double sec = 0, left;
6005
6006 /* TODO: Unclear in XML Schema 1.0 */
6007 /*
6008 * TODO: This results in a normalized output of the value
6009 * - which is NOT conformant to the spec -
6010 * since the exact values of each property are not
6011 * recoverable. Think about extending the structure to
6012 * provide a field for every property.
6013 */
6014 year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
6015 mon = labs(val->value.dur.mon) - 12 * year;
6016
6017 day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
6018 left = fabs(val->value.dur.sec) - day * 86400;
6019 if (left > 0) {
6020 hour = (unsigned long) FQUOTIENT(left, 3600);
6021 left = left - (hour * 3600);
6022 if (left > 0) {
6023 min = (unsigned long) FQUOTIENT(left, 60);
6024 sec = left - (min * 60);
6025 }
6026 }
6027 if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
6028 snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
6029 year, mon, day, hour, min, sec);
6030 else
6031 snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
6032 year, mon, day, hour, min, sec);
6033 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6034 }
6035 break;
6036 case XML_SCHEMAS_GYEAR: {
6037 char buf[30];
6038 /* TODO: Unclear in XML Schema 1.0 */
6039 /* TODO: What to do with the timezone? */
6040 snprintf(buf, 30, "%04ld", val->value.date.year);
6041 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6042 }
6043 break;
6044 case XML_SCHEMAS_GMONTH: {
6045 /* TODO: Unclear in XML Schema 1.0 */
6046 /* TODO: What to do with the timezone? */
6047 *retValue = xmlMalloc(6);
6048 if (*retValue == NULL)
6049 return(-1);
6050 snprintf((char *) *retValue, 6, "--%02u",
6051 val->value.date.mon);
6052 }
6053 break;
6054 case XML_SCHEMAS_GDAY: {
6055 /* TODO: Unclear in XML Schema 1.0 */
6056 /* TODO: What to do with the timezone? */
6057 *retValue = xmlMalloc(6);
6058 if (*retValue == NULL)
6059 return(-1);
6060 snprintf((char *) *retValue, 6, "---%02u",
6061 val->value.date.day);
6062 }
6063 break;
6064 case XML_SCHEMAS_GMONTHDAY: {
6065 /* TODO: Unclear in XML Schema 1.0 */
6066 /* TODO: What to do with the timezone? */
6067 *retValue = xmlMalloc(8);
6068 if (*retValue == NULL)
6069 return(-1);
6070 snprintf((char *) *retValue, 8, "--%02u-%02u",
6071 val->value.date.mon, val->value.date.day);
6072 }
6073 break;
6074 case XML_SCHEMAS_GYEARMONTH: {
6075 char buf[35];
6076 /* TODO: Unclear in XML Schema 1.0 */
6077 /* TODO: What to do with the timezone? */
6078 if (val->value.date.year < 0)
6079 snprintf(buf, 35, "-%04ld-%02u",
6080 labs(val->value.date.year),
6081 val->value.date.mon);
6082 else
6083 snprintf(buf, 35, "%04ld-%02u",
6084 val->value.date.year, val->value.date.mon);
6085 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6086 }
6087 break;
6088 case XML_SCHEMAS_TIME:
6089 {
6090 char buf[30];
6091
6092 if (val->value.date.tz_flag) {
6093 xmlSchemaValPtr norm;
6094
6095 norm = xmlSchemaDateNormalize(val, 0);
6096 if (norm == NULL)
6097 return (-1);
6098 /*
6099 * TODO: Check if "%.14g" is portable.
6100 */
6101 snprintf(buf, 30,
6102 "%02u:%02u:%02.14gZ",
6103 norm->value.date.hour,
6104 norm->value.date.min,
6105 norm->value.date.sec);
6106 xmlSchemaFreeValue(norm);
6107 } else {
6108 snprintf(buf, 30,
6109 "%02u:%02u:%02.14g",
6110 val->value.date.hour,
6111 val->value.date.min,
6112 val->value.date.sec);
6113 }
6114 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6115 }
6116 break;
6117 case XML_SCHEMAS_DATE:
6118 {
6119 char buf[30];
6120
6121 if (val->value.date.tz_flag) {
6122 xmlSchemaValPtr norm;
6123
6124 norm = xmlSchemaDateNormalize(val, 0);
6125 if (norm == NULL)
6126 return (-1);
6127 /*
6128 * TODO: Append the canonical value of the
6129 * recoverable timezone and not "Z".
6130 */
6131 snprintf(buf, 30,
6132 "%04ld-%02u-%02uZ",
6133 norm->value.date.year, norm->value.date.mon,
6134 norm->value.date.day);
6135 xmlSchemaFreeValue(norm);
6136 } else {
6137 snprintf(buf, 30,
6138 "%04ld-%02u-%02u",
6139 val->value.date.year, val->value.date.mon,
6140 val->value.date.day);
6141 }
6142 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6143 }
6144 break;
6145 case XML_SCHEMAS_DATETIME:
6146 {
6147 char buf[50];
6148
6149 if (val->value.date.tz_flag) {
6150 xmlSchemaValPtr norm;
6151
6152 norm = xmlSchemaDateNormalize(val, 0);
6153 if (norm == NULL)
6154 return (-1);
6155 /*
6156 * TODO: Check if "%.14g" is portable.
6157 */
6158 snprintf(buf, 50,
6159 "%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
6160 norm->value.date.year, norm->value.date.mon,
6161 norm->value.date.day, norm->value.date.hour,
6162 norm->value.date.min, norm->value.date.sec);
6163 xmlSchemaFreeValue(norm);
6164 } else {
6165 snprintf(buf, 50,
6166 "%04ld-%02u-%02uT%02u:%02u:%02.14g",
6167 val->value.date.year, val->value.date.mon,
6168 val->value.date.day, val->value.date.hour,
6169 val->value.date.min, val->value.date.sec);
6170 }
6171 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6172 }
6173 break;
6174 case XML_SCHEMAS_HEXBINARY:
6175 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6176 break;
6177 case XML_SCHEMAS_BASE64BINARY:
6178 /*
6179 * TODO: Is the following spec piece implemented?:
6180 * SPEC: "Note: For some values the canonical form defined
6181 * above does not conform to [RFC 2045], which requires breaking
6182 * with linefeeds at appropriate intervals."
6183 */
6184 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6185 break;
6186 case XML_SCHEMAS_FLOAT: {
6187 char buf[30];
6188 /*
6189 * |m| < 16777216, -149 <= e <= 104.
6190 * TODO: Handle, NaN, INF, -INF. The format is not
6191 * yet conformant. The c type float does not cover
6192 * the whole range.
6193 */
6194 snprintf(buf, 30, "%01.14e", val->value.f);
6195 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6196 }
6197 break;
6198 case XML_SCHEMAS_DOUBLE: {
6199 char buf[40];
6200 /* |m| < 9007199254740992, -1075 <= e <= 970 */
6201 /*
6202 * TODO: Handle, NaN, INF, -INF. The format is not
6203 * yet conformant. The c type float does not cover
6204 * the whole range.
6205 */
6206 snprintf(buf, 40, "%01.14e", val->value.d);
6207 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6208 }
6209 break;
6210 default:
6211 *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6212 return (1);
6213 }
6214 if (*retValue == NULL)
6215 return(-1);
6216 return (0);
6217}
6218
6231int
6232xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6233 const xmlChar **retValue,
6234 xmlSchemaWhitespaceValueType ws)
6235{
6236 if ((retValue == NULL) || (val == NULL))
6237 return (-1);
6238 if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6239 (ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6240 return (-1);
6241
6242 *retValue = NULL;
6243 switch (val->type) {
6244 case XML_SCHEMAS_STRING:
6245 if (val->value.str == NULL)
6246 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6247 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6248 *retValue = xmlSchemaCollapseString(val->value.str);
6249 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6250 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6251 if ((*retValue) == NULL)
6252 *retValue = BAD_CAST xmlStrdup(val->value.str);
6253 break;
6254 case XML_SCHEMAS_NORMSTRING:
6255 if (val->value.str == NULL)
6256 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6257 else {
6258 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6259 *retValue = xmlSchemaCollapseString(val->value.str);
6260 else
6261 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6262 if ((*retValue) == NULL)
6263 *retValue = BAD_CAST xmlStrdup(val->value.str);
6264 }
6265 break;
6266 default:
6267 return (xmlSchemaGetCanonValue(val, retValue));
6268 }
6269 return (0);
6270}
6271
6280xmlSchemaValType
6281xmlSchemaGetValType(xmlSchemaValPtr val)
6282{
6283 if (val == NULL)
6284 return(XML_SCHEMAS_UNKNOWN);
6285 return (val->type);
6286}
6287
6288#endif /* LIBXML_SCHEMAS_ENABLED */
#define TODO
Definition: SAX2.c:44
static struct recvd_message * sequence
Definition: SystemMenu.c:63
_Tp _STLP_CALL norm(const complex< _Tp > &__z)
Definition: _complex.h:741
ios_base &_STLP_CALL dec(ios_base &__s)
Definition: _ios_base.h:321
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define xmlIsDigit_ch(c)
Definition: chvalid.h:144
#define HOURS_PER_DAY
Definition: cmdUser.c:15
#define NULL
Definition: types.h:112
#define frac(x)
Definition: texture.c:364
static DOUBLE day(DOUBLE time)
Definition: date.c:117
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
@ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
Definition: entities.h:27
#define cval
Definition: fillbytes.c:26
#define local
Definition: zutil.h:30
FxCollectionEntry * cur
size_t total
#define DBL_DIG
Definition: gcc_float.h:57
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLboolean invert
Definition: gl.h:1949
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLboolean GLboolean g
Definition: glext.h:6204
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLuint GLuint num
Definition: glext.h:9618
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
int hex(char ch)
@ extra
Definition: id3.c:95
#define LONG_MAX
Definition: limits.h:43
#define LONG_MIN
Definition: limits.h:42
_Check_return_ long __cdecl labs(_In_ long x)
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define d
Definition: ke_i.h:81
#define f
Definition: ke_i.h:83
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define sign(x)
Definition: mapdesc.cc:613
__u16 date
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
static unsigned int number
Definition: dsound.c:1479
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
static float(__cdecl *square_half_float)(float x
const char * uri
Definition: sec_mgr.c:1588
#define min(a, b)
Definition: monoChain.cc:55
#define IS_BLANK_CH(c)
#define long
Definition: qsort.c:33
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
static calc_node_t temp
Definition: rpn_ieee.c:38
XMLPUBVAR xmlMallocFunc xmlMallocAtomic
Definition: globals.h:249
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
@ XML_ATTRIBUTE_IDREF
Definition: tree.h:209
@ XML_ATTRIBUTE_ENTITIES
Definition: tree.h:212
@ XML_ATTRIBUTE_IDREFS
Definition: tree.h:210
@ XML_ATTRIBUTE_ID
Definition: tree.h:208
@ XML_ATTRIBUTE_ENTITY
Definition: tree.h:211
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
xmlAttr * xmlAttrPtr
Definition: tree.h:433
XMLPUBFUN xmlChar *XMLCALL xmlSplitQName2(const xmlChar *name, xmlChar **prefix)
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:434
xmlEntityType etype
Definition: entities.h:52
Definition: tree.h:457
Definition: tree.h:489
Definition: tree.h:389
Definition: uri.h:33
Definition: cookie.c:202
char * value
Definition: compiler.c:67
Definition: name.c:39
Definition: mxnamespace.c:45
Definition: dlist.c:348
Definition: pdh_main.c:94
XMLPUBFUN xmlURIPtr XMLCALL xmlParseURI(const char *str)
Definition: uri.c:940
XMLPUBFUN void XMLCALL xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1387
XMLPUBFUN xmlIDPtr XMLCALL xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2672
XML_DEPRECATED XMLPUBFUN xmlRefPtr XMLCALL xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:3003
int ret
static MONITORINFO mi
Definition: win.c:7338
#define snprintf
Definition: wintirpc.h:48
@ XML_FROM_DATATYPE
Definition: xmlerror.h:52
@ XML_SCHEMAV_CVC_MININCLUSIVE_VALID
Definition: xmlerror.h:632
@ XML_SCHEMAV_CVC_MINLENGTH_VALID
Definition: xmlerror.h:630
@ XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID
Definition: xmlerror.h:635
@ XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID
Definition: xmlerror.h:637
@ XML_SCHEMAV_CVC_LENGTH_VALID
Definition: xmlerror.h:629
@ XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID
Definition: xmlerror.h:633
@ XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID
Definition: xmlerror.h:634
@ XML_SCHEMAV_CVC_TOTALDIGITS_VALID
Definition: xmlerror.h:636
@ XML_SCHEMAV_CVC_ENUMERATION_VALID
Definition: xmlerror.h:639
@ XML_SCHEMAV_CVC_MAXLENGTH_VALID
Definition: xmlerror.h:631
@ XML_SCHEMAV_CVC_PATTERN_VALID
Definition: xmlerror.h:638
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
XMLPUBFUN int XMLCALL xmlUTF8Strlen(const xmlChar *utf)
Definition: xmlstring.c:664
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrcmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:133
unsigned char xmlChar
Definition: xmlstring.h:28