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