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