Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenxmlschemastypes.c
Go to the documentation of this file.
00001 /* 00002 * schemastypes.c : implementation of the XML Schema Datatypes 00003 * definition and validity checking 00004 * 00005 * See Copyright for the status of this software. 00006 * 00007 * Daniel Veillard <veillard@redhat.com> 00008 */ 00009 00010 #define IN_LIBXML 00011 #include "libxml.h" 00012 00013 #ifdef LIBXML_SCHEMAS_ENABLED 00014 00015 #include <string.h> 00016 #include <libxml/xmlmemory.h> 00017 #include <libxml/parser.h> 00018 #include <libxml/parserInternals.h> 00019 #include <libxml/hash.h> 00020 #include <libxml/valid.h> 00021 #include <libxml/xpath.h> 00022 #include <libxml/uri.h> 00023 00024 #include <libxml/xmlschemas.h> 00025 #include <libxml/schemasInternals.h> 00026 #include <libxml/xmlschemastypes.h> 00027 00028 #ifdef HAVE_MATH_H 00029 #include <math.h> 00030 #endif 00031 #ifdef HAVE_FLOAT_H 00032 #include <float.h> 00033 #endif 00034 00035 #define DEBUG 00036 00037 #ifndef LIBXML_XPATH_ENABLED 00038 extern double xmlXPathNAN; 00039 extern double xmlXPathPINF; 00040 extern double xmlXPathNINF; 00041 #endif 00042 00043 #define TODO \ 00044 xmlGenericError(xmlGenericErrorContext, \ 00045 "Unimplemented block at %s:%d\n", \ 00046 __FILE__, __LINE__); 00047 00048 #define XML_SCHEMAS_NAMESPACE_NAME \ 00049 (const xmlChar *)"http://www.w3.org/2001/XMLSchema" 00050 00051 #define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \ 00052 ((c) == 0xd)) 00053 00054 #define IS_WSP_SPACE_CH(c) ((c) == 0x20) 00055 00056 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c) 00057 00058 /* Date value */ 00059 typedef struct _xmlSchemaValDate xmlSchemaValDate; 00060 typedef xmlSchemaValDate *xmlSchemaValDatePtr; 00061 struct _xmlSchemaValDate { 00062 long year; 00063 unsigned int mon :4; /* 1 <= mon <= 12 */ 00064 unsigned int day :5; /* 1 <= day <= 31 */ 00065 unsigned int hour :5; /* 0 <= hour <= 23 */ 00066 unsigned int min :6; /* 0 <= min <= 59 */ 00067 double sec; 00068 unsigned int tz_flag :1; /* is tzo explicitely set? */ 00069 signed int tzo :12; /* -1440 <= tzo <= 1440; 00070 currently only -840 to +840 are needed */ 00071 }; 00072 00073 /* Duration value */ 00074 typedef struct _xmlSchemaValDuration xmlSchemaValDuration; 00075 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr; 00076 struct _xmlSchemaValDuration { 00077 long mon; /* mon stores years also */ 00078 long day; 00079 double sec; /* sec stores min and hour also */ 00080 }; 00081 00082 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; 00083 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; 00084 struct _xmlSchemaValDecimal { 00085 /* would use long long but not portable */ 00086 unsigned long lo; 00087 unsigned long mi; 00088 unsigned long hi; 00089 unsigned int extra; 00090 unsigned int sign:1; 00091 unsigned int frac:7; 00092 unsigned int total:8; 00093 }; 00094 00095 typedef struct _xmlSchemaValQName xmlSchemaValQName; 00096 typedef xmlSchemaValQName *xmlSchemaValQNamePtr; 00097 struct _xmlSchemaValQName { 00098 xmlChar *name; 00099 xmlChar *uri; 00100 }; 00101 00102 typedef struct _xmlSchemaValHex xmlSchemaValHex; 00103 typedef xmlSchemaValHex *xmlSchemaValHexPtr; 00104 struct _xmlSchemaValHex { 00105 xmlChar *str; 00106 unsigned int total; 00107 }; 00108 00109 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64; 00110 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr; 00111 struct _xmlSchemaValBase64 { 00112 xmlChar *str; 00113 unsigned int total; 00114 }; 00115 00116 struct _xmlSchemaVal { 00117 xmlSchemaValType type; 00118 struct _xmlSchemaVal *next; 00119 union { 00120 xmlSchemaValDecimal decimal; 00121 xmlSchemaValDate date; 00122 xmlSchemaValDuration dur; 00123 xmlSchemaValQName qname; 00124 xmlSchemaValHex hex; 00125 xmlSchemaValBase64 base64; 00126 float f; 00127 double d; 00128 int b; 00129 xmlChar *str; 00130 } value; 00131 }; 00132 00133 static int xmlSchemaTypesInitialized = 0; 00134 static xmlHashTablePtr xmlSchemaTypesBank = NULL; 00135 00136 /* 00137 * Basic types 00138 */ 00139 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL; 00140 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL; 00141 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL; 00142 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL; 00143 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL; 00144 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL; 00145 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL; 00146 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL; 00147 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL; 00148 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL; 00149 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL; 00150 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL; 00151 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL; 00152 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL; 00153 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL; 00154 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL; 00155 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL; 00156 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL; 00157 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL; 00158 00159 /* 00160 * Derived types 00161 */ 00162 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL; 00163 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL; 00164 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL; 00165 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL; 00166 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL; 00167 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL; 00168 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL; 00169 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL; 00170 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL; 00171 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL; 00172 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL; 00173 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL; 00174 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL; 00175 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL; 00176 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL; 00177 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL; 00178 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL; 00179 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL; 00180 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL; 00181 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL; 00182 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL; 00183 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL; 00184 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL; 00185 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL; 00186 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL; 00187 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL; 00188 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL; 00189 00190 /************************************************************************ 00191 * * 00192 * Datatype error handlers * 00193 * * 00194 ************************************************************************/ 00201 static void 00202 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra) 00203 { 00204 __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra); 00205 } 00206 00207 /************************************************************************ 00208 * * 00209 * Base types support * 00210 * * 00211 ************************************************************************/ 00212 00221 static xmlSchemaValPtr 00222 xmlSchemaNewValue(xmlSchemaValType type) { 00223 xmlSchemaValPtr value; 00224 00225 value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); 00226 if (value == NULL) { 00227 return(NULL); 00228 } 00229 memset(value, 0, sizeof(xmlSchemaVal)); 00230 value->type = type; 00231 return(value); 00232 } 00233 00234 static xmlSchemaFacetPtr 00235 xmlSchemaNewMinLengthFacet(int value) 00236 { 00237 xmlSchemaFacetPtr ret; 00238 00239 ret = xmlSchemaNewFacet(); 00240 if (ret == NULL) { 00241 return(NULL); 00242 } 00243 ret->type = XML_SCHEMA_FACET_MINLENGTH; 00244 ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER); 00245 ret->val->value.decimal.lo = value; 00246 return (ret); 00247 } 00248 00249 /* 00250 * xmlSchemaInitBasicType: 00251 * @name: the type name 00252 * @type: the value type associated 00253 * 00254 * Initialize one primitive built-in type 00255 */ 00256 static xmlSchemaTypePtr 00257 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, 00258 xmlSchemaTypePtr baseType) { 00259 xmlSchemaTypePtr ret; 00260 00261 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); 00262 if (ret == NULL) { 00263 xmlSchemaTypeErrMemory(NULL, "could not initialize basic types"); 00264 return(NULL); 00265 } 00266 memset(ret, 0, sizeof(xmlSchemaType)); 00267 ret->name = (const xmlChar *)name; 00268 ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME; 00269 ret->type = XML_SCHEMA_TYPE_BASIC; 00270 ret->baseType = baseType; 00271 ret->contentType = XML_SCHEMA_CONTENT_BASIC; 00272 /* 00273 * Primitive types. 00274 */ 00275 switch (type) { 00276 case XML_SCHEMAS_STRING: 00277 case XML_SCHEMAS_DECIMAL: 00278 case XML_SCHEMAS_DATE: 00279 case XML_SCHEMAS_DATETIME: 00280 case XML_SCHEMAS_TIME: 00281 case XML_SCHEMAS_GYEAR: 00282 case XML_SCHEMAS_GYEARMONTH: 00283 case XML_SCHEMAS_GMONTH: 00284 case XML_SCHEMAS_GMONTHDAY: 00285 case XML_SCHEMAS_GDAY: 00286 case XML_SCHEMAS_DURATION: 00287 case XML_SCHEMAS_FLOAT: 00288 case XML_SCHEMAS_DOUBLE: 00289 case XML_SCHEMAS_BOOLEAN: 00290 case XML_SCHEMAS_ANYURI: 00291 case XML_SCHEMAS_HEXBINARY: 00292 case XML_SCHEMAS_BASE64BINARY: 00293 case XML_SCHEMAS_QNAME: 00294 case XML_SCHEMAS_NOTATION: 00295 ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE; 00296 break; 00297 default: 00298 break; 00299 } 00300 /* 00301 * Set variety. 00302 */ 00303 switch (type) { 00304 case XML_SCHEMAS_ANYTYPE: 00305 case XML_SCHEMAS_ANYSIMPLETYPE: 00306 break; 00307 case XML_SCHEMAS_IDREFS: 00308 case XML_SCHEMAS_NMTOKENS: 00309 case XML_SCHEMAS_ENTITIES: 00310 ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; 00311 ret->facets = xmlSchemaNewMinLengthFacet(1); 00312 ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; 00313 break; 00314 default: 00315 ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; 00316 break; 00317 } 00318 xmlHashAddEntry2(xmlSchemaTypesBank, ret->name, 00319 XML_SCHEMAS_NAMESPACE_NAME, ret); 00320 ret->builtInType = type; 00321 return(ret); 00322 } 00323 00324 /* 00325 * WARNING: Those type reside normally in xmlschemas.c but are 00326 * redefined here locally in oder of being able to use them for xs:anyType- 00327 * TODO: Remove those definition if we move the types to a header file. 00328 * TODO: Always keep those structs up-to-date with the originals. 00329 */ 00330 #define UNBOUNDED (1 << 30) 00331 00332 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; 00333 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; 00334 struct _xmlSchemaTreeItem { 00335 xmlSchemaTypeType type; 00336 xmlSchemaAnnotPtr annot; 00337 xmlSchemaTreeItemPtr next; 00338 xmlSchemaTreeItemPtr children; 00339 }; 00340 00341 typedef struct _xmlSchemaParticle xmlSchemaParticle; 00342 typedef xmlSchemaParticle *xmlSchemaParticlePtr; 00343 struct _xmlSchemaParticle { 00344 xmlSchemaTypeType type; 00345 xmlSchemaAnnotPtr annot; 00346 xmlSchemaTreeItemPtr next; 00347 xmlSchemaTreeItemPtr children; 00348 int minOccurs; 00349 int maxOccurs; 00350 xmlNodePtr node; 00351 }; 00352 00353 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; 00354 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; 00355 struct _xmlSchemaModelGroup { 00356 xmlSchemaTypeType type; 00357 xmlSchemaAnnotPtr annot; 00358 xmlSchemaTreeItemPtr next; 00359 xmlSchemaTreeItemPtr children; 00360 xmlNodePtr node; 00361 }; 00362 00363 static xmlSchemaParticlePtr 00364 xmlSchemaAddParticle(void) 00365 { 00366 xmlSchemaParticlePtr ret = NULL; 00367 00368 ret = (xmlSchemaParticlePtr) 00369 xmlMalloc(sizeof(xmlSchemaParticle)); 00370 if (ret == NULL) { 00371 xmlSchemaTypeErrMemory(NULL, "allocating particle component"); 00372 return (NULL); 00373 } 00374 memset(ret, 0, sizeof(xmlSchemaParticle)); 00375 ret->type = XML_SCHEMA_TYPE_PARTICLE; 00376 ret->minOccurs = 1; 00377 ret->maxOccurs = 1; 00378 return (ret); 00379 } 00380 00381 /* 00382 * xmlSchemaInitTypes: 00383 * 00384 * Initialize the default XML Schemas type library 00385 */ 00386 void 00387 xmlSchemaInitTypes(void) 00388 { 00389 if (xmlSchemaTypesInitialized != 0) 00390 return; 00391 xmlSchemaTypesBank = xmlHashCreate(40); 00392 00393 00394 /* 00395 * 3.4.7 Built-in Complex Type Definition 00396 */ 00397 xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType", 00398 XML_SCHEMAS_ANYTYPE, 00399 NULL); 00400 xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef; 00401 xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; 00402 /* 00403 * Init the content type. 00404 */ 00405 xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; 00406 { 00407 xmlSchemaParticlePtr particle; 00408 xmlSchemaModelGroupPtr sequence; 00409 xmlSchemaWildcardPtr wild; 00410 /* First particle. */ 00411 particle = xmlSchemaAddParticle(); 00412 if (particle == NULL) 00413 return; 00414 xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle; 00415 /* Sequence model group. */ 00416 sequence = (xmlSchemaModelGroupPtr) 00417 xmlMalloc(sizeof(xmlSchemaModelGroup)); 00418 if (sequence == NULL) { 00419 xmlSchemaTypeErrMemory(NULL, "allocating model group component"); 00420 return; 00421 } 00422 memset(sequence, 0, sizeof(xmlSchemaModelGroup)); 00423 sequence->type = XML_SCHEMA_TYPE_SEQUENCE; 00424 particle->children = (xmlSchemaTreeItemPtr) sequence; 00425 /* Second particle. */ 00426 particle = xmlSchemaAddParticle(); 00427 if (particle == NULL) 00428 return; 00429 particle->minOccurs = 0; 00430 particle->maxOccurs = UNBOUNDED; 00431 sequence->children = (xmlSchemaTreeItemPtr) particle; 00432 /* The wildcard */ 00433 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); 00434 if (wild == NULL) { 00435 xmlSchemaTypeErrMemory(NULL, "allocating wildcard component"); 00436 return; 00437 } 00438 memset(wild, 0, sizeof(xmlSchemaWildcard)); 00439 wild->type = XML_SCHEMA_TYPE_ANY; 00440 wild->any = 1; 00441 wild->processContents = XML_SCHEMAS_ANY_LAX; 00442 particle->children = (xmlSchemaTreeItemPtr) wild; 00443 /* 00444 * Create the attribute wildcard. 00445 */ 00446 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); 00447 if (wild == NULL) { 00448 xmlSchemaTypeErrMemory(NULL, "could not create an attribute " 00449 "wildcard on anyType"); 00450 return; 00451 } 00452 memset(wild, 0, sizeof(xmlSchemaWildcard)); 00453 wild->any = 1; 00454 wild->processContents = XML_SCHEMAS_ANY_LAX; 00455 xmlSchemaTypeAnyTypeDef->attributeWildcard = wild; 00456 } 00457 xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType", 00458 XML_SCHEMAS_ANYSIMPLETYPE, 00459 xmlSchemaTypeAnyTypeDef); 00460 /* 00461 * primitive datatypes 00462 */ 00463 xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string", 00464 XML_SCHEMAS_STRING, 00465 xmlSchemaTypeAnySimpleTypeDef); 00466 xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal", 00467 XML_SCHEMAS_DECIMAL, 00468 xmlSchemaTypeAnySimpleTypeDef); 00469 xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date", 00470 XML_SCHEMAS_DATE, 00471 xmlSchemaTypeAnySimpleTypeDef); 00472 xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime", 00473 XML_SCHEMAS_DATETIME, 00474 xmlSchemaTypeAnySimpleTypeDef); 00475 xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time", 00476 XML_SCHEMAS_TIME, 00477 xmlSchemaTypeAnySimpleTypeDef); 00478 xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear", 00479 XML_SCHEMAS_GYEAR, 00480 xmlSchemaTypeAnySimpleTypeDef); 00481 xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth", 00482 XML_SCHEMAS_GYEARMONTH, 00483 xmlSchemaTypeAnySimpleTypeDef); 00484 xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth", 00485 XML_SCHEMAS_GMONTH, 00486 xmlSchemaTypeAnySimpleTypeDef); 00487 xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay", 00488 XML_SCHEMAS_GMONTHDAY, 00489 xmlSchemaTypeAnySimpleTypeDef); 00490 xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay", 00491 XML_SCHEMAS_GDAY, 00492 xmlSchemaTypeAnySimpleTypeDef); 00493 xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration", 00494 XML_SCHEMAS_DURATION, 00495 xmlSchemaTypeAnySimpleTypeDef); 00496 xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float", 00497 XML_SCHEMAS_FLOAT, 00498 xmlSchemaTypeAnySimpleTypeDef); 00499 xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double", 00500 XML_SCHEMAS_DOUBLE, 00501 xmlSchemaTypeAnySimpleTypeDef); 00502 xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean", 00503 XML_SCHEMAS_BOOLEAN, 00504 xmlSchemaTypeAnySimpleTypeDef); 00505 xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI", 00506 XML_SCHEMAS_ANYURI, 00507 xmlSchemaTypeAnySimpleTypeDef); 00508 xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary", 00509 XML_SCHEMAS_HEXBINARY, 00510 xmlSchemaTypeAnySimpleTypeDef); 00511 xmlSchemaTypeBase64BinaryDef 00512 = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY, 00513 xmlSchemaTypeAnySimpleTypeDef); 00514 xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION", 00515 XML_SCHEMAS_NOTATION, 00516 xmlSchemaTypeAnySimpleTypeDef); 00517 xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName", 00518 XML_SCHEMAS_QNAME, 00519 xmlSchemaTypeAnySimpleTypeDef); 00520 00521 /* 00522 * derived datatypes 00523 */ 00524 xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer", 00525 XML_SCHEMAS_INTEGER, 00526 xmlSchemaTypeDecimalDef); 00527 xmlSchemaTypeNonPositiveIntegerDef = 00528 xmlSchemaInitBasicType("nonPositiveInteger", 00529 XML_SCHEMAS_NPINTEGER, 00530 xmlSchemaTypeIntegerDef); 00531 xmlSchemaTypeNegativeIntegerDef = 00532 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER, 00533 xmlSchemaTypeNonPositiveIntegerDef); 00534 xmlSchemaTypeLongDef = 00535 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG, 00536 xmlSchemaTypeIntegerDef); 00537 xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT, 00538 xmlSchemaTypeLongDef); 00539 xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short", 00540 XML_SCHEMAS_SHORT, 00541 xmlSchemaTypeIntDef); 00542 xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte", 00543 XML_SCHEMAS_BYTE, 00544 xmlSchemaTypeShortDef); 00545 xmlSchemaTypeNonNegativeIntegerDef = 00546 xmlSchemaInitBasicType("nonNegativeInteger", 00547 XML_SCHEMAS_NNINTEGER, 00548 xmlSchemaTypeIntegerDef); 00549 xmlSchemaTypeUnsignedLongDef = 00550 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG, 00551 xmlSchemaTypeNonNegativeIntegerDef); 00552 xmlSchemaTypeUnsignedIntDef = 00553 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT, 00554 xmlSchemaTypeUnsignedLongDef); 00555 xmlSchemaTypeUnsignedShortDef = 00556 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT, 00557 xmlSchemaTypeUnsignedIntDef); 00558 xmlSchemaTypeUnsignedByteDef = 00559 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE, 00560 xmlSchemaTypeUnsignedShortDef); 00561 xmlSchemaTypePositiveIntegerDef = 00562 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER, 00563 xmlSchemaTypeNonNegativeIntegerDef); 00564 xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString", 00565 XML_SCHEMAS_NORMSTRING, 00566 xmlSchemaTypeStringDef); 00567 xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token", 00568 XML_SCHEMAS_TOKEN, 00569 xmlSchemaTypeNormStringDef); 00570 xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language", 00571 XML_SCHEMAS_LANGUAGE, 00572 xmlSchemaTypeTokenDef); 00573 xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name", 00574 XML_SCHEMAS_NAME, 00575 xmlSchemaTypeTokenDef); 00576 xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN", 00577 XML_SCHEMAS_NMTOKEN, 00578 xmlSchemaTypeTokenDef); 00579 xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName", 00580 XML_SCHEMAS_NCNAME, 00581 xmlSchemaTypeNameDef); 00582 xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID, 00583 xmlSchemaTypeNCNameDef); 00584 xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF", 00585 XML_SCHEMAS_IDREF, 00586 xmlSchemaTypeNCNameDef); 00587 xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY", 00588 XML_SCHEMAS_ENTITY, 00589 xmlSchemaTypeNCNameDef); 00590 /* 00591 * Derived list types. 00592 */ 00593 /* ENTITIES */ 00594 xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES", 00595 XML_SCHEMAS_ENTITIES, 00596 xmlSchemaTypeAnySimpleTypeDef); 00597 xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef; 00598 /* IDREFS */ 00599 xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS", 00600 XML_SCHEMAS_IDREFS, 00601 xmlSchemaTypeAnySimpleTypeDef); 00602 xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef; 00603 00604 /* NMTOKENS */ 00605 xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS", 00606 XML_SCHEMAS_NMTOKENS, 00607 xmlSchemaTypeAnySimpleTypeDef); 00608 xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef; 00609 00610 xmlSchemaTypesInitialized = 1; 00611 } 00612 00618 void 00619 xmlSchemaCleanupTypes(void) { 00620 if (xmlSchemaTypesInitialized == 0) 00621 return; 00622 /* 00623 * Free xs:anyType. 00624 */ 00625 { 00626 xmlSchemaParticlePtr particle; 00627 /* Attribute wildcard. */ 00628 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard); 00629 /* Content type. */ 00630 particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes; 00631 /* Wildcard. */ 00632 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) 00633 particle->children->children->children); 00634 xmlFree((xmlSchemaParticlePtr) particle->children->children); 00635 /* Sequence model group. */ 00636 xmlFree((xmlSchemaModelGroupPtr) particle->children); 00637 xmlFree((xmlSchemaParticlePtr) particle); 00638 xmlSchemaTypeAnyTypeDef->subtypes = NULL; 00639 } 00640 xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType); 00641 xmlSchemaTypesInitialized = 0; 00642 } 00643 00655 int 00656 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType) 00657 { 00658 if (type == NULL) 00659 return (-1); 00660 if (type->type != XML_SCHEMA_TYPE_BASIC) 00661 return (-1); 00662 switch (type->builtInType) { 00663 case XML_SCHEMAS_BOOLEAN: 00664 if ((facetType == XML_SCHEMA_FACET_PATTERN) || 00665 (facetType == XML_SCHEMA_FACET_WHITESPACE)) 00666 return (1); 00667 else 00668 return (0); 00669 case XML_SCHEMAS_STRING: 00670 case XML_SCHEMAS_NOTATION: 00671 case XML_SCHEMAS_QNAME: 00672 case XML_SCHEMAS_ANYURI: 00673 case XML_SCHEMAS_BASE64BINARY: 00674 case XML_SCHEMAS_HEXBINARY: 00675 if ((facetType == XML_SCHEMA_FACET_LENGTH) || 00676 (facetType == XML_SCHEMA_FACET_MINLENGTH) || 00677 (facetType == XML_SCHEMA_FACET_MAXLENGTH) || 00678 (facetType == XML_SCHEMA_FACET_PATTERN) || 00679 (facetType == XML_SCHEMA_FACET_ENUMERATION) || 00680 (facetType == XML_SCHEMA_FACET_WHITESPACE)) 00681 return (1); 00682 else 00683 return (0); 00684 case XML_SCHEMAS_DECIMAL: 00685 if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) || 00686 (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) || 00687 (facetType == XML_SCHEMA_FACET_PATTERN) || 00688 (facetType == XML_SCHEMA_FACET_WHITESPACE) || 00689 (facetType == XML_SCHEMA_FACET_ENUMERATION) || 00690 (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || 00691 (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || 00692 (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || 00693 (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) 00694 return (1); 00695 else 00696 return (0); 00697 case XML_SCHEMAS_TIME: 00698 case XML_SCHEMAS_GDAY: 00699 case XML_SCHEMAS_GMONTH: 00700 case XML_SCHEMAS_GMONTHDAY: 00701 case XML_SCHEMAS_GYEAR: 00702 case XML_SCHEMAS_GYEARMONTH: 00703 case XML_SCHEMAS_DATE: 00704 case XML_SCHEMAS_DATETIME: 00705 case XML_SCHEMAS_DURATION: 00706 case XML_SCHEMAS_FLOAT: 00707 case XML_SCHEMAS_DOUBLE: 00708 if ((facetType == XML_SCHEMA_FACET_PATTERN) || 00709 (facetType == XML_SCHEMA_FACET_ENUMERATION) || 00710 (facetType == XML_SCHEMA_FACET_WHITESPACE) || 00711 (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || 00712 (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || 00713 (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || 00714 (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) 00715 return (1); 00716 else 00717 return (0); 00718 default: 00719 break; 00720 } 00721 return (0); 00722 } 00723 00733 xmlSchemaTypePtr 00734 xmlSchemaGetBuiltInType(xmlSchemaValType type) 00735 { 00736 if (xmlSchemaTypesInitialized == 0) 00737 xmlSchemaInitTypes(); 00738 switch (type) { 00739 00740 case XML_SCHEMAS_ANYSIMPLETYPE: 00741 return (xmlSchemaTypeAnySimpleTypeDef); 00742 case XML_SCHEMAS_STRING: 00743 return (xmlSchemaTypeStringDef); 00744 case XML_SCHEMAS_NORMSTRING: 00745 return (xmlSchemaTypeNormStringDef); 00746 case XML_SCHEMAS_DECIMAL: 00747 return (xmlSchemaTypeDecimalDef); 00748 case XML_SCHEMAS_TIME: 00749 return (xmlSchemaTypeTimeDef); 00750 case XML_SCHEMAS_GDAY: 00751 return (xmlSchemaTypeGDayDef); 00752 case XML_SCHEMAS_GMONTH: 00753 return (xmlSchemaTypeGMonthDef); 00754 case XML_SCHEMAS_GMONTHDAY: 00755 return (xmlSchemaTypeGMonthDayDef); 00756 case XML_SCHEMAS_GYEAR: 00757 return (xmlSchemaTypeGYearDef); 00758 case XML_SCHEMAS_GYEARMONTH: 00759 return (xmlSchemaTypeGYearMonthDef); 00760 case XML_SCHEMAS_DATE: 00761 return (xmlSchemaTypeDateDef); 00762 case XML_SCHEMAS_DATETIME: 00763 return (xmlSchemaTypeDatetimeDef); 00764 case XML_SCHEMAS_DURATION: 00765 return (xmlSchemaTypeDurationDef); 00766 case XML_SCHEMAS_FLOAT: 00767 return (xmlSchemaTypeFloatDef); 00768 case XML_SCHEMAS_DOUBLE: 00769 return (xmlSchemaTypeDoubleDef); 00770 case XML_SCHEMAS_BOOLEAN: 00771 return (xmlSchemaTypeBooleanDef); 00772 case XML_SCHEMAS_TOKEN: 00773 return (xmlSchemaTypeTokenDef); 00774 case XML_SCHEMAS_LANGUAGE: 00775 return (xmlSchemaTypeLanguageDef); 00776 case XML_SCHEMAS_NMTOKEN: 00777 return (xmlSchemaTypeNmtokenDef); 00778 case XML_SCHEMAS_NMTOKENS: 00779 return (xmlSchemaTypeNmtokensDef); 00780 case XML_SCHEMAS_NAME: 00781 return (xmlSchemaTypeNameDef); 00782 case XML_SCHEMAS_QNAME: 00783 return (xmlSchemaTypeQNameDef); 00784 case XML_SCHEMAS_NCNAME: 00785 return (xmlSchemaTypeNCNameDef); 00786 case XML_SCHEMAS_ID: 00787 return (xmlSchemaTypeIdDef); 00788 case XML_SCHEMAS_IDREF: 00789 return (xmlSchemaTypeIdrefDef); 00790 case XML_SCHEMAS_IDREFS: 00791 return (xmlSchemaTypeIdrefsDef); 00792 case XML_SCHEMAS_ENTITY: 00793 return (xmlSchemaTypeEntityDef); 00794 case XML_SCHEMAS_ENTITIES: 00795 return (xmlSchemaTypeEntitiesDef); 00796 case XML_SCHEMAS_NOTATION: 00797 return (xmlSchemaTypeNotationDef); 00798 case XML_SCHEMAS_ANYURI: 00799 return (xmlSchemaTypeAnyURIDef); 00800 case XML_SCHEMAS_INTEGER: 00801 return (xmlSchemaTypeIntegerDef); 00802 case XML_SCHEMAS_NPINTEGER: 00803 return (xmlSchemaTypeNonPositiveIntegerDef); 00804 case XML_SCHEMAS_NINTEGER: 00805 return (xmlSchemaTypeNegativeIntegerDef); 00806 case XML_SCHEMAS_NNINTEGER: 00807 return (xmlSchemaTypeNonNegativeIntegerDef); 00808 case XML_SCHEMAS_PINTEGER: 00809 return (xmlSchemaTypePositiveIntegerDef); 00810 case XML_SCHEMAS_INT: 00811 return (xmlSchemaTypeIntDef); 00812 case XML_SCHEMAS_UINT: 00813 return (xmlSchemaTypeUnsignedIntDef); 00814 case XML_SCHEMAS_LONG: 00815 return (xmlSchemaTypeLongDef); 00816 case XML_SCHEMAS_ULONG: 00817 return (xmlSchemaTypeUnsignedLongDef); 00818 case XML_SCHEMAS_SHORT: 00819 return (xmlSchemaTypeShortDef); 00820 case XML_SCHEMAS_USHORT: 00821 return (xmlSchemaTypeUnsignedShortDef); 00822 case XML_SCHEMAS_BYTE: 00823 return (xmlSchemaTypeByteDef); 00824 case XML_SCHEMAS_UBYTE: 00825 return (xmlSchemaTypeUnsignedByteDef); 00826 case XML_SCHEMAS_HEXBINARY: 00827 return (xmlSchemaTypeHexBinaryDef); 00828 case XML_SCHEMAS_BASE64BINARY: 00829 return (xmlSchemaTypeBase64BinaryDef); 00830 case XML_SCHEMAS_ANYTYPE: 00831 return (xmlSchemaTypeAnyTypeDef); 00832 default: 00833 return (NULL); 00834 } 00835 } 00836 00846 int 00847 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) { 00848 00849 if ((prev == NULL) || (cur == NULL)) 00850 return (-1); 00851 prev->next = cur; 00852 return (0); 00853 } 00854 00864 xmlSchemaValPtr 00865 xmlSchemaValueGetNext(xmlSchemaValPtr cur) { 00866 00867 if (cur == NULL) 00868 return (NULL); 00869 return (cur->next); 00870 } 00871 00881 const xmlChar * 00882 xmlSchemaValueGetAsString(xmlSchemaValPtr val) 00883 { 00884 if (val == NULL) 00885 return (NULL); 00886 switch (val->type) { 00887 case XML_SCHEMAS_STRING: 00888 case XML_SCHEMAS_NORMSTRING: 00889 case XML_SCHEMAS_ANYSIMPLETYPE: 00890 case XML_SCHEMAS_TOKEN: 00891 case XML_SCHEMAS_LANGUAGE: 00892 case XML_SCHEMAS_NMTOKEN: 00893 case XML_SCHEMAS_NAME: 00894 case XML_SCHEMAS_NCNAME: 00895 case XML_SCHEMAS_ID: 00896 case XML_SCHEMAS_IDREF: 00897 case XML_SCHEMAS_ENTITY: 00898 case XML_SCHEMAS_ANYURI: 00899 return (BAD_CAST val->value.str); 00900 default: 00901 break; 00902 } 00903 return (NULL); 00904 } 00905 00914 int 00915 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val) 00916 { 00917 if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN)) 00918 return (0); 00919 return (val->value.b); 00920 } 00921 00935 xmlSchemaValPtr 00936 xmlSchemaNewStringValue(xmlSchemaValType type, 00937 const xmlChar *value) 00938 { 00939 xmlSchemaValPtr val; 00940 00941 if (type != XML_SCHEMAS_STRING) 00942 return(NULL); 00943 val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); 00944 if (val == NULL) { 00945 return(NULL); 00946 } 00947 memset(val, 0, sizeof(xmlSchemaVal)); 00948 val->type = type; 00949 val->value.str = (xmlChar *) value; 00950 return(val); 00951 } 00952 00963 xmlSchemaValPtr 00964 xmlSchemaNewNOTATIONValue(const xmlChar *name, 00965 const xmlChar *ns) 00966 { 00967 xmlSchemaValPtr val; 00968 00969 val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); 00970 if (val == NULL) 00971 return (NULL); 00972 00973 val->value.qname.name = (xmlChar *)name; 00974 if (ns != NULL) 00975 val->value.qname.uri = (xmlChar *)ns; 00976 return(val); 00977 } 00978 00989 xmlSchemaValPtr 00990 xmlSchemaNewQNameValue(const xmlChar *namespaceName, 00991 const xmlChar *localName) 00992 { 00993 xmlSchemaValPtr val; 00994 00995 val = xmlSchemaNewValue(XML_SCHEMAS_QNAME); 00996 if (val == NULL) 00997 return (NULL); 00998 00999 val->value.qname.name = (xmlChar *) localName; 01000 val->value.qname.uri = (xmlChar *) namespaceName; 01001 return(val); 01002 } 01003 01010 void 01011 xmlSchemaFreeValue(xmlSchemaValPtr value) { 01012 xmlSchemaValPtr prev; 01013 01014 while (value != NULL) { 01015 switch (value->type) { 01016 case XML_SCHEMAS_STRING: 01017 case XML_SCHEMAS_NORMSTRING: 01018 case XML_SCHEMAS_TOKEN: 01019 case XML_SCHEMAS_LANGUAGE: 01020 case XML_SCHEMAS_NMTOKEN: 01021 case XML_SCHEMAS_NMTOKENS: 01022 case XML_SCHEMAS_NAME: 01023 case XML_SCHEMAS_NCNAME: 01024 case XML_SCHEMAS_ID: 01025 case XML_SCHEMAS_IDREF: 01026 case XML_SCHEMAS_IDREFS: 01027 case XML_SCHEMAS_ENTITY: 01028 case XML_SCHEMAS_ENTITIES: 01029 case XML_SCHEMAS_ANYURI: 01030 case XML_SCHEMAS_ANYSIMPLETYPE: 01031 if (value->value.str != NULL) 01032 xmlFree(value->value.str); 01033 break; 01034 case XML_SCHEMAS_NOTATION: 01035 case XML_SCHEMAS_QNAME: 01036 if (value->value.qname.uri != NULL) 01037 xmlFree(value->value.qname.uri); 01038 if (value->value.qname.name != NULL) 01039 xmlFree(value->value.qname.name); 01040 break; 01041 case XML_SCHEMAS_HEXBINARY: 01042 if (value->value.hex.str != NULL) 01043 xmlFree(value->value.hex.str); 01044 break; 01045 case XML_SCHEMAS_BASE64BINARY: 01046 if (value->value.base64.str != NULL) 01047 xmlFree(value->value.base64.str); 01048 break; 01049 default: 01050 break; 01051 } 01052 prev = value; 01053 value = value->next; 01054 xmlFree(prev); 01055 } 01056 } 01057 01067 xmlSchemaTypePtr 01068 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) { 01069 if (xmlSchemaTypesInitialized == 0) 01070 xmlSchemaInitTypes(); 01071 if (name == NULL) 01072 return(NULL); 01073 return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns)); 01074 } 01075 01085 xmlSchemaTypePtr 01086 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type) 01087 { 01088 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC)) 01089 return (NULL); 01090 switch (type->builtInType) { 01091 case XML_SCHEMAS_NMTOKENS: 01092 return (xmlSchemaTypeNmtokenDef ); 01093 case XML_SCHEMAS_IDREFS: 01094 return (xmlSchemaTypeIdrefDef); 01095 case XML_SCHEMAS_ENTITIES: 01096 return (xmlSchemaTypeEntityDef); 01097 default: 01098 return (NULL); 01099 } 01100 } 01101 01102 /**************************************************************** 01103 * * 01104 * Convenience macros and functions * 01105 * * 01106 ****************************************************************/ 01107 01108 #define IS_TZO_CHAR(c) \ 01109 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-')) 01110 01111 #define VALID_YEAR(yr) (yr != 0) 01112 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12)) 01113 /* VALID_DAY should only be used when month is unknown */ 01114 #define VALID_DAY(day) ((day >= 1) && (day <= 31)) 01115 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23)) 01116 #define VALID_MIN(min) ((min >= 0) && (min <= 59)) 01117 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60)) 01118 #define VALID_TZO(tzo) ((tzo > -840) && (tzo < 840)) 01119 #define IS_LEAP(y) \ 01120 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) 01121 01122 static const unsigned int daysInMonth[12] = 01123 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 01124 static const unsigned int daysInMonthLeap[12] = 01125 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 01126 01127 #define MAX_DAYINMONTH(yr,mon) \ 01128 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1]) 01129 01130 #define VALID_MDAY(dt) \ 01131 (IS_LEAP(dt->year) ? \ 01132 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \ 01133 (dt->day <= daysInMonth[dt->mon - 1])) 01134 01135 #define VALID_DATE(dt) \ 01136 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt)) 01137 01138 #define VALID_TIME(dt) \ 01139 (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \ 01140 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo)) 01141 01142 #define VALID_DATETIME(dt) \ 01143 (VALID_DATE(dt) && VALID_TIME(dt)) 01144 01145 #define SECS_PER_MIN (60) 01146 #define SECS_PER_HOUR (60 * SECS_PER_MIN) 01147 #define SECS_PER_DAY (24 * SECS_PER_HOUR) 01148 01149 static const long dayInYearByMonth[12] = 01150 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 01151 static const long dayInLeapYearByMonth[12] = 01152 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; 01153 01154 #define DAY_IN_YEAR(day, month, year) \ 01155 ((IS_LEAP(year) ? \ 01156 dayInLeapYearByMonth[month - 1] : \ 01157 dayInYearByMonth[month - 1]) + day) 01158 01159 #ifdef DEBUG 01160 #define DEBUG_DATE(dt) \ 01161 xmlGenericError(xmlGenericErrorContext, \ 01162 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \ 01163 dt->type,dt->value.date.year,dt->value.date.mon, \ 01164 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \ 01165 dt->value.date.sec); \ 01166 if (dt->value.date.tz_flag) \ 01167 if (dt->value.date.tzo != 0) \ 01168 xmlGenericError(xmlGenericErrorContext, \ 01169 "%+05d\n",dt->value.date.tzo); \ 01170 else \ 01171 xmlGenericError(xmlGenericErrorContext, "Z\n"); \ 01172 else \ 01173 xmlGenericError(xmlGenericErrorContext,"\n") 01174 #else 01175 #define DEBUG_DATE(dt) 01176 #endif 01177 01190 static int 01191 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) { 01192 const xmlChar *cur = *str, *firstChar; 01193 int isneg = 0, digcnt = 0; 01194 01195 if (((*cur < '0') || (*cur > '9')) && 01196 (*cur != '-') && (*cur != '+')) 01197 return -1; 01198 01199 if (*cur == '-') { 01200 isneg = 1; 01201 cur++; 01202 } 01203 01204 firstChar = cur; 01205 01206 while ((*cur >= '0') && (*cur <= '9')) { 01207 dt->year = dt->year * 10 + (*cur - '0'); 01208 cur++; 01209 digcnt++; 01210 } 01211 01212 /* year must be at least 4 digits (CCYY); over 4 01213 * digits cannot have a leading zero. */ 01214 if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0'))) 01215 return 1; 01216 01217 if (isneg) 01218 dt->year = - dt->year; 01219 01220 if (!VALID_YEAR(dt->year)) 01221 return 2; 01222 01223 *str = cur; 01224 return 0; 01225 } 01226 01238 #define PARSE_2_DIGITS(num, cur, invalid) \ 01239 if ((cur[0] < '0') || (cur[0] > '9') || \ 01240 (cur[1] < '0') || (cur[1] > '9')) \ 01241 invalid = 1; \ 01242 else \ 01243 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \ 01244 cur += 2; 01245 01258 #define PARSE_FLOAT(num, cur, invalid) \ 01259 PARSE_2_DIGITS(num, cur, invalid); \ 01260 if (!invalid && (*cur == '.')) { \ 01261 double mult = 1; \ 01262 cur++; \ 01263 if ((*cur < '0') || (*cur > '9')) \ 01264 invalid = 1; \ 01265 while ((*cur >= '0') && (*cur <= '9')) { \ 01266 mult /= 10; \ 01267 num += (*cur - '0') * mult; \ 01268 cur++; \ 01269 } \ 01270 } 01271 01283 static int 01284 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) { 01285 const xmlChar *cur = *str; 01286 int ret = 0; 01287 unsigned int value = 0; 01288 01289 PARSE_2_DIGITS(value, cur, ret); 01290 if (ret != 0) 01291 return ret; 01292 01293 if (!VALID_MONTH(value)) 01294 return 2; 01295 01296 dt->mon = value; 01297 01298 *str = cur; 01299 return 0; 01300 } 01301 01313 static int 01314 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) { 01315 const xmlChar *cur = *str; 01316 int ret = 0; 01317 unsigned int value = 0; 01318 01319 PARSE_2_DIGITS(value, cur, ret); 01320 if (ret != 0) 01321 return ret; 01322 01323 if (!VALID_DAY(value)) 01324 return 2; 01325 01326 dt->day = value; 01327 *str = cur; 01328 return 0; 01329 } 01330 01343 static int 01344 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) { 01345 const xmlChar *cur = *str; 01346 int ret = 0; 01347 int value = 0; 01348 01349 PARSE_2_DIGITS(value, cur, ret); 01350 if (ret != 0) 01351 return ret; 01352 if (*cur != ':') 01353 return 1; 01354 if (!VALID_HOUR(value)) 01355 return 2; 01356 cur++; 01357 01358 /* the ':' insures this string is xs:time */ 01359 dt->hour = value; 01360 01361 PARSE_2_DIGITS(value, cur, ret); 01362 if (ret != 0) 01363 return ret; 01364 if (!VALID_MIN(value)) 01365 return 2; 01366 dt->min = value; 01367 01368 if (*cur != ':') 01369 return 1; 01370 cur++; 01371 01372 PARSE_FLOAT(dt->sec, cur, ret); 01373 if (ret != 0) 01374 return ret; 01375 01376 if ((!VALID_SEC(dt->sec)) || (!VALID_TZO(dt->tzo))) 01377 return 2; 01378 01379 *str = cur; 01380 return 0; 01381 } 01382 01394 static int 01395 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) { 01396 const xmlChar *cur; 01397 int ret = 0; 01398 01399 if (str == NULL) 01400 return -1; 01401 cur = *str; 01402 01403 switch (*cur) { 01404 case 0: 01405 dt->tz_flag = 0; 01406 dt->tzo = 0; 01407 break; 01408 01409 case 'Z': 01410 dt->tz_flag = 1; 01411 dt->tzo = 0; 01412 cur++; 01413 break; 01414 01415 case '+': 01416 case '-': { 01417 int isneg = 0, tmp = 0; 01418 isneg = (*cur == '-'); 01419 01420 cur++; 01421 01422 PARSE_2_DIGITS(tmp, cur, ret); 01423 if (ret != 0) 01424 return ret; 01425 if (!VALID_HOUR(tmp)) 01426 return 2; 01427 01428 if (*cur != ':') 01429 return 1; 01430 cur++; 01431 01432 dt->tzo = tmp * 60; 01433 01434 PARSE_2_DIGITS(tmp, cur, ret); 01435 if (ret != 0) 01436 return ret; 01437 if (!VALID_MIN(tmp)) 01438 return 2; 01439 01440 dt->tzo += tmp; 01441 if (isneg) 01442 dt->tzo = - dt->tzo; 01443 01444 if (!VALID_TZO(dt->tzo)) 01445 return 2; 01446 01447 dt->tz_flag = 1; 01448 break; 01449 } 01450 default: 01451 return 1; 01452 } 01453 01454 *str = cur; 01455 return 0; 01456 } 01457 01466 static int 01467 _xmlSchemaBase64Decode (const xmlChar ch) { 01468 if (('A' <= ch) && (ch <= 'Z')) return ch - 'A'; 01469 if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26; 01470 if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52; 01471 if ('+' == ch) return 62; 01472 if ('/' == ch) return 63; 01473 if ('=' == ch) return 64; 01474 return -1; 01475 } 01476 01477 /**************************************************************** 01478 * * 01479 * XML Schema Dates/Times Datatypes Handling * 01480 * * 01481 ****************************************************************/ 01482 01494 #define PARSE_DIGITS(num, cur, num_type) \ 01495 if ((*cur < '0') || (*cur > '9')) \ 01496 num_type = -1; \ 01497 else \ 01498 while ((*cur >= '0') && (*cur <= '9')) { \ 01499 num = num * 10 + (*cur - '0'); \ 01500 cur++; \ 01501 } 01502 01516 #define PARSE_NUM(num, cur, num_type) \ 01517 num = 0; \ 01518 PARSE_DIGITS(num, cur, num_type); \ 01519 if (!num_type && (*cur == '.')) { \ 01520 double mult = 1; \ 01521 cur++; \ 01522 if ((*cur < '0') || (*cur > '9')) \ 01523 num_type = -1; \ 01524 else \ 01525 num_type = 1; \ 01526 while ((*cur >= '0') && (*cur <= '9')) { \ 01527 mult /= 10; \ 01528 num += (*cur - '0') * mult; \ 01529 cur++; \ 01530 } \ 01531 } 01532 01545 static int 01546 xmlSchemaValidateDates (xmlSchemaValType type, 01547 const xmlChar *dateTime, xmlSchemaValPtr *val, 01548 int collapse) { 01549 xmlSchemaValPtr dt; 01550 int ret; 01551 const xmlChar *cur = dateTime; 01552 01553 #define RETURN_TYPE_IF_VALID(t) \ 01554 if (IS_TZO_CHAR(*cur)) { \ 01555 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \ 01556 if (ret == 0) { \ 01557 if (*cur != 0) \ 01558 goto error; \ 01559 dt->type = t; \ 01560 goto done; \ 01561 } \ 01562 } 01563 01564 if (dateTime == NULL) 01565 return -1; 01566 01567 if (collapse) 01568 while IS_WSP_BLANK_CH(*cur) cur++; 01569 01570 if ((*cur != '-') && (*cur < '0') && (*cur > '9')) 01571 return 1; 01572 01573 dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN); 01574 if (dt == NULL) 01575 return -1; 01576 01577 if ((cur[0] == '-') && (cur[1] == '-')) { 01578 /* 01579 * It's an incomplete date (xs:gMonthDay, xs:gMonth or 01580 * xs:gDay) 01581 */ 01582 cur += 2; 01583 01584 /* is it an xs:gDay? */ 01585 if (*cur == '-') { 01586 if (type == XML_SCHEMAS_GMONTH) 01587 goto error; 01588 ++cur; 01589 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); 01590 if (ret != 0) 01591 goto error; 01592 01593 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY); 01594 01595 goto error; 01596 } 01597 01598 /* 01599 * it should be an xs:gMonthDay or xs:gMonth 01600 */ 01601 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); 01602 if (ret != 0) 01603 goto error; 01604 01605 /* 01606 * a '-' char could indicate this type is xs:gMonthDay or 01607 * a negative time zone offset. Check for xs:gMonthDay first. 01608 * Also the first three char's of a negative tzo (-MM:SS) can 01609 * appear to be a valid day; so even if the day portion 01610 * of the xs:gMonthDay verifies, we must insure it was not 01611 * a tzo. 01612 */ 01613 if (*cur == '-') { 01614 const xmlChar *rewnd = cur; 01615 cur++; 01616 01617 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); 01618 if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) { 01619 01620 /* 01621 * we can use the VALID_MDAY macro to validate the month 01622 * and day because the leap year test will flag year zero 01623 * as a leap year (even though zero is an invalid year). 01624 * FUTURE TODO: Zero will become valid in XML Schema 1.1 01625 * probably. 01626 */ 01627 if (VALID_MDAY((&(dt->value.date)))) { 01628 01629 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY); 01630 01631 goto error; 01632 } 01633 } 01634 01635 /* 01636 * not xs:gMonthDay so rewind and check if just xs:gMonth 01637 * with an optional time zone. 01638 */ 01639 cur = rewnd; 01640 } 01641 01642 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH); 01643 01644 goto error; 01645 } 01646 01647 /* 01648 * It's a right-truncated date or an xs:time. 01649 * Try to parse an xs:time then fallback on right-truncated dates. 01650 */ 01651 if ((*cur >= '0') && (*cur <= '9')) { 01652 ret = _xmlSchemaParseTime(&(dt->value.date), &cur); 01653 if (ret == 0) { 01654 /* it's an xs:time */ 01655 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME); 01656 } 01657 } 01658 01659 /* fallback on date parsing */ 01660 cur = dateTime; 01661 01662 ret = _xmlSchemaParseGYear(&(dt->value.date), &cur); 01663 if (ret != 0) 01664 goto error; 01665 01666 /* is it an xs:gYear? */ 01667 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR); 01668 01669 if (*cur != '-') 01670 goto error; 01671 cur++; 01672 01673 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); 01674 if (ret != 0) 01675 goto error; 01676 01677 /* is it an xs:gYearMonth? */ 01678 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH); 01679 01680 if (*cur != '-') 01681 goto error; 01682 cur++; 01683 01684 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); 01685 if ((ret != 0) || !VALID_DATE((&(dt->value.date)))) 01686 goto error; 01687 01688 /* is it an xs:date? */ 01689 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE); 01690 01691 if (*cur != 'T') 01692 goto error; 01693 cur++; 01694 01695 /* it should be an xs:dateTime */ 01696 ret = _xmlSchemaParseTime(&(dt->value.date), &cur); 01697 if (ret != 0) 01698 goto error; 01699 01700 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); 01701 if (collapse) 01702 while IS_WSP_BLANK_CH(*cur) cur++; 01703 if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date)))))) 01704 goto error; 01705 01706 01707 dt->type = XML_SCHEMAS_DATETIME; 01708 01709 done: 01710 #if 1 01711 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) 01712 goto error; 01713 #else 01714 /* 01715 * insure the parsed type is equal to or less significant (right 01716 * truncated) than the desired type. 01717 */ 01718 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) { 01719 01720 /* time only matches time */ 01721 if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME)) 01722 goto error; 01723 01724 if ((type == XML_SCHEMAS_DATETIME) && 01725 ((dt->type != XML_SCHEMAS_DATE) || 01726 (dt->type != XML_SCHEMAS_GYEARMONTH) || 01727 (dt->type != XML_SCHEMAS_GYEAR))) 01728 goto error; 01729 01730 if ((type == XML_SCHEMAS_DATE) && 01731 ((dt->type != XML_SCHEMAS_GYEAR) || 01732 (dt->type != XML_SCHEMAS_GYEARMONTH))) 01733 goto error; 01734 01735 if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR)) 01736 goto error; 01737 01738 if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH)) 01739 goto error; 01740 } 01741 #endif 01742 01743 if (val != NULL) 01744 *val = dt; 01745 else 01746 xmlSchemaFreeValue(dt); 01747 01748 return 0; 01749 01750 error: 01751 if (dt != NULL) 01752 xmlSchemaFreeValue(dt); 01753 return 1; 01754 } 01755 01768 static int 01769 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED, 01770 const xmlChar *duration, xmlSchemaValPtr *val, 01771 int collapse) { 01772 const xmlChar *cur = duration; 01773 xmlSchemaValPtr dur; 01774 int isneg = 0; 01775 unsigned int seq = 0; 01776 double num; 01777 int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */ 01778 const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'}; 01779 const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0}; 01780 01781 if (duration == NULL) 01782 return -1; 01783 01784 if (collapse) 01785 while IS_WSP_BLANK_CH(*cur) cur++; 01786 01787 if (*cur == '-') { 01788 isneg = 1; 01789 cur++; 01790 } 01791 01792 /* duration must start with 'P' (after sign) */ 01793 if (*cur++ != 'P') 01794 return 1; 01795 01796 if (*cur == 0) 01797 return 1; 01798 01799 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); 01800 if (dur == NULL) 01801 return -1; 01802 01803 while (*cur != 0) { 01804 01805 /* input string should be empty or invalid date/time item */ 01806 if (seq >= sizeof(desig)) 01807 goto error; 01808 01809 /* T designator must be present for time items */ 01810 if (*cur == 'T') { 01811 if (seq <= 3) { 01812 seq = 3; 01813 cur++; 01814 } else 01815 return 1; 01816 } else if (seq == 3) 01817 goto error; 01818 01819 /* parse the number portion of the item */ 01820 PARSE_NUM(num, cur, num_type); 01821 01822 if ((num_type == -1) || (*cur == 0)) 01823 goto error; 01824 01825 /* update duration based on item type */ 01826 while (seq < sizeof(desig)) { 01827 if (*cur == desig[seq]) { 01828 01829 /* verify numeric type; only seconds can be float */ 01830 if ((num_type != 0) && (seq < (sizeof(desig)-1))) 01831 goto error; 01832 01833 switch (seq) { 01834 case 0: 01835 dur->value.dur.mon = (long)num * 12; 01836 break; 01837 case 1: 01838 dur->value.dur.mon += (long)num; 01839 break; 01840 default: 01841 /* convert to seconds using multiplier */ 01842 dur->value.dur.sec += num * multi[seq]; 01843 seq++; 01844 break; 01845 } 01846 01847 break; /* exit loop */ 01848 } 01849 /* no date designators found? */ 01850 if ((++seq == 3) || (seq == 6)) 01851 goto error; 01852 } 01853 cur++; 01854 if (collapse) 01855 while IS_WSP_BLANK_CH(*cur) cur++; 01856 } 01857 01858 if (isneg) { 01859 dur->value.dur.mon = -dur->value.dur.mon; 01860 dur->value.dur.day = -dur->value.dur.day; 01861 dur->value.dur.sec = -dur->value.dur.sec; 01862 } 01863 01864 if (val != NULL) 01865 *val = dur; 01866 else 01867 xmlSchemaFreeValue(dur); 01868 01869 return 0; 01870 01871 error: 01872 if (dur != NULL) 01873 xmlSchemaFreeValue(dur); 01874 return 1; 01875 } 01876 01885 static xmlChar * 01886 xmlSchemaStrip(const xmlChar *value) { 01887 const xmlChar *start = value, *end, *f; 01888 01889 if (value == NULL) return(NULL); 01890 while ((*start != 0) && (IS_BLANK_CH(*start))) start++; 01891 end = start; 01892 while (*end != 0) end++; 01893 f = end; 01894 end--; 01895 while ((end > start) && (IS_BLANK_CH(*end))) end--; 01896 end++; 01897 if ((start == value) && (f == end)) return(NULL); 01898 return(xmlStrndup(start, end - start)); 01899 } 01900 01909 xmlChar * 01910 xmlSchemaWhiteSpaceReplace(const xmlChar *value) { 01911 const xmlChar *cur = value; 01912 xmlChar *ret = NULL, *mcur; 01913 01914 if (value == NULL) 01915 return(NULL); 01916 01917 while ((*cur != 0) && 01918 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) { 01919 cur++; 01920 } 01921 if (*cur == 0) 01922 return (NULL); 01923 ret = xmlStrdup(value); 01924 /* TODO FIXME: I guess gcc will bark at this. */ 01925 mcur = (xmlChar *) (ret + (cur - value)); 01926 do { 01927 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) ) 01928 *mcur = ' '; 01929 mcur++; 01930 } while (*mcur != 0); 01931 return(ret); 01932 } 01933 01942 xmlChar * 01943 xmlSchemaCollapseString(const xmlChar *value) { 01944 const xmlChar *start = value, *end, *f; 01945 xmlChar *g; 01946 int col = 0; 01947 01948 if (value == NULL) return(NULL); 01949 while ((*start != 0) && (IS_BLANK_CH(*start))) start++; 01950 end = start; 01951 while (*end != 0) { 01952 if ((*end == ' ') && (IS_BLANK_CH(end[1]))) { 01953 col = end - start; 01954 break; 01955 } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) { 01956 col = end - start; 01957 break; 01958 } 01959 end++; 01960 } 01961 if (col == 0) { 01962 f = end; 01963 end--; 01964 while ((end > start) && (IS_BLANK_CH(*end))) end--; 01965 end++; 01966 if ((start == value) && (f == end)) return(NULL); 01967 return(xmlStrndup(start, end - start)); 01968 } 01969 start = xmlStrdup(start); 01970 if (start == NULL) return(NULL); 01971 g = (xmlChar *) (start + col); 01972 end = g; 01973 while (*end != 0) { 01974 if (IS_BLANK_CH(*end)) { 01975 end++; 01976 while (IS_BLANK_CH(*end)) end++; 01977 if (*end != 0) 01978 *g++ = ' '; 01979 } else 01980 *g++ = *end++; 01981 } 01982 *g = 0; 01983 return((xmlChar *) start); 01984 } 01985 01999 static int 02000 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value, 02001 xmlSchemaValPtr *ret, xmlNodePtr node) { 02002 xmlChar *val, *cur, *endval; 02003 int nb_values = 0; 02004 int tmp = 0; 02005 02006 if (value == NULL) { 02007 return(-1); 02008 } 02009 val = xmlStrdup(value); 02010 if (val == NULL) { 02011 return(-1); 02012 } 02013 if (ret != NULL) { 02014 *ret = NULL; 02015 } 02016 cur = val; 02017 /* 02018 * Split the list 02019 */ 02020 while (IS_BLANK_CH(*cur)) *cur++ = 0; 02021 while (*cur != 0) { 02022 if (IS_BLANK_CH(*cur)) { 02023 *cur = 0; 02024 cur++; 02025 while (IS_BLANK_CH(*cur)) *cur++ = 0; 02026 } else { 02027 nb_values++; 02028 cur++; 02029 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; 02030 } 02031 } 02032 if (nb_values == 0) { 02033 xmlFree(val); 02034 return(nb_values); 02035 } 02036 endval = cur; 02037 cur = val; 02038 while ((*cur == 0) && (cur != endval)) cur++; 02039 while (cur != endval) { 02040 tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node); 02041 if (tmp != 0) 02042 break; 02043 while (*cur != 0) cur++; 02044 while ((*cur == 0) && (cur != endval)) cur++; 02045 } 02046 /* TODO what return value ? c.f. bug #158628 02047 if (ret != NULL) { 02048 TODO 02049 } */ 02050 xmlFree(val); 02051 if (tmp == 0) 02052 return(nb_values); 02053 return(-1); 02054 } 02055 02068 static int 02069 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, 02070 unsigned long *lmi, unsigned long *lhi) { 02071 unsigned long lo = 0, mi = 0, hi = 0; 02072 const xmlChar *tmp, *cur = *str; 02073 int ret = 0, i = 0; 02074 02075 if (!((*cur >= '0') && (*cur <= '9'))) 02076 return(-2); 02077 02078 while (*cur == '0') { /* ignore leading zeroes */ 02079 cur++; 02080 } 02081 tmp = cur; 02082 while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) { 02083 i++;tmp++;ret++; 02084 } 02085 if (i > 24) { 02086 *str = tmp; 02087 return(-1); 02088 } 02089 while (i > 16) { 02090 hi = hi * 10 + (*cur++ - '0'); 02091 i--; 02092 } 02093 while (i > 8) { 02094 mi = mi * 10 + (*cur++ - '0'); 02095 i--; 02096 } 02097 while (i > 0) { 02098 lo = lo * 10 + (*cur++ - '0'); 02099 i--; 02100 } 02101 02102 *str = cur; 02103 *llo = lo; 02104 *lmi = mi; 02105 *lhi = hi; 02106 return(ret); 02107 } 02108 02124 static int 02125 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, 02126 xmlSchemaValPtr * val, xmlNodePtr node, int flags, 02127 xmlSchemaWhitespaceValueType ws, 02128 int normOnTheFly, int applyNorm, int createStringValue) 02129 { 02130 xmlSchemaValPtr v; 02131 xmlChar *norm = NULL; 02132 int ret = 0; 02133 02134 if (xmlSchemaTypesInitialized == 0) 02135 xmlSchemaInitTypes(); 02136 if (type == NULL) 02137 return (-1); 02138 02139 /* 02140 * validating a non existant text node is similar to validating 02141 * an empty one. 02142 */ 02143 if (value == NULL) 02144 value = BAD_CAST ""; 02145 02146 if (val != NULL) 02147 *val = NULL; 02148 if ((flags == 0) && (value != NULL)) { 02149 02150 if ((type->builtInType != XML_SCHEMAS_STRING) && 02151 (type->builtInType != XML_SCHEMAS_ANYTYPE) && 02152 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) { 02153 if (type->builtInType == XML_SCHEMAS_NORMSTRING) 02154 norm = xmlSchemaWhiteSpaceReplace(value); 02155 else 02156 norm = xmlSchemaCollapseString(value); 02157 if (norm != NULL) 02158 value = norm; 02159 } 02160 } 02161 02162 switch (type->builtInType) { 02163 case XML_SCHEMAS_UNKNOWN: 02164 goto error; 02165 case XML_SCHEMAS_ANYTYPE: 02166 case XML_SCHEMAS_ANYSIMPLETYPE: 02167 if ((createStringValue) && (val != NULL)) { 02168 v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE); 02169 if (v != NULL) { 02170 v->value.str = xmlStrdup(value); 02171 *val = v; 02172 } else { 02173 goto error; 02174 } 02175 } 02176 goto return0; 02177 case XML_SCHEMAS_STRING: 02178 if (! normOnTheFly) { 02179 const xmlChar *cur = value; 02180 02181 if (ws == XML_SCHEMA_WHITESPACE_REPLACE) { 02182 while (*cur != 0) { 02183 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { 02184 goto return1; 02185 } else { 02186 cur++; 02187 } 02188 } 02189 } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) { 02190 while (*cur != 0) { 02191 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { 02192 goto return1; 02193 } else if IS_WSP_SPACE_CH(*cur) { 02194 cur++; 02195 if IS_WSP_SPACE_CH(*cur) 02196 goto return1; 02197 } else { 02198 cur++; 02199 } 02200 } 02201 } 02202 } 02203 if (createStringValue && (val != NULL)) { 02204 if (applyNorm) { 02205 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 02206 norm = xmlSchemaCollapseString(value); 02207 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) 02208 norm = xmlSchemaWhiteSpaceReplace(value); 02209 if (norm != NULL) 02210 value = norm; 02211 } 02212 v = xmlSchemaNewValue(XML_SCHEMAS_STRING); 02213 if (v != NULL) { 02214 v->value.str = xmlStrdup(value); 02215 *val = v; 02216 } else { 02217 goto error; 02218 } 02219 } 02220 goto return0; 02221 case XML_SCHEMAS_NORMSTRING:{ 02222 if (normOnTheFly) { 02223 if (applyNorm) { 02224 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 02225 norm = xmlSchemaCollapseString(value); 02226 else 02227 norm = xmlSchemaWhiteSpaceReplace(value); 02228 if (norm != NULL) 02229 value = norm; 02230 } 02231 } else { 02232 const xmlChar *cur = value; 02233 while (*cur != 0) { 02234 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { 02235 goto return1; 02236 } else { 02237 cur++; 02238 } 02239 } 02240 } 02241 if (val != NULL) { 02242 v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING); 02243 if (v != NULL) { 02244 v->value.str = xmlStrdup(value); 02245 *val = v; 02246 } else { 02247 goto error; 02248 } 02249 } 02250 goto return0; 02251 } 02252 case XML_SCHEMAS_DECIMAL:{ 02253 const xmlChar *cur = value; 02254 unsigned int len, neg, integ, hasLeadingZeroes; 02255 xmlChar cval[25]; 02256 xmlChar *cptr = cval; 02257 02258 if ((cur == NULL) || (*cur == 0)) 02259 goto return1; 02260 02261 /* 02262 * xs:decimal has a whitespace-facet value of 'collapse'. 02263 */ 02264 if (normOnTheFly) 02265 while IS_WSP_BLANK_CH(*cur) cur++; 02266 02267 /* 02268 * First we handle an optional sign. 02269 */ 02270 neg = 0; 02271 if (*cur == '-') { 02272 neg = 1; 02273 cur++; 02274 } else if (*cur == '+') 02275 cur++; 02276 /* 02277 * Disallow: "", "-", "- " 02278 */ 02279 if (*cur == 0) 02280 goto return1; 02281 /* 02282 * Next we "pre-parse" the number, in preparation for calling 02283 * the common routine xmlSchemaParseUInt. We get rid of any 02284 * leading zeroes (because we have reserved only 25 chars), 02285 * and note the position of a decimal point. 02286 */ 02287 len = 0; 02288 integ = ~0u; 02289 hasLeadingZeroes = 0; 02290 /* 02291 * Skip leading zeroes. 02292 */ 02293 while (*cur == '0') { 02294 cur++; 02295 hasLeadingZeroes = 1; 02296 } 02297 if (*cur != 0) { 02298 do { 02299 if ((*cur >= '0') && (*cur <= '9')) { 02300 *cptr++ = *cur++; 02301 len++; 02302 } else if (*cur == '.') { 02303 cur++; 02304 integ = len; 02305 do { 02306 if ((*cur >= '0') && (*cur <= '9')) { 02307 *cptr++ = *cur++; 02308 len++; 02309 } else 02310 break; 02311 } while (len < 24); 02312 /* 02313 * Disallow "." but allow "00." 02314 */ 02315 if ((len == 0) && (!hasLeadingZeroes)) 02316 goto return1; 02317 break; 02318 } else 02319 break; 02320 } while (len < 24); 02321 } 02322 if (normOnTheFly) 02323 while IS_WSP_BLANK_CH(*cur) cur++; 02324 if (*cur != 0) 02325 goto return1; /* error if any extraneous chars */ 02326 if (val != NULL) { 02327 v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL); 02328 if (v != NULL) { 02329 /* 02330 * Now evaluate the significant digits of the number 02331 */ 02332 if (len != 0) { 02333 02334 if (integ != ~0u) { 02335 /* 02336 * Get rid of trailing zeroes in the 02337 * fractional part. 02338 */ 02339 while ((len != integ) && (*(cptr-1) == '0')) { 02340 cptr--; 02341 len--; 02342 } 02343 } 02344 /* 02345 * Terminate the (preparsed) string. 02346 */ 02347 if (len != 0) { 02348 *cptr = 0; 02349 cptr = cval; 02350 02351 xmlSchemaParseUInt((const xmlChar **)&cptr, 02352 &v->value.decimal.lo, 02353 &v->value.decimal.mi, 02354 &v->value.decimal.hi); 02355 } 02356 } 02357 /* 02358 * Set the total digits to 1 if a zero value. 02359 */ 02360 v->value.decimal.sign = neg; 02361 if (len == 0) { 02362 /* Speedup for zero values. */ 02363 v->value.decimal.total = 1; 02364 } else { 02365 v->value.decimal.total = len; 02366 if (integ == ~0u) 02367 v->value.decimal.frac = 0; 02368 else 02369 v->value.decimal.frac = len - integ; 02370 } 02371 *val = v; 02372 } 02373 } 02374 goto return0; 02375 } 02376 case XML_SCHEMAS_TIME: 02377 case XML_SCHEMAS_GDAY: 02378 case XML_SCHEMAS_GMONTH: 02379 case XML_SCHEMAS_GMONTHDAY: 02380 case XML_SCHEMAS_GYEAR: 02381 case XML_SCHEMAS_GYEARMONTH: 02382 case XML_SCHEMAS_DATE: 02383 case XML_SCHEMAS_DATETIME: 02384 ret = xmlSchemaValidateDates(type->builtInType, value, val, 02385 normOnTheFly); 02386 break; 02387 case XML_SCHEMAS_DURATION: 02388 ret = xmlSchemaValidateDuration(type, value, val, 02389 normOnTheFly); 02390 break; 02391 case XML_SCHEMAS_FLOAT: 02392 case XML_SCHEMAS_DOUBLE: { 02393 const xmlChar *cur = value; 02394 int neg = 0; 02395 int digits_before = 0; 02396 int digits_after = 0; 02397 02398 if (normOnTheFly) 02399 while IS_WSP_BLANK_CH(*cur) cur++; 02400 02401 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) { 02402 cur += 3; 02403 if (*cur != 0) 02404 goto return1; 02405 if (val != NULL) { 02406 if (type == xmlSchemaTypeFloatDef) { 02407 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); 02408 if (v != NULL) { 02409 v->value.f = (float) xmlXPathNAN; 02410 } else { 02411 xmlSchemaFreeValue(v); 02412 goto error; 02413 } 02414 } else { 02415 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); 02416 if (v != NULL) { 02417 v->value.d = xmlXPathNAN; 02418 } else { 02419 xmlSchemaFreeValue(v); 02420 goto error; 02421 } 02422 } 02423 *val = v; 02424 } 02425 goto return0; 02426 } 02427 if (*cur == '-') { 02428 neg = 1; 02429 cur++; 02430 } 02431 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) { 02432 cur += 3; 02433 if (*cur != 0) 02434 goto return1; 02435 if (val != NULL) { 02436 if (type == xmlSchemaTypeFloatDef) { 02437 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); 02438 if (v != NULL) { 02439 if (neg) 02440 v->value.f = (float) xmlXPathNINF; 02441 else 02442 v->value.f = (float) xmlXPathPINF; 02443 } else { 02444 xmlSchemaFreeValue(v); 02445 goto error; 02446 } 02447 } else { 02448 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); 02449 if (v != NULL) { 02450 if (neg) 02451 v->value.d = xmlXPathNINF; 02452 else 02453 v->value.d = xmlXPathPINF; 02454 } else { 02455 xmlSchemaFreeValue(v); 02456 goto error; 02457 } 02458 } 02459 *val = v; 02460 } 02461 goto return0; 02462 } 02463 if ((neg == 0) && (*cur == '+')) 02464 cur++; 02465 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-')) 02466 goto return1; 02467 while ((*cur >= '0') && (*cur <= '9')) { 02468 cur++; 02469 digits_before++; 02470 } 02471 if (*cur == '.') { 02472 cur++; 02473 while ((*cur >= '0') && (*cur <= '9')) { 02474 cur++; 02475 digits_after++; 02476 } 02477 } 02478 if ((digits_before == 0) && (digits_after == 0)) 02479 goto return1; 02480 if ((*cur == 'e') || (*cur == 'E')) { 02481 cur++; 02482 if ((*cur == '-') || (*cur == '+')) 02483 cur++; 02484 while ((*cur >= '0') && (*cur <= '9')) 02485 cur++; 02486 } 02487 if (normOnTheFly) 02488 while IS_WSP_BLANK_CH(*cur) cur++; 02489 02490 if (*cur != 0) 02491 goto return1; 02492 if (val != NULL) { 02493 if (type == xmlSchemaTypeFloatDef) { 02494 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); 02495 if (v != NULL) { 02496 /* 02497 * TODO: sscanf seems not to give the correct 02498 * value for extremely high/low values. 02499 * E.g. "1E-149" results in zero. 02500 */ 02501 if (sscanf((const char *) value, "%f", 02502 &(v->value.f)) == 1) { 02503 *val = v; 02504 } else { 02505 xmlSchemaFreeValue(v); 02506 goto return1; 02507 } 02508 } else { 02509 goto error; 02510 } 02511 } else { 02512 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); 02513 if (v != NULL) { 02514 /* 02515 * TODO: sscanf seems not to give the correct 02516 * value for extremely high/low values. 02517 */ 02518 if (sscanf((const char *) value, "%lf", 02519 &(v->value.d)) == 1) { 02520 *val = v; 02521 } else { 02522 xmlSchemaFreeValue(v); 02523 goto return1; 02524 } 02525 } else { 02526 goto error; 02527 } 02528 } 02529 } 02530 goto return0; 02531 } 02532 case XML_SCHEMAS_BOOLEAN:{ 02533 const xmlChar *cur = value; 02534 02535 if (normOnTheFly) { 02536 while IS_WSP_BLANK_CH(*cur) cur++; 02537 if (*cur == '0') { 02538 ret = 0; 02539 cur++; 02540 } else if (*cur == '1') { 02541 ret = 1; 02542 cur++; 02543 } else if (*cur == 't') { 02544 cur++; 02545 if ((*cur++ == 'r') && (*cur++ == 'u') && 02546 (*cur++ == 'e')) { 02547 ret = 1; 02548 } else 02549 goto return1; 02550 } else if (*cur == 'f') { 02551 cur++; 02552 if ((*cur++ == 'a') && (*cur++ == 'l') && 02553 (*cur++ == 's') && (*cur++ == 'e')) { 02554 ret = 0; 02555 } else 02556 goto return1; 02557 } else 02558 goto return1; 02559 if (*cur != 0) { 02560 while IS_WSP_BLANK_CH(*cur) cur++; 02561 if (*cur != 0) 02562 goto return1; 02563 } 02564 } else { 02565 if ((cur[0] == '0') && (cur[1] == 0)) 02566 ret = 0; 02567 else if ((cur[0] == '1') && (cur[1] == 0)) 02568 ret = 1; 02569 else if ((cur[0] == 't') && (cur[1] == 'r') 02570 && (cur[2] == 'u') && (cur[3] == 'e') 02571 && (cur[4] == 0)) 02572 ret = 1; 02573 else if ((cur[0] == 'f') && (cur[1] == 'a') 02574 && (cur[2] == 'l') && (cur[3] == 's') 02575 && (cur[4] == 'e') && (cur[5] == 0)) 02576 ret = 0; 02577 else 02578 goto return1; 02579 } 02580 if (val != NULL) { 02581 v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN); 02582 if (v != NULL) { 02583 v->value.b = ret; 02584 *val = v; 02585 } else { 02586 goto error; 02587 } 02588 } 02589 goto return0; 02590 } 02591 case XML_SCHEMAS_TOKEN:{ 02592 const xmlChar *cur = value; 02593 02594 if (! normOnTheFly) { 02595 while (*cur != 0) { 02596 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { 02597 goto return1; 02598 } else if (*cur == ' ') { 02599 cur++; 02600 if (*cur == 0) 02601 goto return1; 02602 if (*cur == ' ') 02603 goto return1; 02604 } else { 02605 cur++; 02606 } 02607 } 02608 } 02609 if (val != NULL) { 02610 v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN); 02611 if (v != NULL) { 02612 v->value.str = xmlStrdup(value); 02613 *val = v; 02614 } else { 02615 goto error; 02616 } 02617 } 02618 goto return0; 02619 } 02620 case XML_SCHEMAS_LANGUAGE: 02621 if (normOnTheFly) { 02622 norm = xmlSchemaCollapseString(value); 02623 if (norm != NULL) 02624 value = norm; 02625 } 02626 if (xmlCheckLanguageID(value) == 1) { 02627 if (val != NULL) { 02628 v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE); 02629 if (v != NULL) { 02630 v->value.str = xmlStrdup(value); 02631 *val = v; 02632 } else { 02633 goto error; 02634 } 02635 } 02636 goto return0; 02637 } 02638 goto return1; 02639 case XML_SCHEMAS_NMTOKEN: 02640 if (xmlValidateNMToken(value, 1) == 0) { 02641 if (val != NULL) { 02642 v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN); 02643 if (v != NULL) { 02644 v->value.str = xmlStrdup(value); 02645 *val = v; 02646 } else { 02647 goto error; 02648 } 02649 } 02650 goto return0; 02651 } 02652 goto return1; 02653 case XML_SCHEMAS_NMTOKENS: 02654 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef, 02655 value, val, node); 02656 if (ret > 0) 02657 ret = 0; 02658 else 02659 ret = 1; 02660 goto done; 02661 case XML_SCHEMAS_NAME: 02662 ret = xmlValidateName(value, 1); 02663 if ((ret == 0) && (val != NULL) && (value != NULL)) { 02664 v = xmlSchemaNewValue(XML_SCHEMAS_NAME); 02665 if (v != NULL) { 02666 const xmlChar *start = value, *end; 02667 while (IS_BLANK_CH(*start)) start++; 02668 end = start; 02669 while ((*end != 0) && (!IS_BLANK_CH(*end))) end++; 02670 v->value.str = xmlStrndup(start, end - start); 02671 *val = v; 02672 } else { 02673 goto error; 02674 } 02675 } 02676 goto done; 02677 case XML_SCHEMAS_QNAME:{ 02678 const xmlChar *uri = NULL; 02679 xmlChar *local = NULL; 02680 02681 ret = xmlValidateQName(value, 1); 02682 if (ret != 0) 02683 goto done; 02684 if (node != NULL) { 02685 xmlChar *prefix; 02686 xmlNsPtr ns; 02687 02688 local = xmlSplitQName2(value, &prefix); 02689 ns = xmlSearchNs(node->doc, node, prefix); 02690 if ((ns == NULL) && (prefix != NULL)) { 02691 xmlFree(prefix); 02692 if (local != NULL) 02693 xmlFree(local); 02694 goto return1; 02695 } 02696 if (ns != NULL) 02697 uri = ns->href; 02698 if (prefix != NULL) 02699 xmlFree(prefix); 02700 } 02701 if (val != NULL) { 02702 v = xmlSchemaNewValue(XML_SCHEMAS_QNAME); 02703 if (v == NULL) { 02704 if (local != NULL) 02705 xmlFree(local); 02706 goto error; 02707 } 02708 if (local != NULL) 02709 v->value.qname.name = local; 02710 else 02711 v->value.qname.name = xmlStrdup(value); 02712 if (uri != NULL) 02713 v->value.qname.uri = xmlStrdup(uri); 02714 *val = v; 02715 } else 02716 if (local != NULL) 02717 xmlFree(local); 02718 goto done; 02719 } 02720 case XML_SCHEMAS_NCNAME: 02721 ret = xmlValidateNCName(value, 1); 02722 if ((ret == 0) && (val != NULL)) { 02723 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME); 02724 if (v != NULL) { 02725 v->value.str = xmlStrdup(value); 02726 *val = v; 02727 } else { 02728 goto error; 02729 } 02730 } 02731 goto done; 02732 case XML_SCHEMAS_ID: 02733 ret = xmlValidateNCName(value, 1); 02734 if ((ret == 0) && (val != NULL)) { 02735 v = xmlSchemaNewValue(XML_SCHEMAS_ID); 02736 if (v != NULL) { 02737 v->value.str = xmlStrdup(value); 02738 *val = v; 02739 } else { 02740 goto error; 02741 } 02742 } 02743 if ((ret == 0) && (node != NULL) && 02744 (node->type == XML_ATTRIBUTE_NODE)) { 02745 xmlAttrPtr attr = (xmlAttrPtr) node; 02746 02747 /* 02748 * NOTE: the IDness might have already be declared in the DTD 02749 */ 02750 if (attr->atype != XML_ATTRIBUTE_ID) { 02751 xmlIDPtr res; 02752 xmlChar *strip; 02753 02754 strip = xmlSchemaStrip(value); 02755 if (strip != NULL) { 02756 res = xmlAddID(NULL, node->doc, strip, attr); 02757 xmlFree(strip); 02758 } else 02759 res = xmlAddID(NULL, node->doc, value, attr); 02760 if (res == NULL) { 02761 ret = 2; 02762 } else { 02763 attr->atype = XML_ATTRIBUTE_ID; 02764 } 02765 } 02766 } 02767 goto done; 02768 case XML_SCHEMAS_IDREF: 02769 ret = xmlValidateNCName(value, 1); 02770 if ((ret == 0) && (val != NULL)) { 02771 v = xmlSchemaNewValue(XML_SCHEMAS_IDREF); 02772 if (v == NULL) 02773 goto error; 02774 v->value.str = xmlStrdup(value); 02775 *val = v; 02776 } 02777 if ((ret == 0) && (node != NULL) && 02778 (node->type == XML_ATTRIBUTE_NODE)) { 02779 xmlAttrPtr attr = (xmlAttrPtr) node; 02780 xmlChar *strip; 02781 02782 strip = xmlSchemaStrip(value); 02783 if (strip != NULL) { 02784 xmlAddRef(NULL, node->doc, strip, attr); 02785 xmlFree(strip); 02786 } else 02787 xmlAddRef(NULL, node->doc, value, attr); 02788 attr->atype = XML_ATTRIBUTE_IDREF; 02789 } 02790 goto done; 02791 case XML_SCHEMAS_IDREFS: 02792 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef, 02793 value, val, node); 02794 if (ret < 0) 02795 ret = 2; 02796 else 02797 ret = 0; 02798 if ((ret == 0) && (node != NULL) && 02799 (node->type == XML_ATTRIBUTE_NODE)) { 02800 xmlAttrPtr attr = (xmlAttrPtr) node; 02801 02802 attr->atype = XML_ATTRIBUTE_IDREFS; 02803 } 02804 goto done; 02805 case XML_SCHEMAS_ENTITY:{ 02806 xmlChar *strip; 02807 02808 ret = xmlValidateNCName(value, 1); 02809 if ((node == NULL) || (node->doc == NULL)) 02810 ret = 3; 02811 if (ret == 0) { 02812 xmlEntityPtr ent; 02813 02814 strip = xmlSchemaStrip(value); 02815 if (strip != NULL) { 02816 ent = xmlGetDocEntity(node->doc, strip); 02817 xmlFree(strip); 02818 } else { 02819 ent = xmlGetDocEntity(node->doc, value); 02820 } 02821 if ((ent == NULL) || 02822 (ent->etype != 02823 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY)) 02824 ret = 4; 02825 } 02826 if ((ret == 0) && (val != NULL)) { 02827 TODO; 02828 } 02829 if ((ret == 0) && (node != NULL) && 02830 (node->type == XML_ATTRIBUTE_NODE)) { 02831 xmlAttrPtr attr = (xmlAttrPtr) node; 02832 02833 attr->atype = XML_ATTRIBUTE_ENTITY; 02834 } 02835 goto done; 02836 } 02837 case XML_SCHEMAS_ENTITIES: 02838 if ((node == NULL) || (node->doc == NULL)) 02839 goto return3; 02840 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef, 02841 value, val, node); 02842 if (ret <= 0) 02843 ret = 1; 02844 else 02845 ret = 0; 02846 if ((ret == 0) && (node != NULL) && 02847 (node->type == XML_ATTRIBUTE_NODE)) { 02848 xmlAttrPtr attr = (xmlAttrPtr) node; 02849 02850 attr->atype = XML_ATTRIBUTE_ENTITIES; 02851 } 02852 goto done; 02853 case XML_SCHEMAS_NOTATION:{ 02854 xmlChar *uri = NULL; 02855 xmlChar *local = NULL; 02856 02857 ret = xmlValidateQName(value, 1); 02858 if ((ret == 0) && (node != NULL)) { 02859 xmlChar *prefix; 02860 02861 local = xmlSplitQName2(value, &prefix); 02862 if (prefix != NULL) { 02863 xmlNsPtr ns; 02864 02865 ns = xmlSearchNs(node->doc, node, prefix); 02866 if (ns == NULL) 02867 ret = 1; 02868 else if (val != NULL) 02869 uri = xmlStrdup(ns->href); 02870 } 02871 if ((local != NULL) && ((val == NULL) || (ret != 0))) 02872 xmlFree(local); 02873 if (prefix != NULL) 02874 xmlFree(prefix); 02875 } 02876 if ((node == NULL) || (node->doc == NULL)) 02877 ret = 3; 02878 if (ret == 0) { 02879 ret = xmlValidateNotationUse(NULL, node->doc, value); 02880 if (ret == 1) 02881 ret = 0; 02882 else 02883 ret = 1; 02884 } 02885 if ((ret == 0) && (val != NULL)) { 02886 v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); 02887 if (v != NULL) { 02888 if (local != NULL) 02889 v->value.qname.name = local; 02890 else 02891 v->value.qname.name = xmlStrdup(value); 02892 if (uri != NULL) 02893 v->value.qname.uri = uri; 02894 02895 *val = v; 02896 } else { 02897 if (local != NULL) 02898 xmlFree(local); 02899 if (uri != NULL) 02900 xmlFree(uri); 02901 goto error; 02902 } 02903 } 02904 goto done; 02905 } 02906 case XML_SCHEMAS_ANYURI:{ 02907 if (*value != 0) { 02908 xmlURIPtr uri; 02909 xmlChar *tmpval, *cur; 02910 if (normOnTheFly) { 02911 norm = xmlSchemaCollapseString(value); 02912 if (norm != NULL) 02913 value = norm; 02914 } 02915 tmpval = xmlStrdup(value); 02916 for (cur = tmpval; *cur; ++cur) { 02917 if (*cur < 32 || *cur >= 127 || *cur == ' ' || 02918 *cur == '<' || *cur == '>' || *cur == '"' || 02919 *cur == '{' || *cur == '}' || *cur == '|' || 02920 *cur == '\\' || *cur == '^' || *cur == '`' || 02921 *cur == '\'') 02922 *cur = '_'; 02923 } 02924 uri = xmlParseURI((const char *) tmpval); 02925 xmlFree(tmpval); 02926 if (uri == NULL) 02927 goto return1; 02928 xmlFreeURI(uri); 02929 } 02930 02931 if (val != NULL) { 02932 v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI); 02933 if (v == NULL) 02934 goto error; 02935 v->value.str = xmlStrdup(value); 02936 *val = v; 02937 } 02938 goto return0; 02939 } 02940 case XML_SCHEMAS_HEXBINARY:{ 02941 const xmlChar *cur = value, *start; 02942 xmlChar *base; 02943 int total, i = 0; 02944 02945 if (cur == NULL) 02946 goto return1; 02947 02948 if (normOnTheFly) 02949 while IS_WSP_BLANK_CH(*cur) cur++; 02950 02951 start = cur; 02952 while (((*cur >= '0') && (*cur <= '9')) || 02953 ((*cur >= 'A') && (*cur <= 'F')) || 02954 ((*cur >= 'a') && (*cur <= 'f'))) { 02955 i++; 02956 cur++; 02957 } 02958 if (normOnTheFly) 02959 while IS_WSP_BLANK_CH(*cur) cur++; 02960 02961 if (*cur != 0) 02962 goto return1; 02963 if ((i % 2) != 0) 02964 goto return1; 02965 02966 if (val != NULL) { 02967 02968 v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY); 02969 if (v == NULL) 02970 goto error; 02971 /* 02972 * Copy only the normalized piece. 02973 * CRITICAL TODO: Check this. 02974 */ 02975 cur = xmlStrndup(start, i); 02976 if (cur == NULL) { 02977 xmlSchemaTypeErrMemory(node, "allocating hexbin data"); 02978 xmlFree(v); 02979 goto return1; 02980 } 02981 02982 total = i / 2; /* number of octets */ 02983 02984 base = (xmlChar *) cur; 02985 while (i-- > 0) { 02986 if (*base >= 'a') 02987 *base = *base - ('a' - 'A'); 02988 base++; 02989 } 02990 02991 v->value.hex.str = (xmlChar *) cur; 02992 v->value.hex.total = total; 02993 *val = v; 02994 } 02995 goto return0; 02996 } 02997 case XML_SCHEMAS_BASE64BINARY:{ 02998 /* ISSUE: 02999 * 03000 * Ignore all stray characters? (yes, currently) 03001 * Worry about long lines? (no, currently) 03002 * 03003 * rfc2045.txt: 03004 * 03005 * "The encoded output stream must be represented in lines of 03006 * no more than 76 characters each. All line breaks or other 03007 * characters not found in Table 1 must be ignored by decoding 03008 * software. In base64 data, characters other than those in 03009 * Table 1, line breaks, and other white space probably 03010 * indicate a transmission error, about which a warning 03011 * message or even a message rejection might be appropriate 03012 * under some circumstances." */ 03013 const xmlChar *cur = value; 03014 xmlChar *base; 03015 int total, i = 0, pad = 0; 03016 03017 if (cur == NULL) 03018 goto return1; 03019 03020 for (; *cur; ++cur) { 03021 int decc; 03022 03023 decc = _xmlSchemaBase64Decode(*cur); 03024 if (decc < 0) ; 03025 else if (decc < 64) 03026 i++; 03027 else 03028 break; 03029 } 03030 for (; *cur; ++cur) { 03031 int decc; 03032 03033 decc = _xmlSchemaBase64Decode(*cur); 03034 if (decc < 0) ; 03035 else if (decc < 64) 03036 goto return1; 03037 if (decc == 64) 03038 pad++; 03039 } 03040 03041 /* rfc2045.txt: "Special processing is performed if fewer than 03042 * 24 bits are available at the end of the data being encoded. 03043 * A full encoding quantum is always completed at the end of a 03044 * body. When fewer than 24 input bits are available in an 03045 * input group, zero bits are added (on the right) to form an 03046 * integral number of 6-bit groups. Padding at the end of the 03047 * data is performed using the "=" character. Since all 03048 * base64 input is an integral number of octets, only the 03049 * following cases can arise: (1) the final quantum of 03050 * encoding input is an integral multiple of 24 bits; here, 03051 * the final unit of encoded output will be an integral 03052 * multiple ofindent: Standard input:701: Warning:old style 03053 * assignment ambiguity in "=*". Assuming "= *" 4 characters 03054 * with no "=" padding, (2) the final 03055 * quantum of encoding input is exactly 8 bits; here, the 03056 * final unit of encoded output will be two characters 03057 * followed by two "=" padding characters, or (3) the final 03058 * quantum of encoding input is exactly 16 bits; here, the 03059 * final unit of encoded output will be three characters 03060 * followed by one "=" padding character." */ 03061 03062 total = 3 * (i / 4); 03063 if (pad == 0) { 03064 if (i % 4 != 0) 03065 goto return1; 03066 } else if (pad == 1) { 03067 int decc; 03068 03069 if (i % 4 != 3) 03070 goto return1; 03071 for (decc = _xmlSchemaBase64Decode(*cur); 03072 (decc < 0) || (decc > 63); 03073 decc = _xmlSchemaBase64Decode(*cur)) 03074 --cur; 03075 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/ 03076 /* 00111100 -> 0x3c */ 03077 if (decc & ~0x3c) 03078 goto return1; 03079 total += 2; 03080 } else if (pad == 2) { 03081 int decc; 03082 03083 if (i % 4 != 2) 03084 goto return1; 03085 for (decc = _xmlSchemaBase64Decode(*cur); 03086 (decc < 0) || (decc > 63); 03087 decc = _xmlSchemaBase64Decode(*cur)) 03088 --cur; 03089 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */ 03090 /* 00110000 -> 0x30 */ 03091 if (decc & ~0x30) 03092 goto return1; 03093 total += 1; 03094 } else 03095 goto return1; 03096 03097 if (val != NULL) { 03098 v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY); 03099 if (v == NULL) 03100 goto error; 03101 base = 03102 (xmlChar *) xmlMallocAtomic((i + pad + 1) * 03103 sizeof(xmlChar)); 03104 if (base == NULL) { 03105 xmlSchemaTypeErrMemory(node, "allocating base64 data"); 03106 xmlFree(v); 03107 goto return1; 03108 } 03109 v->value.base64.str = base; 03110 for (cur = value; *cur; ++cur) 03111 if (_xmlSchemaBase64Decode(*cur) >= 0) { 03112 *base = *cur; 03113 ++base; 03114 } 03115 *base = 0; 03116 v->value.base64.total = total; 03117 *val = v; 03118 } 03119 goto return0; 03120 } 03121 case XML_SCHEMAS_INTEGER: 03122 case XML_SCHEMAS_PINTEGER: 03123 case XML_SCHEMAS_NPINTEGER: 03124 case XML_SCHEMAS_NINTEGER: 03125 case XML_SCHEMAS_NNINTEGER:{ 03126 const xmlChar *cur = value; 03127 unsigned long lo, mi, hi; 03128 int sign = 0; 03129 03130 if (cur == NULL) 03131 goto return1; 03132 if (normOnTheFly) 03133 while IS_WSP_BLANK_CH(*cur) cur++; 03134 if (*cur == '-') { 03135 sign = 1; 03136 cur++; 03137 } else if (*cur == '+') 03138 cur++; 03139 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); 03140 if (ret < 0) 03141 goto return1; 03142 if (normOnTheFly) 03143 while IS_WSP_BLANK_CH(*cur) cur++; 03144 if (*cur != 0) 03145 goto return1; 03146 if (type->builtInType == XML_SCHEMAS_NPINTEGER) { 03147 if ((sign == 0) && 03148 ((hi != 0) || (mi != 0) || (lo != 0))) 03149 goto return1; 03150 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) { 03151 if (sign == 1) 03152 goto return1; 03153 if ((hi == 0) && (mi == 0) && (lo == 0)) 03154 goto return1; 03155 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) { 03156 if (sign == 0) 03157 goto return1; 03158 if ((hi == 0) && (mi == 0) && (lo == 0)) 03159 goto return1; 03160 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) { 03161 if ((sign == 1) && 03162 ((hi != 0) || (mi != 0) || (lo != 0))) 03163 goto return1; 03164 } 03165 if (val != NULL) { 03166 v = xmlSchemaNewValue(type->builtInType); 03167 if (v != NULL) { 03168 if (ret == 0) 03169 ret++; 03170 v->value.decimal.lo = lo; 03171 v->value.decimal.mi = mi; 03172 v->value.decimal.hi = hi; 03173 v->value.decimal.sign = sign; 03174 v->value.decimal.frac = 0; 03175 v->value.decimal.total = ret; 03176 *val = v; 03177 } 03178 } 03179 goto return0; 03180 } 03181 case XML_SCHEMAS_LONG: 03182 case XML_SCHEMAS_BYTE: 03183 case XML_SCHEMAS_SHORT: 03184 case XML_SCHEMAS_INT:{ 03185 const xmlChar *cur = value; 03186 unsigned long lo, mi, hi; 03187 int sign = 0; 03188 03189 if (cur == NULL) 03190 goto return1; 03191 if (*cur == '-') { 03192 sign = 1; 03193 cur++; 03194 } else if (*cur == '+') 03195 cur++; 03196 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); 03197 if (ret < 0) 03198 goto return1; 03199 if (*cur != 0) 03200 goto return1; 03201 if (type->builtInType == XML_SCHEMAS_LONG) { 03202 if (hi >= 922) { 03203 if (hi > 922) 03204 goto return1; 03205 if (mi >= 33720368) { 03206 if (mi > 33720368) 03207 goto return1; 03208 if ((sign == 0) && (lo > 54775807)) 03209 goto return1; 03210 if ((sign == 1) && (lo > 54775808)) 03211 goto return1; 03212 } 03213 } 03214 } else if (type->builtInType == XML_SCHEMAS_INT) { 03215 if (hi != 0) 03216 goto return1; 03217 if (mi >= 21) { 03218 if (mi > 21) 03219 goto return1; 03220 if ((sign == 0) && (lo > 47483647)) 03221 goto return1; 03222 if ((sign == 1) && (lo > 47483648)) 03223 goto return1; 03224 } 03225 } else if (type->builtInType == XML_SCHEMAS_SHORT) { 03226 if ((mi != 0) || (hi != 0)) 03227 goto return1; 03228 if ((sign == 1) && (lo > 32768)) 03229 goto return1; 03230 if ((sign == 0) && (lo > 32767)) 03231 goto return1; 03232 } else if (type->builtInType == XML_SCHEMAS_BYTE) { 03233 if ((mi != 0) || (hi != 0)) 03234 goto return1; 03235 if ((sign == 1) && (lo > 128)) 03236 goto return1; 03237 if ((sign == 0) && (lo > 127)) 03238 goto return1; 03239 } 03240 if (val != NULL) { 03241 v = xmlSchemaNewValue(type->builtInType); 03242 if (v != NULL) { 03243 v->value.decimal.lo = lo; 03244 v->value.decimal.mi = mi; 03245 v->value.decimal.hi = hi; 03246 v->value.decimal.sign = sign; 03247 v->value.decimal.frac = 0; 03248 v->value.decimal.total = ret; 03249 *val = v; 03250 } 03251 } 03252 goto return0; 03253 } 03254 case XML_SCHEMAS_UINT: 03255 case XML_SCHEMAS_ULONG: 03256 case XML_SCHEMAS_USHORT: 03257 case XML_SCHEMAS_UBYTE:{ 03258 const xmlChar *cur = value; 03259 unsigned long lo, mi, hi; 03260 03261 if (cur == NULL) 03262 goto return1; 03263 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); 03264 if (ret < 0) 03265 goto return1; 03266 if (*cur != 0) 03267 goto return1; 03268 if (type->builtInType == XML_SCHEMAS_ULONG) { 03269 if (hi >= 1844) { 03270 if (hi > 1844) 03271 goto return1; 03272 if (mi >= 67440737) { 03273 if (mi > 67440737) 03274 goto return1; 03275 if (lo > 9551615) 03276 goto return1; 03277 } 03278 } 03279 } else if (type->builtInType == XML_SCHEMAS_UINT) { 03280 if (hi != 0) 03281 goto return1; 03282 if (mi >= 42) { 03283 if (mi > 42) 03284 goto return1; 03285 if (lo > 94967295) 03286 goto return1; 03287 } 03288 } else if (type->builtInType == XML_SCHEMAS_USHORT) { 03289 if ((mi != 0) || (hi != 0)) 03290 goto return1; 03291 if (lo > 65535) 03292 goto return1; 03293 } else if (type->builtInType == XML_SCHEMAS_UBYTE) { 03294 if ((mi != 0) || (hi != 0)) 03295 goto return1; 03296 if (lo > 255) 03297 goto return1; 03298 } 03299 if (val != NULL) { 03300 v = xmlSchemaNewValue(type->builtInType); 03301 if (v != NULL) { 03302 v->value.decimal.lo = lo; 03303 v->value.decimal.mi = mi; 03304 v->value.decimal.hi = hi; 03305 v->value.decimal.sign = 0; 03306 v->value.decimal.frac = 0; 03307 v->value.decimal.total = ret; 03308 *val = v; 03309 } 03310 } 03311 goto return0; 03312 } 03313 } 03314 03315 done: 03316 if (norm != NULL) 03317 xmlFree(norm); 03318 return (ret); 03319 return3: 03320 if (norm != NULL) 03321 xmlFree(norm); 03322 return (3); 03323 return1: 03324 if (norm != NULL) 03325 xmlFree(norm); 03326 return (1); 03327 return0: 03328 if (norm != NULL) 03329 xmlFree(norm); 03330 return (0); 03331 error: 03332 if (norm != NULL) 03333 xmlFree(norm); 03334 return (-1); 03335 } 03336 03350 int 03351 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value, 03352 xmlSchemaValPtr *val, xmlNodePtr node) { 03353 return(xmlSchemaValAtomicType(type, value, val, node, 0, 03354 XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0)); 03355 } 03356 03371 int 03372 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value, 03373 xmlSchemaValPtr *val, xmlNodePtr node) { 03374 return(xmlSchemaValAtomicType(type, value, val, node, 1, 03375 XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1)); 03376 } 03377 03390 int 03391 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value, 03392 xmlSchemaValPtr *val) { 03393 return(xmlSchemaValPredefTypeNode(type, value, val, NULL)); 03394 } 03395 03405 static int 03406 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) 03407 { 03408 xmlSchemaValPtr swp; 03409 int order = 1, integx, integy, dlen; 03410 unsigned long hi, mi, lo; 03411 03412 /* 03413 * First test: If x is -ve and not zero 03414 */ 03415 if ((x->value.decimal.sign) && 03416 ((x->value.decimal.lo != 0) || 03417 (x->value.decimal.mi != 0) || 03418 (x->value.decimal.hi != 0))) { 03419 /* 03420 * Then if y is -ve and not zero reverse the compare 03421 */ 03422 if ((y->value.decimal.sign) && 03423 ((y->value.decimal.lo != 0) || 03424 (y->value.decimal.mi != 0) || 03425 (y->value.decimal.hi != 0))) 03426 order = -1; 03427 /* 03428 * Otherwise (y >= 0) we have the answer 03429 */ 03430 else 03431 return (-1); 03432 /* 03433 * If x is not -ve and y is -ve we have the answer 03434 */ 03435 } else if ((y->value.decimal.sign) && 03436 ((y->value.decimal.lo != 0) || 03437 (y->value.decimal.mi != 0) || 03438 (y->value.decimal.hi != 0))) { 03439 return (1); 03440 } 03441 /* 03442 * If it's not simply determined by a difference in sign, 03443 * then we need to compare the actual values of the two nums. 03444 * To do this, we start by looking at the integral parts. 03445 * If the number of integral digits differ, then we have our 03446 * answer. 03447 */ 03448 integx = x->value.decimal.total - x->value.decimal.frac; 03449 integy = y->value.decimal.total - y->value.decimal.frac; 03450 /* 03451 * NOTE: We changed the "total" for values like "0.1" 03452 * (or "-0.1" or ".1") to be 1, which was 2 previously. 03453 * Therefore the special case, when such values are 03454 * compared with 0, needs to be handled separately; 03455 * otherwise a zero would be recognized incorrectly as 03456 * greater than those values. This has the nice side effect 03457 * that we gain an overall optimized comparison with zeroes. 03458 * Note that a "0" has a "total" of 1 already. 03459 */ 03460 if (integx == 1) { 03461 if (x->value.decimal.lo == 0) { 03462 if (integy != 1) 03463 return -order; 03464 else if (y->value.decimal.lo != 0) 03465 return -order; 03466 else 03467 return(0); 03468 } 03469 } 03470 if (integy == 1) { 03471 if (y->value.decimal.lo == 0) { 03472 if (integx != 1) 03473 return order; 03474 else if (x->value.decimal.lo != 0) 03475 return order; 03476 else 03477 return(0); 03478 } 03479 } 03480 03481 if (integx > integy) 03482 return order; 03483 else if (integy > integx) 03484 return -order; 03485 03486 /* 03487 * If the number of integral digits is the same for both numbers, 03488 * then things get a little more complicated. We need to "normalize" 03489 * the numbers in order to properly compare them. To do this, we 03490 * look at the total length of each number (length => number of 03491 * significant digits), and divide the "shorter" by 10 (decreasing 03492 * the length) until they are of equal length. 03493 */ 03494 dlen = x->value.decimal.total - y->value.decimal.total; 03495 if (dlen < 0) { /* y has more digits than x */ 03496 swp = x; 03497 hi = y->value.decimal.hi; 03498 mi = y->value.decimal.mi; 03499 lo = y->value.decimal.lo; 03500 dlen = -dlen; 03501 order = -order; 03502 } else { /* x has more digits than y */ 03503 swp = y; 03504 hi = x->value.decimal.hi; 03505 mi = x->value.decimal.mi; 03506 lo = x->value.decimal.lo; 03507 } 03508 while (dlen > 8) { /* in effect, right shift by 10**8 */ 03509 lo = mi; 03510 mi = hi; 03511 hi = 0; 03512 dlen -= 8; 03513 } 03514 while (dlen > 0) { 03515 unsigned long rem1, rem2; 03516 rem1 = (hi % 10) * 100000000L; 03517 hi = hi / 10; 03518 rem2 = (mi % 10) * 100000000L; 03519 mi = (mi + rem1) / 10; 03520 lo = (lo + rem2) / 10; 03521 dlen--; 03522 } 03523 if (hi > swp->value.decimal.hi) { 03524 return order; 03525 } else if (hi == swp->value.decimal.hi) { 03526 if (mi > swp->value.decimal.mi) { 03527 return order; 03528 } else if (mi == swp->value.decimal.mi) { 03529 if (lo > swp->value.decimal.lo) { 03530 return order; 03531 } else if (lo == swp->value.decimal.lo) { 03532 if (x->value.decimal.total == y->value.decimal.total) { 03533 return 0; 03534 } else { 03535 return order; 03536 } 03537 } 03538 } 03539 } 03540 return -order; 03541 } 03542 03553 static int 03554 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y) 03555 { 03556 long carry, mon, day; 03557 double sec; 03558 int invert = 1; 03559 long xmon, xday, myear, minday, maxday; 03560 static const long dayRange [2][12] = { 03561 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, }, 03562 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} }; 03563 03564 if ((x == NULL) || (y == NULL)) 03565 return -2; 03566 03567 /* months */ 03568 mon = x->value.dur.mon - y->value.dur.mon; 03569 03570 /* seconds */ 03571 sec = x->value.dur.sec - y->value.dur.sec; 03572 carry = (long)sec / SECS_PER_DAY; 03573 sec -= (double)(carry * SECS_PER_DAY); 03574 03575 /* days */ 03576 day = x->value.dur.day - y->value.dur.day + carry; 03577 03578 /* easy test */ 03579 if (mon == 0) { 03580 if (day == 0) 03581 if (sec == 0.0) 03582 return 0; 03583 else if (sec < 0.0) 03584 return -1; 03585 else 03586 return 1; 03587 else if (day < 0) 03588 return -1; 03589 else 03590 return 1; 03591 } 03592 03593 if (mon > 0) { 03594 if ((day >= 0) && (sec >= 0.0)) 03595 return 1; 03596 else { 03597 xmon = mon; 03598 xday = -day; 03599 } 03600 } else if ((day <= 0) && (sec <= 0.0)) { 03601 return -1; 03602 } else { 03603 invert = -1; 03604 xmon = -mon; 03605 xday = day; 03606 } 03607 03608 myear = xmon / 12; 03609 if (myear == 0) { 03610 minday = 0; 03611 maxday = 0; 03612 } else { 03613 maxday = 366 * ((myear + 3) / 4) + 03614 365 * ((myear - 1) % 4); 03615 minday = maxday - 1; 03616 } 03617 03618 xmon = xmon % 12; 03619 minday += dayRange[0][xmon]; 03620 maxday += dayRange[1][xmon]; 03621 03622 if ((maxday == minday) && (maxday == xday)) 03623 return(0); /* can this really happen ? */ 03624 if (maxday < xday) 03625 return(-invert); 03626 if (minday > xday) 03627 return(invert); 03628 03629 /* indeterminate */ 03630 return 2; 03631 } 03632 03633 /* 03634 * macros for adding date/times and durations 03635 */ 03636 #define FQUOTIENT(a,b) (floor(((double)a/(double)b))) 03637 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b) 03638 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low))) 03639 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low) 03640 03650 static xmlSchemaValPtr 03651 xmlSchemaDupVal (xmlSchemaValPtr v) 03652 { 03653 xmlSchemaValPtr ret = xmlSchemaNewValue(v->type); 03654 if (ret == NULL) 03655 return NULL; 03656 03657 memcpy(ret, v, sizeof(xmlSchemaVal)); 03658 ret->next = NULL; 03659 return ret; 03660 } 03661 03670 xmlSchemaValPtr 03671 xmlSchemaCopyValue(xmlSchemaValPtr val) 03672 { 03673 xmlSchemaValPtr ret = NULL, prev = NULL, cur; 03674 03675 /* 03676 * Copy the string values. 03677 */ 03678 while (val != NULL) { 03679 switch (val->type) { 03680 case XML_SCHEMAS_ANYTYPE: 03681 case XML_SCHEMAS_IDREFS: 03682 case XML_SCHEMAS_ENTITIES: 03683 case XML_SCHEMAS_NMTOKENS: 03684 xmlSchemaFreeValue(ret); 03685 return (NULL); 03686 case XML_SCHEMAS_ANYSIMPLETYPE: 03687 case XML_SCHEMAS_STRING: 03688 case XML_SCHEMAS_NORMSTRING: 03689 case XML_SCHEMAS_TOKEN: 03690 case XML_SCHEMAS_LANGUAGE: 03691 case XML_SCHEMAS_NAME: 03692 case XML_SCHEMAS_NCNAME: 03693 case XML_SCHEMAS_ID: 03694 case XML_SCHEMAS_IDREF: 03695 case XML_SCHEMAS_ENTITY: 03696 case XML_SCHEMAS_NMTOKEN: 03697 case XML_SCHEMAS_ANYURI: 03698 cur = xmlSchemaDupVal(val); 03699 if (val->value.str != NULL) 03700 cur->value.str = xmlStrdup(BAD_CAST val->value.str); 03701 break; 03702 case XML_SCHEMAS_QNAME: 03703 case XML_SCHEMAS_NOTATION: 03704 cur = xmlSchemaDupVal(val); 03705 if (val->value.qname.name != NULL) 03706 cur->value.qname.name = 03707 xmlStrdup(BAD_CAST val->value.qname.name); 03708 if (val->value.qname.uri != NULL) 03709 cur->value.qname.uri = 03710 xmlStrdup(BAD_CAST val->value.qname.uri); 03711 break; 03712 case XML_SCHEMAS_HEXBINARY: 03713 cur = xmlSchemaDupVal(val); 03714 if (val->value.hex.str != NULL) 03715 cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str); 03716 break; 03717 case XML_SCHEMAS_BASE64BINARY: 03718 cur = xmlSchemaDupVal(val); 03719 if (val->value.base64.str != NULL) 03720 cur->value.base64.str = 03721 xmlStrdup(BAD_CAST val->value.base64.str); 03722 break; 03723 default: 03724 cur = xmlSchemaDupVal(val); 03725 break; 03726 } 03727 if (ret == NULL) 03728 ret = cur; 03729 else 03730 prev->next = cur; 03731 prev = cur; 03732 val = val->next; 03733 } 03734 return (ret); 03735 } 03736 03749 static xmlSchemaValPtr 03750 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur) 03751 { 03752 xmlSchemaValPtr ret, tmp; 03753 long carry, tempdays, temp; 03754 xmlSchemaValDatePtr r, d; 03755 xmlSchemaValDurationPtr u; 03756 03757 if ((dt == NULL) || (dur == NULL)) 03758 return NULL; 03759 03760 ret = xmlSchemaNewValue(dt->type); 03761 if (ret == NULL) 03762 return NULL; 03763 03764 /* make a copy so we don't alter the original value */ 03765 tmp = xmlSchemaDupVal(dt); 03766 if (tmp == NULL) { 03767 xmlSchemaFreeValue(ret); 03768 return NULL; 03769 } 03770 03771 r = &(ret->value.date); 03772 d = &(tmp->value.date); 03773 u = &(dur->value.dur); 03774 03775 /* normalization */ 03776 if (d->mon == 0) 03777 d->mon = 1; 03778 03779 /* normalize for time zone offset */ 03780 u->sec -= (d->tzo * 60); 03781 d->tzo = 0; 03782 03783 /* normalization */ 03784 if (d->day == 0) 03785 d->day = 1; 03786 03787 /* month */ 03788 carry = d->mon + u->mon; 03789 r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13); 03790 carry = (long) FQUOTIENT_RANGE(carry, 1, 13); 03791 03792 /* year (may be modified later) */ 03793 r->year = d->year + carry; 03794 if (r->year == 0) { 03795 if (d->year > 0) 03796 r->year--; 03797 else 03798 r->year++; 03799 } 03800 03801 /* time zone */ 03802 r->tzo = d->tzo; 03803 r->tz_flag = d->tz_flag; 03804 03805 /* seconds */ 03806 r->sec = d->sec + u->sec; 03807 carry = (long) FQUOTIENT((long)r->sec, 60); 03808 if (r->sec != 0.0) { 03809 r->sec = MODULO(r->sec, 60.0); 03810 } 03811 03812 /* minute */ 03813 carry += d->min; 03814 r->min = (unsigned int) MODULO(carry, 60); 03815 carry = (long) FQUOTIENT(carry, 60); 03816 03817 /* hours */ 03818 carry += d->hour; 03819 r->hour = (unsigned int) MODULO(carry, 24); 03820 carry = (long)FQUOTIENT(carry, 24); 03821 03822 /* 03823 * days 03824 * Note we use tempdays because the temporary values may need more 03825 * than 5 bits 03826 */ 03827 if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) && 03828 (d->day > MAX_DAYINMONTH(r->year, r->mon))) 03829 tempdays = MAX_DAYINMONTH(r->year, r->mon); 03830 else if (d->day < 1) 03831 tempdays = 1; 03832 else 03833 tempdays = d->day; 03834 03835 tempdays += u->day + carry; 03836 03837 while (1) { 03838 if (tempdays < 1) { 03839 long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13); 03840 long tyr = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13); 03841 if (tyr == 0) 03842 tyr--; 03843 /* 03844 * Coverity detected an overrun in daysInMonth 03845 * of size 12 at position 12 with index variable "((r)->mon - 1)" 03846 */ 03847 if (tmon < 0) 03848 tmon = 0; 03849 if (tmon > 12) 03850 tmon = 12; 03851 tempdays += MAX_DAYINMONTH(tyr, tmon); 03852 carry = -1; 03853 } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) { 03854 tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon); 03855 carry = 1; 03856 } else 03857 break; 03858 03859 temp = r->mon + carry; 03860 r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13); 03861 r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13); 03862 if (r->year == 0) { 03863 if (temp < 1) 03864 r->year--; 03865 else 03866 r->year++; 03867 } 03868 } 03869 03870 r->day = tempdays; 03871 03872 /* 03873 * adjust the date/time type to the date values 03874 */ 03875 if (ret->type != XML_SCHEMAS_DATETIME) { 03876 if ((r->hour) || (r->min) || (r->sec)) 03877 ret->type = XML_SCHEMAS_DATETIME; 03878 else if (ret->type != XML_SCHEMAS_DATE) { 03879 if ((r->mon != 1) && (r->day != 1)) 03880 ret->type = XML_SCHEMAS_DATE; 03881 else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1)) 03882 ret->type = XML_SCHEMAS_GYEARMONTH; 03883 } 03884 } 03885 03886 xmlSchemaFreeValue(tmp); 03887 03888 return ret; 03889 } 03890 03901 static xmlSchemaValPtr 03902 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset) 03903 { 03904 xmlSchemaValPtr dur, ret; 03905 03906 if (dt == NULL) 03907 return NULL; 03908 03909 if (((dt->type != XML_SCHEMAS_TIME) && 03910 (dt->type != XML_SCHEMAS_DATETIME) && 03911 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0)) 03912 return xmlSchemaDupVal(dt); 03913 03914 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); 03915 if (dur == NULL) 03916 return NULL; 03917 03918 dur->value.date.sec -= offset; 03919 03920 ret = _xmlSchemaDateAdd(dt, dur); 03921 if (ret == NULL) 03922 return NULL; 03923 03924 xmlSchemaFreeValue(dur); 03925 03926 /* ret->value.date.tzo = 0; */ 03927 return ret; 03928 } 03929 03941 static long 03942 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt) 03943 { 03944 long ret; 03945 int mon; 03946 03947 mon = dt->value.date.mon; 03948 if (mon <= 0) mon = 1; /* normalization */ 03949 03950 if (dt->value.date.year <= 0) 03951 ret = (dt->value.date.year * 365) + 03952 (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+ 03953 ((dt->value.date.year+1)/400)) + 03954 DAY_IN_YEAR(0, mon, dt->value.date.year); 03955 else 03956 ret = ((dt->value.date.year-1) * 365) + 03957 (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+ 03958 ((dt->value.date.year-1)/400)) + 03959 DAY_IN_YEAR(0, mon, dt->value.date.year); 03960 03961 return ret; 03962 } 03963 03972 #define TIME_TO_NUMBER(dt) \ 03973 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \ 03974 (dt->value.date.min * SECS_PER_MIN) + \ 03975 (dt->value.date.tzo * SECS_PER_MIN)) + \ 03976 dt->value.date.sec) 03977 03988 static int 03989 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y) 03990 { 03991 unsigned char xmask, ymask, xor_mask, and_mask; 03992 xmlSchemaValPtr p1, p2, q1, q2; 03993 long p1d, p2d, q1d, q2d; 03994 03995 if ((x == NULL) || (y == NULL)) 03996 return -2; 03997 03998 if (x->value.date.tz_flag) { 03999 04000 if (!y->value.date.tz_flag) { 04001 p1 = xmlSchemaDateNormalize(x, 0); 04002 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; 04003 /* normalize y + 14:00 */ 04004 q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR)); 04005 04006 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; 04007 if (p1d < q1d) { 04008 xmlSchemaFreeValue(p1); 04009 xmlSchemaFreeValue(q1); 04010 return -1; 04011 } else if (p1d == q1d) { 04012 double sec; 04013 04014 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); 04015 if (sec < 0.0) { 04016 xmlSchemaFreeValue(p1); 04017 xmlSchemaFreeValue(q1); 04018 return -1; 04019 } else { 04020 int ret = 0; 04021 /* normalize y - 14:00 */ 04022 q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR)); 04023 q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day; 04024 if (p1d > q2d) 04025 ret = 1; 04026 else if (p1d == q2d) { 04027 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2); 04028 if (sec > 0.0) 04029 ret = 1; 04030 else 04031 ret = 2; /* indeterminate */ 04032 } 04033 xmlSchemaFreeValue(p1); 04034 xmlSchemaFreeValue(q1); 04035 xmlSchemaFreeValue(q2); 04036 if (ret != 0) 04037 return(ret); 04038 } 04039 } else { 04040 xmlSchemaFreeValue(p1); 04041 xmlSchemaFreeValue(q1); 04042 } 04043 } 04044 } else if (y->value.date.tz_flag) { 04045 q1 = xmlSchemaDateNormalize(y, 0); 04046 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; 04047 04048 /* normalize x - 14:00 */ 04049 p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR)); 04050 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; 04051 04052 if (p1d < q1d) { 04053 xmlSchemaFreeValue(p1); 04054 xmlSchemaFreeValue(q1); 04055 return -1; 04056 } else if (p1d == q1d) { 04057 double sec; 04058 04059 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); 04060 if (sec < 0.0) { 04061 xmlSchemaFreeValue(p1); 04062 xmlSchemaFreeValue(q1); 04063 return -1; 04064 } else { 04065 int ret = 0; 04066 /* normalize x + 14:00 */ 04067 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR)); 04068 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day; 04069 04070 if (p2d > q1d) { 04071 ret = 1; 04072 } else if (p2d == q1d) { 04073 sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1); 04074 if (sec > 0.0) 04075 ret = 1; 04076 else 04077 ret = 2; /* indeterminate */ 04078 } 04079 xmlSchemaFreeValue(p1); 04080 xmlSchemaFreeValue(q1); 04081 xmlSchemaFreeValue(p2); 04082 if (ret != 0) 04083 return(ret); 04084 } 04085 } else { 04086 xmlSchemaFreeValue(p1); 04087 xmlSchemaFreeValue(q1); 04088 } 04089 } 04090 04091 /* 04092 * if the same type then calculate the difference 04093 */ 04094 if (x->type == y->type) { 04095 int ret = 0; 04096 q1 = xmlSchemaDateNormalize(y, 0); 04097 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; 04098 04099 p1 = xmlSchemaDateNormalize(x, 0); 04100 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; 04101 04102 if (p1d < q1d) { 04103 ret = -1; 04104 } else if (p1d > q1d) { 04105 ret = 1; 04106 } else { 04107 double sec; 04108 04109 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); 04110 if (sec < 0.0) 04111 ret = -1; 04112 else if (sec > 0.0) 04113 ret = 1; 04114 04115 } 04116 xmlSchemaFreeValue(p1); 04117 xmlSchemaFreeValue(q1); 04118 return(ret); 04119 } 04120 04121 switch (x->type) { 04122 case XML_SCHEMAS_DATETIME: 04123 xmask = 0xf; 04124 break; 04125 case XML_SCHEMAS_DATE: 04126 xmask = 0x7; 04127 break; 04128 case XML_SCHEMAS_GYEAR: 04129 xmask = 0x1; 04130 break; 04131 case XML_SCHEMAS_GMONTH: 04132 xmask = 0x2; 04133 break; 04134 case XML_SCHEMAS_GDAY: 04135 xmask = 0x3; 04136 break; 04137 case XML_SCHEMAS_GYEARMONTH: 04138 xmask = 0x3; 04139 break; 04140 case XML_SCHEMAS_GMONTHDAY: 04141 xmask = 0x6; 04142 break; 04143 case XML_SCHEMAS_TIME: 04144 xmask = 0x8; 04145 break; 04146 default: 04147 xmask = 0; 04148 break; 04149 } 04150 04151 switch (y->type) { 04152 case XML_SCHEMAS_DATETIME: 04153 ymask = 0xf; 04154 break; 04155 case XML_SCHEMAS_DATE: 04156 ymask = 0x7; 04157 break; 04158 case XML_SCHEMAS_GYEAR: 04159 ymask = 0x1; 04160 break; 04161 case XML_SCHEMAS_GMONTH: 04162 ymask = 0x2; 04163 break; 04164 case XML_SCHEMAS_GDAY: 04165 ymask = 0x3; 04166 break; 04167 case XML_SCHEMAS_GYEARMONTH: 04168 ymask = 0x3; 04169 break; 04170 case XML_SCHEMAS_GMONTHDAY: 04171 ymask = 0x6; 04172 break; 04173 case XML_SCHEMAS_TIME: 04174 ymask = 0x8; 04175 break; 04176 default: 04177 ymask = 0; 04178 break; 04179 } 04180 04181 xor_mask = xmask ^ ymask; /* mark type differences */ 04182 and_mask = xmask & ymask; /* mark field specification */ 04183 04184 /* year */ 04185 if (xor_mask & 1) 04186 return 2; /* indeterminate */ 04187 else if (and_mask & 1) { 04188 if (x->value.date.year < y->value.date.year) 04189 return -1; 04190 else if (x->value.date.year > y->value.date.year) 04191 return 1; 04192 } 04193 04194 /* month */ 04195 if (xor_mask & 2) 04196 return 2; /* indeterminate */ 04197 else if (and_mask & 2) { 04198 if (x->value.date.mon < y->value.date.mon) 04199 return -1; 04200 else if (x->value.date.mon > y->value.date.mon) 04201 return 1; 04202 } 04203 04204 /* day */ 04205 if (xor_mask & 4) 04206 return 2; /* indeterminate */ 04207 else if (and_mask & 4) { 04208 if (x->value.date.day < y->value.date.day) 04209 return -1; 04210 else if (x->value.date.day > y->value.date.day) 04211 return 1; 04212 } 04213 04214 /* time */ 04215 if (xor_mask & 8) 04216 return 2; /* indeterminate */ 04217 else if (and_mask & 8) { 04218 if (x->value.date.hour < y->value.date.hour) 04219 return -1; 04220 else if (x->value.date.hour > y->value.date.hour) 04221 return 1; 04222 else if (x->value.date.min < y->value.date.min) 04223 return -1; 04224 else if (x->value.date.min > y->value.date.min) 04225 return 1; 04226 else if (x->value.date.sec < y->value.date.sec) 04227 return -1; 04228 else if (x->value.date.sec > y->value.date.sec) 04229 return 1; 04230 } 04231 04232 return 0; 04233 } 04234 04249 static int 04250 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x, 04251 const xmlChar *y, 04252 int invert) 04253 { 04254 int tmp; 04255 04256 while ((*x != 0) && (*y != 0)) { 04257 if (IS_WSP_REPLACE_CH(*y)) { 04258 if (! IS_WSP_SPACE_CH(*x)) { 04259 if ((*x - 0x20) < 0) { 04260 if (invert) 04261 return(1); 04262 else 04263 return(-1); 04264 } else { 04265 if (invert) 04266 return(-1); 04267 else 04268 return(1); 04269 } 04270 } 04271 } else { 04272 tmp = *x - *y; 04273 if (tmp < 0) { 04274 if (invert) 04275 return(1); 04276 else 04277 return(-1); 04278 } 04279 if (tmp > 0) { 04280 if (invert) 04281 return(-1); 04282 else 04283 return(1); 04284 } 04285 } 04286 x++; 04287 y++; 04288 } 04289 if (*x != 0) { 04290 if (invert) 04291 return(-1); 04292 else 04293 return(1); 04294 } 04295 if (*y != 0) { 04296 if (invert) 04297 return(1); 04298 else 04299 return(-1); 04300 } 04301 return(0); 04302 } 04303 04317 static int 04318 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x, 04319 const xmlChar *y, 04320 int invert) 04321 { 04322 int tmp; 04323 04324 /* 04325 * Skip leading blank chars of the collapsed string. 04326 */ 04327 while IS_WSP_BLANK_CH(*y) 04328 y++; 04329 04330 while ((*x != 0) && (*y != 0)) { 04331 if IS_WSP_BLANK_CH(*y) { 04332 if (! IS_WSP_SPACE_CH(*x)) { 04333 /* 04334 * The yv character would have been replaced to 0x20. 04335 */ 04336 if ((*x - 0x20) < 0) { 04337 if (invert) 04338 return(1); 04339 else 04340 return(-1); 04341 } else { 04342 if (invert) 04343 return(-1); 04344 else 04345 return(1); 04346 } 04347 } 04348 x++; 04349 y++; 04350 /* 04351 * Skip contiguous blank chars of the collapsed string. 04352 */ 04353 while IS_WSP_BLANK_CH(*y) 04354 y++; 04355 } else { 04356 tmp = *x++ - *y++; 04357 if (tmp < 0) { 04358 if (invert) 04359 return(1); 04360 else 04361 return(-1); 04362 } 04363 if (tmp > 0) { 04364 if (invert) 04365 return(-1); 04366 else 04367 return(1); 04368 } 04369 } 04370 } 04371 if (*x != 0) { 04372 if (invert) 04373 return(-1); 04374 else 04375 return(1); 04376 } 04377 if (*y != 0) { 04378 /* 04379 * Skip trailing blank chars of the collapsed string. 04380 */ 04381 while IS_WSP_BLANK_CH(*y) 04382 y++; 04383 if (*y != 0) { 04384 if (invert) 04385 return(1); 04386 else 04387 return(-1); 04388 } 04389 } 04390 return(0); 04391 } 04392 04406 static int 04407 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x, 04408 const xmlChar *y, 04409 int invert) 04410 { 04411 int tmp; 04412 04413 /* 04414 * Skip leading blank chars of the collapsed string. 04415 */ 04416 while IS_WSP_BLANK_CH(*y) 04417 y++; 04418 04419 while ((*x != 0) && (*y != 0)) { 04420 if IS_WSP_BLANK_CH(*y) { 04421 if (! IS_WSP_BLANK_CH(*x)) { 04422 /* 04423 * The yv character would have been replaced to 0x20. 04424 */ 04425 if ((*x - 0x20) < 0) { 04426 if (invert) 04427 return(1); 04428 else 04429 return(-1); 04430 } else { 04431 if (invert) 04432 return(-1); 04433 else 04434 return(1); 04435 } 04436 } 04437 x++; 04438 y++; 04439 /* 04440 * Skip contiguous blank chars of the collapsed string. 04441 */ 04442 while IS_WSP_BLANK_CH(*y) 04443 y++; 04444 } else { 04445 if IS_WSP_BLANK_CH(*x) { 04446 /* 04447 * The xv character would have been replaced to 0x20. 04448 */ 04449 if ((0x20 - *y) < 0) { 04450 if (invert) 04451 return(1); 04452 else 04453 return(-1); 04454 } else { 04455 if (invert) 04456 return(-1); 04457 else 04458 return(1); 04459 } 04460 } 04461 tmp = *x++ - *y++; 04462 if (tmp < 0) 04463 return(-1); 04464 if (tmp > 0) 04465 return(1); 04466 } 04467 } 04468 if (*x != 0) { 04469 if (invert) 04470 return(-1); 04471 else 04472 return(1); 04473 } 04474 if (*y != 0) { 04475 /* 04476 * Skip trailing blank chars of the collapsed string. 04477 */ 04478 while IS_WSP_BLANK_CH(*y) 04479 y++; 04480 if (*y != 0) { 04481 if (invert) 04482 return(1); 04483 else 04484 return(-1); 04485 } 04486 } 04487 return(0); 04488 } 04489 04490 04501 static int 04502 xmlSchemaCompareReplacedStrings(const xmlChar *x, 04503 const xmlChar *y) 04504 { 04505 int tmp; 04506 04507 while ((*x != 0) && (*y != 0)) { 04508 if IS_WSP_BLANK_CH(*y) { 04509 if (! IS_WSP_BLANK_CH(*x)) { 04510 if ((*x - 0x20) < 0) 04511 return(-1); 04512 else 04513 return(1); 04514 } 04515 } else { 04516 if IS_WSP_BLANK_CH(*x) { 04517 if ((0x20 - *y) < 0) 04518 return(-1); 04519 else 04520 return(1); 04521 } 04522 tmp = *x - *y; 04523 if (tmp < 0) 04524 return(-1); 04525 if (tmp > 0) 04526 return(1); 04527 } 04528 x++; 04529 y++; 04530 } 04531 if (*x != 0) 04532 return(1); 04533 if (*y != 0) 04534 return(-1); 04535 return(0); 04536 } 04537 04548 static int 04549 xmlSchemaCompareNormStrings(const xmlChar *x, 04550 const xmlChar *y) { 04551 int tmp; 04552 04553 while (IS_BLANK_CH(*x)) x++; 04554 while (IS_BLANK_CH(*y)) y++; 04555 while ((*x != 0) && (*y != 0)) { 04556 if (IS_BLANK_CH(*x)) { 04557 if (!IS_BLANK_CH(*y)) { 04558 tmp = *x - *y; 04559 return(tmp); 04560 } 04561 while (IS_BLANK_CH(*x)) x++; 04562 while (IS_BLANK_CH(*y)) y++; 04563 } else { 04564 tmp = *x++ - *y++; 04565 if (tmp < 0) 04566 return(-1); 04567 if (tmp > 0) 04568 return(1); 04569 } 04570 } 04571 if (*x != 0) { 04572 while (IS_BLANK_CH(*x)) x++; 04573 if (*x != 0) 04574 return(1); 04575 } 04576 if (*y != 0) { 04577 while (IS_BLANK_CH(*y)) y++; 04578 if (*y != 0) 04579 return(-1); 04580 } 04581 return(0); 04582 } 04583 04594 static int 04595 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) { 04596 double d1, d2; 04597 04598 if ((x == NULL) || (y == NULL)) 04599 return(-2); 04600 04601 /* 04602 * Cast everything to doubles. 04603 */ 04604 if (x->type == XML_SCHEMAS_DOUBLE) 04605 d1 = x->value.d; 04606 else if (x->type == XML_SCHEMAS_FLOAT) 04607 d1 = x->value.f; 04608 else 04609 return(-2); 04610 04611 if (y->type == XML_SCHEMAS_DOUBLE) 04612 d2 = y->value.d; 04613 else if (y->type == XML_SCHEMAS_FLOAT) 04614 d2 = y->value.f; 04615 else 04616 return(-2); 04617 04618 /* 04619 * Check for special cases. 04620 */ 04621 if (xmlXPathIsNaN(d1)) { 04622 if (xmlXPathIsNaN(d2)) 04623 return(0); 04624 return(1); 04625 } 04626 if (xmlXPathIsNaN(d2)) 04627 return(-1); 04628 if (d1 == xmlXPathPINF) { 04629 if (d2 == xmlXPathPINF) 04630 return(0); 04631 return(1); 04632 } 04633 if (d2 == xmlXPathPINF) 04634 return(-1); 04635 if (d1 == xmlXPathNINF) { 04636 if (d2 == xmlXPathNINF) 04637 return(0); 04638 return(-1); 04639 } 04640 if (d2 == xmlXPathNINF) 04641 return(1); 04642 04643 /* 04644 * basic tests, the last one we should have equality, but 04645 * portability is more important than speed and handling 04646 * NaN or Inf in a portable way is always a challenge, so ... 04647 */ 04648 if (d1 < d2) 04649 return(-1); 04650 if (d1 > d2) 04651 return(1); 04652 if (d1 == d2) 04653 return(0); 04654 return(2); 04655 } 04656 04671 static int 04672 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype, 04673 xmlSchemaValPtr x, 04674 const xmlChar *xvalue, 04675 xmlSchemaWhitespaceValueType xws, 04676 xmlSchemaValType ytype, 04677 xmlSchemaValPtr y, 04678 const xmlChar *yvalue, 04679 xmlSchemaWhitespaceValueType yws) 04680 { 04681 switch (xtype) { 04682 case XML_SCHEMAS_UNKNOWN: 04683 case XML_SCHEMAS_ANYTYPE: 04684 return(-2); 04685 case XML_SCHEMAS_INTEGER: 04686 case XML_SCHEMAS_NPINTEGER: 04687 case XML_SCHEMAS_NINTEGER: 04688 case XML_SCHEMAS_NNINTEGER: 04689 case XML_SCHEMAS_PINTEGER: 04690 case XML_SCHEMAS_INT: 04691 case XML_SCHEMAS_UINT: 04692 case XML_SCHEMAS_LONG: 04693 case XML_SCHEMAS_ULONG: 04694 case XML_SCHEMAS_SHORT: 04695 case XML_SCHEMAS_USHORT: 04696 case XML_SCHEMAS_BYTE: 04697 case XML_SCHEMAS_UBYTE: 04698 case XML_SCHEMAS_DECIMAL: 04699 if ((x == NULL) || (y == NULL)) 04700 return(-2); 04701 if (ytype == xtype) 04702 return(xmlSchemaCompareDecimals(x, y)); 04703 if ((ytype == XML_SCHEMAS_DECIMAL) || 04704 (ytype == XML_SCHEMAS_INTEGER) || 04705 (ytype == XML_SCHEMAS_NPINTEGER) || 04706 (ytype == XML_SCHEMAS_NINTEGER) || 04707 (ytype == XML_SCHEMAS_NNINTEGER) || 04708 (ytype == XML_SCHEMAS_PINTEGER) || 04709 (ytype == XML_SCHEMAS_INT) || 04710 (ytype == XML_SCHEMAS_UINT) || 04711 (ytype == XML_SCHEMAS_LONG) || 04712 (ytype == XML_SCHEMAS_ULONG) || 04713 (ytype == XML_SCHEMAS_SHORT) || 04714 (ytype == XML_SCHEMAS_USHORT) || 04715 (ytype == XML_SCHEMAS_BYTE) || 04716 (ytype == XML_SCHEMAS_UBYTE)) 04717 return(xmlSchemaCompareDecimals(x, y)); 04718 return(-2); 04719 case XML_SCHEMAS_DURATION: 04720 if ((x == NULL) || (y == NULL)) 04721 return(-2); 04722 if (ytype == XML_SCHEMAS_DURATION) 04723 return(xmlSchemaCompareDurations(x, y)); 04724 return(-2); 04725 case XML_SCHEMAS_TIME: 04726 case XML_SCHEMAS_GDAY: 04727 case XML_SCHEMAS_GMONTH: 04728 case XML_SCHEMAS_GMONTHDAY: 04729 case XML_SCHEMAS_GYEAR: 04730 case XML_SCHEMAS_GYEARMONTH: 04731 case XML_SCHEMAS_DATE: 04732 case XML_SCHEMAS_DATETIME: 04733 if ((x == NULL) || (y == NULL)) 04734 return(-2); 04735 if ((ytype == XML_SCHEMAS_DATETIME) || 04736 (ytype == XML_SCHEMAS_TIME) || 04737 (ytype == XML_SCHEMAS_GDAY) || 04738 (ytype == XML_SCHEMAS_GMONTH) || 04739 (ytype == XML_SCHEMAS_GMONTHDAY) || 04740 (ytype == XML_SCHEMAS_GYEAR) || 04741 (ytype == XML_SCHEMAS_DATE) || 04742 (ytype == XML_SCHEMAS_GYEARMONTH)) 04743 return (xmlSchemaCompareDates(x, y)); 04744 return (-2); 04745 /* 04746 * Note that we will support comparison of string types against 04747 * anySimpleType as well. 04748 */ 04749 case XML_SCHEMAS_ANYSIMPLETYPE: 04750 case XML_SCHEMAS_STRING: 04751 case XML_SCHEMAS_NORMSTRING: 04752 case XML_SCHEMAS_TOKEN: 04753 case XML_SCHEMAS_LANGUAGE: 04754 case XML_SCHEMAS_NMTOKEN: 04755 case XML_SCHEMAS_NAME: 04756 case XML_SCHEMAS_NCNAME: 04757 case XML_SCHEMAS_ID: 04758 case XML_SCHEMAS_IDREF: 04759 case XML_SCHEMAS_ENTITY: 04760 case XML_SCHEMAS_ANYURI: 04761 { 04762 const xmlChar *xv, *yv; 04763 04764 if (x == NULL) 04765 xv = xvalue; 04766 else 04767 xv = x->value.str; 04768 if (y == NULL) 04769 yv = yvalue; 04770 else 04771 yv = y->value.str; 04772 /* 04773 * TODO: Compare those against QName. 04774 */ 04775 if (ytype == XML_SCHEMAS_QNAME) { 04776 TODO 04777 if (y == NULL) 04778 return(-2); 04779 return (-2); 04780 } 04781 if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) || 04782 (ytype == XML_SCHEMAS_STRING) || 04783 (ytype == XML_SCHEMAS_NORMSTRING) || 04784 (ytype == XML_SCHEMAS_TOKEN) || 04785 (ytype == XML_SCHEMAS_LANGUAGE) || 04786 (ytype == XML_SCHEMAS_NMTOKEN) || 04787 (ytype == XML_SCHEMAS_NAME) || 04788 (ytype == XML_SCHEMAS_NCNAME) || 04789 (ytype == XML_SCHEMAS_ID) || 04790 (ytype == XML_SCHEMAS_IDREF) || 04791 (ytype == XML_SCHEMAS_ENTITY) || 04792 (ytype == XML_SCHEMAS_ANYURI)) { 04793 04794 if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) { 04795 04796 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) { 04797 /* TODO: What about x < y or x > y. */ 04798 if (xmlStrEqual(xv, yv)) 04799 return (0); 04800 else 04801 return (2); 04802 } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE) 04803 return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0)); 04804 else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) 04805 return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0)); 04806 04807 } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) { 04808 04809 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) 04810 return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1)); 04811 if (yws == XML_SCHEMA_WHITESPACE_REPLACE) 04812 return (xmlSchemaCompareReplacedStrings(xv, yv)); 04813 if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) 04814 return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0)); 04815 04816 } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) { 04817 04818 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) 04819 return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1)); 04820 if (yws == XML_SCHEMA_WHITESPACE_REPLACE) 04821 return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1)); 04822 if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) 04823 return (xmlSchemaCompareNormStrings(xv, yv)); 04824 } else 04825 return (-2); 04826 04827 } 04828 return (-2); 04829 } 04830 case XML_SCHEMAS_QNAME: 04831 case XML_SCHEMAS_NOTATION: 04832 if ((x == NULL) || (y == NULL)) 04833 return(-2); 04834 if ((ytype == XML_SCHEMAS_QNAME) || 04835 (ytype == XML_SCHEMAS_NOTATION)) { 04836 if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) && 04837 (xmlStrEqual(x->value.qname.uri, y->value.qname.uri))) 04838 return(0); 04839 return(2); 04840 } 04841 return (-2); 04842 case XML_SCHEMAS_FLOAT: 04843 case XML_SCHEMAS_DOUBLE: 04844 if ((x == NULL) || (y == NULL)) 04845 return(-2); 04846 if ((ytype == XML_SCHEMAS_FLOAT) || 04847 (ytype == XML_SCHEMAS_DOUBLE)) 04848 return (xmlSchemaCompareFloats(x, y)); 04849 return (-2); 04850 case XML_SCHEMAS_BOOLEAN: 04851 if ((x == NULL) || (y == NULL)) 04852 return(-2); 04853 if (ytype == XML_SCHEMAS_BOOLEAN) { 04854 if (x->value.b == y->value.b) 04855 return(0); 04856 if (x->value.b == 0) 04857 return(-1); 04858 return(1); 04859 } 04860 return (-2); 04861 case XML_SCHEMAS_HEXBINARY: 04862 if ((x == NULL) || (y == NULL)) 04863 return(-2); 04864 if (ytype == XML_SCHEMAS_HEXBINARY) { 04865 if (x->value.hex.total == y->value.hex.total) { 04866 int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str); 04867 if (ret > 0) 04868 return(1); 04869 else if (ret == 0) 04870 return(0); 04871 } 04872 else if (x->value.hex.total > y->value.hex.total) 04873 return(1); 04874 04875 return(-1); 04876 } 04877 return (-2); 04878 case XML_SCHEMAS_BASE64BINARY: 04879 if ((x == NULL) || (y == NULL)) 04880 return(-2); 04881 if (ytype == XML_SCHEMAS_BASE64BINARY) { 04882 if (x->value.base64.total == y->value.base64.total) { 04883 int ret = xmlStrcmp(x->value.base64.str, 04884 y->value.base64.str); 04885 if (ret > 0) 04886 return(1); 04887 else if (ret == 0) 04888 return(0); 04889 else 04890 return(-1); 04891 } 04892 else if (x->value.base64.total > y->value.base64.total) 04893 return(1); 04894 else 04895 return(-1); 04896 } 04897 return (-2); 04898 case XML_SCHEMAS_IDREFS: 04899 case XML_SCHEMAS_ENTITIES: 04900 case XML_SCHEMAS_NMTOKENS: 04901 TODO 04902 break; 04903 } 04904 return -2; 04905 } 04906 04917 int 04918 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) { 04919 xmlSchemaWhitespaceValueType xws, yws; 04920 04921 if ((x == NULL) || (y == NULL)) 04922 return(-2); 04923 if (x->type == XML_SCHEMAS_STRING) 04924 xws = XML_SCHEMA_WHITESPACE_PRESERVE; 04925 else if (x->type == XML_SCHEMAS_NORMSTRING) 04926 xws = XML_SCHEMA_WHITESPACE_REPLACE; 04927 else 04928 xws = XML_SCHEMA_WHITESPACE_COLLAPSE; 04929 04930 if (y->type == XML_SCHEMAS_STRING) 04931 yws = XML_SCHEMA_WHITESPACE_PRESERVE; 04932 else if (x->type == XML_SCHEMAS_NORMSTRING) 04933 yws = XML_SCHEMA_WHITESPACE_REPLACE; 04934 else 04935 yws = XML_SCHEMA_WHITESPACE_COLLAPSE; 04936 04937 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, 04938 y, NULL, yws)); 04939 } 04940 04953 int 04954 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x, 04955 xmlSchemaWhitespaceValueType xws, 04956 xmlSchemaValPtr y, 04957 xmlSchemaWhitespaceValueType yws) 04958 { 04959 if ((x == NULL) || (y == NULL)) 04960 return(-2); 04961 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, 04962 y, NULL, yws)); 04963 } 04964 04977 static int 04978 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype, 04979 xmlSchemaValPtr x, 04980 const xmlChar *xvalue, 04981 xmlSchemaWhitespaceValueType xws, 04982 xmlSchemaValType ytype, 04983 xmlSchemaValPtr y, 04984 const xmlChar *yvalue, 04985 xmlSchemaWhitespaceValueType yws) 04986 { 04987 return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y, 04988 yvalue, yws)); 04989 } 04990 04999 static int 05000 xmlSchemaNormLen(const xmlChar *value) { 05001 const xmlChar *utf; 05002 int ret = 0; 05003 05004 if (value == NULL) 05005 return(-1); 05006 utf = value; 05007 while (IS_BLANK_CH(*utf)) utf++; 05008 while (*utf != 0) { 05009 if (utf[0] & 0x80) { 05010 if ((utf[1] & 0xc0) != 0x80) 05011 return(-1); 05012 if ((utf[0] & 0xe0) == 0xe0) { 05013 if ((utf[2] & 0xc0) != 0x80) 05014 return(-1); 05015 if ((utf[0] & 0xf0) == 0xf0) { 05016 if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) 05017 return(-1); 05018 utf += 4; 05019 } else { 05020 utf += 3; 05021 } 05022 } else { 05023 utf += 2; 05024 } 05025 } else if (IS_BLANK_CH(*utf)) { 05026 while (IS_BLANK_CH(*utf)) utf++; 05027 if (*utf == 0) 05028 break; 05029 } else { 05030 utf++; 05031 } 05032 ret++; 05033 } 05034 return(ret); 05035 } 05036 05045 unsigned long 05046 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet) 05047 { 05048 /* 05049 * TODO: Check if this is a decimal. 05050 */ 05051 if (facet == NULL) 05052 return 0; 05053 return ((unsigned long) facet->val->value.decimal.lo); 05054 } 05055 05068 int 05069 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet, 05070 const xmlChar *value, 05071 unsigned long actualLen, 05072 unsigned long *expectedLen) 05073 { 05074 if (facet == NULL) 05075 return(-1); 05076 /* 05077 * TODO: Check if this will work with large numbers. 05078 * (compare value.decimal.mi and value.decimal.hi as well?). 05079 */ 05080 if (facet->type == XML_SCHEMA_FACET_LENGTH) { 05081 if (actualLen != facet->val->value.decimal.lo) { 05082 if (expectedLen != NULL) 05083 *expectedLen = facet->val->value.decimal.lo; 05084 return (XML_SCHEMAV_CVC_LENGTH_VALID); 05085 } 05086 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { 05087 if (actualLen < facet->val->value.decimal.lo) { 05088 if (expectedLen != NULL) 05089 *expectedLen = facet->val->value.decimal.lo; 05090 return (XML_SCHEMAV_CVC_MINLENGTH_VALID); 05091 } 05092 } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) { 05093 if (actualLen > facet->val->value.decimal.lo) { 05094 if (expectedLen != NULL) 05095 *expectedLen = facet->val->value.decimal.lo; 05096 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID); 05097 } 05098 } else 05099 /* 05100 * NOTE: That we can pass NULL as xmlSchemaValPtr to 05101 * xmlSchemaValidateFacet, since the remaining facet types 05102 * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION. 05103 */ 05104 return(xmlSchemaValidateFacet(NULL, facet, value, NULL)); 05105 return (0); 05106 } 05107 05123 static int 05124 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet, 05125 xmlSchemaTypeType valType, 05126 const xmlChar *value, 05127 xmlSchemaValPtr val, 05128 unsigned long *length, 05129 xmlSchemaWhitespaceValueType ws) 05130 { 05131 unsigned int len = 0; 05132 05133 if ((length == NULL) || (facet == NULL)) 05134 return (-1); 05135 *length = 0; 05136 if ((facet->type != XML_SCHEMA_FACET_LENGTH) && 05137 (facet->type != XML_SCHEMA_FACET_MAXLENGTH) && 05138 (facet->type != XML_SCHEMA_FACET_MINLENGTH)) 05139 return (-1); 05140 05141 /* 05142 * TODO: length, maxLength and minLength must be of type 05143 * nonNegativeInteger only. Check if decimal is used somehow. 05144 */ 05145 if ((facet->val == NULL) || 05146 ((facet->val->type != XML_SCHEMAS_DECIMAL) && 05147 (facet->val->type != XML_SCHEMAS_NNINTEGER)) || 05148 (facet->val->value.decimal.frac != 0)) { 05149 return(-1); 05150 } 05151 if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) 05152 len = val->value.hex.total; 05153 else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) 05154 len = val->value.base64.total; 05155 else { 05156 switch (valType) { 05157 case XML_SCHEMAS_STRING: 05158 case XML_SCHEMAS_NORMSTRING: 05159 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { 05160 /* 05161 * This is to ensure API compatibility with the old 05162 * xmlSchemaValidateLengthFacet(). Anyway, this was and 05163 * is not the correct handling. 05164 * TODO: Get rid of this case somehow. 05165 */ 05166 if (valType == XML_SCHEMAS_STRING) 05167 len = xmlUTF8Strlen(value); 05168 else 05169 len = xmlSchemaNormLen(value); 05170 } else if (value != NULL) { 05171 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 05172 len = xmlSchemaNormLen(value); 05173 else 05174 /* 05175 * Should be OK for "preserve" as well. 05176 */ 05177 len = xmlUTF8Strlen(value); 05178 } 05179 break; 05180 case XML_SCHEMAS_IDREF: 05181 case XML_SCHEMAS_TOKEN: 05182 case XML_SCHEMAS_LANGUAGE: 05183 case XML_SCHEMAS_NMTOKEN: 05184 case XML_SCHEMAS_NAME: 05185 case XML_SCHEMAS_NCNAME: 05186 case XML_SCHEMAS_ID: 05187 /* 05188 * FIXME: What exactly to do with anyURI? 05189 */ 05190 case XML_SCHEMAS_ANYURI: 05191 if (value != NULL) 05192 len = xmlSchemaNormLen(value); 05193 break; 05194 case XML_SCHEMAS_QNAME: 05195 case XML_SCHEMAS_NOTATION: 05196 /* 05197 * For QName and NOTATION, those facets are 05198 * deprecated and should be ignored. 05199 */ 05200 return (0); 05201 default: 05202 TODO 05203 } 05204 } 05205 *length = (unsigned long) len; 05206 /* 05207 * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi". 05208 */ 05209 if (facet->type == XML_SCHEMA_FACET_LENGTH) { 05210 if (len != facet->val->value.decimal.lo) 05211 return(XML_SCHEMAV_CVC_LENGTH_VALID); 05212 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { 05213 if (len < facet->val->value.decimal.lo) 05214 return(XML_SCHEMAV_CVC_MINLENGTH_VALID); 05215 } else { 05216 if (len > facet->val->value.decimal.lo) 05217 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); 05218 } 05219 05220 return (0); 05221 } 05222 05237 int 05238 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type, 05239 xmlSchemaFacetPtr facet, 05240 const xmlChar *value, 05241 xmlSchemaValPtr val, 05242 unsigned long *length) 05243 { 05244 if (type == NULL) 05245 return(-1); 05246 return (xmlSchemaValidateLengthFacetInternal(facet, 05247 type->builtInType, value, val, length, 05248 XML_SCHEMA_WHITESPACE_UNKNOWN)); 05249 } 05250 05266 int 05267 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, 05268 xmlSchemaValType valType, 05269 const xmlChar *value, 05270 xmlSchemaValPtr val, 05271 unsigned long *length, 05272 xmlSchemaWhitespaceValueType ws) 05273 { 05274 return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val, 05275 length, ws)); 05276 } 05277 05292 static int 05293 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, 05294 xmlSchemaWhitespaceValueType fws, 05295 xmlSchemaValType valType, 05296 const xmlChar *value, 05297 xmlSchemaValPtr val, 05298 xmlSchemaWhitespaceValueType ws) 05299 { 05300 int ret; 05301 05302 if (facet == NULL) 05303 return(-1); 05304 05305 switch (facet->type) { 05306 case XML_SCHEMA_FACET_PATTERN: 05307 /* 05308 * NOTE that for patterns, the @value needs to be the normalized 05309 * value, *not* the lexical initial value or the canonical value. 05310 */ 05311 if (value == NULL) 05312 return(-1); 05313 ret = xmlRegexpExec(facet->regexp, value); 05314 if (ret == 1) 05315 return(0); 05316 if (ret == 0) 05317 return(XML_SCHEMAV_CVC_PATTERN_VALID); 05318 return(ret); 05319 case XML_SCHEMA_FACET_MAXEXCLUSIVE: 05320 ret = xmlSchemaCompareValues(val, facet->val); 05321 if (ret == -2) 05322 return(-1); 05323 if (ret == -1) 05324 return(0); 05325 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID); 05326 case XML_SCHEMA_FACET_MAXINCLUSIVE: 05327 ret = xmlSchemaCompareValues(val, facet->val); 05328 if (ret == -2) 05329 return(-1); 05330 if ((ret == -1) || (ret == 0)) 05331 return(0); 05332 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID); 05333 case XML_SCHEMA_FACET_MINEXCLUSIVE: 05334 ret = xmlSchemaCompareValues(val, facet->val); 05335 if (ret == -2) 05336 return(-1); 05337 if (ret == 1) 05338 return(0); 05339 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID); 05340 case XML_SCHEMA_FACET_MININCLUSIVE: 05341 ret = xmlSchemaCompareValues(val, facet->val); 05342 if (ret == -2) 05343 return(-1); 05344 if ((ret == 1) || (ret == 0)) 05345 return(0); 05346 return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID); 05347 case XML_SCHEMA_FACET_WHITESPACE: 05348 /* TODO whitespaces */ 05349 /* 05350 * NOTE: Whitespace should be handled to normalize 05351 * the value to be validated against a the facets; 05352 * not to normalize the value in-between. 05353 */ 05354 return(0); 05355 case XML_SCHEMA_FACET_ENUMERATION: 05356 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { 05357 /* 05358 * This is to ensure API compatibility with the old 05359 * xmlSchemaValidateFacet(). 05360 * TODO: Get rid of this case. 05361 */ 05362 if ((facet->value != NULL) && 05363 (xmlStrEqual(facet->value, value))) 05364 return(0); 05365 } else { 05366 ret = xmlSchemaCompareValuesWhtspExt(facet->val->type, 05367 facet->val, facet->value, fws, valType, val, 05368 value, ws); 05369 if (ret == -2) 05370 return(-1); 05371 if (ret == 0) 05372 return(0); 05373 } 05374 return(XML_SCHEMAV_CVC_ENUMERATION_VALID); 05375 case XML_SCHEMA_FACET_LENGTH: 05376 /* 05377 * SPEC (1.3) "if {primitive type definition} is QName or NOTATION, 05378 * then any {value} is facet-valid." 05379 */ 05380 if ((valType == XML_SCHEMAS_QNAME) || 05381 (valType == XML_SCHEMAS_NOTATION)) 05382 return (0); 05383 /* No break on purpose. */ 05384 case XML_SCHEMA_FACET_MAXLENGTH: 05385 case XML_SCHEMA_FACET_MINLENGTH: { 05386 unsigned int len = 0; 05387 05388 if ((valType == XML_SCHEMAS_QNAME) || 05389 (valType == XML_SCHEMAS_NOTATION)) 05390 return (0); 05391 /* 05392 * TODO: length, maxLength and minLength must be of type 05393 * nonNegativeInteger only. Check if decimal is used somehow. 05394 */ 05395 if ((facet->val == NULL) || 05396 ((facet->val->type != XML_SCHEMAS_DECIMAL) && 05397 (facet->val->type != XML_SCHEMAS_NNINTEGER)) || 05398 (facet->val->value.decimal.frac != 0)) { 05399 return(-1); 05400 } 05401 if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) 05402 len = val->value.hex.total; 05403 else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) 05404 len = val->value.base64.total; 05405 else { 05406 switch (valType) { 05407 case XML_SCHEMAS_STRING: 05408 case XML_SCHEMAS_NORMSTRING: 05409 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { 05410 /* 05411 * This is to ensure API compatibility with the old 05412 * xmlSchemaValidateFacet(). Anyway, this was and 05413 * is not the correct handling. 05414 * TODO: Get rid of this case somehow. 05415 */ 05416 if (valType == XML_SCHEMAS_STRING) 05417 len = xmlUTF8Strlen(value); 05418 else 05419 len = xmlSchemaNormLen(value); 05420 } else if (value != NULL) { 05421 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 05422 len = xmlSchemaNormLen(value); 05423 else 05424 /* 05425 * Should be OK for "preserve" as well. 05426 */ 05427 len = xmlUTF8Strlen(value); 05428 } 05429 break; 05430 case XML_SCHEMAS_IDREF: 05431 case XML_SCHEMAS_TOKEN: 05432 case XML_SCHEMAS_LANGUAGE: 05433 case XML_SCHEMAS_NMTOKEN: 05434 case XML_SCHEMAS_NAME: 05435 case XML_SCHEMAS_NCNAME: 05436 case XML_SCHEMAS_ID: 05437 case XML_SCHEMAS_ANYURI: 05438 if (value != NULL) 05439 len = xmlSchemaNormLen(value); 05440 break; 05441 default: 05442 TODO 05443 } 05444 } 05445 if (facet->type == XML_SCHEMA_FACET_LENGTH) { 05446 if (len != facet->val->value.decimal.lo) 05447 return(XML_SCHEMAV_CVC_LENGTH_VALID); 05448 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { 05449 if (len < facet->val->value.decimal.lo) 05450 return(XML_SCHEMAV_CVC_MINLENGTH_VALID); 05451 } else { 05452 if (len > facet->val->value.decimal.lo) 05453 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); 05454 } 05455 break; 05456 } 05457 case XML_SCHEMA_FACET_TOTALDIGITS: 05458 case XML_SCHEMA_FACET_FRACTIONDIGITS: 05459 05460 if ((facet->val == NULL) || 05461 ((facet->val->type != XML_SCHEMAS_PINTEGER) && 05462 (facet->val->type != XML_SCHEMAS_NNINTEGER)) || 05463 (facet->val->value.decimal.frac != 0)) { 05464 return(-1); 05465 } 05466 if ((val == NULL) || 05467 ((val->type != XML_SCHEMAS_DECIMAL) && 05468 (val->type != XML_SCHEMAS_INTEGER) && 05469 (val->type != XML_SCHEMAS_NPINTEGER) && 05470 (val->type != XML_SCHEMAS_NINTEGER) && 05471 (val->type != XML_SCHEMAS_NNINTEGER) && 05472 (val->type != XML_SCHEMAS_PINTEGER) && 05473 (val->type != XML_SCHEMAS_INT) && 05474 (val->type != XML_SCHEMAS_UINT) && 05475 (val->type != XML_SCHEMAS_LONG) && 05476 (val->type != XML_SCHEMAS_ULONG) && 05477 (val->type != XML_SCHEMAS_SHORT) && 05478 (val->type != XML_SCHEMAS_USHORT) && 05479 (val->type != XML_SCHEMAS_BYTE) && 05480 (val->type != XML_SCHEMAS_UBYTE))) { 05481 return(-1); 05482 } 05483 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { 05484 if (val->value.decimal.total > facet->val->value.decimal.lo) 05485 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID); 05486 05487 } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { 05488 if (val->value.decimal.frac > facet->val->value.decimal.lo) 05489 return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID); 05490 } 05491 break; 05492 default: 05493 TODO 05494 } 05495 return(0); 05496 05497 } 05498 05511 int 05512 xmlSchemaValidateFacet(xmlSchemaTypePtr base, 05513 xmlSchemaFacetPtr facet, 05514 const xmlChar *value, 05515 xmlSchemaValPtr val) 05516 { 05517 /* 05518 * This tries to ensure API compatibility regarding the old 05519 * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and 05520 * xmlSchemaValidateFacetWhtsp(). 05521 */ 05522 if (val != NULL) 05523 return(xmlSchemaValidateFacetInternal(facet, 05524 XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val, 05525 XML_SCHEMA_WHITESPACE_UNKNOWN)); 05526 else if (base != NULL) 05527 return(xmlSchemaValidateFacetInternal(facet, 05528 XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val, 05529 XML_SCHEMA_WHITESPACE_UNKNOWN)); 05530 return(-1); 05531 } 05532 05550 int 05551 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet, 05552 xmlSchemaWhitespaceValueType fws, 05553 xmlSchemaValType valType, 05554 const xmlChar *value, 05555 xmlSchemaValPtr val, 05556 xmlSchemaWhitespaceValueType ws) 05557 { 05558 return(xmlSchemaValidateFacetInternal(facet, fws, valType, 05559 value, val, ws)); 05560 } 05561 05562 #if 0 05563 #ifndef DBL_DIG 05564 #define DBL_DIG 16 05565 #endif 05566 #ifndef DBL_EPSILON 05567 #define DBL_EPSILON 1E-9 05568 #endif 05569 05570 #define INTEGER_DIGITS DBL_DIG 05571 #define FRACTION_DIGITS (DBL_DIG + 1) 05572 #define EXPONENT_DIGITS (3 + 2) 05573 05582 static void 05583 xmlSchemaFormatFloat(double number, char buffer[], int buffersize) 05584 { 05585 switch (xmlXPathIsInf(number)) { 05586 case 1: 05587 if (buffersize > (int)sizeof("INF")) 05588 snprintf(buffer, buffersize, "INF"); 05589 break; 05590 case -1: 05591 if (buffersize > (int)sizeof("-INF")) 05592 snprintf(buffer, buffersize, "-INF"); 05593 break; 05594 default: 05595 if (xmlXPathIsNaN(number)) { 05596 if (buffersize > (int)sizeof("NaN")) 05597 snprintf(buffer, buffersize, "NaN"); 05598 } else if (number == 0) { 05599 snprintf(buffer, buffersize, "0.0E0"); 05600 } else { 05601 /* 3 is sign, decimal point, and terminating zero */ 05602 char work[DBL_DIG + EXPONENT_DIGITS + 3]; 05603 int integer_place, fraction_place; 05604 char *ptr; 05605 char *after_fraction; 05606 double absolute_value; 05607 int size; 05608 05609 absolute_value = fabs(number); 05610 05611 /* 05612 * Result is in work, and after_fraction points 05613 * just past the fractional part. 05614 * Use scientific notation 05615 */ 05616 integer_place = DBL_DIG + EXPONENT_DIGITS + 1; 05617 fraction_place = DBL_DIG - 1; 05618 snprintf(work, sizeof(work),"%*.*e", 05619 integer_place, fraction_place, number); 05620 after_fraction = strchr(work + DBL_DIG, 'e'); 05621 /* Remove fractional trailing zeroes */ 05622 ptr = after_fraction; 05623 while (*(--ptr) == '0') 05624 ; 05625 if (*ptr != '.') 05626 ptr++; 05627 while ((*ptr++ = *after_fraction++) != 0); 05628 05629 /* Finally copy result back to caller */ 05630 size = strlen(work) + 1; 05631 if (size > buffersize) { 05632 work[buffersize - 1] = 0; 05633 size = buffersize; 05634 } 05635 memmove(buffer, work, size); 05636 } 05637 break; 05638 } 05639 } 05640 #endif 05641 05661 int 05662 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue) 05663 { 05664 if ((retValue == NULL) || (val == NULL)) 05665 return (-1); 05666 *retValue = NULL; 05667 switch (val->type) { 05668 case XML_SCHEMAS_STRING: 05669 if (val->value.str == NULL) 05670 *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); 05671 else 05672 *retValue = 05673 BAD_CAST xmlStrdup((const xmlChar *) val->value.str); 05674 break; 05675 case XML_SCHEMAS_NORMSTRING: 05676 if (val->value.str == NULL) 05677 *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); 05678 else { 05679 *retValue = xmlSchemaWhiteSpaceReplace( 05680 (const xmlChar *) val->value.str); 05681 if ((*retValue) == NULL) 05682 *retValue = BAD_CAST xmlStrdup( 05683 (const xmlChar *) val->value.str); 05684 } 05685 break; 05686 case XML_SCHEMAS_TOKEN: 05687 case XML_SCHEMAS_LANGUAGE: 05688 case XML_SCHEMAS_NMTOKEN: 05689 case XML_SCHEMAS_NAME: 05690 case XML_SCHEMAS_NCNAME: 05691 case XML_SCHEMAS_ID: 05692 case XML_SCHEMAS_IDREF: 05693 case XML_SCHEMAS_ENTITY: 05694 case XML_SCHEMAS_NOTATION: /* Unclear */ 05695 case XML_SCHEMAS_ANYURI: /* Unclear */ 05696 if (val->value.str == NULL) 05697 return (-1); 05698 *retValue = 05699 BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str); 05700 if (*retValue == NULL) 05701 *retValue = 05702 BAD_CAST xmlStrdup((const xmlChar *) val->value.str); 05703 break; 05704 case XML_SCHEMAS_QNAME: 05705 /* TODO: Unclear in XML Schema 1.0. */ 05706 if (val->value.qname.uri == NULL) { 05707 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name); 05708 return (0); 05709 } else { 05710 *retValue = BAD_CAST xmlStrdup(BAD_CAST "{"); 05711 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), 05712 BAD_CAST val->value.qname.uri); 05713 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), 05714 BAD_CAST "}"); 05715 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), 05716 BAD_CAST val->value.qname.uri); 05717 } 05718 break; 05719 case XML_SCHEMAS_DECIMAL: 05720 /* 05721 * TODO: Lookout for a more simple implementation. 05722 */ 05723 if ((val->value.decimal.total == 1) && 05724 (val->value.decimal.lo == 0)) { 05725 *retValue = xmlStrdup(BAD_CAST "0.0"); 05726 } else { 05727 xmlSchemaValDecimal dec = val->value.decimal; 05728 int bufsize; 05729 char *buf = NULL, *offs; 05730 05731 /* Add room for the decimal point as well. */ 05732 bufsize = dec.total + 2; 05733 if (dec.sign) 05734 bufsize++; 05735 /* Add room for leading/trailing zero. */ 05736 if ((dec.frac == 0) || (dec.frac == dec.total)) 05737 bufsize++; 05738 buf = xmlMalloc(bufsize); 05739 if (buf == NULL) 05740 return(-1); 05741 offs = buf; 05742 if (dec.sign) 05743 *offs++ = '-'; 05744 if (dec.frac == dec.total) { 05745 *offs++ = '0'; 05746 *offs++ = '.'; 05747 } 05748 if (dec.hi != 0) 05749 snprintf(offs, bufsize - (offs - buf), 05750 "%lu%lu%lu", dec.hi, dec.mi, dec.lo); 05751 else if (dec.mi != 0) 05752 snprintf(offs, bufsize - (offs - buf), 05753 "%lu%lu", dec.mi, dec.lo); 05754 else 05755 snprintf(offs, bufsize - (offs - buf), 05756 "%lu", dec.lo); 05757 05758 if (dec.frac != 0) { 05759 if (dec.frac != dec.total) { 05760 int diff = dec.total - dec.frac; 05761 /* 05762 * Insert the decimal point. 05763 */ 05764 memmove(offs + diff + 1, offs + diff, dec.frac +1); 05765 offs[diff] = '.'; 05766 } else { 05767 unsigned int i = 0; 05768 /* 05769 * Insert missing zeroes behind the decimal point. 05770 */ 05771 while (*(offs + i) != 0) 05772 i++; 05773 if (i < dec.total) { 05774 memmove(offs + (dec.total - i), offs, i +1); 05775 memset(offs, '0', dec.total - i); 05776 } 05777 } 05778 } else { 05779 /* 05780 * Append decimal point and zero. 05781 */ 05782 offs = buf + bufsize - 1; 05783 *offs-- = 0; 05784 *offs-- = '0'; 05785 *offs-- = '.'; 05786 } 05787 *retValue = BAD_CAST buf; 05788 } 05789 break; 05790 case XML_SCHEMAS_INTEGER: 05791 case XML_SCHEMAS_PINTEGER: 05792 case XML_SCHEMAS_NPINTEGER: 05793 case XML_SCHEMAS_NINTEGER: 05794 case XML_SCHEMAS_NNINTEGER: 05795 case XML_SCHEMAS_LONG: 05796 case XML_SCHEMAS_BYTE: 05797 case XML_SCHEMAS_SHORT: 05798 case XML_SCHEMAS_INT: 05799 case XML_SCHEMAS_UINT: 05800 case XML_SCHEMAS_ULONG: 05801 case XML_SCHEMAS_USHORT: 05802 case XML_SCHEMAS_UBYTE: 05803 if ((val->value.decimal.total == 1) && 05804 (val->value.decimal.lo == 0)) 05805 *retValue = xmlStrdup(BAD_CAST "0"); 05806 else { 05807 xmlSchemaValDecimal dec = val->value.decimal; 05808 int bufsize = dec.total + 1; 05809 05810 /* Add room for the decimal point as well. */ 05811 if (dec.sign) 05812 bufsize++; 05813 *retValue = xmlMalloc(bufsize); 05814 if (*retValue == NULL) 05815 return(-1); 05816 if (dec.hi != 0) { 05817 if (dec.sign) 05818 snprintf((char *) *retValue, bufsize, 05819 "-%lu%lu%lu", dec.hi, dec.mi, dec.lo); 05820 else 05821 snprintf((char *) *retValue, bufsize, 05822 "%lu%lu%lu", dec.hi, dec.mi, dec.lo); 05823 } else if (dec.mi != 0) { 05824 if (dec.sign) 05825 snprintf((char *) *retValue, bufsize, 05826 "-%lu%lu", dec.mi, dec.lo); 05827 else 05828 snprintf((char *) *retValue, bufsize, 05829 "%lu%lu", dec.mi, dec.lo); 05830 } else { 05831 if (dec.sign) 05832 snprintf((char *) *retValue, bufsize, "-%lu", dec.lo); 05833 else 05834 snprintf((char *) *retValue, bufsize, "%lu", dec.lo); 05835 } 05836 } 05837 break; 05838 case XML_SCHEMAS_BOOLEAN: 05839 if (val->value.b) 05840 *retValue = BAD_CAST xmlStrdup(BAD_CAST "true"); 05841 else 05842 *retValue = BAD_CAST xmlStrdup(BAD_CAST "false"); 05843 break; 05844 case XML_SCHEMAS_DURATION: { 05845 char buf[100]; 05846 unsigned long year; 05847 unsigned long mon, day, hour = 0, min = 0; 05848 double sec = 0, left; 05849 05850 /* TODO: Unclear in XML Schema 1.0 */ 05851 /* 05852 * TODO: This results in a normalized output of the value 05853 * - which is NOT conformant to the spec - 05854 * since the exact values of each property are not 05855 * recoverable. Think about extending the structure to 05856 * provide a field for every property. 05857 */ 05858 year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12); 05859 mon = labs(val->value.dur.mon) - 12 * year; 05860 05861 day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400); 05862 left = fabs(val->value.dur.sec) - day * 86400; 05863 if (left > 0) { 05864 hour = (unsigned long) FQUOTIENT(left, 3600); 05865 left = left - (hour * 3600); 05866 if (left > 0) { 05867 min = (unsigned long) FQUOTIENT(left, 60); 05868 sec = left - (min * 60); 05869 } 05870 } 05871 if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0)) 05872 snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS", 05873 year, mon, day, hour, min, sec); 05874 else 05875 snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS", 05876 year, mon, day, hour, min, sec); 05877 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 05878 } 05879 break; 05880 case XML_SCHEMAS_GYEAR: { 05881 char buf[30]; 05882 /* TODO: Unclear in XML Schema 1.0 */ 05883 /* TODO: What to do with the timezone? */ 05884 snprintf(buf, 30, "%04ld", val->value.date.year); 05885 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 05886 } 05887 break; 05888 case XML_SCHEMAS_GMONTH: { 05889 /* TODO: Unclear in XML Schema 1.0 */ 05890 /* TODO: What to do with the timezone? */ 05891 *retValue = xmlMalloc(6); 05892 if (*retValue == NULL) 05893 return(-1); 05894 snprintf((char *) *retValue, 6, "--%02u", 05895 val->value.date.mon); 05896 } 05897 break; 05898 case XML_SCHEMAS_GDAY: { 05899 /* TODO: Unclear in XML Schema 1.0 */ 05900 /* TODO: What to do with the timezone? */ 05901 *retValue = xmlMalloc(6); 05902 if (*retValue == NULL) 05903 return(-1); 05904 snprintf((char *) *retValue, 6, "---%02u", 05905 val->value.date.day); 05906 } 05907 break; 05908 case XML_SCHEMAS_GMONTHDAY: { 05909 /* TODO: Unclear in XML Schema 1.0 */ 05910 /* TODO: What to do with the timezone? */ 05911 *retValue = xmlMalloc(8); 05912 if (*retValue == NULL) 05913 return(-1); 05914 snprintf((char *) *retValue, 8, "--%02u-%02u", 05915 val->value.date.mon, val->value.date.day); 05916 } 05917 break; 05918 case XML_SCHEMAS_GYEARMONTH: { 05919 char buf[35]; 05920 /* TODO: Unclear in XML Schema 1.0 */ 05921 /* TODO: What to do with the timezone? */ 05922 if (val->value.date.year < 0) 05923 snprintf(buf, 35, "-%04ld-%02u", 05924 labs(val->value.date.year), 05925 val->value.date.mon); 05926 else 05927 snprintf(buf, 35, "%04ld-%02u", 05928 val->value.date.year, val->value.date.mon); 05929 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 05930 } 05931 break; 05932 case XML_SCHEMAS_TIME: 05933 { 05934 char buf[30]; 05935 05936 if (val->value.date.tz_flag) { 05937 xmlSchemaValPtr norm; 05938 05939 norm = xmlSchemaDateNormalize(val, 0); 05940 if (norm == NULL) 05941 return (-1); 05942 /* 05943 * TODO: Check if "%.14g" is portable. 05944 */ 05945 snprintf(buf, 30, 05946 "%02u:%02u:%02.14gZ", 05947 norm->value.date.hour, 05948 norm->value.date.min, 05949 norm->value.date.sec); 05950 xmlSchemaFreeValue(norm); 05951 } else { 05952 snprintf(buf, 30, 05953 "%02u:%02u:%02.14g", 05954 val->value.date.hour, 05955 val->value.date.min, 05956 val->value.date.sec); 05957 } 05958 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 05959 } 05960 break; 05961 case XML_SCHEMAS_DATE: 05962 { 05963 char buf[30]; 05964 05965 if (val->value.date.tz_flag) { 05966 xmlSchemaValPtr norm; 05967 05968 norm = xmlSchemaDateNormalize(val, 0); 05969 if (norm == NULL) 05970 return (-1); 05971 /* 05972 * TODO: Append the canonical value of the 05973 * recoverable timezone and not "Z". 05974 */ 05975 snprintf(buf, 30, 05976 "%04ld:%02u:%02uZ", 05977 norm->value.date.year, norm->value.date.mon, 05978 norm->value.date.day); 05979 xmlSchemaFreeValue(norm); 05980 } else { 05981 snprintf(buf, 30, 05982 "%04ld:%02u:%02u", 05983 val->value.date.year, val->value.date.mon, 05984 val->value.date.day); 05985 } 05986 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 05987 } 05988 break; 05989 case XML_SCHEMAS_DATETIME: 05990 { 05991 char buf[50]; 05992 05993 if (val->value.date.tz_flag) { 05994 xmlSchemaValPtr norm; 05995 05996 norm = xmlSchemaDateNormalize(val, 0); 05997 if (norm == NULL) 05998 return (-1); 05999 /* 06000 * TODO: Check if "%.14g" is portable. 06001 */ 06002 snprintf(buf, 50, 06003 "%04ld:%02u:%02uT%02u:%02u:%02.14gZ", 06004 norm->value.date.year, norm->value.date.mon, 06005 norm->value.date.day, norm->value.date.hour, 06006 norm->value.date.min, norm->value.date.sec); 06007 xmlSchemaFreeValue(norm); 06008 } else { 06009 snprintf(buf, 50, 06010 "%04ld:%02u:%02uT%02u:%02u:%02.14g", 06011 val->value.date.year, val->value.date.mon, 06012 val->value.date.day, val->value.date.hour, 06013 val->value.date.min, val->value.date.sec); 06014 } 06015 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 06016 } 06017 break; 06018 case XML_SCHEMAS_HEXBINARY: 06019 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str); 06020 break; 06021 case XML_SCHEMAS_BASE64BINARY: 06022 /* 06023 * TODO: Is the following spec piece implemented?: 06024 * SPEC: "Note: For some values the canonical form defined 06025 * above does not conform to [RFC 2045], which requires breaking 06026 * with linefeeds at appropriate intervals." 06027 */ 06028 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str); 06029 break; 06030 case XML_SCHEMAS_FLOAT: { 06031 char buf[30]; 06032 /* 06033 * |m| < 16777216, -149 <= e <= 104. 06034 * TODO: Handle, NaN, INF, -INF. The format is not 06035 * yet conformant. The c type float does not cover 06036 * the whole range. 06037 */ 06038 snprintf(buf, 30, "%01.14e", val->value.f); 06039 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 06040 } 06041 break; 06042 case XML_SCHEMAS_DOUBLE: { 06043 char buf[40]; 06044 /* |m| < 9007199254740992, -1075 <= e <= 970 */ 06045 /* 06046 * TODO: Handle, NaN, INF, -INF. The format is not 06047 * yet conformant. The c type float does not cover 06048 * the whole range. 06049 */ 06050 snprintf(buf, 40, "%01.14e", val->value.d); 06051 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); 06052 } 06053 break; 06054 default: 06055 *retValue = BAD_CAST xmlStrdup(BAD_CAST "???"); 06056 return (1); 06057 } 06058 if (*retValue == NULL) 06059 return(-1); 06060 return (0); 06061 } 06062 06075 int 06076 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val, 06077 const xmlChar **retValue, 06078 xmlSchemaWhitespaceValueType ws) 06079 { 06080 if ((retValue == NULL) || (val == NULL)) 06081 return (-1); 06082 if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) || 06083 (ws > XML_SCHEMA_WHITESPACE_COLLAPSE)) 06084 return (-1); 06085 06086 *retValue = NULL; 06087 switch (val->type) { 06088 case XML_SCHEMAS_STRING: 06089 if (val->value.str == NULL) 06090 *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); 06091 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 06092 *retValue = xmlSchemaCollapseString(val->value.str); 06093 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) 06094 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); 06095 if ((*retValue) == NULL) 06096 *retValue = BAD_CAST xmlStrdup(val->value.str); 06097 break; 06098 case XML_SCHEMAS_NORMSTRING: 06099 if (val->value.str == NULL) 06100 *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); 06101 else { 06102 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) 06103 *retValue = xmlSchemaCollapseString(val->value.str); 06104 else 06105 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); 06106 if ((*retValue) == NULL) 06107 *retValue = BAD_CAST xmlStrdup(val->value.str); 06108 } 06109 break; 06110 default: 06111 return (xmlSchemaGetCanonValue(val, retValue)); 06112 } 06113 return (0); 06114 } 06115 06124 xmlSchemaValType 06125 xmlSchemaGetValType(xmlSchemaValPtr val) 06126 { 06127 if (val == NULL) 06128 return(XML_SCHEMAS_UNKNOWN); 06129 return (val->type); 06130 } 06131 06132 #define bottom_xmlschemastypes 06133 #include "elfgcchack.h" 06134 #endif /* LIBXML_SCHEMAS_ENABLED */ Generated on Sat May 26 2012 04:33:53 for ReactOS by
1.7.6.1
|