You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			1553 lines
		
	
	
		
			68 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1553 lines
		
	
	
		
			68 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------
 | |
| namespace System.Xml
 | |
| {
 | |
|     using System;
 | |
|     using System.IO;
 | |
|     using System.Runtime;
 | |
|     using System.Runtime.Serialization;
 | |
|     using System.Security;
 | |
| 
 | |
|     public interface IXmlBinaryReaderInitializer
 | |
|     {
 | |
|         void SetInput(byte[] buffer, int offset, int count,
 | |
|                             IXmlDictionary dictionary,
 | |
|                             XmlDictionaryReaderQuotas quotas,
 | |
|                             XmlBinaryReaderSession session,
 | |
|                             OnXmlDictionaryReaderClose onClose);
 | |
|         void SetInput(Stream stream,
 | |
|                              IXmlDictionary dictionary,
 | |
|                              XmlDictionaryReaderQuotas quotas,
 | |
|                              XmlBinaryReaderSession session,
 | |
|                              OnXmlDictionaryReaderClose onClose);
 | |
|     }
 | |
| 
 | |
|     class XmlBinaryReader : XmlBaseReader, IXmlBinaryReaderInitializer
 | |
|     {
 | |
|         bool isTextWithEndElement;
 | |
|         bool buffered;
 | |
|         ArrayState arrayState;
 | |
|         int arrayCount;
 | |
|         int maxBytesPerRead;
 | |
|         XmlBinaryNodeType arrayNodeType;
 | |
|         OnXmlDictionaryReaderClose onClose;
 | |
| 
 | |
|         public XmlBinaryReader()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public void SetInput(byte[] buffer, int offset, int count,
 | |
|                             IXmlDictionary dictionary,
 | |
|                             XmlDictionaryReaderQuotas quotas,
 | |
|                             XmlBinaryReaderSession session,
 | |
|                             OnXmlDictionaryReaderClose onClose)
 | |
|         {
 | |
|             if (buffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
 | |
|             if (offset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (offset > buffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
 | |
|             if (count < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (count > buffer.Length - offset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
 | |
|             MoveToInitial(quotas, session, onClose);
 | |
|             BufferReader.SetBuffer(buffer, offset, count, dictionary, session);
 | |
|             this.buffered = true;
 | |
|         }
 | |
| 
 | |
|         public void SetInput(Stream stream,
 | |
|                              IXmlDictionary dictionary,
 | |
|                              XmlDictionaryReaderQuotas quotas,
 | |
|                              XmlBinaryReaderSession session,
 | |
|                              OnXmlDictionaryReaderClose onClose)
 | |
|         {
 | |
|             if (stream == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
 | |
|             MoveToInitial(quotas, session, onClose);
 | |
|             BufferReader.SetBuffer(stream, dictionary, session);
 | |
|             this.buffered = false;
 | |
|         }
 | |
| 
 | |
|         void MoveToInitial(XmlDictionaryReaderQuotas quotas, XmlBinaryReaderSession session, OnXmlDictionaryReaderClose onClose)
 | |
|         {
 | |
|             MoveToInitial(quotas);
 | |
|             this.maxBytesPerRead = quotas.MaxBytesPerRead;
 | |
|             this.arrayState = ArrayState.None;
 | |
|             this.onClose = onClose;
 | |
|             this.isTextWithEndElement = false;
 | |
|         }
 | |
| 
 | |
|         public override void Close()
 | |
|         {
 | |
|             base.Close();
 | |
|             OnXmlDictionaryReaderClose onClose = this.onClose;
 | |
|             this.onClose = null;
 | |
|             if (onClose != null)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     onClose(this);
 | |
|                 }
 | |
|                 catch (Exception e)
 | |
|                 {
 | |
|                     if (Fx.IsFatal(e)) throw;
 | |
| 
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override string ReadElementContentAsString()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (!CanOptimizeReadElementContent())
 | |
|                 return base.ReadElementContentAsString();
 | |
|             string value;
 | |
|             switch (GetNodeType())
 | |
|             {
 | |
|                 case XmlBinaryNodeType.Chars8TextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = BufferReader.ReadUTF8String(ReadUInt8());
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.DictionaryTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = BufferReader.GetDictionaryString(ReadDictionaryKey()).Value;
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 default:
 | |
|                     value = base.ReadElementContentAsString();
 | |
|                     break;
 | |
|             }
 | |
|             if (value.Length > Quotas.MaxStringContentLength)
 | |
|                 XmlExceptionHelper.ThrowMaxStringContentLengthExceeded(this, Quotas.MaxStringContentLength);
 | |
|             return value;
 | |
|         }
 | |
| 
 | |
|         public override bool ReadElementContentAsBoolean()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (!CanOptimizeReadElementContent())
 | |
|                 return base.ReadElementContentAsBoolean();
 | |
|             bool value;
 | |
|             switch (GetNodeType())
 | |
|             {
 | |
|                 case XmlBinaryNodeType.TrueTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = true;
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.FalseTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = false;
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.BoolTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = (BufferReader.ReadUInt8() != 0);
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 default:
 | |
|                     value = base.ReadElementContentAsBoolean();
 | |
|                     break;
 | |
|             }
 | |
|             return value;
 | |
|         }
 | |
| 
 | |
|         public override int ReadElementContentAsInt()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (!CanOptimizeReadElementContent())
 | |
|                 return base.ReadElementContentAsInt();
 | |
|             int value;
 | |
|             switch (GetNodeType())
 | |
|             {
 | |
|                 case XmlBinaryNodeType.ZeroTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = 0;
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.OneTextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = 1;
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int8TextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = BufferReader.ReadInt8();
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int16TextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = BufferReader.ReadInt16();
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int32TextWithEndElement:
 | |
|                     SkipNodeType();
 | |
|                     value = BufferReader.ReadInt32();
 | |
|                     ReadTextWithEndElement();
 | |
|                     break;
 | |
|                 default:
 | |
|                     value = base.ReadElementContentAsInt();
 | |
|                     break;
 | |
|             }
 | |
|             return value;
 | |
|         }
 | |
| 
 | |
|         bool CanOptimizeReadElementContent()
 | |
|         {
 | |
|             return (arrayState == ArrayState.None && !Signing);
 | |
|         }
 | |
| 
 | |
|         public override float ReadElementContentAsFloat()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.FloatTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 float value = BufferReader.ReadSingle();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsFloat();
 | |
|         }
 | |
| 
 | |
|         public override double ReadElementContentAsDouble()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.DoubleTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 double value = BufferReader.ReadDouble();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsDouble();
 | |
|         }
 | |
| 
 | |
|         public override decimal ReadElementContentAsDecimal()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.DecimalTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 decimal value = BufferReader.ReadDecimal();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsDecimal();
 | |
|         }
 | |
| 
 | |
|         public override DateTime ReadElementContentAsDateTime()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.DateTimeTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 DateTime value = BufferReader.ReadDateTime();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsDateTime();
 | |
|         }
 | |
| 
 | |
|         public override TimeSpan ReadElementContentAsTimeSpan()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.TimeSpanTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 TimeSpan value = BufferReader.ReadTimeSpan();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsTimeSpan();
 | |
|         }
 | |
| 
 | |
|         public override Guid ReadElementContentAsGuid()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.GuidTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 Guid value = BufferReader.ReadGuid();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsGuid();
 | |
|         }
 | |
| 
 | |
|         public override UniqueId ReadElementContentAsUniqueId()
 | |
|         {
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 MoveToStartElement();
 | |
|             if (CanOptimizeReadElementContent() && GetNodeType() == XmlBinaryNodeType.UniqueIdTextWithEndElement)
 | |
|             {
 | |
|                 SkipNodeType();
 | |
|                 UniqueId value = BufferReader.ReadUniqueId();
 | |
|                 ReadTextWithEndElement();
 | |
|                 return value;
 | |
|             }
 | |
|             return base.ReadElementContentAsUniqueId();
 | |
|         }
 | |
| 
 | |
|         public override bool TryGetBase64ContentLength(out int length)
 | |
|         {
 | |
|             length = 0;
 | |
|             if (!buffered)
 | |
|                 return false;
 | |
|             if (arrayState != ArrayState.None)
 | |
|                 return false;
 | |
|             int totalLength;
 | |
|             if (!this.Node.Value.TryGetByteArrayLength(out totalLength))
 | |
|                 return false;
 | |
|             int offset = BufferReader.Offset;
 | |
|             try
 | |
|             {
 | |
|                 bool done = false;
 | |
|                 while (!done && !BufferReader.EndOfFile)
 | |
|                 {
 | |
|                     XmlBinaryNodeType nodeType = GetNodeType();
 | |
|                     SkipNodeType();
 | |
|                     int actual;
 | |
|                     switch (nodeType)
 | |
|                     {
 | |
|                         case XmlBinaryNodeType.Bytes8TextWithEndElement:
 | |
|                             actual = BufferReader.ReadUInt8();
 | |
|                             done = true;
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.Bytes16TextWithEndElement:
 | |
|                             actual = BufferReader.ReadUInt16();
 | |
|                             done = true;
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.Bytes32TextWithEndElement:
 | |
|                             actual = BufferReader.ReadUInt31();
 | |
|                             done = true;
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.EndElement:
 | |
|                             actual = 0;
 | |
|                             done = true;
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.Bytes8Text:
 | |
|                             actual = BufferReader.ReadUInt8();
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.Bytes16Text:
 | |
|                             actual = BufferReader.ReadUInt16();
 | |
|                             break;
 | |
|                         case XmlBinaryNodeType.Bytes32Text:
 | |
|                             actual = BufferReader.ReadUInt31();
 | |
|                             break;
 | |
|                         default:
 | |
|                             // Non-optimal or unexpected node - fallback
 | |
|                             return false;
 | |
|                     }
 | |
|                     BufferReader.Advance(actual);
 | |
|                     if (totalLength > int.MaxValue - actual)
 | |
|                         return false;
 | |
|                     totalLength += actual;
 | |
|                 }
 | |
|                 length = totalLength;
 | |
|                 return true;
 | |
|             }
 | |
|             finally
 | |
|             {
 | |
|                 BufferReader.Offset = offset;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadTextWithEndElement()
 | |
|         {
 | |
|             ExitScope();
 | |
|             ReadNode();
 | |
|         }
 | |
| 
 | |
|         XmlAtomicTextNode MoveToAtomicTextWithEndElement()
 | |
|         {
 | |
|             isTextWithEndElement = true;
 | |
|             return MoveToAtomicText();
 | |
|         }
 | |
| 
 | |
|         public override bool Read()
 | |
|         {
 | |
|             if (this.Node.ReadState == ReadState.Closed)
 | |
|                 return false;
 | |
|             SignNode();
 | |
|             if (isTextWithEndElement)
 | |
|             {
 | |
|                 isTextWithEndElement = false;
 | |
|                 MoveToEndElement();
 | |
|                 return true;
 | |
|             }
 | |
|             if (arrayState == ArrayState.Content)
 | |
|             {
 | |
|                 if (arrayCount != 0)
 | |
|                 {
 | |
|                     MoveToArrayElement();
 | |
|                     return true;
 | |
|                 }
 | |
|                 arrayState = ArrayState.None;
 | |
|             }
 | |
|             if (this.Node.ExitScope)
 | |
|             {
 | |
|                 ExitScope();
 | |
|             }
 | |
|             return ReadNode();
 | |
|         }
 | |
| 
 | |
|         bool ReadNode()
 | |
|         {
 | |
|             if (!buffered)
 | |
|                 BufferReader.SetWindow(ElementNode.BufferOffset, this.maxBytesPerRead);
 | |
| 
 | |
|             if (BufferReader.EndOfFile)
 | |
|             {
 | |
|                 MoveToEndOfFile();
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
| 
 | |
|             XmlBinaryNodeType nodeType;
 | |
|             if (arrayState == ArrayState.None)
 | |
|             {
 | |
|                 nodeType = GetNodeType();
 | |
|                 SkipNodeType();
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Fx.Assert(arrayState == ArrayState.Element, "");
 | |
|                 nodeType = arrayNodeType;
 | |
|                 arrayCount--;
 | |
|                 arrayState = ArrayState.Content;
 | |
|             }
 | |
| 
 | |
|             XmlElementNode elementNode;
 | |
|             PrefixHandleType prefix;
 | |
|             switch (nodeType)
 | |
|             {
 | |
|                 case XmlBinaryNodeType.ShortElement:
 | |
|                     elementNode = EnterScope();
 | |
|                     elementNode.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                     ReadName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(PrefixHandleType.Empty);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Element:
 | |
|                     elementNode = EnterScope();
 | |
|                     ReadName(elementNode.Prefix);
 | |
|                     ReadName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(elementNode.Prefix);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.ShortDictionaryElement:
 | |
|                     elementNode = EnterScope();
 | |
|                     elementNode.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                     ReadDictionaryName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(PrefixHandleType.Empty);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.DictionaryElement:
 | |
|                     elementNode = EnterScope();
 | |
|                     ReadName(elementNode.Prefix);
 | |
|                     ReadDictionaryName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(elementNode.Prefix);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.PrefixElementA:
 | |
|                 case XmlBinaryNodeType.PrefixElementB:
 | |
|                 case XmlBinaryNodeType.PrefixElementC:
 | |
|                 case XmlBinaryNodeType.PrefixElementD:
 | |
|                 case XmlBinaryNodeType.PrefixElementE:
 | |
|                 case XmlBinaryNodeType.PrefixElementF:
 | |
|                 case XmlBinaryNodeType.PrefixElementG:
 | |
|                 case XmlBinaryNodeType.PrefixElementH:
 | |
|                 case XmlBinaryNodeType.PrefixElementI:
 | |
|                 case XmlBinaryNodeType.PrefixElementJ:
 | |
|                 case XmlBinaryNodeType.PrefixElementK:
 | |
|                 case XmlBinaryNodeType.PrefixElementL:
 | |
|                 case XmlBinaryNodeType.PrefixElementM:
 | |
|                 case XmlBinaryNodeType.PrefixElementN:
 | |
|                 case XmlBinaryNodeType.PrefixElementO:
 | |
|                 case XmlBinaryNodeType.PrefixElementP:
 | |
|                 case XmlBinaryNodeType.PrefixElementQ:
 | |
|                 case XmlBinaryNodeType.PrefixElementR:
 | |
|                 case XmlBinaryNodeType.PrefixElementS:
 | |
|                 case XmlBinaryNodeType.PrefixElementT:
 | |
|                 case XmlBinaryNodeType.PrefixElementU:
 | |
|                 case XmlBinaryNodeType.PrefixElementV:
 | |
|                 case XmlBinaryNodeType.PrefixElementW:
 | |
|                 case XmlBinaryNodeType.PrefixElementX:
 | |
|                 case XmlBinaryNodeType.PrefixElementY:
 | |
|                 case XmlBinaryNodeType.PrefixElementZ:
 | |
|                     elementNode = EnterScope();
 | |
|                     prefix = PrefixHandle.GetAlphaPrefix((int)nodeType - (int)XmlBinaryNodeType.PrefixElementA);
 | |
|                     elementNode.Prefix.SetValue(prefix);
 | |
|                     ReadName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(prefix);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementA:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementB:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementC:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementD:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementE:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementF:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementG:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementH:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementI:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementJ:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementK:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementL:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementM:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementN:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementO:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementP:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementQ:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementR:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementS:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementT:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementU:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementV:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementW:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementX:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementY:
 | |
|                 case XmlBinaryNodeType.PrefixDictionaryElementZ:
 | |
|                     elementNode = EnterScope();
 | |
|                     prefix = PrefixHandle.GetAlphaPrefix((int)nodeType - (int)XmlBinaryNodeType.PrefixDictionaryElementA);
 | |
|                     elementNode.Prefix.SetValue(prefix);
 | |
|                     ReadDictionaryName(elementNode.LocalName);
 | |
|                     ReadAttributes();
 | |
|                     elementNode.Namespace = LookupNamespace(prefix);
 | |
|                     elementNode.BufferOffset = BufferReader.Offset;
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.EndElement:
 | |
|                     MoveToEndElement();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Comment:
 | |
|                     ReadName(MoveToComment().Value);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.EmptyTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ValueHandleType.Empty);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.ZeroTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ValueHandleType.Zero);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.OneTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ValueHandleType.One);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.TrueTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ValueHandleType.True);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.FalseTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ValueHandleType.False);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.BoolTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetValue(ReadUInt8() != 0 ? ValueHandleType.True : ValueHandleType.False);
 | |
|                     if (this.OutsideRootElement)
 | |
|                         VerifyWhitespace();
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars8TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UTF8, ReadUInt8());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(true, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars8Text:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToComplexText(), ValueHandleType.UTF8, ReadUInt8());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(false, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars16TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UTF8, ReadUInt16());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(true, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars16Text:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToComplexText(), ValueHandleType.UTF8, ReadUInt16());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(false, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars32TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UTF8, ReadUInt31());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(true, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Chars32Text:
 | |
|                     if (buffered)
 | |
|                         ReadText(MoveToComplexText(), ValueHandleType.UTF8, ReadUInt31());
 | |
|                     else
 | |
|                         ReadPartialUTF8Text(false, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars8TextWithEndElement:
 | |
|                     ReadUnicodeText(true, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars8Text:
 | |
|                     ReadUnicodeText(false, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars16TextWithEndElement:
 | |
|                     ReadUnicodeText(true, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars16Text:
 | |
|                     ReadUnicodeText(false, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars32TextWithEndElement:
 | |
|                     ReadUnicodeText(true, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UnicodeChars32Text:
 | |
|                     ReadUnicodeText(false, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes8TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToAtomicTextWithEndElement(), ReadUInt8());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(true, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes8Text:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToComplexText(), ReadUInt8());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(false, ReadUInt8());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes16TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToAtomicTextWithEndElement(), ReadUInt16());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(true, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes16Text:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToComplexText(), ReadUInt16());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(false, ReadUInt16());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes32TextWithEndElement:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToAtomicTextWithEndElement(), ReadUInt31());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(true, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Bytes32Text:
 | |
|                     if (buffered)
 | |
|                         ReadBinaryText(MoveToComplexText(), ReadUInt31());
 | |
|                     else
 | |
|                         ReadPartialBinaryText(false, ReadUInt31());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.DictionaryTextWithEndElement:
 | |
|                     MoveToAtomicTextWithEndElement().Value.SetDictionaryValue(ReadDictionaryKey());
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UniqueIdTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UniqueId, ValueHandleLength.UniqueId);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.GuidTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Guid, ValueHandleLength.Guid);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.DecimalTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Decimal, ValueHandleLength.Decimal);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Int8TextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Int8, ValueHandleLength.Int8);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Int16TextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Int16, ValueHandleLength.Int16);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Int32TextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Int32, ValueHandleLength.Int32);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Int64TextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Int64, ValueHandleLength.Int64);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.UInt64TextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UInt64, ValueHandleLength.UInt64);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.FloatTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Single, ValueHandleLength.Single);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.DoubleTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Double, ValueHandleLength.Double);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.TimeSpanTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.TimeSpan, ValueHandleLength.TimeSpan);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.DateTimeTextWithEndElement:
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.DateTime, ValueHandleLength.DateTime);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.QNameDictionaryTextWithEndElement:
 | |
|                     BufferReader.ReadQName(MoveToAtomicTextWithEndElement().Value);
 | |
|                     return true;
 | |
|                 case XmlBinaryNodeType.Array:
 | |
|                     ReadArray();
 | |
|                     return true;
 | |
|                 default:
 | |
|                     BufferReader.ReadValue(nodeType, MoveToComplexText().Value);
 | |
|                     return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void VerifyWhitespace()
 | |
|         {
 | |
|             if (!this.Node.Value.IsWhitespace())
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|         }
 | |
| 
 | |
|         void ReadAttributes()
 | |
|         {
 | |
|             XmlBinaryNodeType nodeType = GetNodeType();
 | |
|             if (nodeType < XmlBinaryNodeType.MinAttribute || nodeType > XmlBinaryNodeType.MaxAttribute)
 | |
|                 return;
 | |
|             ReadAttributes2();
 | |
|         }
 | |
| 
 | |
|         void ReadAttributes2()
 | |
|         {
 | |
|             int startOffset = 0;
 | |
|             if (buffered)
 | |
|                 startOffset = BufferReader.Offset;
 | |
| 
 | |
|             while (true)
 | |
|             {
 | |
|                 XmlAttributeNode attributeNode;
 | |
|                 Namespace nameSpace;
 | |
|                 PrefixHandleType prefix;
 | |
|                 XmlBinaryNodeType nodeType = GetNodeType();
 | |
|                 switch (nodeType)
 | |
|                 {
 | |
|                     case XmlBinaryNodeType.ShortAttribute:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         attributeNode.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                         ReadName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.Attribute:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         ReadName(attributeNode.Prefix);
 | |
|                         ReadName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         FixXmlAttribute(attributeNode);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.ShortDictionaryAttribute:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         attributeNode.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                         ReadDictionaryName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.DictionaryAttribute:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         ReadName(attributeNode.Prefix);
 | |
|                         ReadDictionaryName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.XmlnsAttribute:
 | |
|                         SkipNodeType();
 | |
|                         nameSpace = AddNamespace();
 | |
|                         ReadName(nameSpace.Prefix);
 | |
|                         ReadName(nameSpace.Uri);
 | |
|                         attributeNode = AddXmlnsAttribute(nameSpace);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.ShortXmlnsAttribute:
 | |
|                         SkipNodeType();
 | |
|                         nameSpace = AddNamespace();
 | |
|                         nameSpace.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                         ReadName(nameSpace.Uri);
 | |
|                         attributeNode = AddXmlnsAttribute(nameSpace);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.ShortDictionaryXmlnsAttribute:
 | |
|                         SkipNodeType();
 | |
|                         nameSpace = AddNamespace();
 | |
|                         nameSpace.Prefix.SetValue(PrefixHandleType.Empty);
 | |
|                         ReadDictionaryName(nameSpace.Uri);
 | |
|                         attributeNode = AddXmlnsAttribute(nameSpace);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.DictionaryXmlnsAttribute:
 | |
|                         SkipNodeType();
 | |
|                         nameSpace = AddNamespace();
 | |
|                         ReadName(nameSpace.Prefix);
 | |
|                         ReadDictionaryName(nameSpace.Uri);
 | |
|                         attributeNode = AddXmlnsAttribute(nameSpace);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeA:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeB:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeC:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeD:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeE:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeF:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeG:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeH:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeI:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeJ:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeK:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeL:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeM:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeN:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeO:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeP:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeQ:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeR:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeS:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeT:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeU:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeV:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeW:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeX:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeY:
 | |
|                     case XmlBinaryNodeType.PrefixDictionaryAttributeZ:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         prefix = PrefixHandle.GetAlphaPrefix((int)nodeType - (int)XmlBinaryNodeType.PrefixDictionaryAttributeA);
 | |
|                         attributeNode.Prefix.SetValue(prefix);
 | |
|                         ReadDictionaryName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         break;
 | |
|                     case XmlBinaryNodeType.PrefixAttributeA:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeB:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeC:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeD:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeE:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeF:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeG:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeH:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeI:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeJ:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeK:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeL:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeM:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeN:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeO:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeP:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeQ:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeR:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeS:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeT:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeU:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeV:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeW:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeX:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeY:
 | |
|                     case XmlBinaryNodeType.PrefixAttributeZ:
 | |
|                         SkipNodeType();
 | |
|                         attributeNode = AddAttribute();
 | |
|                         prefix = PrefixHandle.GetAlphaPrefix((int)nodeType - (int)XmlBinaryNodeType.PrefixAttributeA);
 | |
|                         attributeNode.Prefix.SetValue(prefix);
 | |
|                         ReadName(attributeNode.LocalName);
 | |
|                         ReadAttributeText(attributeNode.AttributeText);
 | |
|                         break;
 | |
|                     default:
 | |
|                         if (buffered && (BufferReader.Offset - startOffset) > this.maxBytesPerRead)
 | |
|                             XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(this, this.maxBytesPerRead);
 | |
|                         ProcessAttributes();
 | |
|                         return;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadText(XmlTextNode textNode, ValueHandleType type, int length)
 | |
|         {
 | |
|             int offset = BufferReader.ReadBytes(length);
 | |
|             textNode.Value.SetValue(type, offset, length);
 | |
|             if (this.OutsideRootElement)
 | |
|                 VerifyWhitespace();
 | |
|         }
 | |
| 
 | |
|         void ReadBinaryText(XmlTextNode textNode, int length)
 | |
|         {
 | |
|             ReadText(textNode, ValueHandleType.Base64, length);
 | |
|         }
 | |
| 
 | |
|         void ReadPartialUTF8Text(bool withEndElement, int length)
 | |
|         {
 | |
|             // The maxBytesPerRead includes the quota for the XmlBinaryNodeType.TextNode, so we need
 | |
|             // to account for that.
 | |
|             const int maxTextNodeLength = 5;
 | |
|             int maxLength = Math.Max(this.maxBytesPerRead - maxTextNodeLength, 0);
 | |
|             if (length <= maxLength)
 | |
|             {
 | |
|                 if (withEndElement)
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.UTF8, length);
 | |
|                 else
 | |
|                     ReadText(MoveToComplexText(), ValueHandleType.UTF8, length);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // We also need to make sure we have enough room to insert a new XmlBinaryNodeType.TextNode
 | |
|                 // for the split data.
 | |
|                 int actual = Math.Max(maxLength - maxTextNodeLength, 0);
 | |
|                 int offset = BufferReader.ReadBytes(actual);
 | |
| 
 | |
|                 // We need to make sure we don't split a utf8  character, so scan backwards for a 
 | |
|                 // character boundary.  We'll actually always push off at least one character since 
 | |
|                 // although we find the character boundary, we don't bother to figure out if we have 
 | |
|                 // all the bytes that comprise the character.
 | |
|                 int i;
 | |
|                 for (i = offset + actual - 1; i >= offset; i--)
 | |
|                 {
 | |
|                     byte b = BufferReader.GetByte(i);
 | |
|                     // The first byte of UTF8 character sequence has either the high bit off, or the
 | |
|                     // two high bits set.
 | |
|                     if ((b & 0x80) == 0 || (b & 0xC0) == 0xC0)
 | |
|                         break;
 | |
|                 }
 | |
| 
 | |
|                 // Move any split characters so we can insert the node
 | |
|                 int byteCount = (offset + actual - i);
 | |
| 
 | |
|                 // Include the split characters in the count
 | |
|                 BufferReader.Offset = BufferReader.Offset - byteCount;
 | |
|                 actual -= byteCount;
 | |
|                 MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, actual);
 | |
|                 if (this.OutsideRootElement)
 | |
|                     VerifyWhitespace();
 | |
| 
 | |
|                 XmlBinaryNodeType nodeType = (withEndElement ? XmlBinaryNodeType.Chars32TextWithEndElement : XmlBinaryNodeType.Chars32Text);
 | |
|                 InsertNode(nodeType, length - actual);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadUnicodeText(bool withEndElement, int length)
 | |
|         {
 | |
|             if ((length & 1) != 0)
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             if (buffered)
 | |
|             {
 | |
|                 if (withEndElement)
 | |
|                 {
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Unicode, length);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     ReadText(MoveToComplexText(), ValueHandleType.Unicode, length);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ReadPartialUnicodeText(withEndElement, length);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadPartialUnicodeText(bool withEndElement, int length)
 | |
|         {
 | |
|             // The maxBytesPerRead includes the quota for the XmlBinaryNodeType.TextNode, so we need
 | |
|             // to account for that.
 | |
|             const int maxTextNodeLength = 5;
 | |
|             int maxLength = Math.Max(this.maxBytesPerRead - maxTextNodeLength, 0);
 | |
|             if (length <= maxLength)
 | |
|             {
 | |
|                 if (withEndElement)
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Unicode, length);
 | |
|                 else
 | |
|                     ReadText(MoveToComplexText(), ValueHandleType.Unicode, length);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // We also need to make sure we have enough room to insert a new XmlBinaryNodeType.TextNode
 | |
|                 // for the split data.
 | |
|                 int actual = Math.Max(maxLength - maxTextNodeLength, 0);
 | |
| 
 | |
|                 // Make sure we break on a char boundary
 | |
|                 if ((actual & 1) != 0)
 | |
|                     actual--;
 | |
| 
 | |
|                 int offset = BufferReader.ReadBytes(actual);
 | |
| 
 | |
|                 // We need to make sure we don't split a unicode surrogate character
 | |
|                 int byteCount = 0;
 | |
|                 char ch = (char)BufferReader.GetInt16(offset + actual - sizeof(char));
 | |
|                 // If the last char is a high surrogate char, then move back
 | |
|                 if (ch >= 0xD800 && ch < 0xDC00)
 | |
|                     byteCount = sizeof(char);
 | |
| 
 | |
|                 // Include the split characters in the count
 | |
|                 BufferReader.Offset = BufferReader.Offset - byteCount;
 | |
|                 actual -= byteCount;
 | |
|                 MoveToComplexText().Value.SetValue(ValueHandleType.Unicode, offset, actual);
 | |
|                 if (this.OutsideRootElement)
 | |
|                     VerifyWhitespace();
 | |
| 
 | |
|                 XmlBinaryNodeType nodeType = (withEndElement ? XmlBinaryNodeType.UnicodeChars32TextWithEndElement : XmlBinaryNodeType.UnicodeChars32Text);
 | |
|                 InsertNode(nodeType, length - actual);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadPartialBinaryText(bool withEndElement, int length)
 | |
|         {
 | |
|             const int nodeLength = 5;
 | |
|             int maxBytesPerRead = Math.Max(this.maxBytesPerRead - nodeLength, 0);
 | |
|             if (length <= maxBytesPerRead)
 | |
|             {
 | |
|                 if (withEndElement)
 | |
|                     ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Base64, length);
 | |
|                 else
 | |
|                     ReadText(MoveToComplexText(), ValueHandleType.Base64, length);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 int actual = maxBytesPerRead;
 | |
|                 if (actual > 3)
 | |
|                     actual -= (actual % 3);
 | |
|                 ReadText(MoveToComplexText(), ValueHandleType.Base64, actual);
 | |
|                 XmlBinaryNodeType nodeType = (withEndElement ? XmlBinaryNodeType.Bytes32TextWithEndElement : XmlBinaryNodeType.Bytes32Text);
 | |
|                 InsertNode(nodeType, length - actual);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void InsertNode(XmlBinaryNodeType nodeType, int length)
 | |
|         {
 | |
|             byte[] buffer = new byte[5];
 | |
|             buffer[0] = (byte)nodeType;
 | |
|             buffer[1] = (byte)length;
 | |
|             length >>= 8;
 | |
|             buffer[2] = (byte)length;
 | |
|             length >>= 8;
 | |
|             buffer[3] = (byte)length;
 | |
|             length >>= 8;
 | |
|             buffer[4] = (byte)length;
 | |
|             BufferReader.InsertBytes(buffer, 0, buffer.Length);
 | |
|         }
 | |
| 
 | |
|         void ReadAttributeText(XmlAttributeTextNode textNode)
 | |
|         {
 | |
|             XmlBinaryNodeType nodeType = GetNodeType();
 | |
|             SkipNodeType();
 | |
|             BufferReader.ReadValue(nodeType, textNode.Value);
 | |
|         }
 | |
| 
 | |
|         void ReadName(ValueHandle value)
 | |
|         {
 | |
|             int length = ReadMultiByteUInt31();
 | |
|             int offset = BufferReader.ReadBytes(length);
 | |
|             value.SetValue(ValueHandleType.UTF8, offset, length);
 | |
|         }
 | |
| 
 | |
|         void ReadName(StringHandle handle)
 | |
|         {
 | |
|             int length = ReadMultiByteUInt31();
 | |
|             int offset = BufferReader.ReadBytes(length);
 | |
|             handle.SetValue(offset, length);
 | |
|         }
 | |
| 
 | |
|         void ReadName(PrefixHandle prefix)
 | |
|         {
 | |
|             int length = ReadMultiByteUInt31();
 | |
|             int offset = BufferReader.ReadBytes(length);
 | |
|             prefix.SetValue(offset, length);
 | |
|         }
 | |
| 
 | |
|         void ReadDictionaryName(StringHandle s)
 | |
|         {
 | |
|             int key = ReadDictionaryKey();
 | |
|             s.SetValue(key);
 | |
|         }
 | |
| 
 | |
|         XmlBinaryNodeType GetNodeType()
 | |
|         {
 | |
|             return BufferReader.GetNodeType();
 | |
|         }
 | |
| 
 | |
|         void SkipNodeType()
 | |
|         {
 | |
|             BufferReader.SkipNodeType();
 | |
|         }
 | |
| 
 | |
|         int ReadDictionaryKey()
 | |
|         {
 | |
|             return BufferReader.ReadDictionaryKey();
 | |
|         }
 | |
| 
 | |
|         int ReadMultiByteUInt31()
 | |
|         {
 | |
|             return BufferReader.ReadMultiByteUInt31();
 | |
|         }
 | |
| 
 | |
|         int ReadUInt8()
 | |
|         {
 | |
|             return BufferReader.ReadUInt8();
 | |
|         }
 | |
| 
 | |
|         int ReadUInt16()
 | |
|         {
 | |
|             return BufferReader.ReadUInt16();
 | |
|         }
 | |
| 
 | |
|         int ReadUInt31()
 | |
|         {
 | |
|             return BufferReader.ReadUInt31();
 | |
|         }
 | |
| 
 | |
|         bool IsValidArrayType(XmlBinaryNodeType nodeType)
 | |
|         {
 | |
|             switch (nodeType)
 | |
|             {
 | |
|                 case XmlBinaryNodeType.BoolTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.Int16TextWithEndElement:
 | |
|                 case XmlBinaryNodeType.Int32TextWithEndElement:
 | |
|                 case XmlBinaryNodeType.Int64TextWithEndElement:
 | |
|                 case XmlBinaryNodeType.FloatTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.DoubleTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.DecimalTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.DateTimeTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.TimeSpanTextWithEndElement:
 | |
|                 case XmlBinaryNodeType.GuidTextWithEndElement:
 | |
|                     return true;
 | |
|                 default:
 | |
|                     return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ReadArray()
 | |
|         {
 | |
|             if (GetNodeType() == XmlBinaryNodeType.Array) // Prevent recursion
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             ReadNode(); // ReadStartElement
 | |
|             if (this.Node.NodeType != XmlNodeType.Element)
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             if (GetNodeType() == XmlBinaryNodeType.Array) // Prevent recursion
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             ReadNode(); // ReadEndElement
 | |
|             if (this.Node.NodeType != XmlNodeType.EndElement)
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             arrayState = ArrayState.Element;
 | |
|             arrayNodeType = GetNodeType();
 | |
|             if (!IsValidArrayType(arrayNodeType))
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             SkipNodeType();
 | |
|             arrayCount = ReadMultiByteUInt31();
 | |
|             if (arrayCount == 0)
 | |
|                 XmlExceptionHelper.ThrowInvalidBinaryFormat(this);
 | |
|             MoveToArrayElement();
 | |
|         }
 | |
| 
 | |
|         void MoveToArrayElement()
 | |
|         {
 | |
|             arrayState = ArrayState.Element;
 | |
|             MoveToNode(ElementNode);
 | |
|         }
 | |
| 
 | |
|         void SkipArrayElements(int count)
 | |
|         {
 | |
|             arrayCount -= count;
 | |
|             if (arrayCount == 0)
 | |
|             {
 | |
|                 arrayState = ArrayState.None;
 | |
|                 ExitScope();
 | |
|                 ReadNode();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override bool IsStartArray(out Type type)
 | |
|         {
 | |
|             type = null;
 | |
|             if (arrayState != ArrayState.Element)
 | |
|                 return false;
 | |
|             switch (arrayNodeType)
 | |
|             {
 | |
|                 case XmlBinaryNodeType.BoolTextWithEndElement:
 | |
|                     type = typeof(bool);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int16TextWithEndElement:
 | |
|                     type = typeof(Int16);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int32TextWithEndElement:
 | |
|                     type = typeof(Int32);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.Int64TextWithEndElement:
 | |
|                     type = typeof(Int64);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.FloatTextWithEndElement:
 | |
|                     type = typeof(float);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.DoubleTextWithEndElement:
 | |
|                     type = typeof(double);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.DecimalTextWithEndElement:
 | |
|                     type = typeof(decimal);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.DateTimeTextWithEndElement:
 | |
|                     type = typeof(DateTime);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.GuidTextWithEndElement:
 | |
|                     type = typeof(Guid);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.TimeSpanTextWithEndElement:
 | |
|                     type = typeof(TimeSpan);
 | |
|                     break;
 | |
|                 case XmlBinaryNodeType.UniqueIdTextWithEndElement:
 | |
|                     type = typeof(UniqueId);
 | |
|                     break;
 | |
|                 default:
 | |
|                     return false;
 | |
|             }
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         public override bool TryGetArrayLength(out int count)
 | |
|         {
 | |
|             count = 0;
 | |
|             if (!buffered)
 | |
|                 return false;
 | |
|             if (arrayState != ArrayState.Element)
 | |
|                 return false;
 | |
|             count = arrayCount;
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         bool IsStartArray(string localName, string namespaceUri, XmlBinaryNodeType nodeType)
 | |
|         {
 | |
|             return IsStartElement(localName, namespaceUri) && arrayState == ArrayState.Element && arrayNodeType == nodeType && !Signing;
 | |
|         }
 | |
| 
 | |
|         bool IsStartArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, XmlBinaryNodeType nodeType)
 | |
|         {
 | |
|             return IsStartElement(localName, namespaceUri) && arrayState == ArrayState.Element && arrayNodeType == nodeType && !Signing;
 | |
|         }
 | |
| 
 | |
|         void CheckArray(Array array, int offset, int count)
 | |
|         {
 | |
|             if (array == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("array"));
 | |
|             if (offset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (offset > array.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, array.Length)));
 | |
|             if (count < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (count > array.Length - offset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, array.Length - offset)));
 | |
|         }
 | |
| 
 | |
|         // bool
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(bool[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (bool* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, bool[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.BoolTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.BoolTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // Int16
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(Int16[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (Int16* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, Int16[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int16TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int16[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int16TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // Int32
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(Int32[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (Int32* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, Int32[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int32TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int32[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int32TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // Int64
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(Int64[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (Int64* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, Int64[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int64TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int64[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.Int64TextWithEndElement) && BitConverter.IsLittleEndian)
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // float
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(float[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (float* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, float[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.FloatTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // double
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(double[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (double* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, double[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DoubleTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // decimal
 | |
|         [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
 | |
|             Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
 | |
|         [SecuritySafeCritical]
 | |
|         unsafe int ReadArray(decimal[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             fixed (decimal* items = &array[offset])
 | |
|             {
 | |
|                 BufferReader.UnsafeReadArray((byte*)items, (byte*)&items[actual]);
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, decimal[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DecimalTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // DateTime
 | |
|         int ReadArray(DateTime[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             for (int i = 0; i < actual; i++)
 | |
|             {
 | |
|                 array[offset + i] = BufferReader.ReadDateTime();
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, DateTime[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DateTimeTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.DateTimeTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // Guid
 | |
|         int ReadArray(Guid[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             for (int i = 0; i < actual; i++)
 | |
|             {
 | |
|                 array[offset + i] = BufferReader.ReadGuid();
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, Guid[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.GuidTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.GuidTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         // TimeSpan
 | |
|         int ReadArray(TimeSpan[] array, int offset, int count)
 | |
|         {
 | |
|             CheckArray(array, offset, count);
 | |
|             int actual = Math.Min(count, arrayCount);
 | |
|             for (int i = 0; i < actual; i++)
 | |
|             {
 | |
|                 array[offset + i] = BufferReader.ReadTimeSpan();
 | |
|             }
 | |
|             SkipArrayElements(actual);
 | |
|             return actual;
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.TimeSpanTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         public override int ReadArray(XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
 | |
|         {
 | |
|             if (IsStartArray(localName, namespaceUri, XmlBinaryNodeType.TimeSpanTextWithEndElement))
 | |
|                 return ReadArray(array, offset, count);
 | |
|             return base.ReadArray(localName, namespaceUri, array, offset, count);
 | |
|         }
 | |
| 
 | |
|         enum ArrayState
 | |
|         {
 | |
|             None,
 | |
|             Element,
 | |
|             Content
 | |
|         }
 | |
| 
 | |
|         protected override XmlSigningNodeWriter CreateSigningNodeWriter()
 | |
|         {
 | |
|             return new XmlSigningNodeWriter(false);
 | |
|         }
 | |
|     }
 | |
| }
 |