|
//------------------------------------------------------------
// 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);
}
}
}
|