| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.Xml
- {
- using System;
- using System.Collections;
- using System.Globalization;
- using System.IO;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.Security;
- using System.Text;
- class XmlBufferReader
- {
- XmlDictionaryReader reader;
- Stream stream;
- byte[] streamBuffer;
- byte[] buffer;
- int offsetMin;
- int offsetMax;
- IXmlDictionary dictionary;
- XmlBinaryReaderSession session;
- byte[] guid;
- int offset;
- const int maxBytesPerChar = 3;
- char[] chars;
- int windowOffset;
- int windowOffsetMax;
- ValueHandle listValue;
- static byte[] emptyByteArray = new byte[0];
- static XmlBufferReader empty = new XmlBufferReader(emptyByteArray);
- public XmlBufferReader(XmlDictionaryReader reader)
- {
- this.reader = reader;
- }
- public XmlBufferReader(byte[] buffer)
- {
- this.reader = null;
- this.buffer = buffer;
- }
- static public XmlBufferReader Empty
- {
- get
- {
- return empty;
- }
- }
- public byte[] Buffer
- {
- get
- {
- return buffer;
- }
- }
- public bool IsStreamed
- {
- get
- {
- return stream != null;
- }
- }
- public void SetBuffer(Stream stream, IXmlDictionary dictionary, XmlBinaryReaderSession session)
- {
- if (streamBuffer == null)
- {
- streamBuffer = new byte[128];
- }
- SetBuffer(stream, streamBuffer, 0, 0, dictionary, session);
- this.windowOffset = 0;
- this.windowOffsetMax = streamBuffer.Length;
- }
- public void SetBuffer(byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session)
- {
- SetBuffer(null, buffer, offset, count, dictionary, session);
- }
- void SetBuffer(Stream stream, byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session)
- {
- this.stream = stream;
- this.buffer = buffer;
- this.offsetMin = offset;
- this.offset = offset;
- this.offsetMax = offset + count;
- this.dictionary = dictionary;
- this.session = session;
- }
- public void Close()
- {
- if (streamBuffer != null && streamBuffer.Length > 4096)
- {
- streamBuffer = null;
- }
- if (stream != null)
- {
- stream.Close();
- this.stream = null;
- }
- this.buffer = emptyByteArray;
- this.offset = 0;
- this.offsetMax = 0;
- this.windowOffset = 0;
- this.windowOffsetMax = 0;
- this.dictionary = null;
- this.session = null;
- }
- public bool EndOfFile
- {
- get
- {
- return offset == offsetMax && !TryEnsureByte();
- }
- }
- public byte GetByte()
- {
- int offset = this.offset;
- if (offset < offsetMax)
- return buffer[offset];
- else
- return GetByteHard();
- }
- public void SkipByte()
- {
- Advance(1);
- }
- byte GetByteHard()
- {
- EnsureByte();
- return buffer[offset];
- }
- public byte[] GetBuffer(int count, out int offset)
- {
- offset = this.offset;
- if (offset <= this.offsetMax - count)
- return buffer;
- return GetBufferHard(count, out offset);
- }
- public byte[] GetBuffer(int count, out int offset, out int offsetMax)
- {
- offset = this.offset;
- if (offset <= this.offsetMax - count)
- {
- offsetMax = this.offset + count;
- }
- else
- {
- TryEnsureBytes(Math.Min(count, windowOffsetMax - offset));
- offsetMax = this.offsetMax;
- }
- return buffer;
- }
- public byte[] GetBuffer(out int offset, out int offsetMax)
- {
- offset = this.offset;
- offsetMax = this.offsetMax;
- return buffer;
- }
- byte[] GetBufferHard(int count, out int offset)
- {
- offset = this.offset;
- EnsureBytes(count);
- return buffer;
- }
- void EnsureByte()
- {
- if (!TryEnsureByte())
- XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader);
- }
- bool TryEnsureByte()
- {
- if (stream == null)
- return false;
- if (offsetMax >= windowOffsetMax)
- XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset);
- if (offsetMax >= buffer.Length)
- return TryEnsureBytes(1);
- int b = stream.ReadByte();
- if (b == -1)
- return false;
- buffer[offsetMax++] = (byte)b;
- return true;
- }
- void EnsureBytes(int count)
- {
- if (!TryEnsureBytes(count))
- XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader);
- }
- bool TryEnsureBytes(int count)
- {
- if (stream == null)
- return false;
- if (offset > int.MaxValue - count)
- XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset);
- int newOffsetMax = offset + count;
- if (newOffsetMax < offsetMax)
- return true;
- if (newOffsetMax > windowOffsetMax)
- XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset);
- if (newOffsetMax > buffer.Length)
- {
- byte[] newBuffer = new byte[Math.Max(newOffsetMax, buffer.Length * 2)];
- System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, offsetMax);
- buffer = newBuffer;
- streamBuffer = newBuffer;
- }
- int needed = newOffsetMax - offsetMax;
- while (needed > 0)
- {
- int actual = stream.Read(buffer, offsetMax, needed);
- if (actual == 0)
- return false;
- offsetMax += actual;
- needed -= actual;
- }
- return true;
- }
- #if NO
- void ReadByte(byte b)
- {
- if (BufferReader.GetByte() != b)
- XmlExceptionHelper.ThrowTokenExpected(this, ((char)b).ToString(), (char)BufferReader.GetByte());
- }
- #endif
- public void Advance(int count)
- {
- Fx.Assert(this.offset + count <= offsetMax, "");
- this.offset += count;
- }
- public void InsertBytes(byte[] buffer, int offset, int count)
- {
- Fx.Assert(stream != null, "");
- if (offsetMax > buffer.Length - count)
- {
- byte[] newBuffer = new byte[offsetMax + count];
- System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, this.offsetMax);
- this.buffer = newBuffer;
- this.streamBuffer = newBuffer;
- }
- System.Buffer.BlockCopy(this.buffer, this.offset, this.buffer, this.offset + count, this.offsetMax - this.offset);
- offsetMax += count;
- System.Buffer.BlockCopy(buffer, offset, this.buffer, this.offset, count);
- }
- public void SetWindow(int windowOffset, int windowLength)
- {
- // [0...elementOffset-1][elementOffset..offset][offset..offsetMax-1][offsetMax..buffer.Length]
- // ^--Elements, Attributes in scope
- // ^-- The node just consumed
- // ^--Data buffered, not consumed
- // ^--Unused space
- if (windowOffset > int.MaxValue - windowLength)
- windowLength = int.MaxValue - windowOffset;
- if (offset != windowOffset)
- {
- System.Buffer.BlockCopy(buffer, offset, buffer, windowOffset, offsetMax - offset);
- offsetMax = windowOffset + (offsetMax - offset);
- offset = windowOffset;
- }
- this.windowOffset = windowOffset;
- this.windowOffsetMax = Math.Max(windowOffset + windowLength, offsetMax);
- }
- public int Offset
- {
- get
- {
- return offset;
- }
- set
- {
- Fx.Assert(value >= offsetMin && value <= offsetMax, "");
- this.offset = value;
- }
- }
- public int ReadBytes(int count)
- {
- Fx.Assert(count >= 0, "");
- int offset = this.offset;
- if (offset > offsetMax - count)
- EnsureBytes(count);
- this.offset += count;
- return offset;
- }
- public int ReadMultiByteUInt31()
- {
- int i = GetByte();
- Advance(1);
- if ((i & 0x80) == 0)
- return i;
- i &= 0x7F;
- int j = GetByte();
- Advance(1);
- i |= ((j & 0x7F) << 7);
- if ((j & 0x80) == 0)
- return i;
- int k = GetByte();
- Advance(1);
- i |= ((k & 0x7F) << 14);
- if ((k & 0x80) == 0)
- return i;
- int l = GetByte();
- Advance(1);
- i |= ((l & 0x7F) << 21);
- if ((l & 0x80) == 0)
- return i;
- int m = GetByte();
- Advance(1);
- i |= (m << 28);
- if ((m & 0xF8) != 0)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- return i;
- }
- public int ReadUInt8()
- {
- byte b = GetByte();
- Advance(1);
- return b;
- }
- public int ReadInt8()
- {
- return (sbyte)ReadUInt8();
- }
- public int ReadUInt16()
- {
- int offset;
- byte[] buffer = GetBuffer(2, out offset);
- int i = buffer[offset + 0] + (buffer[offset + 1] << 8);
- Advance(2);
- return i;
- }
- public int ReadInt16()
- {
- return (Int16)ReadUInt16();
- }
- public int ReadInt32()
- {
- int offset;
- byte[] buffer = GetBuffer(4, out offset);
- byte b1 = buffer[offset + 0];
- byte b2 = buffer[offset + 1];
- byte b3 = buffer[offset + 2];
- byte b4 = buffer[offset + 3];
- Advance(4);
- return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- }
- public int ReadUInt31()
- {
- int i = ReadInt32();
- if (i < 0)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- return i;
- }
- public long ReadInt64()
- {
- Int64 lo = (UInt32)ReadInt32();
- Int64 hi = (UInt32)ReadInt32();
- return (hi << 32) + lo;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public float ReadSingle()
- {
- int offset;
- byte[] buffer = GetBuffer(ValueHandleLength.Single, out offset);
- float value;
- byte* pb = (byte*)&value;
- Fx.Assert(sizeof(float) == 4, "");
- pb[0] = buffer[offset + 0];
- pb[1] = buffer[offset + 1];
- pb[2] = buffer[offset + 2];
- pb[3] = buffer[offset + 3];
- Advance(ValueHandleLength.Single);
- return value;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public double ReadDouble()
- {
- int offset;
- byte[] buffer = GetBuffer(ValueHandleLength.Double, out offset);
- double value;
- byte* pb = (byte*)&value;
- Fx.Assert(sizeof(double) == 8, "");
- pb[0] = buffer[offset + 0];
- pb[1] = buffer[offset + 1];
- pb[2] = buffer[offset + 2];
- pb[3] = buffer[offset + 3];
- pb[4] = buffer[offset + 4];
- pb[5] = buffer[offset + 5];
- pb[6] = buffer[offset + 6];
- pb[7] = buffer[offset + 7];
- Advance(ValueHandleLength.Double);
- return value;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public decimal ReadDecimal()
- {
- const int SignMask = unchecked((int)0x80000000);
- const int ScaleMask = 0x00FF0000;
- int offset;
- byte[] buffer = GetBuffer(ValueHandleLength.Decimal, out offset);
- byte b1 = buffer[offset + 0];
- byte b2 = buffer[offset + 1];
- byte b3 = buffer[offset + 2];
- byte b4 = buffer[offset + 3];
- int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- //this logic mirrors the code in Decimal(int []) ctor.
- if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16))
- {
- decimal value;
- byte* pb = (byte*)&value;
- for (int i = 0; i < sizeof(decimal); i++)
- pb[i] = buffer[offset + i];
- Advance(ValueHandleLength.Decimal);
- return value;
- }
- else
- {
- XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader);
- }
- //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws,
- //so we have to have a return statement here even though we shouldn't hit this code path...
- Fx.Assert("A decimal value should have been returned or an exception should have been thrown.");
- return default(decimal);
- }
- public UniqueId ReadUniqueId()
- {
- int offset;
- byte[] buffer = GetBuffer(ValueHandleLength.UniqueId, out offset);
- UniqueId uniqueId = new UniqueId(buffer, offset);
- Advance(ValueHandleLength.UniqueId);
- return uniqueId;
- }
- public DateTime ReadDateTime()
- {
- long value = 0;
- try
- {
- value = ReadInt64();
- return DateTime.FromBinary(value);
- }
- catch (ArgumentException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception));
- }
- catch (FormatException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception));
- }
- catch (OverflowException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception));
- }
- }
- public TimeSpan ReadTimeSpan()
- {
- long value = 0;
- try
- {
- value = ReadInt64();
- return TimeSpan.FromTicks(value);
- }
- catch (ArgumentException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception));
- }
- catch (FormatException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception));
- }
- catch (OverflowException exception)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception));
- }
- }
- public Guid ReadGuid()
- {
- int offset;
- byte[] buffer = GetBuffer(ValueHandleLength.Guid, out offset);
- Guid guid = GetGuid(offset);
- Advance(ValueHandleLength.Guid);
- return guid;
- }
- public string ReadUTF8String(int length)
- {
- int offset;
- byte[] buffer = GetBuffer(length, out offset);
- char[] chars = GetCharBuffer(length);
- int charCount = GetChars(offset, length, chars);
- string value = new string(chars, 0, charCount);
- Advance(length);
- return value;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")]
- [SecurityCritical]
- unsafe public void UnsafeReadArray(byte* dst, byte* dstMax)
- {
- UnsafeReadArray(dst, (int)(dstMax - dst));
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")]
- [SecurityCritical]
- unsafe void UnsafeReadArray(byte* dst, int length)
- {
- if (stream != null)
- {
- const int chunk = 256;
- while (length >= chunk)
- {
- byte[] _buffer = GetBuffer(chunk, out offset);
- for (int i = 0; i < chunk; i++)
- {
- *dst++ = _buffer[offset + i];
- }
- Advance(chunk);
- length -= chunk;
- }
- }
- if (length > 0)
- {
- byte[] buffer = GetBuffer(length, out offset);
- fixed (byte* _src = &buffer[offset])
- {
- byte* src = _src;
- byte* dstMax = dst + length;
- while (dst < dstMax)
- {
- *dst = *src;
- dst++;
- src++;
- }
- }
- Advance(length);
- }
- }
- char[] GetCharBuffer(int count)
- {
- if (count > 1024)
- return new char[count];
- if (chars == null || chars.Length < count)
- chars = new char[count];
- return chars;
- }
- int GetChars(int offset, int length, char[] chars)
- {
- byte[] buffer = this.buffer;
- for (int i = 0; i < length; i++)
- {
- byte b = buffer[offset + i];
- if (b >= 0x80)
- return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, i);
- chars[i] = (char)b;
- }
- return length;
- }
- int GetChars(int offset, int length, char[] chars, int charOffset)
- {
- byte[] buffer = this.buffer;
- for (int i = 0; i < length; i++)
- {
- byte b = buffer[offset + i];
- if (b >= 0x80)
- return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, charOffset + i);
- chars[charOffset + i] = (char)b;
- }
- return length;
- }
- public string GetString(int offset, int length)
- {
- char[] chars = GetCharBuffer(length);
- int charCount = GetChars(offset, length, chars);
- return new string(chars, 0, charCount);
- }
- public string GetUnicodeString(int offset, int length)
- {
- return XmlConverter.ToStringUnicode(buffer, offset, length);
- }
- public string GetString(int offset, int length, XmlNameTable nameTable)
- {
- char[] chars = GetCharBuffer(length);
- int charCount = GetChars(offset, length, chars);
- return nameTable.Add(chars, 0, charCount);
- }
- public int GetEscapedChars(int offset, int length, char[] chars)
- {
- byte[] buffer = this.buffer;
- int charCount = 0;
- int textOffset = offset;
- int offsetMax = offset + length;
- while (true)
- {
- while (offset < offsetMax && IsAttrChar(buffer[offset]))
- offset++;
- charCount += GetChars(textOffset, offset - textOffset, chars, charCount);
- if (offset == offsetMax)
- break;
- textOffset = offset;
- if (buffer[offset] == '&')
- {
- while (offset < offsetMax && buffer[offset] != ';')
- offset++;
- offset++;
- int ch = GetCharEntity(textOffset, offset - textOffset);
- textOffset = offset;
- if (ch > char.MaxValue)
- {
- SurrogateChar surrogate = new SurrogateChar(ch);
- chars[charCount++] = surrogate.HighChar;
- chars[charCount++] = surrogate.LowChar;
- }
- else
- {
- chars[charCount++] = (char)ch;
- }
- }
- else if (buffer[offset] == '\n' || buffer[offset] == '\t')
- {
- chars[charCount++] = ' ';
- offset++;
- textOffset = offset;
- }
- else // '\r'
- {
- chars[charCount++] = ' ';
- offset++;
- if (offset < offsetMax && buffer[offset] == '\n')
- offset++;
- textOffset = offset;
- }
- }
- return charCount;
- }
- bool IsAttrChar(int ch)
- {
- switch (ch)
- {
- case '&':
- case '\r':
- case '\t':
- case '\n':
- return false;
- default:
- return true;
- }
- }
- public string GetEscapedString(int offset, int length)
- {
- char[] chars = GetCharBuffer(length);
- int charCount = GetEscapedChars(offset, length, chars);
- return new string(chars, 0, charCount);
- }
- public string GetEscapedString(int offset, int length, XmlNameTable nameTable)
- {
- char[] chars = GetCharBuffer(length);
- int charCount = GetEscapedChars(offset, length, chars);
- return nameTable.Add(chars, 0, charCount);
- }
- int GetLessThanCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- if (length != 4 ||
- buffer[offset + 1] != (byte)'l' ||
- buffer[offset + 2] != (byte)'t')
- {
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return (int)'<';
- }
- int GetGreaterThanCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- if (length != 4 ||
- buffer[offset + 1] != (byte)'g' ||
- buffer[offset + 2] != (byte)'t')
- {
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return (int)'>';
- }
- int GetQuoteCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- if (length != 6 ||
- buffer[offset + 1] != (byte)'q' ||
- buffer[offset + 2] != (byte)'u' ||
- buffer[offset + 3] != (byte)'o' ||
- buffer[offset + 4] != (byte)'t')
- {
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return (int)'"';
- }
- int GetAmpersandCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- if (length != 5 ||
- buffer[offset + 1] != (byte)'a' ||
- buffer[offset + 2] != (byte)'m' ||
- buffer[offset + 3] != (byte)'p')
- {
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return (int)'&';
- }
- int GetApostropheCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- if (length != 6 ||
- buffer[offset + 1] != (byte)'a' ||
- buffer[offset + 2] != (byte)'p' ||
- buffer[offset + 3] != (byte)'o' ||
- buffer[offset + 4] != (byte)'s')
- {
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return (int)'\'';
- }
- int GetDecimalCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- Fx.Assert(buffer[offset + 0] == '&', "");
- Fx.Assert(buffer[offset + 1] == '#', "");
- Fx.Assert(buffer[offset + length - 1] == ';', "");
- int value = 0;
- for (int i = 2; i < length - 1; i++)
- {
- byte ch = buffer[offset + i];
- if (ch < (byte)'0' || ch > (byte)'9')
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- value = value * 10 + (ch - '0');
- if (value > SurrogateChar.MaxValue)
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return value;
- }
- int GetHexCharEntity(int offset, int length)
- {
- byte[] buffer = this.buffer;
- Fx.Assert(buffer[offset + 0] == '&', "");
- Fx.Assert(buffer[offset + 1] == '#', "");
- Fx.Assert(buffer[offset + 2] == 'x', "");
- Fx.Assert(buffer[offset + length - 1] == ';', "");
- int value = 0;
- for (int i = 3; i < length - 1; i++)
- {
- byte ch = buffer[offset + i];
- int digit = 0;
- if (ch >= '0' && ch <= '9')
- digit = (ch - '0');
- else if (ch >= 'a' && ch <= 'f')
- digit = 10 + (ch - 'a');
- else if (ch >= 'A' && ch <= 'F')
- digit = 10 + (ch - 'A');
- else
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- Fx.Assert(digit >= 0 && digit < 16, "");
- value = value * 16 + digit;
- if (value > SurrogateChar.MaxValue)
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- }
- return value;
- }
- public int GetCharEntity(int offset, int length)
- {
- if (length < 3)
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- byte[] buffer = this.buffer;
- Fx.Assert(buffer[offset] == '&', "");
- Fx.Assert(buffer[offset + length - 1] == ';', "");
- switch (buffer[offset + 1])
- {
- case (byte)'l':
- return GetLessThanCharEntity(offset, length);
- case (byte)'g':
- return GetGreaterThanCharEntity(offset, length);
- case (byte)'a':
- if (buffer[offset + 2] == (byte)'m')
- return GetAmpersandCharEntity(offset, length);
- else
- return GetApostropheCharEntity(offset, length);
- case (byte)'q':
- return GetQuoteCharEntity(offset, length);
- case (byte)'#':
- if (buffer[offset + 2] == (byte)'x')
- return GetHexCharEntity(offset, length);
- else
- return GetDecimalCharEntity(offset, length);
- default:
- XmlExceptionHelper.ThrowInvalidCharRef(reader);
- return 0;
- }
- }
- public bool IsWhitespaceKey(int key)
- {
- string s = GetDictionaryString(key).Value;
- for (int i = 0; i < s.Length; i++)
- {
- if (!XmlConverter.IsWhitespace(s[i]))
- return false;
- }
- return true;
- }
- public bool IsWhitespaceUTF8(int offset, int length)
- {
- byte[] buffer = this.buffer;
- for (int i = 0; i < length; i++)
- {
- if (!XmlConverter.IsWhitespace((char)buffer[offset + i]))
- return false;
- }
- return true;
- }
- public bool IsWhitespaceUnicode(int offset, int length)
- {
- byte[] buffer = this.buffer;
- for (int i = 0; i < length; i += sizeof(char))
- {
- char ch = (char)GetInt16(offset + i);
- if (!XmlConverter.IsWhitespace(ch))
- return false;
- }
- return true;
- }
- public bool Equals2(int key1, int key2, XmlBufferReader bufferReader2)
- {
- // If the keys aren't from the same dictionary, they still might be the same
- if (key1 == key2)
- return true;
- else
- return GetDictionaryString(key1).Value == bufferReader2.GetDictionaryString(key2).Value;
- }
- public bool Equals2(int key1, XmlDictionaryString xmlString2)
- {
- if ((key1 & 1) == 0 && xmlString2.Dictionary == dictionary)
- return xmlString2.Key == (key1 >> 1);
- else
- return GetDictionaryString(key1).Value == xmlString2.Value;
- }
- public bool Equals2(int offset1, int length1, byte[] buffer2)
- {
- int length2 = buffer2.Length;
- if (length1 != length2)
- return false;
- byte[] buffer1 = this.buffer;
- for (int i = 0; i < length1; i++)
- {
- if (buffer1[offset1 + i] != buffer2[i])
- return false;
- }
- return true;
- }
- public bool Equals2(int offset1, int length1, XmlBufferReader bufferReader2, int offset2, int length2)
- {
- if (length1 != length2)
- return false;
- byte[] buffer1 = this.buffer;
- byte[] buffer2 = bufferReader2.buffer;
- for (int i = 0; i < length1; i++)
- {
- if (buffer1[offset1 + i] != buffer2[offset2 + i])
- return false;
- }
- return true;
- }
- public bool Equals2(int offset1, int length1, int offset2, int length2)
- {
- if (length1 != length2)
- return false;
- if (offset1 == offset2)
- return true;
- byte[] buffer = this.buffer;
- for (int i = 0; i < length1; i++)
- {
- if (buffer[offset1 + i] != buffer[offset2 + i])
- return false;
- }
- return true;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public bool Equals2(int offset1, int length1, string s2)
- {
- int byteLength = length1;
- int charLength = s2.Length;
- // N unicode chars will be represented in at least N bytes, but
- // no more than N * 3 bytes. If the byte count falls outside of this
- // range, then the strings cannot be equal.
- if (byteLength < charLength || byteLength > charLength * maxBytesPerChar)
- return false;
- byte[] buffer = this.buffer;
- if (length1 < 8)
- {
- int length = Math.Min(byteLength, charLength);
- int offset = offset1;
- for (int i = 0; i < length; i++)
- {
- byte b = buffer[offset + i];
- if (b >= 0x80)
- return XmlConverter.ToString(buffer, offset1, length1) == s2;
- if (s2[i] != (char)b)
- return false;
- }
- return byteLength == charLength;
- }
- else
- {
- int length = Math.Min(byteLength, charLength);
- fixed (byte* _pb = &buffer[offset1])
- {
- byte* pb = _pb;
- byte* pbMax = pb + length;
- fixed (char* _pch = s2)
- {
- char* pch = _pch;
- // Try to do the fast comparison in ascii space
- int t = 0;
- while (pb < pbMax && *pb < 0x80)
- {
- t = *pb - (byte)(*pch);
- // The code generated is better if we break out then return
- if (t != 0)
- break;
- pb++;
- pch++;
- }
- if (t != 0)
- return false;
- if (pb == pbMax)
- return (byteLength == charLength);
- }
- }
- return XmlConverter.ToString(buffer, offset1, length1) == s2;
- }
- }
- public int Compare(int offset1, int length1, int offset2, int length2)
- {
- byte[] buffer = this.buffer;
- int length = Math.Min(length1, length2);
- for (int i = 0; i < length; i++)
- {
- int s = buffer[offset1 + i] - buffer[offset2 + i];
- if (s != 0)
- return s;
- }
- return length1 - length2;
- }
- public byte GetByte(int offset)
- {
- return buffer[offset];
- }
- public int GetInt8(int offset)
- {
- return (sbyte)GetByte(offset);
- }
- public int GetInt16(int offset)
- {
- byte[] buffer = this.buffer;
- return (Int16)(buffer[offset] + (buffer[offset + 1] << 8));
- }
- public int GetInt32(int offset)
- {
- byte[] buffer = this.buffer;
- byte b1 = buffer[offset + 0];
- byte b2 = buffer[offset + 1];
- byte b3 = buffer[offset + 2];
- byte b4 = buffer[offset + 3];
- return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- }
- public long GetInt64(int offset)
- {
- byte[] buffer = this.buffer;
- byte b1, b2, b3, b4;
- b1 = buffer[offset + 0];
- b2 = buffer[offset + 1];
- b3 = buffer[offset + 2];
- b4 = buffer[offset + 3];
- Int64 lo = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- b1 = buffer[offset + 4];
- b2 = buffer[offset + 5];
- b3 = buffer[offset + 6];
- b4 = buffer[offset + 7];
- Int64 hi = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- return (hi << 32) + lo;
- }
- public ulong GetUInt64(int offset)
- {
- return (ulong)GetInt64(offset);
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public float GetSingle(int offset)
- {
- byte[] buffer = this.buffer;
- float value;
- byte* pb = (byte*)&value;
- Fx.Assert(sizeof(float) == 4, "");
- pb[0] = buffer[offset + 0];
- pb[1] = buffer[offset + 1];
- pb[2] = buffer[offset + 2];
- pb[3] = buffer[offset + 3];
- return value;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- unsafe public double GetDouble(int offset)
- {
- byte[] buffer = this.buffer;
- double value;
- byte* pb = (byte*)&value;
- Fx.Assert(sizeof(double) == 8, "");
- pb[0] = buffer[offset + 0];
- pb[1] = buffer[offset + 1];
- pb[2] = buffer[offset + 2];
- pb[3] = buffer[offset + 3];
- pb[4] = buffer[offset + 4];
- pb[5] = buffer[offset + 5];
- pb[6] = buffer[offset + 6];
- pb[7] = buffer[offset + 7];
- return value;
- }
- [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
- Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
- [SecuritySafeCritical]
- public unsafe decimal GetDecimal(int offset)
- {
- const int SignMask = unchecked((int)0x80000000);
- const int ScaleMask = 0x00FF0000;
- byte[] buffer = this.buffer;
- byte b1 = buffer[offset + 0];
- byte b2 = buffer[offset + 1];
- byte b3 = buffer[offset + 2];
- byte b4 = buffer[offset + 3];
- int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
- //this logic mirrors the code in Decimal(int []) ctor.
- if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16))
- {
- decimal value;
- byte* pb = (byte*)&value;
- for (int i = 0; i < sizeof(decimal); i++)
- pb[i] = buffer[offset + i];
- return value;
- }
- else
- {
- XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader);
- }
- //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws,
- //so we have to have a return statement here even though we shouldn't hit this code path...
- Fx.Assert("A decimal value should have been returned or an exception should have been thrown.");
- return default(decimal);
- }
- public UniqueId GetUniqueId(int offset)
- {
- return new UniqueId(this.buffer, offset);
- }
- public Guid GetGuid(int offset)
- {
- if (guid == null)
- guid = new byte[16];
- System.Buffer.BlockCopy(buffer, offset, guid, 0, guid.Length);
- return new Guid(guid);
- }
- public void GetBase64(int srcOffset, byte[] buffer, int dstOffset, int count)
- {
- System.Buffer.BlockCopy(this.buffer, srcOffset, buffer, dstOffset, count);
- }
- public XmlBinaryNodeType GetNodeType()
- {
- return (XmlBinaryNodeType)GetByte();
- }
- public void SkipNodeType()
- {
- SkipByte();
- }
- public object[] GetList(int offset, int count)
- {
- int bufferOffset = this.Offset;
- this.Offset = offset;
- try
- {
- object[] objects = new object[count];
- for (int i = 0; i < count; i++)
- {
- XmlBinaryNodeType nodeType = GetNodeType();
- SkipNodeType();
- Fx.Assert(nodeType != XmlBinaryNodeType.StartListText, "");
- ReadValue(nodeType, listValue);
- objects[i] = listValue.ToObject();
- }
- return objects;
- }
- finally
- {
- this.Offset = bufferOffset;
- }
- }
- public XmlDictionaryString GetDictionaryString(int key)
- {
- IXmlDictionary keyDictionary;
- if ((key & 1) != 0)
- {
- keyDictionary = session;
- }
- else
- {
- keyDictionary = dictionary;
- }
- XmlDictionaryString s;
- if (!keyDictionary.TryLookup(key >> 1, out s))
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- return s;
- }
- public int ReadDictionaryKey()
- {
- int key = ReadMultiByteUInt31();
- if ((key & 1) != 0)
- {
- if (session == null)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- int sessionKey = (key >> 1);
- XmlDictionaryString xmlString;
- if (!session.TryLookup(sessionKey, out xmlString))
- {
- if (sessionKey < XmlDictionaryString.MinKey || sessionKey > XmlDictionaryString.MaxKey)
- XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader);
- XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedSession(this.reader, sessionKey);
- }
- }
- else
- {
- if (dictionary == null)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- int staticKey = (key >> 1);
- XmlDictionaryString xmlString;
- if (!dictionary.TryLookup(staticKey, out xmlString))
- {
- if (staticKey < XmlDictionaryString.MinKey || staticKey > XmlDictionaryString.MaxKey)
- XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader);
- XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedStatic(this.reader, staticKey);
- }
- }
- return key;
- }
- public void ReadValue(XmlBinaryNodeType nodeType, ValueHandle value)
- {
- switch (nodeType)
- {
- case XmlBinaryNodeType.EmptyText:
- value.SetValue(ValueHandleType.Empty);
- break;
- case XmlBinaryNodeType.ZeroText:
- value.SetValue(ValueHandleType.Zero);
- break;
- case XmlBinaryNodeType.OneText:
- value.SetValue(ValueHandleType.One);
- break;
- case XmlBinaryNodeType.TrueText:
- value.SetValue(ValueHandleType.True);
- break;
- case XmlBinaryNodeType.FalseText:
- value.SetValue(ValueHandleType.False);
- break;
- case XmlBinaryNodeType.BoolText:
- value.SetValue(ReadUInt8() != 0 ? ValueHandleType.True : ValueHandleType.False);
- break;
- case XmlBinaryNodeType.Chars8Text:
- ReadValue(value, ValueHandleType.UTF8, ReadUInt8());
- break;
- case XmlBinaryNodeType.Chars16Text:
- ReadValue(value, ValueHandleType.UTF8, ReadUInt16());
- break;
- case XmlBinaryNodeType.Chars32Text:
- ReadValue(value, ValueHandleType.UTF8, ReadUInt31());
- break;
- case XmlBinaryNodeType.UnicodeChars8Text:
- ReadUnicodeValue(value, ReadUInt8());
- break;
- case XmlBinaryNodeType.UnicodeChars16Text:
- ReadUnicodeValue(value, ReadUInt16());
- break;
- case XmlBinaryNodeType.UnicodeChars32Text:
- ReadUnicodeValue(value, ReadUInt31());
- break;
- case XmlBinaryNodeType.Bytes8Text:
- ReadValue(value, ValueHandleType.Base64, ReadUInt8());
- break;
- case XmlBinaryNodeType.Bytes16Text:
- ReadValue(value, ValueHandleType.Base64, ReadUInt16());
- break;
- case XmlBinaryNodeType.Bytes32Text:
- ReadValue(value, ValueHandleType.Base64, ReadUInt31());
- break;
- case XmlBinaryNodeType.DictionaryText:
- value.SetDictionaryValue(ReadDictionaryKey());
- break;
- case XmlBinaryNodeType.UniqueIdText:
- ReadValue(value, ValueHandleType.UniqueId, ValueHandleLength.UniqueId);
- break;
- case XmlBinaryNodeType.GuidText:
- ReadValue(value, ValueHandleType.Guid, ValueHandleLength.Guid);
- break;
- case XmlBinaryNodeType.DecimalText:
- ReadValue(value, ValueHandleType.Decimal, ValueHandleLength.Decimal);
- break;
- case XmlBinaryNodeType.Int8Text:
- ReadValue(value, ValueHandleType.Int8, ValueHandleLength.Int8);
- break;
- case XmlBinaryNodeType.Int16Text:
- ReadValue(value, ValueHandleType.Int16, ValueHandleLength.Int16);
- break;
- case XmlBinaryNodeType.Int32Text:
- ReadValue(value, ValueHandleType.Int32, ValueHandleLength.Int32);
- break;
- case XmlBinaryNodeType.Int64Text:
- ReadValue(value, ValueHandleType.Int64, ValueHandleLength.Int64);
- break;
- case XmlBinaryNodeType.UInt64Text:
- ReadValue(value, ValueHandleType.UInt64, ValueHandleLength.UInt64);
- break;
- case XmlBinaryNodeType.FloatText:
- ReadValue(value, ValueHandleType.Single, ValueHandleLength.Single);
- break;
- case XmlBinaryNodeType.DoubleText:
- ReadValue(value, ValueHandleType.Double, ValueHandleLength.Double);
- break;
- case XmlBinaryNodeType.TimeSpanText:
- ReadValue(value, ValueHandleType.TimeSpan, ValueHandleLength.TimeSpan);
- break;
- case XmlBinaryNodeType.DateTimeText:
- ReadValue(value, ValueHandleType.DateTime, ValueHandleLength.DateTime);
- break;
- case XmlBinaryNodeType.StartListText:
- ReadList(value);
- break;
- case XmlBinaryNodeType.QNameDictionaryText:
- ReadQName(value);
- break;
- default:
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- break;
- }
- }
- void ReadValue(ValueHandle value, ValueHandleType type, int length)
- {
- int offset = ReadBytes(length);
- value.SetValue(type, offset, length);
- }
- void ReadUnicodeValue(ValueHandle value, int length)
- {
- if ((length & 1) != 0)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- ReadValue(value, ValueHandleType.Unicode, length);
- }
- void ReadList(ValueHandle value)
- {
- if (listValue == null)
- {
- listValue = new ValueHandle(this);
- }
- int count = 0;
- int offset = this.Offset;
- while (true)
- {
- XmlBinaryNodeType nodeType = GetNodeType();
- SkipNodeType();
- if (nodeType == XmlBinaryNodeType.StartListText)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- if (nodeType == XmlBinaryNodeType.EndListText)
- break;
- ReadValue(nodeType, listValue);
- count++;
- }
- value.SetValue(ValueHandleType.List, offset, count);
- }
- public void ReadQName(ValueHandle value)
- {
- int prefix = ReadUInt8();
- if (prefix >= 26)
- XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
- int key = ReadDictionaryKey();
- value.SetQNameValue(prefix, key);
- }
- public int[] GetRows()
- {
- if (buffer == null)
- {
- return new int[1] { 0 };
- }
- ArrayList list = new ArrayList();
- list.Add(offsetMin);
- for (int i = offsetMin; i < offsetMax; i++)
- {
- if (buffer[i] == (byte)13 || buffer[i] == (byte)10)
- {
- if (i + 1 < offsetMax && buffer[i + 1] == (byte)10)
- i++;
- list.Add(i + 1);
- }
- }
- return (int[])list.ToArray(typeof(int));
- }
- }
- }
|