You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			1017 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1017 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------
 | |
| namespace System.Xml
 | |
| {
 | |
|     using System.Collections;
 | |
|     using System.IO;
 | |
|     using System.Runtime;
 | |
|     using System.Runtime.Serialization;
 | |
|     using System.Text;
 | |
| 
 | |
|     sealed class XmlCanonicalWriter
 | |
|     {
 | |
|         XmlUTF8NodeWriter writer;
 | |
|         MemoryStream elementStream;
 | |
|         byte[] elementBuffer;
 | |
|         XmlUTF8NodeWriter elementWriter;
 | |
|         bool inStartElement;
 | |
|         int depth;
 | |
|         Scope[] scopes;
 | |
|         int xmlnsAttributeCount;
 | |
|         XmlnsAttribute[] xmlnsAttributes;
 | |
|         int attributeCount;
 | |
|         Attribute[] attributes;
 | |
|         Attribute attribute;
 | |
|         Element element;
 | |
|         byte[] xmlnsBuffer;
 | |
|         int xmlnsOffset;
 | |
|         const int maxBytesPerChar = 3;
 | |
|         int xmlnsStartOffset;
 | |
|         bool includeComments;
 | |
|         string[] inclusivePrefixes;
 | |
|         const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/";
 | |
| 
 | |
|         static readonly bool[] isEscapedAttributeChar = new bool[]
 | |
|         {
 | |
|             true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, // All
 | |
|             true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
 | |
|             false, false, true, false, false, false, true, false, false, false, false, false, false, false, false, false, // '"', '&'
 | |
|             false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false  // '<'
 | |
|         };
 | |
|         static readonly bool[] isEscapedElementChar = new bool[]
 | |
|         {
 | |
|             true, true, true, true, true, true, true, true, true, false, false, true, true, true, true, true, // All but 0x09, 0x0A
 | |
|             true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
 | |
|             false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, // '&'
 | |
|             false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false  // '<', '>'
 | |
|         };
 | |
| 
 | |
|         public XmlCanonicalWriter()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public void SetOutput(Stream stream, bool includeComments, string[] inclusivePrefixes)
 | |
|         {
 | |
|             if (stream == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
 | |
| 
 | |
|             if (writer == null)
 | |
|             {
 | |
|                 writer = new XmlUTF8NodeWriter(isEscapedAttributeChar, isEscapedElementChar);
 | |
|             }
 | |
|             writer.SetOutput(stream, false, null);
 | |
| 
 | |
|             if (elementStream == null)
 | |
|             {
 | |
|                 elementStream = new MemoryStream();
 | |
|             }
 | |
| 
 | |
|             if (elementWriter == null)
 | |
|             {
 | |
|                 elementWriter = new XmlUTF8NodeWriter(isEscapedAttributeChar, isEscapedElementChar);
 | |
|             }
 | |
|             elementWriter.SetOutput(elementStream, false, null);
 | |
| 
 | |
|             if (xmlnsAttributes == null)
 | |
|             {
 | |
|                 xmlnsAttributeCount = 0;
 | |
|                 xmlnsOffset = 0;
 | |
|                 WriteXmlnsAttribute("xml", "http://www.w3.org/XML/1998/namespace");
 | |
|                 WriteXmlnsAttribute("xmlns", xmlnsNamespace);
 | |
|                 WriteXmlnsAttribute(string.Empty, string.Empty);
 | |
|                 xmlnsStartOffset = xmlnsOffset;
 | |
|                 for (int i = 0; i < 3; i++)
 | |
|                 {
 | |
|                     xmlnsAttributes[i].referred = true;
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 xmlnsAttributeCount = 3;
 | |
|                 xmlnsOffset = xmlnsStartOffset;
 | |
|             }
 | |
| 
 | |
|             depth = 0;
 | |
|             inStartElement = false;
 | |
|             this.includeComments = includeComments;
 | |
|             this.inclusivePrefixes = null;
 | |
|             if (inclusivePrefixes != null)
 | |
|             {
 | |
|                 this.inclusivePrefixes = new string[inclusivePrefixes.Length];
 | |
|                 for (int i = 0; i < inclusivePrefixes.Length; ++i)
 | |
|                 {
 | |
|                     if (inclusivePrefixes[i] == null)
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.InvalidInclusivePrefixListCollection));
 | |
|                     }
 | |
|                     this.inclusivePrefixes[i] = inclusivePrefixes[i];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void Flush()
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             writer.Flush();
 | |
|         }
 | |
| 
 | |
|         public void Close()
 | |
|         {
 | |
|             if (writer != null)
 | |
|                 writer.Close();
 | |
|             if (elementWriter != null)
 | |
|                 elementWriter.Close();
 | |
|             if (elementStream != null && elementStream.Length > 512)
 | |
|                 elementStream = null;
 | |
|             elementBuffer = null;
 | |
|             if (scopes != null && scopes.Length > 16)
 | |
|                 scopes = null;
 | |
|             if (attributes != null && attributes.Length > 16)
 | |
|                 attributes = null;
 | |
|             if (xmlnsBuffer != null && xmlnsBuffer.Length > 1024)
 | |
|             {
 | |
|                 xmlnsAttributes = null;
 | |
|                 xmlnsBuffer = null;
 | |
|             }
 | |
|             inclusivePrefixes = null;
 | |
|         }
 | |
| 
 | |
|         public void WriteDeclaration()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public void WriteComment(string value)
 | |
|         {
 | |
|             if (value == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
 | |
|             ThrowIfClosed();
 | |
|             if (includeComments)
 | |
|             {
 | |
|                 writer.WriteComment(value);
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         void StartElement()
 | |
|         {
 | |
|             if (scopes == null)
 | |
|             {
 | |
|                 scopes = new Scope[4];
 | |
|             }
 | |
|             else if (depth == scopes.Length)
 | |
|             {
 | |
|                 Scope[] newScopes = new Scope[depth * 2];
 | |
|                 Array.Copy(scopes, newScopes, depth);
 | |
|                 scopes = newScopes;
 | |
|             }
 | |
|             scopes[depth].xmlnsAttributeCount = xmlnsAttributeCount;
 | |
|             scopes[depth].xmlnsOffset = xmlnsOffset;
 | |
|             depth++;
 | |
|             inStartElement = true;
 | |
|             attributeCount = 0;
 | |
|             elementStream.Position = 0;
 | |
|         }
 | |
| 
 | |
|         void EndElement()
 | |
|         {
 | |
|             depth--;
 | |
|             xmlnsAttributeCount = scopes[depth].xmlnsAttributeCount;
 | |
|             xmlnsOffset = scopes[depth].xmlnsOffset;
 | |
|         }
 | |
| 
 | |
|         public void WriteStartElement(string prefix, string localName)
 | |
|         {
 | |
|             if (prefix == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("prefix");
 | |
|             if (localName == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName");
 | |
|             ThrowIfClosed();
 | |
|             bool isRootElement = (this.depth == 0);
 | |
| 
 | |
|             StartElement();
 | |
|             element.prefixOffset = elementWriter.Position + 1;
 | |
|             element.prefixLength = Encoding.UTF8.GetByteCount(prefix);
 | |
|             element.localNameOffset = element.prefixOffset + element.prefixLength + (element.prefixLength != 0 ? 1 : 0);
 | |
|             element.localNameLength = Encoding.UTF8.GetByteCount(localName);
 | |
|             elementWriter.WriteStartElement(prefix, localName);
 | |
| 
 | |
|             // If we have a inclusivenamespace prefix list and the namespace declaration is in the 
 | |
|             // outer context, then Add it to the root element.
 | |
|             if (isRootElement && (this.inclusivePrefixes != null))
 | |
|             {
 | |
|                 // Scan through all the namespace declarations in the outer scope.
 | |
|                 for (int i = 0; i < this.scopes[0].xmlnsAttributeCount; ++i)
 | |
|                 {
 | |
|                     if (IsInclusivePrefix(ref xmlnsAttributes[i]))
 | |
|                     {
 | |
|                         XmlnsAttribute attribute = xmlnsAttributes[i];
 | |
|                         AddXmlnsAttribute(ref attribute);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteStartElement(byte[] prefixBuffer, int prefixOffset, int prefixLength, byte[] localNameBuffer, int localNameOffset, int localNameLength)
 | |
|         {
 | |
|             if (prefixBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("prefixBuffer"));
 | |
|             if (prefixOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixOffset > prefixBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.OffsetExceedsBufferSize, prefixBuffer.Length)));
 | |
|             if (prefixLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixLength > prefixBuffer.Length - prefixOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, prefixBuffer.Length - prefixOffset)));
 | |
| 
 | |
|             if (localNameBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localNameBuffer"));
 | |
|             if (localNameOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (localNameOffset > localNameBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameOffset", SR.GetString(SR.OffsetExceedsBufferSize, localNameBuffer.Length)));
 | |
|             if (localNameLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (localNameLength > localNameBuffer.Length - localNameOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, localNameBuffer.Length - localNameOffset)));
 | |
|             ThrowIfClosed();
 | |
|             bool isRootElement = (this.depth == 0);
 | |
| 
 | |
|             StartElement();
 | |
|             element.prefixOffset = elementWriter.Position + 1;
 | |
|             element.prefixLength = prefixLength;
 | |
|             element.localNameOffset = element.prefixOffset + prefixLength + (prefixLength != 0 ? 1 : 0);
 | |
|             element.localNameLength = localNameLength;
 | |
|             elementWriter.WriteStartElement(prefixBuffer, prefixOffset, prefixLength, localNameBuffer, localNameOffset, localNameLength);
 | |
| 
 | |
|             // If we have a inclusivenamespace prefix list and the namespace declaration is in the 
 | |
|             // outer context, then Add it to the root element.
 | |
|             if (isRootElement && (this.inclusivePrefixes != null))
 | |
|             {
 | |
|                 // Scan through all the namespace declarations in the outer scope.
 | |
|                 for (int i = 0; i < this.scopes[0].xmlnsAttributeCount; ++i)
 | |
|                 {
 | |
|                     if (IsInclusivePrefix(ref xmlnsAttributes[i]))
 | |
|                     {
 | |
|                         XmlnsAttribute attribute = xmlnsAttributes[i];
 | |
|                         AddXmlnsAttribute(ref attribute);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         bool IsInclusivePrefix(ref XmlnsAttribute xmlnsAttribute)
 | |
|         {
 | |
|             for (int i = 0; i < this.inclusivePrefixes.Length; ++i)
 | |
|             {
 | |
|                 if (this.inclusivePrefixes[i].Length == xmlnsAttribute.prefixLength)
 | |
|                 {
 | |
|                     if (String.Compare(Encoding.UTF8.GetString(xmlnsBuffer, xmlnsAttribute.prefixOffset, xmlnsAttribute.prefixLength), this.inclusivePrefixes[i], StringComparison.Ordinal) == 0)
 | |
|                     {
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         public void WriteEndStartElement(bool isEmpty)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             elementWriter.Flush();
 | |
|             elementBuffer = elementStream.GetBuffer();
 | |
|             inStartElement = false;
 | |
|             ResolvePrefixes();
 | |
|             writer.WriteStartElement(elementBuffer, element.prefixOffset, element.prefixLength, elementBuffer, element.localNameOffset, element.localNameLength);
 | |
|             for (int i = scopes[depth - 1].xmlnsAttributeCount; i < xmlnsAttributeCount; i++)
 | |
|             {
 | |
|                 // Check if this prefix with the same namespace has already been rendered.
 | |
|                 int j = i - 1;
 | |
|                 bool alreadyReferred = false;
 | |
|                 while (j >= 0)
 | |
|                 {
 | |
|                     if (Equals(xmlnsBuffer, xmlnsAttributes[i].prefixOffset, xmlnsAttributes[i].prefixLength, xmlnsBuffer, xmlnsAttributes[j].prefixOffset, xmlnsAttributes[j].prefixLength))
 | |
|                     {
 | |
|                         // Check if the namespace is also equal.
 | |
|                         if (Equals(xmlnsBuffer, xmlnsAttributes[i].nsOffset, xmlnsAttributes[i].nsLength, xmlnsBuffer, xmlnsAttributes[j].nsOffset, xmlnsAttributes[j].nsLength))
 | |
|                         {
 | |
|                             // We have found the prefix with the same namespace occur before. See if this has been
 | |
|                             // referred.
 | |
|                             if (xmlnsAttributes[j].referred)
 | |
|                             {
 | |
|                                 // This has been referred previously. So we don't have 
 | |
|                                 // to output the namespace again.
 | |
|                                 alreadyReferred = true;
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             // The prefix is the same, but the namespace value has changed. So we have to 
 | |
|                             // output this namespace.
 | |
|                             break;
 | |
|                         }
 | |
|                     }
 | |
|                     --j;
 | |
|                 }
 | |
| 
 | |
|                 if (!alreadyReferred)
 | |
|                 {
 | |
|                     WriteXmlnsAttribute(ref xmlnsAttributes[i]);
 | |
|                 }
 | |
|             }
 | |
|             if (attributeCount > 0)
 | |
|             {
 | |
|                 if (attributeCount > 1)
 | |
|                 {
 | |
|                     SortAttributes();
 | |
|                 }
 | |
| 
 | |
|                 for (int i = 0; i < attributeCount; i++)
 | |
|                 {
 | |
|                     writer.WriteText(elementBuffer, attributes[i].offset, attributes[i].length);
 | |
|                 }
 | |
|             }
 | |
|             writer.WriteEndStartElement(false);
 | |
|             if (isEmpty)
 | |
|             {
 | |
|                 writer.WriteEndElement(elementBuffer, element.prefixOffset, element.prefixLength, elementBuffer, element.localNameOffset, element.localNameLength);
 | |
|                 EndElement();
 | |
|             }
 | |
|             elementBuffer = null;
 | |
|         }
 | |
| 
 | |
|         public void WriteEndElement(string prefix, string localName)
 | |
|         {
 | |
|             if (prefix == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("prefix");
 | |
|             if (localName == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName");
 | |
|             ThrowIfClosed();
 | |
|             writer.WriteEndElement(prefix, localName);
 | |
|             EndElement();
 | |
|         }
 | |
| 
 | |
|         void EnsureXmlnsBuffer(int byteCount)
 | |
|         {
 | |
|             if (xmlnsBuffer == null)
 | |
|             {
 | |
|                 xmlnsBuffer = new byte[Math.Max(byteCount, 128)];
 | |
|             }
 | |
|             else if (xmlnsOffset + byteCount > xmlnsBuffer.Length)
 | |
|             {
 | |
|                 byte[] newBuffer = new byte[Math.Max(xmlnsOffset + byteCount, xmlnsBuffer.Length * 2)];
 | |
|                 Buffer.BlockCopy(xmlnsBuffer, 0, newBuffer, 0, xmlnsOffset);
 | |
|                 xmlnsBuffer = newBuffer;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteXmlnsAttribute(string prefix, string ns)
 | |
|         {
 | |
|             if (prefix == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("prefix");
 | |
|             if (ns == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns");
 | |
|             ThrowIfClosed();
 | |
|             if (prefix.Length > int.MaxValue - ns.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("ns", SR.GetString(SR.CombinedPrefixNSLength, int.MaxValue / maxBytesPerChar)));
 | |
|             int totalLength = prefix.Length + ns.Length;
 | |
|             if (totalLength > int.MaxValue / maxBytesPerChar)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("ns", SR.GetString(SR.CombinedPrefixNSLength, int.MaxValue / maxBytesPerChar)));
 | |
|             EnsureXmlnsBuffer(totalLength * maxBytesPerChar);
 | |
|             XmlnsAttribute xmlnsAttribute;
 | |
|             xmlnsAttribute.prefixOffset = xmlnsOffset;
 | |
|             xmlnsAttribute.prefixLength = Encoding.UTF8.GetBytes(prefix, 0, prefix.Length, xmlnsBuffer, xmlnsOffset);
 | |
|             xmlnsOffset += xmlnsAttribute.prefixLength;
 | |
|             xmlnsAttribute.nsOffset = xmlnsOffset;
 | |
|             xmlnsAttribute.nsLength = Encoding.UTF8.GetBytes(ns, 0, ns.Length, xmlnsBuffer, xmlnsOffset);
 | |
|             xmlnsOffset += xmlnsAttribute.nsLength;
 | |
|             xmlnsAttribute.referred = false;
 | |
|             AddXmlnsAttribute(ref xmlnsAttribute);
 | |
|         }
 | |
| 
 | |
|         public void WriteXmlnsAttribute(byte[] prefixBuffer, int prefixOffset, int prefixLength, byte[] nsBuffer, int nsOffset, int nsLength)
 | |
|         {
 | |
|             if (prefixBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("prefixBuffer"));
 | |
|             if (prefixOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixOffset > prefixBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.OffsetExceedsBufferSize, prefixBuffer.Length)));
 | |
|             if (prefixLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixLength > prefixBuffer.Length - prefixOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, prefixBuffer.Length - prefixOffset)));
 | |
| 
 | |
|             if (nsBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("nsBuffer"));
 | |
|             if (nsOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nsOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (nsOffset > nsBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nsOffset", SR.GetString(SR.OffsetExceedsBufferSize, nsBuffer.Length)));
 | |
|             if (nsLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nsLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (nsLength > nsBuffer.Length - nsOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nsLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, nsBuffer.Length - nsOffset)));
 | |
|             ThrowIfClosed();
 | |
|             if (prefixLength > int.MaxValue - nsLength)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nsLength", SR.GetString(SR.CombinedPrefixNSLength, int.MaxValue)));
 | |
|             EnsureXmlnsBuffer(prefixLength + nsLength);
 | |
|             XmlnsAttribute xmlnsAttribute;
 | |
|             xmlnsAttribute.prefixOffset = xmlnsOffset;
 | |
|             xmlnsAttribute.prefixLength = prefixLength;
 | |
|             Buffer.BlockCopy(prefixBuffer, prefixOffset, xmlnsBuffer, xmlnsOffset, prefixLength);
 | |
|             xmlnsOffset += prefixLength;
 | |
|             xmlnsAttribute.nsOffset = xmlnsOffset;
 | |
|             xmlnsAttribute.nsLength = nsLength;
 | |
|             Buffer.BlockCopy(nsBuffer, nsOffset, xmlnsBuffer, xmlnsOffset, nsLength);
 | |
|             xmlnsOffset += nsLength;
 | |
|             xmlnsAttribute.referred = false;
 | |
|             AddXmlnsAttribute(ref xmlnsAttribute);
 | |
|         }
 | |
| 
 | |
|         public void WriteStartAttribute(string prefix, string localName)
 | |
|         {
 | |
|             if (prefix == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("prefix");
 | |
|             if (localName == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName");
 | |
|             ThrowIfClosed();
 | |
|             attribute.offset = elementWriter.Position;
 | |
|             attribute.length = 0;
 | |
|             attribute.prefixOffset = attribute.offset + 1; // WriteStartAttribute emits a space
 | |
|             attribute.prefixLength = Encoding.UTF8.GetByteCount(prefix);
 | |
|             attribute.localNameOffset = attribute.prefixOffset + attribute.prefixLength + (attribute.prefixLength != 0 ? 1 : 0);
 | |
|             attribute.localNameLength = Encoding.UTF8.GetByteCount(localName);
 | |
|             attribute.nsOffset = 0;
 | |
|             attribute.nsLength = 0;
 | |
|             elementWriter.WriteStartAttribute(prefix, localName);
 | |
|         }
 | |
| 
 | |
|         public void WriteStartAttribute(byte[] prefixBuffer, int prefixOffset, int prefixLength, byte[] localNameBuffer, int localNameOffset, int localNameLength)
 | |
|         {
 | |
|             if (prefixBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("prefixBuffer"));
 | |
|             if (prefixOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixOffset > prefixBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixOffset", SR.GetString(SR.OffsetExceedsBufferSize, prefixBuffer.Length)));
 | |
|             if (prefixLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (prefixLength > prefixBuffer.Length - prefixOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("prefixLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, prefixBuffer.Length - prefixOffset)));
 | |
| 
 | |
|             if (localNameBuffer == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localNameBuffer"));
 | |
|             if (localNameOffset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameOffset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (localNameOffset > localNameBuffer.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameOffset", SR.GetString(SR.OffsetExceedsBufferSize, localNameBuffer.Length)));
 | |
|             if (localNameLength < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameLength", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (localNameLength > localNameBuffer.Length - localNameOffset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("localNameLength", SR.GetString(SR.SizeExceedsRemainingBufferSpace, localNameBuffer.Length - localNameOffset)));
 | |
|             ThrowIfClosed();
 | |
|             attribute.offset = elementWriter.Position;
 | |
|             attribute.length = 0;
 | |
|             attribute.prefixOffset = attribute.offset + 1; // WriteStartAttribute emits a space
 | |
|             attribute.prefixLength = prefixLength;
 | |
|             attribute.localNameOffset = attribute.prefixOffset + prefixLength + (prefixLength != 0 ? 1 : 0);
 | |
|             attribute.localNameLength = localNameLength;
 | |
|             attribute.nsOffset = 0;
 | |
|             attribute.nsLength = 0;
 | |
|             elementWriter.WriteStartAttribute(prefixBuffer, prefixOffset, prefixLength, localNameBuffer, localNameOffset, localNameLength);
 | |
|         }
 | |
| 
 | |
|         public void WriteEndAttribute()
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             elementWriter.WriteEndAttribute();
 | |
|             attribute.length = elementWriter.Position - attribute.offset;
 | |
|             AddAttribute(ref attribute);
 | |
|         }
 | |
| 
 | |
|         public void WriteCharEntity(int ch)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             if (ch <= char.MaxValue)
 | |
|             {
 | |
|                 char[] chars = new char[1] { (char)ch };
 | |
|                 WriteEscapedText(chars, 0, 1);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 WriteText(ch);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteEscapedText(string value)
 | |
|         {
 | |
|             if (value == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
 | |
|             ThrowIfClosed();
 | |
|             // Skip all white spaces before the start of root element.
 | |
|             if (this.depth > 0)
 | |
|             {
 | |
|                 if (inStartElement)
 | |
|                 {
 | |
|                     elementWriter.WriteEscapedText(value);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     writer.WriteEscapedText(value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteEscapedText(byte[] chars, int offset, int count)
 | |
|         {
 | |
|             if (chars == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
 | |
|             if (offset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (offset > chars.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
 | |
|             if (count < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (count > chars.Length - offset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
 | |
|             ThrowIfClosed();
 | |
|             // Skip all white spaces before the start of root element.
 | |
|             if (this.depth > 0)
 | |
|             {
 | |
|                 if (inStartElement)
 | |
|                 {
 | |
|                     elementWriter.WriteEscapedText(chars, offset, count);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     writer.WriteEscapedText(chars, offset, count);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteEscapedText(char[] chars, int offset, int count)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             // Skip all white spaces before the start of root element.
 | |
|             if (this.depth > 0)
 | |
|             {
 | |
|                 if (inStartElement)
 | |
|                 {
 | |
|                     elementWriter.WriteEscapedText(chars, offset, count);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     writer.WriteEscapedText(chars, offset, count);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
| #if OLDWRITER
 | |
|         unsafe internal void WriteText(char* chars, int charCount)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             if (inStartElement)
 | |
|             {
 | |
|                 elementWriter.WriteText(chars, charCount);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 writer.WriteText(chars, charCount);
 | |
|             }
 | |
|         }
 | |
|         unsafe internal void WriteEscapedText(char* chars, int count)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             // Skip all white spaces before the start of root element.
 | |
|             if (this.depth > 0)
 | |
|             {
 | |
|                 if (inStartElement)
 | |
|                 {
 | |
|                     elementWriter.WriteEscapedText(chars, count);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     writer.WriteEscapedText(chars, count);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         public void WriteText(int ch)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             if (inStartElement)
 | |
|             {
 | |
|                 elementWriter.WriteText(ch);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 writer.WriteText(ch);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteText(byte[] chars, int offset, int count)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             if (chars == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
 | |
|             if (offset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (offset > chars.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
 | |
|             if (count < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (count > chars.Length - offset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
 | |
|             if (inStartElement)
 | |
|             {
 | |
|                 elementWriter.WriteText(chars, offset, count);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 writer.WriteText(chars, offset, count);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteText(string value)
 | |
|         {
 | |
|             if (value == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
 | |
|             if (value.Length > 0)
 | |
|             {
 | |
|                 if (inStartElement)
 | |
|                 {
 | |
|                     elementWriter.WriteText(value);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     writer.WriteText(value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void WriteText(char[] chars, int offset, int count)
 | |
|         {
 | |
|             ThrowIfClosed();
 | |
|             if (chars == null)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
 | |
|             if (offset < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (offset > chars.Length)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
 | |
|             if (count < 0)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
 | |
|             if (count > chars.Length - offset)
 | |
|                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
 | |
|             if (inStartElement)
 | |
|             {
 | |
|                 elementWriter.WriteText(chars, offset, count);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 writer.WriteText(chars, offset, count);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ThrowIfClosed()
 | |
|         {
 | |
|             if (writer == null)
 | |
|                 ThrowClosed();
 | |
|         }
 | |
| 
 | |
|         void ThrowClosed()
 | |
|         {
 | |
|             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString()));
 | |
|         }
 | |
| 
 | |
|         void WriteXmlnsAttribute(ref XmlnsAttribute xmlnsAttribute)
 | |
|         {
 | |
|             if (xmlnsAttribute.referred)
 | |
|             {
 | |
|                 writer.WriteXmlnsAttribute(xmlnsBuffer, xmlnsAttribute.prefixOffset, xmlnsAttribute.prefixLength, xmlnsBuffer, xmlnsAttribute.nsOffset, xmlnsAttribute.nsLength);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void SortAttributes()
 | |
|         {
 | |
|             if (attributeCount < 16)
 | |
|             {
 | |
|                 for (int i = 0; i < attributeCount - 1; i++)
 | |
|                 {
 | |
|                     int attributeMin = i;
 | |
|                     for (int j = i + 1; j < attributeCount; j++)
 | |
|                     {
 | |
|                         if (Compare(ref attributes[j], ref attributes[attributeMin]) < 0)
 | |
|                         {
 | |
|                             attributeMin = j;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     if (attributeMin != i)
 | |
|                     {
 | |
|                         Attribute temp = attributes[i];
 | |
|                         attributes[i] = attributes[attributeMin];
 | |
|                         attributes[attributeMin] = temp;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 new AttributeSorter(this).Sort();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void AddAttribute(ref Attribute attribute)
 | |
|         {
 | |
|             if (attributes == null)
 | |
|             {
 | |
|                 attributes = new Attribute[4];
 | |
|             }
 | |
|             else if (attributeCount == attributes.Length)
 | |
|             {
 | |
|                 Attribute[] newAttributes = new Attribute[attributeCount * 2];
 | |
|                 Array.Copy(attributes, newAttributes, attributeCount);
 | |
|                 attributes = newAttributes;
 | |
|             }
 | |
| 
 | |
|             attributes[attributeCount] = attribute;
 | |
|             attributeCount++;
 | |
|         }
 | |
| 
 | |
|         void AddXmlnsAttribute(ref XmlnsAttribute xmlnsAttribute)
 | |
|         {
 | |
|             //            Console.WriteLine("{0}={1}", Encoding.UTF8.GetString(xmlnsBuffer, xmlnsAttribute.prefixOffset, xmlnsAttribute.prefixLength), 
 | |
|             //                                Encoding.UTF8.GetString(xmlnsBuffer, xmlnsAttribute.nsOffset, xmlnsAttribute.nsLength));
 | |
| 
 | |
|             if (xmlnsAttributes == null)
 | |
|             {
 | |
|                 xmlnsAttributes = new XmlnsAttribute[4];
 | |
|             }
 | |
|             else if (xmlnsAttributes.Length == xmlnsAttributeCount)
 | |
|             {
 | |
|                 XmlnsAttribute[] newXmlnsAttributes = new XmlnsAttribute[xmlnsAttributeCount * 2];
 | |
|                 Array.Copy(xmlnsAttributes, newXmlnsAttributes, xmlnsAttributeCount);
 | |
|                 xmlnsAttributes = newXmlnsAttributes;
 | |
|             }
 | |
| 
 | |
|             // If the prefix is in the inclusive prefix list, then mark it as 
 | |
|             // to be rendered. Depth 0 is outer context and those can be ignored
 | |
|             // for now.
 | |
|             if ((depth > 0) && (this.inclusivePrefixes != null))
 | |
|             {
 | |
|                 if (IsInclusivePrefix(ref xmlnsAttribute))
 | |
|                 {
 | |
|                     xmlnsAttribute.referred = true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (depth == 0)
 | |
|             {
 | |
|                 // XmlnsAttributes at depth 0 are the outer context.  They don't need to be sorted.
 | |
|                 xmlnsAttributes[xmlnsAttributeCount++] = xmlnsAttribute;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // Sort the xmlns xmlnsAttribute
 | |
|                 int xmlnsAttributeIndex = scopes[depth - 1].xmlnsAttributeCount;
 | |
|                 bool isNewPrefix = true;
 | |
|                 while (xmlnsAttributeIndex < xmlnsAttributeCount)
 | |
|                 {
 | |
|                     int result = Compare(ref xmlnsAttribute, ref xmlnsAttributes[xmlnsAttributeIndex]);
 | |
|                     if (result > 0)
 | |
|                     {
 | |
|                         xmlnsAttributeIndex++;
 | |
|                     }
 | |
|                     else if (result == 0)
 | |
|                     {
 | |
|                         // We already have the same prefix at this scope. So let's
 | |
|                         // just replace the old one with the new.
 | |
|                         xmlnsAttributes[xmlnsAttributeIndex] = xmlnsAttribute;
 | |
|                         isNewPrefix = false;
 | |
|                         break;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 if (isNewPrefix)
 | |
|                 {
 | |
|                     Array.Copy(xmlnsAttributes, xmlnsAttributeIndex, xmlnsAttributes, xmlnsAttributeIndex + 1, xmlnsAttributeCount - xmlnsAttributeIndex);
 | |
|                     xmlnsAttributes[xmlnsAttributeIndex] = xmlnsAttribute;
 | |
|                     xmlnsAttributeCount++;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ResolvePrefix(int prefixOffset, int prefixLength, out int nsOffset, out int nsLength)
 | |
|         {
 | |
|             int xmlnsAttributeMin = scopes[depth - 1].xmlnsAttributeCount;
 | |
| 
 | |
|             // Lookup the attribute; it has to be there.  The decls are in sorted order
 | |
|             // so we could do a binary search.
 | |
|             int j = xmlnsAttributeCount - 1;
 | |
|             while (!Equals(elementBuffer, prefixOffset, prefixLength,
 | |
|                            xmlnsBuffer, xmlnsAttributes[j].prefixOffset, xmlnsAttributes[j].prefixLength))
 | |
|             {
 | |
|                 j--;
 | |
|             }
 | |
| 
 | |
|             nsOffset = xmlnsAttributes[j].nsOffset;
 | |
|             nsLength = xmlnsAttributes[j].nsLength;
 | |
| 
 | |
|             if (j < xmlnsAttributeMin)
 | |
|             {
 | |
|                 // If the xmlns decl isn't at this scope, see if we need to copy it down
 | |
|                 if (!xmlnsAttributes[j].referred)
 | |
|                 {
 | |
|                     XmlnsAttribute xmlnsAttribute = xmlnsAttributes[j];
 | |
|                     xmlnsAttribute.referred = true;
 | |
| 
 | |
|                     // This inserts the xmlns attribute in sorted order, so j is no longer valid
 | |
|                     AddXmlnsAttribute(ref xmlnsAttribute);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // Found at this scope, indicate we need to emit it
 | |
|                 xmlnsAttributes[j].referred = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ResolvePrefix(ref Attribute attribute)
 | |
|         {
 | |
|             if (attribute.prefixLength != 0)
 | |
|             {
 | |
|                 ResolvePrefix(attribute.prefixOffset, attribute.prefixLength, out attribute.nsOffset, out attribute.nsLength);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 // These should've been set when we added the prefix
 | |
|                 Fx.Assert(attribute.nsOffset == 0 && attribute.nsLength == 0, "");
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void ResolvePrefixes()
 | |
|         {
 | |
|             int nsOffset;
 | |
|             int nsLength;
 | |
|             ResolvePrefix(element.prefixOffset, element.prefixLength, out nsOffset, out nsLength);
 | |
| 
 | |
|             for (int i = 0; i < attributeCount; i++)
 | |
|             {
 | |
|                 ResolvePrefix(ref attributes[i]);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         int Compare(ref XmlnsAttribute xmlnsAttribute1, ref XmlnsAttribute xmlnsAttribute2)
 | |
|         {
 | |
|             return Compare(xmlnsBuffer,
 | |
|                            xmlnsAttribute1.prefixOffset, xmlnsAttribute1.prefixLength,
 | |
|                            xmlnsAttribute2.prefixOffset, xmlnsAttribute2.prefixLength);
 | |
|         }
 | |
| 
 | |
|         int Compare(ref Attribute attribute1, ref Attribute attribute2)
 | |
|         {
 | |
|             int s = Compare(xmlnsBuffer,
 | |
|                             attribute1.nsOffset, attribute1.nsLength,
 | |
|                             attribute2.nsOffset, attribute2.nsLength);
 | |
| 
 | |
|             if (s == 0)
 | |
|             {
 | |
|                 s = Compare(elementBuffer,
 | |
|                             attribute1.localNameOffset, attribute1.localNameLength,
 | |
|                             attribute2.localNameOffset, attribute2.localNameLength);
 | |
|             }
 | |
| 
 | |
|             return s;
 | |
|         }
 | |
| 
 | |
|         int Compare(byte[] buffer, int offset1, int length1, int offset2, int length2)
 | |
|         {
 | |
|             if (offset1 == offset2)
 | |
|             {
 | |
|                 return length1 - length2;
 | |
|             }
 | |
| 
 | |
|             return Compare(buffer, offset1, length1, buffer, offset2, length2);
 | |
|         }
 | |
| 
 | |
|         int Compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2)
 | |
|         {
 | |
|             //            Console.WriteLine("Compare: \"{0}\", \"{1}\"", Encoding.UTF8.GetString(sourceBuffer, offset1, length1), Encoding.UTF8.GetString(sourceBuffer, offset2, length2));
 | |
| 
 | |
|             int length = Math.Min(length1, length2);
 | |
| 
 | |
|             int s = 0;
 | |
|             for (int i = 0; i < length && s == 0; i++)
 | |
|             {
 | |
|                 s = buffer1[offset1 + i] - buffer2[offset2 + i];
 | |
|             }
 | |
| 
 | |
|             if (s == 0)
 | |
|             {
 | |
|                 s = length1 - length2;
 | |
|             }
 | |
| 
 | |
|             return s;
 | |
|         }
 | |
| 
 | |
|         bool Equals(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2)
 | |
|         {
 | |
|             //            Console.WriteLine("Equals: \"{0}\", \"{1}\"", Encoding.UTF8.GetString(buffer1, offset1, length1), Encoding.UTF8.GetString(buffer2, offset2, length2));
 | |
| 
 | |
|             if (length1 != length2)
 | |
|                 return false;
 | |
| 
 | |
|             for (int i = 0; i < length1; i++)
 | |
|             {
 | |
|                 if (buffer1[offset1 + i] != buffer2[offset2 + i])
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         class AttributeSorter : IComparer
 | |
|         {
 | |
|             XmlCanonicalWriter writer;
 | |
| 
 | |
|             public AttributeSorter(XmlCanonicalWriter writer)
 | |
|             {
 | |
|                 this.writer = writer;
 | |
|             }
 | |
| 
 | |
|             public void Sort()
 | |
|             {
 | |
|                 object[] indeces = new object[writer.attributeCount];
 | |
| 
 | |
|                 for (int i = 0; i < indeces.Length; i++)
 | |
|                 {
 | |
|                     indeces[i] = i;
 | |
|                 }
 | |
| 
 | |
|                 Array.Sort(indeces, this);
 | |
| 
 | |
|                 Attribute[] attributes = new Attribute[writer.attributes.Length];
 | |
|                 for (int i = 0; i < indeces.Length; i++)
 | |
|                 {
 | |
|                     attributes[i] = writer.attributes[(int)indeces[i]];
 | |
|                 }
 | |
| 
 | |
|                 writer.attributes = attributes;
 | |
|             }
 | |
| 
 | |
|             public int Compare(object obj1, object obj2)
 | |
|             {
 | |
|                 int attributeIndex1 = (int)obj1;
 | |
|                 int attributeIndex2 = (int)obj2;
 | |
|                 return writer.Compare(ref writer.attributes[attributeIndex1], ref writer.attributes[attributeIndex2]);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         struct Scope
 | |
|         {
 | |
|             public int xmlnsAttributeCount;
 | |
|             public int xmlnsOffset;
 | |
|         }
 | |
| 
 | |
|         struct Element
 | |
|         {
 | |
|             public int prefixOffset;
 | |
|             public int prefixLength;
 | |
|             public int localNameOffset;
 | |
|             public int localNameLength;
 | |
|         }
 | |
| 
 | |
|         struct Attribute
 | |
|         {
 | |
|             public int prefixOffset;
 | |
|             public int prefixLength;
 | |
|             public int localNameOffset;
 | |
|             public int localNameLength;
 | |
|             public int nsOffset;
 | |
|             public int nsLength;
 | |
|             public int offset;
 | |
|             public int length;
 | |
|         }
 | |
| 
 | |
|         struct XmlnsAttribute
 | |
|         {
 | |
|             public int prefixOffset;
 | |
|             public int prefixLength;
 | |
|             public int nsOffset;
 | |
|             public int nsLength;
 | |
|             public bool referred;
 | |
|         }
 | |
|     }
 | |
| }
 |