1 //------------------------------------------------------------ 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //------------------------------------------------------------ 4 namespace System.Xml 5 { 6 using System; 7 using System.Collections; 8 using System.Globalization; 9 using System.IO; 10 using System.Runtime; 11 using System.Runtime.Serialization; 12 using System.Security; 13 using System.Text; 14 15 class XmlBufferReader 16 { 17 XmlDictionaryReader reader; 18 Stream stream; 19 byte[] streamBuffer; 20 byte[] buffer; 21 int offsetMin; 22 int offsetMax; 23 IXmlDictionary dictionary; 24 XmlBinaryReaderSession session; 25 byte[] guid; 26 int offset; 27 const int maxBytesPerChar = 3; 28 char[] chars; 29 int windowOffset; 30 int windowOffsetMax; 31 ValueHandle listValue; 32 static byte[] emptyByteArray = new byte[0]; 33 static XmlBufferReader empty = new XmlBufferReader(emptyByteArray); 34 XmlBufferReader(XmlDictionaryReader reader)35 public XmlBufferReader(XmlDictionaryReader reader) 36 { 37 this.reader = reader; 38 } 39 XmlBufferReader(byte[] buffer)40 public XmlBufferReader(byte[] buffer) 41 { 42 this.reader = null; 43 this.buffer = buffer; 44 } 45 46 static public XmlBufferReader Empty 47 { 48 get 49 { 50 return empty; 51 } 52 } 53 54 public byte[] Buffer 55 { 56 get 57 { 58 return buffer; 59 } 60 } 61 62 public bool IsStreamed 63 { 64 get 65 { 66 return stream != null; 67 } 68 } 69 SetBuffer(Stream stream, IXmlDictionary dictionary, XmlBinaryReaderSession session)70 public void SetBuffer(Stream stream, IXmlDictionary dictionary, XmlBinaryReaderSession session) 71 { 72 if (streamBuffer == null) 73 { 74 streamBuffer = new byte[128]; 75 } 76 SetBuffer(stream, streamBuffer, 0, 0, dictionary, session); 77 this.windowOffset = 0; 78 this.windowOffsetMax = streamBuffer.Length; 79 } 80 SetBuffer(byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session)81 public void SetBuffer(byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session) 82 { 83 SetBuffer(null, buffer, offset, count, dictionary, session); 84 } 85 SetBuffer(Stream stream, byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session)86 void SetBuffer(Stream stream, byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session) 87 { 88 this.stream = stream; 89 this.buffer = buffer; 90 this.offsetMin = offset; 91 this.offset = offset; 92 this.offsetMax = offset + count; 93 this.dictionary = dictionary; 94 this.session = session; 95 } 96 Close()97 public void Close() 98 { 99 if (streamBuffer != null && streamBuffer.Length > 4096) 100 { 101 streamBuffer = null; 102 } 103 if (stream != null) 104 { 105 stream.Close(); 106 this.stream = null; 107 } 108 this.buffer = emptyByteArray; 109 this.offset = 0; 110 this.offsetMax = 0; 111 this.windowOffset = 0; 112 this.windowOffsetMax = 0; 113 this.dictionary = null; 114 this.session = null; 115 } 116 117 public bool EndOfFile 118 { 119 get 120 { 121 return offset == offsetMax && !TryEnsureByte(); 122 } 123 } 124 GetByte()125 public byte GetByte() 126 { 127 int offset = this.offset; 128 if (offset < offsetMax) 129 return buffer[offset]; 130 else 131 return GetByteHard(); 132 } 133 SkipByte()134 public void SkipByte() 135 { 136 Advance(1); 137 } 138 GetByteHard()139 byte GetByteHard() 140 { 141 EnsureByte(); 142 return buffer[offset]; 143 } 144 GetBuffer(int count, out int offset)145 public byte[] GetBuffer(int count, out int offset) 146 { 147 offset = this.offset; 148 if (offset <= this.offsetMax - count) 149 return buffer; 150 return GetBufferHard(count, out offset); 151 } 152 GetBuffer(int count, out int offset, out int offsetMax)153 public byte[] GetBuffer(int count, out int offset, out int offsetMax) 154 { 155 offset = this.offset; 156 if (offset <= this.offsetMax - count) 157 { 158 offsetMax = this.offset + count; 159 } 160 else 161 { 162 TryEnsureBytes(Math.Min(count, windowOffsetMax - offset)); 163 offsetMax = this.offsetMax; 164 } 165 return buffer; 166 } 167 GetBuffer(out int offset, out int offsetMax)168 public byte[] GetBuffer(out int offset, out int offsetMax) 169 { 170 offset = this.offset; 171 offsetMax = this.offsetMax; 172 return buffer; 173 } 174 GetBufferHard(int count, out int offset)175 byte[] GetBufferHard(int count, out int offset) 176 { 177 offset = this.offset; 178 EnsureBytes(count); 179 return buffer; 180 } 181 EnsureByte()182 void EnsureByte() 183 { 184 if (!TryEnsureByte()) 185 XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader); 186 } 187 TryEnsureByte()188 bool TryEnsureByte() 189 { 190 if (stream == null) 191 return false; 192 if (offsetMax >= windowOffsetMax) 193 XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset); 194 if (offsetMax >= buffer.Length) 195 return TryEnsureBytes(1); 196 int b = stream.ReadByte(); 197 if (b == -1) 198 return false; 199 buffer[offsetMax++] = (byte)b; 200 return true; 201 } 202 EnsureBytes(int count)203 void EnsureBytes(int count) 204 { 205 if (!TryEnsureBytes(count)) 206 XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader); 207 } 208 TryEnsureBytes(int count)209 bool TryEnsureBytes(int count) 210 { 211 if (stream == null) 212 return false; 213 if (offset > int.MaxValue - count) 214 XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset); 215 int newOffsetMax = offset + count; 216 if (newOffsetMax < offsetMax) 217 return true; 218 if (newOffsetMax > windowOffsetMax) 219 XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset); 220 if (newOffsetMax > buffer.Length) 221 { 222 byte[] newBuffer = new byte[Math.Max(newOffsetMax, buffer.Length * 2)]; 223 System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, offsetMax); 224 buffer = newBuffer; 225 streamBuffer = newBuffer; 226 } 227 int needed = newOffsetMax - offsetMax; 228 while (needed > 0) 229 { 230 int actual = stream.Read(buffer, offsetMax, needed); 231 if (actual == 0) 232 return false; 233 offsetMax += actual; 234 needed -= actual; 235 } 236 return true; 237 } 238 239 #if NO ReadByte(byte b)240 void ReadByte(byte b) 241 { 242 if (BufferReader.GetByte() != b) 243 XmlExceptionHelper.ThrowTokenExpected(this, ((char)b).ToString(), (char)BufferReader.GetByte()); 244 } 245 #endif Advance(int count)246 public void Advance(int count) 247 { 248 Fx.Assert(this.offset + count <= offsetMax, ""); 249 this.offset += count; 250 } 251 InsertBytes(byte[] buffer, int offset, int count)252 public void InsertBytes(byte[] buffer, int offset, int count) 253 { 254 Fx.Assert(stream != null, ""); 255 if (offsetMax > buffer.Length - count) 256 { 257 byte[] newBuffer = new byte[offsetMax + count]; 258 System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, this.offsetMax); 259 this.buffer = newBuffer; 260 this.streamBuffer = newBuffer; 261 } 262 System.Buffer.BlockCopy(this.buffer, this.offset, this.buffer, this.offset + count, this.offsetMax - this.offset); 263 offsetMax += count; 264 System.Buffer.BlockCopy(buffer, offset, this.buffer, this.offset, count); 265 } 266 SetWindow(int windowOffset, int windowLength)267 public void SetWindow(int windowOffset, int windowLength) 268 { 269 // [0...elementOffset-1][elementOffset..offset][offset..offsetMax-1][offsetMax..buffer.Length] 270 // ^--Elements, Attributes in scope 271 // ^-- The node just consumed 272 // ^--Data buffered, not consumed 273 // ^--Unused space 274 if (windowOffset > int.MaxValue - windowLength) 275 windowLength = int.MaxValue - windowOffset; 276 277 if (offset != windowOffset) 278 { 279 System.Buffer.BlockCopy(buffer, offset, buffer, windowOffset, offsetMax - offset); 280 offsetMax = windowOffset + (offsetMax - offset); 281 offset = windowOffset; 282 } 283 this.windowOffset = windowOffset; 284 this.windowOffsetMax = Math.Max(windowOffset + windowLength, offsetMax); 285 } 286 287 public int Offset 288 { 289 get 290 { 291 return offset; 292 } 293 set 294 { 295 Fx.Assert(value >= offsetMin && value <= offsetMax, ""); 296 this.offset = value; 297 } 298 } 299 ReadBytes(int count)300 public int ReadBytes(int count) 301 { 302 Fx.Assert(count >= 0, ""); 303 int offset = this.offset; 304 if (offset > offsetMax - count) 305 EnsureBytes(count); 306 this.offset += count; 307 return offset; 308 } 309 ReadMultiByteUInt31()310 public int ReadMultiByteUInt31() 311 { 312 int i = GetByte(); 313 Advance(1); 314 if ((i & 0x80) == 0) 315 return i; 316 i &= 0x7F; 317 318 int j = GetByte(); 319 Advance(1); 320 i |= ((j & 0x7F) << 7); 321 if ((j & 0x80) == 0) 322 return i; 323 324 int k = GetByte(); 325 Advance(1); 326 i |= ((k & 0x7F) << 14); 327 if ((k & 0x80) == 0) 328 return i; 329 330 int l = GetByte(); 331 Advance(1); 332 i |= ((l & 0x7F) << 21); 333 if ((l & 0x80) == 0) 334 return i; 335 336 int m = GetByte(); 337 Advance(1); 338 i |= (m << 28); 339 if ((m & 0xF8) != 0) 340 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 341 342 return i; 343 } 344 ReadUInt8()345 public int ReadUInt8() 346 { 347 byte b = GetByte(); 348 Advance(1); 349 return b; 350 } 351 ReadInt8()352 public int ReadInt8() 353 { 354 return (sbyte)ReadUInt8(); 355 } 356 ReadUInt16()357 public int ReadUInt16() 358 { 359 int offset; 360 byte[] buffer = GetBuffer(2, out offset); 361 int i = buffer[offset + 0] + (buffer[offset + 1] << 8); 362 Advance(2); 363 return i; 364 } 365 ReadInt16()366 public int ReadInt16() 367 { 368 return (Int16)ReadUInt16(); 369 } 370 ReadInt32()371 public int ReadInt32() 372 { 373 int offset; 374 byte[] buffer = GetBuffer(4, out offset); 375 byte b1 = buffer[offset + 0]; 376 byte b2 = buffer[offset + 1]; 377 byte b3 = buffer[offset + 2]; 378 byte b4 = buffer[offset + 3]; 379 Advance(4); 380 return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 381 } 382 ReadUInt31()383 public int ReadUInt31() 384 { 385 int i = ReadInt32(); 386 if (i < 0) 387 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 388 return i; 389 } 390 ReadInt64()391 public long ReadInt64() 392 { 393 Int64 lo = (UInt32)ReadInt32(); 394 Int64 hi = (UInt32)ReadInt32(); 395 return (hi << 32) + lo; 396 } 397 398 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 399 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 400 [SecuritySafeCritical] ReadSingle()401 unsafe public float ReadSingle() 402 { 403 int offset; 404 byte[] buffer = GetBuffer(ValueHandleLength.Single, out offset); 405 float value; 406 byte* pb = (byte*)&value; 407 Fx.Assert(sizeof(float) == 4, ""); 408 pb[0] = buffer[offset + 0]; 409 pb[1] = buffer[offset + 1]; 410 pb[2] = buffer[offset + 2]; 411 pb[3] = buffer[offset + 3]; 412 Advance(ValueHandleLength.Single); 413 return value; 414 } 415 416 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 417 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 418 [SecuritySafeCritical] ReadDouble()419 unsafe public double ReadDouble() 420 { 421 int offset; 422 byte[] buffer = GetBuffer(ValueHandleLength.Double, out offset); 423 double value; 424 byte* pb = (byte*)&value; 425 Fx.Assert(sizeof(double) == 8, ""); 426 pb[0] = buffer[offset + 0]; 427 pb[1] = buffer[offset + 1]; 428 pb[2] = buffer[offset + 2]; 429 pb[3] = buffer[offset + 3]; 430 pb[4] = buffer[offset + 4]; 431 pb[5] = buffer[offset + 5]; 432 pb[6] = buffer[offset + 6]; 433 pb[7] = buffer[offset + 7]; 434 Advance(ValueHandleLength.Double); 435 return value; 436 } 437 438 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 439 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 440 [SecuritySafeCritical] ReadDecimal()441 unsafe public decimal ReadDecimal() 442 { 443 const int SignMask = unchecked((int)0x80000000); 444 const int ScaleMask = 0x00FF0000; 445 446 int offset; 447 byte[] buffer = GetBuffer(ValueHandleLength.Decimal, out offset); 448 byte b1 = buffer[offset + 0]; 449 byte b2 = buffer[offset + 1]; 450 byte b3 = buffer[offset + 2]; 451 byte b4 = buffer[offset + 3]; 452 int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 453 454 //this logic mirrors the code in Decimal(int []) ctor. 455 if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) 456 { 457 decimal value; 458 byte* pb = (byte*)&value; 459 for (int i = 0; i < sizeof(decimal); i++) 460 pb[i] = buffer[offset + i]; 461 462 Advance(ValueHandleLength.Decimal); 463 return value; 464 } 465 else 466 { 467 XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader); 468 } 469 470 //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws, 471 //so we have to have a return statement here even though we shouldn't hit this code path... 472 Fx.Assert("A decimal value should have been returned or an exception should have been thrown."); 473 return default(decimal); 474 } 475 ReadUniqueId()476 public UniqueId ReadUniqueId() 477 { 478 int offset; 479 byte[] buffer = GetBuffer(ValueHandleLength.UniqueId, out offset); 480 UniqueId uniqueId = new UniqueId(buffer, offset); 481 Advance(ValueHandleLength.UniqueId); 482 return uniqueId; 483 } 484 ReadDateTime()485 public DateTime ReadDateTime() 486 { 487 long value = 0; 488 try 489 { 490 value = ReadInt64(); 491 return DateTime.FromBinary(value); 492 } 493 catch (ArgumentException exception) 494 { 495 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception)); 496 } 497 catch (FormatException exception) 498 { 499 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception)); 500 } 501 catch (OverflowException exception) 502 { 503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception)); 504 } 505 } 506 ReadTimeSpan()507 public TimeSpan ReadTimeSpan() 508 { 509 long value = 0; 510 try 511 { 512 value = ReadInt64(); 513 return TimeSpan.FromTicks(value); 514 } 515 catch (ArgumentException exception) 516 { 517 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception)); 518 } 519 catch (FormatException exception) 520 { 521 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception)); 522 } 523 catch (OverflowException exception) 524 { 525 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception)); 526 } 527 } 528 ReadGuid()529 public Guid ReadGuid() 530 { 531 int offset; 532 byte[] buffer = GetBuffer(ValueHandleLength.Guid, out offset); 533 Guid guid = GetGuid(offset); 534 Advance(ValueHandleLength.Guid); 535 return guid; 536 } 537 ReadUTF8String(int length)538 public string ReadUTF8String(int length) 539 { 540 int offset; 541 byte[] buffer = GetBuffer(length, out offset); 542 char[] chars = GetCharBuffer(length); 543 int charCount = GetChars(offset, length, chars); 544 string value = new string(chars, 0, charCount); 545 Advance(length); 546 return value; 547 } 548 549 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 550 [SecurityCritical] UnsafeReadArray(byte* dst, byte* dstMax)551 unsafe public void UnsafeReadArray(byte* dst, byte* dstMax) 552 { 553 UnsafeReadArray(dst, (int)(dstMax - dst)); 554 } 555 556 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 557 [SecurityCritical] UnsafeReadArray(byte* dst, int length)558 unsafe void UnsafeReadArray(byte* dst, int length) 559 { 560 if (stream != null) 561 { 562 const int chunk = 256; 563 while (length >= chunk) 564 { 565 byte[] _buffer = GetBuffer(chunk, out offset); 566 for (int i = 0; i < chunk; i++) 567 { 568 *dst++ = _buffer[offset + i]; 569 } 570 Advance(chunk); 571 length -= chunk; 572 } 573 } 574 575 if (length > 0) 576 { 577 byte[] buffer = GetBuffer(length, out offset); 578 fixed (byte* _src = &buffer[offset]) 579 { 580 byte* src = _src; 581 byte* dstMax = dst + length; 582 while (dst < dstMax) 583 { 584 *dst = *src; 585 dst++; 586 src++; 587 } 588 } 589 Advance(length); 590 } 591 } 592 GetCharBuffer(int count)593 char[] GetCharBuffer(int count) 594 { 595 if (count > 1024) 596 return new char[count]; 597 if (chars == null || chars.Length < count) 598 chars = new char[count]; 599 return chars; 600 } 601 GetChars(int offset, int length, char[] chars)602 int GetChars(int offset, int length, char[] chars) 603 { 604 byte[] buffer = this.buffer; 605 for (int i = 0; i < length; i++) 606 { 607 byte b = buffer[offset + i]; 608 if (b >= 0x80) 609 return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, i); 610 chars[i] = (char)b; 611 } 612 return length; 613 } 614 GetChars(int offset, int length, char[] chars, int charOffset)615 int GetChars(int offset, int length, char[] chars, int charOffset) 616 { 617 byte[] buffer = this.buffer; 618 for (int i = 0; i < length; i++) 619 { 620 byte b = buffer[offset + i]; 621 if (b >= 0x80) 622 return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, charOffset + i); 623 chars[charOffset + i] = (char)b; 624 } 625 return length; 626 } 627 GetString(int offset, int length)628 public string GetString(int offset, int length) 629 { 630 char[] chars = GetCharBuffer(length); 631 int charCount = GetChars(offset, length, chars); 632 return new string(chars, 0, charCount); 633 } 634 GetUnicodeString(int offset, int length)635 public string GetUnicodeString(int offset, int length) 636 { 637 return XmlConverter.ToStringUnicode(buffer, offset, length); 638 } 639 GetString(int offset, int length, XmlNameTable nameTable)640 public string GetString(int offset, int length, XmlNameTable nameTable) 641 { 642 char[] chars = GetCharBuffer(length); 643 int charCount = GetChars(offset, length, chars); 644 return nameTable.Add(chars, 0, charCount); 645 } 646 GetEscapedChars(int offset, int length, char[] chars)647 public int GetEscapedChars(int offset, int length, char[] chars) 648 { 649 byte[] buffer = this.buffer; 650 int charCount = 0; 651 int textOffset = offset; 652 int offsetMax = offset + length; 653 while (true) 654 { 655 while (offset < offsetMax && IsAttrChar(buffer[offset])) 656 offset++; 657 charCount += GetChars(textOffset, offset - textOffset, chars, charCount); 658 if (offset == offsetMax) 659 break; 660 textOffset = offset; 661 if (buffer[offset] == '&') 662 { 663 while (offset < offsetMax && buffer[offset] != ';') 664 offset++; 665 offset++; 666 int ch = GetCharEntity(textOffset, offset - textOffset); 667 textOffset = offset; 668 if (ch > char.MaxValue) 669 { 670 SurrogateChar surrogate = new SurrogateChar(ch); 671 chars[charCount++] = surrogate.HighChar; 672 chars[charCount++] = surrogate.LowChar; 673 } 674 else 675 { 676 chars[charCount++] = (char)ch; 677 } 678 } 679 else if (buffer[offset] == '\n' || buffer[offset] == '\t') 680 { 681 chars[charCount++] = ' '; 682 offset++; 683 textOffset = offset; 684 } 685 else // '\r' 686 { 687 chars[charCount++] = ' '; 688 offset++; 689 690 if (offset < offsetMax && buffer[offset] == '\n') 691 offset++; 692 693 textOffset = offset; 694 } 695 696 } 697 return charCount; 698 } 699 IsAttrChar(int ch)700 bool IsAttrChar(int ch) 701 { 702 switch (ch) 703 { 704 case '&': 705 case '\r': 706 case '\t': 707 case '\n': 708 return false; 709 710 default: 711 return true; 712 } 713 } 714 GetEscapedString(int offset, int length)715 public string GetEscapedString(int offset, int length) 716 { 717 char[] chars = GetCharBuffer(length); 718 int charCount = GetEscapedChars(offset, length, chars); 719 return new string(chars, 0, charCount); 720 } 721 GetEscapedString(int offset, int length, XmlNameTable nameTable)722 public string GetEscapedString(int offset, int length, XmlNameTable nameTable) 723 { 724 char[] chars = GetCharBuffer(length); 725 int charCount = GetEscapedChars(offset, length, chars); 726 return nameTable.Add(chars, 0, charCount); 727 } 728 GetLessThanCharEntity(int offset, int length)729 int GetLessThanCharEntity(int offset, int length) 730 { 731 byte[] buffer = this.buffer; 732 if (length != 4 || 733 buffer[offset + 1] != (byte)'l' || 734 buffer[offset + 2] != (byte)'t') 735 { 736 XmlExceptionHelper.ThrowInvalidCharRef(reader); 737 } 738 return (int)'<'; 739 } 740 GetGreaterThanCharEntity(int offset, int length)741 int GetGreaterThanCharEntity(int offset, int length) 742 { 743 byte[] buffer = this.buffer; 744 if (length != 4 || 745 buffer[offset + 1] != (byte)'g' || 746 buffer[offset + 2] != (byte)'t') 747 { 748 XmlExceptionHelper.ThrowInvalidCharRef(reader); 749 } 750 return (int)'>'; 751 } 752 GetQuoteCharEntity(int offset, int length)753 int GetQuoteCharEntity(int offset, int length) 754 { 755 byte[] buffer = this.buffer; 756 if (length != 6 || 757 buffer[offset + 1] != (byte)'q' || 758 buffer[offset + 2] != (byte)'u' || 759 buffer[offset + 3] != (byte)'o' || 760 buffer[offset + 4] != (byte)'t') 761 { 762 XmlExceptionHelper.ThrowInvalidCharRef(reader); 763 } 764 return (int)'"'; 765 } 766 GetAmpersandCharEntity(int offset, int length)767 int GetAmpersandCharEntity(int offset, int length) 768 { 769 byte[] buffer = this.buffer; 770 if (length != 5 || 771 buffer[offset + 1] != (byte)'a' || 772 buffer[offset + 2] != (byte)'m' || 773 buffer[offset + 3] != (byte)'p') 774 { 775 XmlExceptionHelper.ThrowInvalidCharRef(reader); 776 } 777 return (int)'&'; 778 } 779 GetApostropheCharEntity(int offset, int length)780 int GetApostropheCharEntity(int offset, int length) 781 { 782 byte[] buffer = this.buffer; 783 if (length != 6 || 784 buffer[offset + 1] != (byte)'a' || 785 buffer[offset + 2] != (byte)'p' || 786 buffer[offset + 3] != (byte)'o' || 787 buffer[offset + 4] != (byte)'s') 788 { 789 XmlExceptionHelper.ThrowInvalidCharRef(reader); 790 } 791 return (int)'\''; 792 } 793 GetDecimalCharEntity(int offset, int length)794 int GetDecimalCharEntity(int offset, int length) 795 { 796 byte[] buffer = this.buffer; 797 Fx.Assert(buffer[offset + 0] == '&', ""); 798 Fx.Assert(buffer[offset + 1] == '#', ""); 799 Fx.Assert(buffer[offset + length - 1] == ';', ""); 800 int value = 0; 801 for (int i = 2; i < length - 1; i++) 802 { 803 byte ch = buffer[offset + i]; 804 if (ch < (byte)'0' || ch > (byte)'9') 805 XmlExceptionHelper.ThrowInvalidCharRef(reader); 806 value = value * 10 + (ch - '0'); 807 if (value > SurrogateChar.MaxValue) 808 XmlExceptionHelper.ThrowInvalidCharRef(reader); 809 } 810 return value; 811 } 812 GetHexCharEntity(int offset, int length)813 int GetHexCharEntity(int offset, int length) 814 { 815 byte[] buffer = this.buffer; 816 Fx.Assert(buffer[offset + 0] == '&', ""); 817 Fx.Assert(buffer[offset + 1] == '#', ""); 818 Fx.Assert(buffer[offset + 2] == 'x', ""); 819 Fx.Assert(buffer[offset + length - 1] == ';', ""); 820 int value = 0; 821 for (int i = 3; i < length - 1; i++) 822 { 823 byte ch = buffer[offset + i]; 824 int digit = 0; 825 if (ch >= '0' && ch <= '9') 826 digit = (ch - '0'); 827 else if (ch >= 'a' && ch <= 'f') 828 digit = 10 + (ch - 'a'); 829 else if (ch >= 'A' && ch <= 'F') 830 digit = 10 + (ch - 'A'); 831 else 832 XmlExceptionHelper.ThrowInvalidCharRef(reader); 833 Fx.Assert(digit >= 0 && digit < 16, ""); 834 value = value * 16 + digit; 835 if (value > SurrogateChar.MaxValue) 836 XmlExceptionHelper.ThrowInvalidCharRef(reader); 837 } 838 return value; 839 } 840 GetCharEntity(int offset, int length)841 public int GetCharEntity(int offset, int length) 842 { 843 if (length < 3) 844 XmlExceptionHelper.ThrowInvalidCharRef(reader); 845 byte[] buffer = this.buffer; 846 Fx.Assert(buffer[offset] == '&', ""); 847 Fx.Assert(buffer[offset + length - 1] == ';', ""); 848 switch (buffer[offset + 1]) 849 { 850 case (byte)'l': 851 return GetLessThanCharEntity(offset, length); 852 case (byte)'g': 853 return GetGreaterThanCharEntity(offset, length); 854 case (byte)'a': 855 if (buffer[offset + 2] == (byte)'m') 856 return GetAmpersandCharEntity(offset, length); 857 else 858 return GetApostropheCharEntity(offset, length); 859 case (byte)'q': 860 return GetQuoteCharEntity(offset, length); 861 case (byte)'#': 862 if (buffer[offset + 2] == (byte)'x') 863 return GetHexCharEntity(offset, length); 864 else 865 return GetDecimalCharEntity(offset, length); 866 default: 867 XmlExceptionHelper.ThrowInvalidCharRef(reader); 868 return 0; 869 } 870 } 871 IsWhitespaceKey(int key)872 public bool IsWhitespaceKey(int key) 873 { 874 string s = GetDictionaryString(key).Value; 875 for (int i = 0; i < s.Length; i++) 876 { 877 if (!XmlConverter.IsWhitespace(s[i])) 878 return false; 879 } 880 return true; 881 } 882 IsWhitespaceUTF8(int offset, int length)883 public bool IsWhitespaceUTF8(int offset, int length) 884 { 885 byte[] buffer = this.buffer; 886 for (int i = 0; i < length; i++) 887 { 888 if (!XmlConverter.IsWhitespace((char)buffer[offset + i])) 889 return false; 890 } 891 return true; 892 } 893 IsWhitespaceUnicode(int offset, int length)894 public bool IsWhitespaceUnicode(int offset, int length) 895 { 896 byte[] buffer = this.buffer; 897 for (int i = 0; i < length; i += sizeof(char)) 898 { 899 char ch = (char)GetInt16(offset + i); 900 if (!XmlConverter.IsWhitespace(ch)) 901 return false; 902 } 903 return true; 904 } 905 Equals2(int key1, int key2, XmlBufferReader bufferReader2)906 public bool Equals2(int key1, int key2, XmlBufferReader bufferReader2) 907 { 908 // If the keys aren't from the same dictionary, they still might be the same 909 if (key1 == key2) 910 return true; 911 else 912 return GetDictionaryString(key1).Value == bufferReader2.GetDictionaryString(key2).Value; 913 } 914 Equals2(int key1, XmlDictionaryString xmlString2)915 public bool Equals2(int key1, XmlDictionaryString xmlString2) 916 { 917 if ((key1 & 1) == 0 && xmlString2.Dictionary == dictionary) 918 return xmlString2.Key == (key1 >> 1); 919 else 920 return GetDictionaryString(key1).Value == xmlString2.Value; 921 } 922 Equals2(int offset1, int length1, byte[] buffer2)923 public bool Equals2(int offset1, int length1, byte[] buffer2) 924 { 925 int length2 = buffer2.Length; 926 if (length1 != length2) 927 return false; 928 byte[] buffer1 = this.buffer; 929 for (int i = 0; i < length1; i++) 930 { 931 if (buffer1[offset1 + i] != buffer2[i]) 932 return false; 933 } 934 return true; 935 } 936 Equals2(int offset1, int length1, XmlBufferReader bufferReader2, int offset2, int length2)937 public bool Equals2(int offset1, int length1, XmlBufferReader bufferReader2, int offset2, int length2) 938 { 939 if (length1 != length2) 940 return false; 941 byte[] buffer1 = this.buffer; 942 byte[] buffer2 = bufferReader2.buffer; 943 for (int i = 0; i < length1; i++) 944 { 945 if (buffer1[offset1 + i] != buffer2[offset2 + i]) 946 return false; 947 } 948 return true; 949 } 950 Equals2(int offset1, int length1, int offset2, int length2)951 public bool Equals2(int offset1, int length1, int offset2, int length2) 952 { 953 if (length1 != length2) 954 return false; 955 if (offset1 == offset2) 956 return true; 957 byte[] buffer = this.buffer; 958 for (int i = 0; i < length1; i++) 959 { 960 if (buffer[offset1 + i] != buffer[offset2 + i]) 961 return false; 962 } 963 return true; 964 } 965 966 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 967 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 968 [SecuritySafeCritical] Equals2(int offset1, int length1, string s2)969 unsafe public bool Equals2(int offset1, int length1, string s2) 970 { 971 int byteLength = length1; 972 int charLength = s2.Length; 973 974 // N unicode chars will be represented in at least N bytes, but 975 // no more than N * 3 bytes. If the byte count falls outside of this 976 // range, then the strings cannot be equal. 977 if (byteLength < charLength || byteLength > charLength * maxBytesPerChar) 978 return false; 979 980 byte[] buffer = this.buffer; 981 if (length1 < 8) 982 { 983 int length = Math.Min(byteLength, charLength); 984 int offset = offset1; 985 for (int i = 0; i < length; i++) 986 { 987 byte b = buffer[offset + i]; 988 if (b >= 0x80) 989 return XmlConverter.ToString(buffer, offset1, length1) == s2; 990 if (s2[i] != (char)b) 991 return false; 992 } 993 return byteLength == charLength; 994 } 995 else 996 { 997 int length = Math.Min(byteLength, charLength); 998 fixed (byte* _pb = &buffer[offset1]) 999 { 1000 byte* pb = _pb; 1001 byte* pbMax = pb + length; 1002 fixed (char* _pch = s2) 1003 { 1004 char* pch = _pch; 1005 // Try to do the fast comparison in ascii space 1006 int t = 0; 1007 while (pb < pbMax && *pb < 0x80) 1008 { 1009 t = *pb - (byte)(*pch); 1010 // The code generated is better if we break out then return 1011 if (t != 0) 1012 break; 1013 pb++; 1014 pch++; 1015 } 1016 if (t != 0) 1017 return false; 1018 if (pb == pbMax) 1019 return (byteLength == charLength); 1020 } 1021 } 1022 return XmlConverter.ToString(buffer, offset1, length1) == s2; 1023 } 1024 } 1025 Compare(int offset1, int length1, int offset2, int length2)1026 public int Compare(int offset1, int length1, int offset2, int length2) 1027 { 1028 byte[] buffer = this.buffer; 1029 int length = Math.Min(length1, length2); 1030 for (int i = 0; i < length; i++) 1031 { 1032 int s = buffer[offset1 + i] - buffer[offset2 + i]; 1033 if (s != 0) 1034 return s; 1035 } 1036 return length1 - length2; 1037 } 1038 GetByte(int offset)1039 public byte GetByte(int offset) 1040 { 1041 return buffer[offset]; 1042 } 1043 GetInt8(int offset)1044 public int GetInt8(int offset) 1045 { 1046 return (sbyte)GetByte(offset); 1047 } 1048 GetInt16(int offset)1049 public int GetInt16(int offset) 1050 { 1051 byte[] buffer = this.buffer; 1052 return (Int16)(buffer[offset] + (buffer[offset + 1] << 8)); 1053 } 1054 GetInt32(int offset)1055 public int GetInt32(int offset) 1056 { 1057 byte[] buffer = this.buffer; 1058 byte b1 = buffer[offset + 0]; 1059 byte b2 = buffer[offset + 1]; 1060 byte b3 = buffer[offset + 2]; 1061 byte b4 = buffer[offset + 3]; 1062 return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 1063 } 1064 GetInt64(int offset)1065 public long GetInt64(int offset) 1066 { 1067 byte[] buffer = this.buffer; 1068 byte b1, b2, b3, b4; 1069 b1 = buffer[offset + 0]; 1070 b2 = buffer[offset + 1]; 1071 b3 = buffer[offset + 2]; 1072 b4 = buffer[offset + 3]; 1073 Int64 lo = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 1074 b1 = buffer[offset + 4]; 1075 b2 = buffer[offset + 5]; 1076 b3 = buffer[offset + 6]; 1077 b4 = buffer[offset + 7]; 1078 Int64 hi = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 1079 return (hi << 32) + lo; 1080 } 1081 GetUInt64(int offset)1082 public ulong GetUInt64(int offset) 1083 { 1084 return (ulong)GetInt64(offset); 1085 } 1086 1087 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 1088 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 1089 [SecuritySafeCritical] GetSingle(int offset)1090 unsafe public float GetSingle(int offset) 1091 { 1092 byte[] buffer = this.buffer; 1093 float value; 1094 byte* pb = (byte*)&value; 1095 Fx.Assert(sizeof(float) == 4, ""); 1096 pb[0] = buffer[offset + 0]; 1097 pb[1] = buffer[offset + 1]; 1098 pb[2] = buffer[offset + 2]; 1099 pb[3] = buffer[offset + 3]; 1100 return value; 1101 } 1102 1103 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 1104 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 1105 [SecuritySafeCritical] GetDouble(int offset)1106 unsafe public double GetDouble(int offset) 1107 { 1108 byte[] buffer = this.buffer; 1109 double value; 1110 byte* pb = (byte*)&value; 1111 Fx.Assert(sizeof(double) == 8, ""); 1112 pb[0] = buffer[offset + 0]; 1113 pb[1] = buffer[offset + 1]; 1114 pb[2] = buffer[offset + 2]; 1115 pb[3] = buffer[offset + 3]; 1116 pb[4] = buffer[offset + 4]; 1117 pb[5] = buffer[offset + 5]; 1118 pb[6] = buffer[offset + 6]; 1119 pb[7] = buffer[offset + 7]; 1120 return value; 1121 } 1122 1123 [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 1124 Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 1125 [SecuritySafeCritical] GetDecimal(int offset)1126 public unsafe decimal GetDecimal(int offset) 1127 { 1128 const int SignMask = unchecked((int)0x80000000); 1129 const int ScaleMask = 0x00FF0000; 1130 1131 byte[] buffer = this.buffer; 1132 byte b1 = buffer[offset + 0]; 1133 byte b2 = buffer[offset + 1]; 1134 byte b3 = buffer[offset + 2]; 1135 byte b4 = buffer[offset + 3]; 1136 int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 1137 1138 //this logic mirrors the code in Decimal(int []) ctor. 1139 if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) 1140 { 1141 decimal value; 1142 byte* pb = (byte*)&value; 1143 for (int i = 0; i < sizeof(decimal); i++) 1144 pb[i] = buffer[offset + i]; 1145 return value; 1146 } 1147 else 1148 { 1149 XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader); 1150 } 1151 1152 //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws, 1153 //so we have to have a return statement here even though we shouldn't hit this code path... 1154 Fx.Assert("A decimal value should have been returned or an exception should have been thrown."); 1155 return default(decimal); 1156 } 1157 GetUniqueId(int offset)1158 public UniqueId GetUniqueId(int offset) 1159 { 1160 return new UniqueId(this.buffer, offset); 1161 } 1162 GetGuid(int offset)1163 public Guid GetGuid(int offset) 1164 { 1165 if (guid == null) 1166 guid = new byte[16]; 1167 System.Buffer.BlockCopy(buffer, offset, guid, 0, guid.Length); 1168 return new Guid(guid); 1169 } 1170 GetBase64(int srcOffset, byte[] buffer, int dstOffset, int count)1171 public void GetBase64(int srcOffset, byte[] buffer, int dstOffset, int count) 1172 { 1173 System.Buffer.BlockCopy(this.buffer, srcOffset, buffer, dstOffset, count); 1174 } 1175 GetNodeType()1176 public XmlBinaryNodeType GetNodeType() 1177 { 1178 return (XmlBinaryNodeType)GetByte(); 1179 } 1180 SkipNodeType()1181 public void SkipNodeType() 1182 { 1183 SkipByte(); 1184 } 1185 GetList(int offset, int count)1186 public object[] GetList(int offset, int count) 1187 { 1188 int bufferOffset = this.Offset; 1189 this.Offset = offset; 1190 try 1191 { 1192 object[] objects = new object[count]; 1193 for (int i = 0; i < count; i++) 1194 { 1195 XmlBinaryNodeType nodeType = GetNodeType(); 1196 SkipNodeType(); 1197 Fx.Assert(nodeType != XmlBinaryNodeType.StartListText, ""); 1198 ReadValue(nodeType, listValue); 1199 objects[i] = listValue.ToObject(); 1200 } 1201 return objects; 1202 } 1203 finally 1204 { 1205 this.Offset = bufferOffset; 1206 } 1207 } 1208 GetDictionaryString(int key)1209 public XmlDictionaryString GetDictionaryString(int key) 1210 { 1211 IXmlDictionary keyDictionary; 1212 if ((key & 1) != 0) 1213 { 1214 keyDictionary = session; 1215 } 1216 else 1217 { 1218 keyDictionary = dictionary; 1219 } 1220 XmlDictionaryString s; 1221 if (!keyDictionary.TryLookup(key >> 1, out s)) 1222 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1223 return s; 1224 } 1225 ReadDictionaryKey()1226 public int ReadDictionaryKey() 1227 { 1228 int key = ReadMultiByteUInt31(); 1229 if ((key & 1) != 0) 1230 { 1231 if (session == null) 1232 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1233 int sessionKey = (key >> 1); 1234 XmlDictionaryString xmlString; 1235 if (!session.TryLookup(sessionKey, out xmlString)) 1236 { 1237 if (sessionKey < XmlDictionaryString.MinKey || sessionKey > XmlDictionaryString.MaxKey) 1238 XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader); 1239 XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedSession(this.reader, sessionKey); 1240 } 1241 } 1242 else 1243 { 1244 if (dictionary == null) 1245 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1246 int staticKey = (key >> 1); 1247 XmlDictionaryString xmlString; 1248 if (!dictionary.TryLookup(staticKey, out xmlString)) 1249 { 1250 if (staticKey < XmlDictionaryString.MinKey || staticKey > XmlDictionaryString.MaxKey) 1251 XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader); 1252 XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedStatic(this.reader, staticKey); 1253 } 1254 } 1255 1256 return key; 1257 } 1258 ReadValue(XmlBinaryNodeType nodeType, ValueHandle value)1259 public void ReadValue(XmlBinaryNodeType nodeType, ValueHandle value) 1260 { 1261 switch (nodeType) 1262 { 1263 case XmlBinaryNodeType.EmptyText: 1264 value.SetValue(ValueHandleType.Empty); 1265 break; 1266 case XmlBinaryNodeType.ZeroText: 1267 value.SetValue(ValueHandleType.Zero); 1268 break; 1269 case XmlBinaryNodeType.OneText: 1270 value.SetValue(ValueHandleType.One); 1271 break; 1272 case XmlBinaryNodeType.TrueText: 1273 value.SetValue(ValueHandleType.True); 1274 break; 1275 case XmlBinaryNodeType.FalseText: 1276 value.SetValue(ValueHandleType.False); 1277 break; 1278 case XmlBinaryNodeType.BoolText: 1279 value.SetValue(ReadUInt8() != 0 ? ValueHandleType.True : ValueHandleType.False); 1280 break; 1281 case XmlBinaryNodeType.Chars8Text: 1282 ReadValue(value, ValueHandleType.UTF8, ReadUInt8()); 1283 break; 1284 case XmlBinaryNodeType.Chars16Text: 1285 ReadValue(value, ValueHandleType.UTF8, ReadUInt16()); 1286 break; 1287 case XmlBinaryNodeType.Chars32Text: 1288 ReadValue(value, ValueHandleType.UTF8, ReadUInt31()); 1289 break; 1290 case XmlBinaryNodeType.UnicodeChars8Text: 1291 ReadUnicodeValue(value, ReadUInt8()); 1292 break; 1293 case XmlBinaryNodeType.UnicodeChars16Text: 1294 ReadUnicodeValue(value, ReadUInt16()); 1295 break; 1296 case XmlBinaryNodeType.UnicodeChars32Text: 1297 ReadUnicodeValue(value, ReadUInt31()); 1298 break; 1299 case XmlBinaryNodeType.Bytes8Text: 1300 ReadValue(value, ValueHandleType.Base64, ReadUInt8()); 1301 break; 1302 case XmlBinaryNodeType.Bytes16Text: 1303 ReadValue(value, ValueHandleType.Base64, ReadUInt16()); 1304 break; 1305 case XmlBinaryNodeType.Bytes32Text: 1306 ReadValue(value, ValueHandleType.Base64, ReadUInt31()); 1307 break; 1308 case XmlBinaryNodeType.DictionaryText: 1309 value.SetDictionaryValue(ReadDictionaryKey()); 1310 break; 1311 case XmlBinaryNodeType.UniqueIdText: 1312 ReadValue(value, ValueHandleType.UniqueId, ValueHandleLength.UniqueId); 1313 break; 1314 case XmlBinaryNodeType.GuidText: 1315 ReadValue(value, ValueHandleType.Guid, ValueHandleLength.Guid); 1316 break; 1317 case XmlBinaryNodeType.DecimalText: 1318 ReadValue(value, ValueHandleType.Decimal, ValueHandleLength.Decimal); 1319 break; 1320 case XmlBinaryNodeType.Int8Text: 1321 ReadValue(value, ValueHandleType.Int8, ValueHandleLength.Int8); 1322 break; 1323 case XmlBinaryNodeType.Int16Text: 1324 ReadValue(value, ValueHandleType.Int16, ValueHandleLength.Int16); 1325 break; 1326 case XmlBinaryNodeType.Int32Text: 1327 ReadValue(value, ValueHandleType.Int32, ValueHandleLength.Int32); 1328 break; 1329 case XmlBinaryNodeType.Int64Text: 1330 ReadValue(value, ValueHandleType.Int64, ValueHandleLength.Int64); 1331 break; 1332 case XmlBinaryNodeType.UInt64Text: 1333 ReadValue(value, ValueHandleType.UInt64, ValueHandleLength.UInt64); 1334 break; 1335 case XmlBinaryNodeType.FloatText: 1336 ReadValue(value, ValueHandleType.Single, ValueHandleLength.Single); 1337 break; 1338 case XmlBinaryNodeType.DoubleText: 1339 ReadValue(value, ValueHandleType.Double, ValueHandleLength.Double); 1340 break; 1341 case XmlBinaryNodeType.TimeSpanText: 1342 ReadValue(value, ValueHandleType.TimeSpan, ValueHandleLength.TimeSpan); 1343 break; 1344 case XmlBinaryNodeType.DateTimeText: 1345 ReadValue(value, ValueHandleType.DateTime, ValueHandleLength.DateTime); 1346 break; 1347 case XmlBinaryNodeType.StartListText: 1348 ReadList(value); 1349 break; 1350 case XmlBinaryNodeType.QNameDictionaryText: 1351 ReadQName(value); 1352 break; 1353 default: 1354 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1355 break; 1356 } 1357 } 1358 ReadValue(ValueHandle value, ValueHandleType type, int length)1359 void ReadValue(ValueHandle value, ValueHandleType type, int length) 1360 { 1361 int offset = ReadBytes(length); 1362 value.SetValue(type, offset, length); 1363 } 1364 ReadUnicodeValue(ValueHandle value, int length)1365 void ReadUnicodeValue(ValueHandle value, int length) 1366 { 1367 if ((length & 1) != 0) 1368 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1369 ReadValue(value, ValueHandleType.Unicode, length); 1370 } 1371 ReadList(ValueHandle value)1372 void ReadList(ValueHandle value) 1373 { 1374 if (listValue == null) 1375 { 1376 listValue = new ValueHandle(this); 1377 } 1378 int count = 0; 1379 int offset = this.Offset; 1380 while (true) 1381 { 1382 XmlBinaryNodeType nodeType = GetNodeType(); 1383 SkipNodeType(); 1384 if (nodeType == XmlBinaryNodeType.StartListText) 1385 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1386 if (nodeType == XmlBinaryNodeType.EndListText) 1387 break; 1388 ReadValue(nodeType, listValue); 1389 count++; 1390 } 1391 value.SetValue(ValueHandleType.List, offset, count); 1392 } 1393 ReadQName(ValueHandle value)1394 public void ReadQName(ValueHandle value) 1395 { 1396 int prefix = ReadUInt8(); 1397 if (prefix >= 26) 1398 XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 1399 int key = ReadDictionaryKey(); 1400 value.SetQNameValue(prefix, key); 1401 } 1402 GetRows()1403 public int[] GetRows() 1404 { 1405 if (buffer == null) 1406 { 1407 return new int[1] { 0 }; 1408 } 1409 1410 ArrayList list = new ArrayList(); 1411 list.Add(offsetMin); 1412 for (int i = offsetMin; i < offsetMax; i++) 1413 { 1414 if (buffer[i] == (byte)13 || buffer[i] == (byte)10) 1415 { 1416 if (i + 1 < offsetMax && buffer[i + 1] == (byte)10) 1417 i++; 1418 list.Add(i + 1); 1419 } 1420 } 1421 return (int[])list.ToArray(typeof(int)); 1422 } 1423 } 1424 } 1425