VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/xmlschemastypes.c

最後變更 在這個檔案是 105420,由 vboxsync 提交於 8 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette