VirtualBox

source: vbox/trunk/src/libs/libxml2-2.6.30/xmlschemastypes.c@ 25275

Last change on this file since 25275 was 6365, checked in by vboxsync, 16 years ago

Get rid of the sometimes very annoying libxml2 memory debugging output
for debug builds.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use