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