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