1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Diagnostics; 7 using System.IO; 8 using System.Text; 9 using System.Xml.Schema; 10 11 namespace System.Xml.Xsl 12 { 13 /// <summary> 14 /// XmlQueryType contains static type information that describes the structure and possible values of dynamic 15 /// instances of the Xml data model. 16 /// 17 /// Every XmlQueryType is composed of a Prime type and a cardinality. The Prime type itself may be a union 18 /// between several item types. The XmlQueryType IList<XmlQueryType/> implementation allows callers 19 /// to enumerate the item types. Other properties expose other information about the type. 20 /// </summary> 21 internal abstract class XmlQueryType : ListBase<XmlQueryType> 22 { 23 private static readonly BitMatrix s_typeCodeDerivation; 24 private int _hashCode; 25 26 27 //----------------------------------------------- 28 // Static Constructor 29 //----------------------------------------------- XmlQueryType()30 static XmlQueryType() 31 { 32 s_typeCodeDerivation = new BitMatrix(s_baseTypeCodes.Length); 33 34 // Build derivation matrix 35 for (int i = 0; i < s_baseTypeCodes.Length; i++) 36 { 37 int nextAncestor = i; 38 39 while (true) 40 { 41 s_typeCodeDerivation[i, nextAncestor] = true; 42 if ((int)s_baseTypeCodes[nextAncestor] == nextAncestor) 43 break; 44 45 nextAncestor = (int)s_baseTypeCodes[nextAncestor]; 46 } 47 } 48 } 49 50 51 //----------------------------------------------- 52 // ItemType, OccurrenceIndicator Properties 53 //----------------------------------------------- 54 55 /// <summary> 56 /// Static data type code. The dynamic type is guaranteed to be this type or a subtype of this code. 57 /// This type code includes support for XQuery types that are not part of Xsd, such as Item, 58 /// Node, AnyAtomicType, and Comment. 59 /// </summary> 60 public abstract XmlTypeCode TypeCode { get; } 61 62 /// <summary> 63 /// Set of allowed names for element, document{element}, attribute and PI 64 /// Returns XmlQualifiedName.Wildcard for all other types 65 /// </summary> 66 public abstract XmlQualifiedNameTest NameTest { get; } 67 68 /// <summary> 69 /// Static Xsd schema type. The dynamic type is guaranteed to be this type or a subtype of this type. 70 /// SchemaType will follow these rules: 71 /// 1. If TypeCode is an atomic type code, then SchemaType will be the corresponding non-null simple type 72 /// 2. If TypeCode is Element or Attribute, then SchemaType will be the non-null content type 73 /// 3. If TypeCode is Item, Node, Comment, PI, Text, Document, Namespace, None, then SchemaType will be AnyType 74 /// </summary> 75 public abstract XmlSchemaType SchemaType { get; } 76 77 /// <summary> 78 /// Permits the element or document{element} node to have the nilled property. 79 /// Returns false for all other types 80 /// </summary> 81 public abstract bool IsNillable { get; } 82 83 /// <summary> 84 /// This property is always XmlNodeKindFlags.None unless TypeCode = XmlTypeCode.Node, in which case this 85 /// property lists all node kinds that instances of this type may be. 86 /// </summary> 87 public abstract XmlNodeKindFlags NodeKinds { get; } 88 89 /// <summary> 90 /// If IsStrict is true, then the dynamic type is guaranteed to be the exact same as the static type, and 91 /// will therefore never be a subtype of the static type. 92 /// </summary> 93 public abstract bool IsStrict { get; } 94 95 /// <summary> 96 /// This property specifies the possible cardinalities that instances of this type may have. 97 /// </summary> 98 public abstract XmlQueryCardinality Cardinality { get; } 99 100 /// <summary> 101 /// This property returns this type's Prime type, which is always cardinality One. 102 /// </summary> 103 public abstract XmlQueryType Prime { get; } 104 105 /// <summary> 106 /// True if dynamic data type of all items in this sequence is guaranteed to be not a subtype of Rtf. 107 /// </summary> 108 public abstract bool IsNotRtf { get; } 109 110 /// <summary> 111 /// True if items in the sequence are guaranteed to be nodes in document order with no duplicates. 112 /// </summary> 113 public abstract bool IsDod { get; } 114 115 /// <summary> 116 /// The XmlValueConverter maps each XmlQueryType to various Clr types which are capable of representing it. 117 /// </summary> 118 public abstract XmlValueConverter ClrMapping { get; } 119 120 121 //----------------------------------------------- 122 // Type Operations 123 //----------------------------------------------- 124 125 /// <summary> 126 /// Returns true if every possible dynamic instance of this type is also an instance of "baseType". 127 /// </summary> IsSubtypeOf(XmlQueryType baseType)128 public bool IsSubtypeOf(XmlQueryType baseType) 129 { 130 XmlQueryType thisPrime, basePrime; 131 132 // Check cardinality sub-typing rules 133 if (!(Cardinality <= baseType.Cardinality) || (!IsDod && baseType.IsDod)) 134 return false; 135 136 if (!IsDod && baseType.IsDod) 137 return false; 138 139 // Check early for common case that two types are the same object 140 thisPrime = Prime; 141 basePrime = baseType.Prime; 142 if ((object)thisPrime == (object)basePrime) 143 return true; 144 145 // Check early for common case that two prime types are item types 146 if (thisPrime.Count == 1 && basePrime.Count == 1) 147 return thisPrime.IsSubtypeOfItemType(basePrime); 148 149 // Check that each item type in this type is a subtype of some item type in "baseType" 150 foreach (XmlQueryType thisItem in thisPrime) 151 { 152 bool match = false; 153 154 foreach (XmlQueryType baseItem in basePrime) 155 { 156 if (thisItem.IsSubtypeOfItemType(baseItem)) 157 { 158 match = true; 159 break; 160 } 161 } 162 163 if (match == false) 164 return false; 165 } 166 167 return true; 168 } 169 170 /// <summary> 171 /// Returns true if a dynamic instance (type None never has an instance) of this type can never be a subtype of "baseType". 172 /// </summary> NeverSubtypeOf(XmlQueryType baseType)173 public bool NeverSubtypeOf(XmlQueryType baseType) 174 { 175 // Check cardinalities 176 if (Cardinality.NeverSubset(baseType.Cardinality)) 177 return true; 178 179 // If both this type and "other" type might be empty, it doesn't matter what the prime types are 180 if (MaybeEmpty && baseType.MaybeEmpty) 181 return false; 182 183 // None is subtype of every other type 184 if (Count == 0) 185 return false; 186 187 // Check item types 188 foreach (XmlQueryType typThis in this) 189 { 190 foreach (XmlQueryType typThat in baseType) 191 { 192 if (typThis.HasIntersectionItemType(typThat)) 193 return false; 194 } 195 } 196 197 return true; 198 } 199 200 /// <summary> 201 /// Strongly-typed Equals that returns true if this type and "that" type are equivalent. 202 /// </summary> Equals(XmlQueryType that)203 public bool Equals(XmlQueryType that) 204 { 205 if (that == null) 206 return false; 207 208 // Check cardinality and DocOrderDistinct property 209 if (Cardinality != that.Cardinality || IsDod != that.IsDod) 210 return false; 211 212 // Check early for common case that two types are the same object 213 XmlQueryType thisPrime = Prime; 214 XmlQueryType thatPrime = that.Prime; 215 if ((object)thisPrime == (object)thatPrime) 216 return true; 217 218 // Check that count of item types is equal 219 if (thisPrime.Count != thatPrime.Count) 220 return false; 221 222 // Check early for common case that two prime types are item types 223 if (thisPrime.Count == 1) 224 { 225 return (thisPrime.TypeCode == thatPrime.TypeCode && 226 thisPrime.NameTest == thatPrime.NameTest && 227 thisPrime.SchemaType == thatPrime.SchemaType && 228 thisPrime.IsStrict == thatPrime.IsStrict && 229 thisPrime.IsNotRtf == thatPrime.IsNotRtf); 230 } 231 232 233 // Check that each item type in this type is equal to some item type in "baseType" 234 // (string | int) should be the same type as (int | string) 235 foreach (XmlQueryType thisItem in this) 236 { 237 bool match = false; 238 239 foreach (XmlQueryType thatItem in that) 240 { 241 if (thisItem.TypeCode == thatItem.TypeCode && 242 thisItem.NameTest == thatItem.NameTest && 243 thisItem.SchemaType == thatItem.SchemaType && 244 thisItem.IsStrict == thatItem.IsStrict && 245 thisItem.IsNotRtf == thatItem.IsNotRtf) 246 { 247 // Found match so proceed to next type 248 match = true; 249 break; 250 } 251 } 252 253 if (match == false) 254 return false; 255 } 256 257 return true; 258 } 259 260 /// <summary> 261 /// Overload == operator to call Equals rather than do reference equality. 262 /// </summary> operator ==(XmlQueryType left, XmlQueryType right)263 public static bool operator ==(XmlQueryType left, XmlQueryType right) 264 { 265 if ((object)left == null) 266 return ((object)right == null); 267 268 return left.Equals(right); 269 } 270 271 /// <summary> 272 /// Overload != operator to call Equals rather than do reference inequality. 273 /// </summary> operator !=(XmlQueryType left, XmlQueryType right)274 public static bool operator !=(XmlQueryType left, XmlQueryType right) 275 { 276 if ((object)left == null) 277 return ((object)right != null); 278 279 return !left.Equals(right); 280 } 281 282 283 //----------------------------------------------- 284 // Convenience Properties 285 //----------------------------------------------- 286 287 /// <summary> 288 /// True if dynamic cardinality of this sequence is guaranteed to be 0. 289 /// </summary> 290 public bool IsEmpty 291 { 292 get { return Cardinality <= XmlQueryCardinality.Zero; } 293 } 294 295 /// <summary> 296 /// True if dynamic cardinality of this sequence is guaranteed to be 1. 297 /// </summary> 298 public bool IsSingleton 299 { 300 get { return Cardinality <= XmlQueryCardinality.One; } 301 } 302 303 /// <summary> 304 /// True if dynamic cardinality of this sequence might be 0. 305 /// </summary> 306 public bool MaybeEmpty 307 { 308 get { return XmlQueryCardinality.Zero <= Cardinality; } 309 } 310 311 /// <summary> 312 /// True if dynamic cardinality of this sequence might be >1. 313 /// </summary> 314 public bool MaybeMany 315 { 316 get { return XmlQueryCardinality.More <= Cardinality; } 317 } 318 319 /// <summary> 320 /// True if dynamic data type of all items in this sequence is guaranteed to be a subtype of Node. 321 /// Equivalent to calling IsSubtypeOf(TypeFactory.NodeS). 322 /// </summary> 323 public bool IsNode 324 { 325 get { return (s_typeCodeToFlags[(int)TypeCode] & TypeFlags.IsNode) != 0; } 326 } 327 328 /// <summary> 329 /// True if dynamic data type of all items in this sequence is guaranteed to be a subtype of AnyAtomicType. 330 /// Equivalent to calling IsSubtypeOf(TypeFactory.AnyAtomicTypeS). 331 /// </summary> 332 public bool IsAtomicValue 333 { 334 get { return (s_typeCodeToFlags[(int)TypeCode] & TypeFlags.IsAtomicValue) != 0; } 335 } 336 337 /// <summary> 338 /// True if dynamic data type of all items in this sequence is guaranteed to be a subtype of Decimal, Double, or Float. 339 /// Equivalent to calling IsSubtypeOf(TypeFactory.NumericS). 340 /// </summary> 341 public bool IsNumeric 342 { 343 get { return (s_typeCodeToFlags[(int)TypeCode] & TypeFlags.IsNumeric) != 0; } 344 } 345 346 347 //----------------------------------------------- 348 // System.Object implementation 349 //----------------------------------------------- 350 351 /// <summary> 352 /// True if "obj" is an XmlQueryType, and this type is the exact same static type. 353 /// </summary> Equals(object obj)354 public override bool Equals(object obj) 355 { 356 XmlQueryType that = obj as XmlQueryType; 357 358 if (that == null) 359 return false; 360 361 return Equals(that); 362 } 363 364 /// <summary> 365 /// Return hash code of this instance. 366 /// </summary> GetHashCode()367 public override int GetHashCode() 368 { 369 if (_hashCode == 0) 370 { 371 int hash; 372 XmlSchemaType schemaType; 373 374 hash = (int)TypeCode; 375 schemaType = SchemaType; 376 377 unchecked 378 { 379 if (schemaType != null) 380 hash += (hash << 7) ^ schemaType.GetHashCode(); 381 382 hash += (hash << 7) ^ (int)NodeKinds; 383 hash += (hash << 7) ^ Cardinality.GetHashCode(); 384 hash += (hash << 7) ^ (IsStrict ? 1 : 0); 385 386 // Mix hash code a bit more 387 hash -= hash >> 17; 388 hash -= hash >> 11; 389 hash -= hash >> 5; 390 } 391 392 // Save hashcode. Don't save 0, so that it won't ever be recomputed. 393 _hashCode = (hash == 0) ? 1 : hash; 394 } 395 396 return _hashCode; 397 } 398 399 /// <summary> 400 /// Return a user-friendly string representation of the XmlQueryType. 401 /// </summary> ToString()402 public override string ToString() 403 { 404 return ToString("G"); 405 } 406 407 /// <summary> 408 /// Return a string representation of the XmlQueryType using the specified format. The following formats are 409 /// supported: 410 /// 411 /// "G" (General): This is the default mode, and is used if no other format is recognized. This format is 412 /// easier to read than the canonical format, since it excludes redundant information. 413 /// (e.g. element instead of element(*, xs:anyType)) 414 /// 415 /// "X" (XQuery): Return the canonical XQuery representation, which excludes Qil specific information and 416 /// includes extra, redundant information, such as fully specified types. 417 /// (e.g. element(*, xs:anyType) instead of element) 418 /// 419 /// "S" (Serialized): This format is used to serialize parts of the type which can be serialized easily, in 420 /// a format that is easy to parse. Only the cardinality, type code, and strictness flag 421 /// are serialized. User-defined type information and element/attribute content types 422 /// are lost. 423 /// (e.g. One;Attribute|String|Int;true) 424 /// 425 /// </summary> ToString(string format)426 public string ToString(string format) 427 { 428 string[] sa; 429 StringBuilder sb; 430 bool isXQ; 431 432 if (format == "S") 433 { 434 sb = new StringBuilder(); 435 sb.Append(Cardinality.ToString(format)); 436 sb.Append(';'); 437 438 for (int i = 0; i < Count; i++) 439 { 440 if (i != 0) 441 sb.Append("|"); 442 sb.Append(this[i].TypeCode.ToString()); 443 } 444 445 sb.Append(';'); 446 sb.Append(IsStrict); 447 return sb.ToString(); 448 } 449 450 isXQ = (format == "X"); 451 452 if (Cardinality == XmlQueryCardinality.None) 453 { 454 return "none"; 455 } 456 else if (Cardinality == XmlQueryCardinality.Zero) 457 { 458 return "empty"; 459 } 460 461 sb = new StringBuilder(); 462 463 switch (Count) 464 { 465 case 0: 466 // This assert depends on the way we are going to represent None 467 // Debug.Assert(false); 468 sb.Append("none"); 469 break; 470 case 1: 471 sb.Append(this[0].ItemTypeToString(isXQ)); 472 break; 473 default: 474 sa = new string[Count]; 475 for (int i = 0; i < Count; i++) 476 sa[i] = this[i].ItemTypeToString(isXQ); 477 478 Array.Sort(sa); 479 480 sb = new StringBuilder(); 481 sb.Append('('); 482 sb.Append(sa[0]); 483 for (int i = 1; i < sa.Length; i++) 484 { 485 sb.Append(" | "); 486 sb.Append(sa[i]); 487 } 488 489 sb.Append(')'); 490 break; 491 } 492 493 sb.Append(Cardinality.ToString()); 494 495 if (!isXQ && IsDod) 496 sb.Append('#'); 497 498 return sb.ToString(); 499 } 500 501 502 //----------------------------------------------- 503 // Serialization 504 //----------------------------------------------- 505 506 /// <summary> 507 /// Serialize the object to BinaryWriter. 508 /// </summary> GetObjectData(BinaryWriter writer)509 public abstract void GetObjectData(BinaryWriter writer); 510 511 //----------------------------------------------- 512 // Helpers 513 //----------------------------------------------- 514 515 /// <summary> 516 /// Returns true if this item type is a subtype of another item type. 517 /// </summary> IsSubtypeOfItemType(XmlQueryType baseType)518 private bool IsSubtypeOfItemType(XmlQueryType baseType) 519 { 520 Debug.Assert(Count == 1 && IsSingleton, "This method should only be called for item types."); 521 Debug.Assert(baseType.Count == 1 && baseType.IsSingleton, "This method should only be called for item types."); 522 Debug.Assert(!IsDod && !baseType.IsDod, "Singleton types may not have DocOrderDistinct property"); 523 XmlSchemaType baseSchemaType = baseType.SchemaType; 524 525 if (TypeCode != baseType.TypeCode) 526 { 527 // If "baseType" is strict, then IsSubtypeOf must be false 528 if (baseType.IsStrict) 529 return false; 530 531 // If type codes are not the same, then IsSubtypeOf can return true *only* if "baseType" is a built-in type 532 XmlSchemaType builtInType = XmlSchemaType.GetBuiltInSimpleType(baseType.TypeCode); 533 if (builtInType != null && baseSchemaType != builtInType) 534 return false; 535 536 // Now check whether TypeCode is derived from baseType.TypeCode 537 return s_typeCodeDerivation[TypeCode, baseType.TypeCode]; 538 } 539 else if (baseType.IsStrict) 540 { 541 // only atomic values can be strict 542 Debug.Assert(IsAtomicValue && baseType.IsAtomicValue); 543 544 // If schema types are not the same, then IsSubtype is false if "baseType" is strict 545 return IsStrict && SchemaType == baseSchemaType; 546 } 547 else 548 { 549 // Otherwise, check derivation tree 550 return (IsNotRtf || !baseType.IsNotRtf) && NameTest.IsSubsetOf(baseType.NameTest) && 551 (baseSchemaType == XmlSchemaComplexType.AnyType || XmlSchemaType.IsDerivedFrom(SchemaType, baseSchemaType, /* except:*/XmlSchemaDerivationMethod.Empty)) && 552 (!IsNillable || baseType.IsNillable); 553 } 554 } 555 556 /// <summary> 557 /// Returns true if the intersection between this item type and "other" item type is not empty. 558 /// </summary> HasIntersectionItemType(XmlQueryType other)559 private bool HasIntersectionItemType(XmlQueryType other) 560 { 561 Debug.Assert(this.Count == 1 && this.IsSingleton, "this should be an item"); 562 Debug.Assert(other.Count == 1 && other.IsSingleton, "other should be an item"); 563 564 if (this.TypeCode == other.TypeCode && (this.NodeKinds & (XmlNodeKindFlags.Document | XmlNodeKindFlags.Element | XmlNodeKindFlags.Attribute)) != 0) 565 { 566 if (this.TypeCode == XmlTypeCode.Node) 567 return true; 568 569 // Intersect name tests 570 if (!this.NameTest.HasIntersection(other.NameTest)) 571 return false; 572 573 if (!XmlSchemaType.IsDerivedFrom(this.SchemaType, other.SchemaType, /* except:*/XmlSchemaDerivationMethod.Empty) && 574 !XmlSchemaType.IsDerivedFrom(other.SchemaType, this.SchemaType, /* except:*/XmlSchemaDerivationMethod.Empty)) 575 { 576 return false; 577 } 578 579 return true; 580 } 581 else if (this.IsSubtypeOf(other) || other.IsSubtypeOf(this)) 582 { 583 return true; 584 } 585 586 return false; 587 } 588 589 /// <summary> 590 /// Return the string representation of an item type (cannot be a union or a sequence). 591 /// </summary> ItemTypeToString(bool isXQ)592 private string ItemTypeToString(bool isXQ) 593 { 594 string s; 595 Debug.Assert(Count == 1, "Do not pass a Union type to this method."); 596 Debug.Assert(IsSingleton, "Do not pass a Sequence type to this method."); 597 598 if (IsNode) 599 { 600 // Map TypeCode to string 601 s = s_typeNames[(int)TypeCode]; 602 603 switch (TypeCode) 604 { 605 case XmlTypeCode.Document: 606 if (!isXQ) 607 goto case XmlTypeCode.Element; 608 609 s += "{(element" + NameAndType(true) + "?&text?&comment?&processing-instruction?)*}"; 610 break; 611 612 case XmlTypeCode.Element: 613 case XmlTypeCode.Attribute: 614 s += NameAndType(isXQ); 615 break; 616 } 617 } 618 else if (SchemaType != XmlSchemaComplexType.AnyType) 619 { 620 // Get QualifiedName from SchemaType 621 if (SchemaType.QualifiedName.IsEmpty) 622 s = "<:" + s_typeNames[(int)TypeCode]; 623 else 624 s = QNameToString(SchemaType.QualifiedName); 625 } 626 else 627 { 628 // Map TypeCode to string 629 s = s_typeNames[(int)TypeCode]; 630 } 631 632 if (!isXQ && IsStrict) 633 s += "="; 634 635 return s; 636 } 637 638 /// <summary> 639 /// Return "(name-test, type-name)" for this type. If isXQ is false, normalize xs:anySimpleType and 640 /// xs:anyType to "*". 641 /// </summary> NameAndType(bool isXQ)642 private string NameAndType(bool isXQ) 643 { 644 string nodeName = NameTest.ToString(); 645 string typeName = "*"; 646 647 if (SchemaType.QualifiedName.IsEmpty) 648 { 649 typeName = "typeof(" + nodeName + ")"; 650 } 651 else 652 { 653 if (isXQ || (SchemaType != XmlSchemaComplexType.AnyType && SchemaType != DatatypeImplementation.AnySimpleType)) 654 typeName = QNameToString(SchemaType.QualifiedName); 655 } 656 657 if (IsNillable) 658 typeName += " nillable"; 659 660 // Normalize "(*, *)" to "" 661 if (nodeName == "*" && typeName == "*") 662 return ""; 663 664 return "(" + nodeName + ", " + typeName + ")"; 665 } 666 667 /// <summary> 668 /// Convert an XmlQualifiedName to a string, using somewhat different rules than XmlQualifiedName.ToString(): 669 /// 1. Empty QNames are assumed to be wildcard names, so return "*" 670 /// 2. Recognize the built-in xs: and xdt: namespaces and print the short prefix rather than the long namespace 671 /// 3. Use brace characters "{", "}" around the namespace portion of the QName 672 /// </summary> QNameToString(XmlQualifiedName name)673 private static string QNameToString(XmlQualifiedName name) 674 { 675 if (name.IsEmpty) 676 { 677 return "*"; 678 } 679 else if (name.Namespace.Length == 0) 680 { 681 return name.Name; 682 } 683 else if (name.Namespace == XmlReservedNs.NsXs) 684 { 685 return "xs:" + name.Name; 686 } 687 else if (name.Namespace == XmlReservedNs.NsXQueryDataType) 688 { 689 return "xdt:" + name.Name; 690 } 691 else 692 { 693 return "{" + name.Namespace + "}" + name.Name; 694 } 695 } 696 697 #region TypeFlags 698 private enum TypeFlags 699 { 700 None = 0, 701 IsNode = 1, 702 IsAtomicValue = 2, 703 IsNumeric = 4, 704 } 705 #endregion 706 707 #region TypeCodeToFlags 708 private static readonly TypeFlags[] s_typeCodeToFlags = { 709 /* XmlTypeCode.None */ TypeFlags.IsNode | TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 710 /* XmlTypeCode.Item */ TypeFlags.None, 711 /* XmlTypeCode.Node */ TypeFlags.IsNode, 712 /* XmlTypeCode.Document */ TypeFlags.IsNode, 713 /* XmlTypeCode.Element */ TypeFlags.IsNode, 714 /* XmlTypeCode.Attribute */ TypeFlags.IsNode, 715 /* XmlTypeCode.Namespace */ TypeFlags.IsNode, 716 /* XmlTypeCode.ProcessingInstruction */ TypeFlags.IsNode, 717 /* XmlTypeCode.Comment */ TypeFlags.IsNode, 718 /* XmlTypeCode.Text */ TypeFlags.IsNode, 719 /* XmlTypeCode.AnyAtomicType */ TypeFlags.IsAtomicValue, 720 /* XmlTypeCode.UntypedAtomic */ TypeFlags.IsAtomicValue, 721 /* XmlTypeCode.String */ TypeFlags.IsAtomicValue, 722 /* XmlTypeCode.Boolean */ TypeFlags.IsAtomicValue, 723 /* XmlTypeCode.Decimal */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 724 /* XmlTypeCode.Float */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 725 /* XmlTypeCode.Double */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 726 /* XmlTypeCode.Duration */ TypeFlags.IsAtomicValue, 727 /* XmlTypeCode.DateTime */ TypeFlags.IsAtomicValue, 728 /* XmlTypeCode.Time */ TypeFlags.IsAtomicValue, 729 /* XmlTypeCode.Date */ TypeFlags.IsAtomicValue, 730 /* XmlTypeCode.GYearMonth */ TypeFlags.IsAtomicValue, 731 /* XmlTypeCode.GYear */ TypeFlags.IsAtomicValue, 732 /* XmlTypeCode.GMonthDay */ TypeFlags.IsAtomicValue, 733 /* XmlTypeCode.GDay */ TypeFlags.IsAtomicValue, 734 /* XmlTypeCode.GMonth */ TypeFlags.IsAtomicValue, 735 /* XmlTypeCode.HexBinary */ TypeFlags.IsAtomicValue, 736 /* XmlTypeCode.Base64Binary */ TypeFlags.IsAtomicValue, 737 /* XmlTypeCode.AnyUri */ TypeFlags.IsAtomicValue, 738 /* XmlTypeCode.QName */ TypeFlags.IsAtomicValue, 739 /* XmlTypeCode.Notation */ TypeFlags.IsAtomicValue, 740 /* XmlTypeCode.NormalizedString */ TypeFlags.IsAtomicValue, 741 /* XmlTypeCode.Token */ TypeFlags.IsAtomicValue, 742 /* XmlTypeCode.Language */ TypeFlags.IsAtomicValue, 743 /* XmlTypeCode.NmToken */ TypeFlags.IsAtomicValue, 744 /* XmlTypeCode.Name */ TypeFlags.IsAtomicValue, 745 /* XmlTypeCode.NCName */ TypeFlags.IsAtomicValue, 746 /* XmlTypeCode.Id */ TypeFlags.IsAtomicValue, 747 /* XmlTypeCode.Idref */ TypeFlags.IsAtomicValue, 748 /* XmlTypeCode.Entity */ TypeFlags.IsAtomicValue, 749 /* XmlTypeCode.Integer */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 750 /* XmlTypeCode.NonPositiveInteger */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 751 /* XmlTypeCode.NegativeInteger */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 752 /* XmlTypeCode.Long */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 753 /* XmlTypeCode.Int */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 754 /* XmlTypeCode.Short */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 755 /* XmlTypeCode.Byte */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 756 /* XmlTypeCode.NonNegativeInteger */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 757 /* XmlTypeCode.UnsignedLong */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 758 /* XmlTypeCode.UnsignedInt */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 759 /* XmlTypeCode.UnsignedShort */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 760 /* XmlTypeCode.UnsignedByte */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 761 /* XmlTypeCode.PositiveInteger */ TypeFlags.IsAtomicValue | TypeFlags.IsNumeric, 762 /* XmlTypeCode.YearMonthDuration */ TypeFlags.IsAtomicValue, 763 /* XmlTypeCode.DayTimeDuration */ TypeFlags.IsAtomicValue, 764 }; 765 766 private static readonly XmlTypeCode[] s_baseTypeCodes = { 767 /* None */ XmlTypeCode.None, 768 /* Item */ XmlTypeCode.Item, 769 /* Node */ XmlTypeCode.Item, 770 /* Document */ XmlTypeCode.Node, 771 /* Element */ XmlTypeCode.Node, 772 /* Attribute */ XmlTypeCode.Node, 773 /* Namespace */ XmlTypeCode.Node, 774 /* ProcessingInstruction */ XmlTypeCode.Node, 775 /* Comment */ XmlTypeCode.Node, 776 /* Text */ XmlTypeCode.Node, 777 /* AnyAtomicType */ XmlTypeCode.Item, 778 /* UntypedAtomic */ XmlTypeCode.AnyAtomicType, 779 /* String */ XmlTypeCode.AnyAtomicType, 780 /* Boolean */ XmlTypeCode.AnyAtomicType, 781 /* Decimal */ XmlTypeCode.AnyAtomicType, 782 /* Float */ XmlTypeCode.AnyAtomicType, 783 /* Double */ XmlTypeCode.AnyAtomicType, 784 /* Duration */ XmlTypeCode.AnyAtomicType, 785 /* DateTime */ XmlTypeCode.AnyAtomicType, 786 /* Time */ XmlTypeCode.AnyAtomicType, 787 /* Date */ XmlTypeCode.AnyAtomicType, 788 /* GYearMonth */ XmlTypeCode.AnyAtomicType, 789 /* GYear */ XmlTypeCode.AnyAtomicType, 790 /* GMonthDay */ XmlTypeCode.AnyAtomicType, 791 /* GDay */ XmlTypeCode.AnyAtomicType, 792 /* GMonth */ XmlTypeCode.AnyAtomicType, 793 /* HexBinary */ XmlTypeCode.AnyAtomicType, 794 /* Base64Binary */ XmlTypeCode.AnyAtomicType, 795 /* AnyUri */ XmlTypeCode.AnyAtomicType, 796 /* QName */ XmlTypeCode.AnyAtomicType, 797 /* Notation */ XmlTypeCode.AnyAtomicType, 798 /* NormalizedString */ XmlTypeCode.String, 799 /* Token */ XmlTypeCode.NormalizedString, 800 /* Language */ XmlTypeCode.Token, 801 /* NmToken */ XmlTypeCode.Token, 802 /* Name */ XmlTypeCode.Token, 803 /* NCName */ XmlTypeCode.Name, 804 /* Id */ XmlTypeCode.NCName, 805 /* Idref */ XmlTypeCode.NCName, 806 /* Entity */ XmlTypeCode.NCName, 807 /* Integer */ XmlTypeCode.Decimal, 808 /* NonPositiveInteger */ XmlTypeCode.Integer, 809 /* NegativeInteger */ XmlTypeCode.NonPositiveInteger, 810 /* Long */ XmlTypeCode.Integer, 811 /* Int */ XmlTypeCode.Long, 812 /* Short */ XmlTypeCode.Int, 813 /* Byte */ XmlTypeCode.Short, 814 /* NonNegativeInteger */ XmlTypeCode.Integer, 815 /* UnsignedLong */ XmlTypeCode.NonNegativeInteger, 816 /* UnsignedInt */ XmlTypeCode.UnsignedLong, 817 /* UnsignedShort */ XmlTypeCode.UnsignedInt, 818 /* UnsignedByte */ XmlTypeCode.UnsignedShort, 819 /* PositiveInteger */ XmlTypeCode.NonNegativeInteger, 820 /* YearMonthDuration */ XmlTypeCode.Duration, 821 /* DayTimeDuration */ XmlTypeCode.Duration, 822 }; 823 824 private static readonly string[] s_typeNames = { 825 /* None */ "none", 826 /* Item */ "item", 827 /* Node */ "node", 828 /* Document */ "document", 829 /* Element */ "element", 830 /* Attribute */ "attribute", 831 /* Namespace */ "namespace", 832 /* ProcessingInstruction */ "processing-instruction", 833 /* Comment */ "comment", 834 /* Text */ "text", 835 /* AnyAtomicType */ "xdt:anyAtomicType", 836 /* UntypedAtomic */ "xdt:untypedAtomic", 837 /* String */ "xs:string", 838 /* Boolean */ "xs:boolean", 839 /* Decimal */ "xs:decimal", 840 /* Float */ "xs:float", 841 /* Double */ "xs:double", 842 /* Duration */ "xs:duration", 843 /* DateTime */ "xs:dateTime", 844 /* Time */ "xs:time", 845 /* Date */ "xs:date", 846 /* GYearMonth */ "xs:gYearMonth", 847 /* GYear */ "xs:gYear", 848 /* GMonthDay */ "xs:gMonthDay", 849 /* GDay */ "xs:gDay", 850 /* GMonth */ "xs:gMonth", 851 /* HexBinary */ "xs:hexBinary", 852 /* Base64Binary */ "xs:base64Binary", 853 /* AnyUri */ "xs:anyUri", 854 /* QName */ "xs:QName", 855 /* Notation */ "xs:NOTATION", 856 /* NormalizedString */ "xs:normalizedString", 857 /* Token */ "xs:token", 858 /* Language */ "xs:language", 859 /* NmToken */ "xs:NMTOKEN", 860 /* Name */ "xs:Name", 861 /* NCName */ "xs:NCName", 862 /* Id */ "xs:ID", 863 /* Idref */ "xs:IDREF", 864 /* Entity */ "xs:ENTITY", 865 /* Integer */ "xs:integer", 866 /* NonPositiveInteger */ "xs:nonPositiveInteger", 867 /* NegativeInteger */ "xs:negativeInteger", 868 /* Long */ "xs:long", 869 /* Int */ "xs:int", 870 /* Short */ "xs:short", 871 /* Byte */ "xs:byte", 872 /* NonNegativeInteger */ "xs:nonNegativeInteger", 873 /* UnsignedLong */ "xs:unsignedLong", 874 /* UnsignedInt */ "xs:unsignedInt", 875 /* UnsignedShort */ "xs:unsignedShort", 876 /* UnsignedByte */ "xs:unsignedByte", 877 /* PositiveInteger */ "xs:positiveInteger", 878 /* YearMonthDuration */ "xdt:yearMonthDuration", 879 /* DayTimeDuration */ "xdt:dayTimeDuration", 880 }; 881 #endregion 882 883 /// <summary> 884 /// Implements an NxN bit matrix. 885 /// </summary> 886 private sealed class BitMatrix 887 { 888 private ulong[] _bits; 889 890 /// <summary> 891 /// Create NxN bit matrix, where N = count. 892 /// </summary> BitMatrix(int count)893 public BitMatrix(int count) 894 { 895 Debug.Assert(count < 64, "BitMatrix currently only handles up to 64x64 matrix."); 896 _bits = new ulong[count]; 897 } 898 899 // /// <summary> 900 // /// Return the number of rows and columns in the matrix. 901 // /// </summary> 902 // public int Size { 903 // get { return bits.Length; } 904 // } 905 // 906 /// <summary> 907 /// Get or set a bit in the matrix at position (index1, index2). 908 /// </summary> 909 public bool this[int index1, int index2] 910 { 911 get 912 { 913 Debug.Assert(index1 < _bits.Length && index2 < _bits.Length, "Index out of range."); 914 return (_bits[index1] & ((ulong)1 << index2)) != 0; 915 } 916 set 917 { 918 Debug.Assert(index1 < _bits.Length && index2 < _bits.Length, "Index out of range."); 919 if (value == true) 920 { 921 _bits[index1] |= (ulong)1 << index2; 922 } 923 else 924 { 925 _bits[index1] &= ~((ulong)1 << index2); 926 } 927 } 928 } 929 930 /// <summary> 931 /// Strongly typed indexer. 932 /// </summary> 933 public bool this[XmlTypeCode index1, XmlTypeCode index2] 934 { 935 get 936 { 937 return this[(int)index1, (int)index2]; 938 } 939 // set { 940 // this[(int)index1, (int)index2] = value; 941 // } 942 } 943 } 944 } 945 } 946