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