The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlEncodedRawTextWriter

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlRawTextWriterGenerator.cxx" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. // WARNING: This file is generated and should not be modified directly. Instead,
  16. // modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
  17. // This batch file will execute the following commands:
  18. //
  19. // cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter.cs
  20. // cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter.cs
  21. //
  22. // Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
  23. // is used to generate each implementation from one template file, using macros and ifdefs.
  24. using System;
  25. using System.IO;
  26. using System.Xml;
  27. using System.Text;
  28. using System.Xml.Schema;
  29. using System.Diagnostics;
  30. using System.Globalization;
  31. namespace System.Xml
  32. {
  33.    
  34.     // Concrete implementation of XmlWriter abstract class that serializes events as encoded XML
  35.     // text. The general-purpose XmlEncodedTextWriter uses the Encoder class to output to any
  36.     // encoding. The XmlUtf8TextWriter class combined the encoding operation with serialization
  37.     // in order to achieve better performance.
  38.     internal class XmlEncodedRawTextWriter : XmlRawWriter
  39.     {
  40.         //
  41.         // Fields
  42.         //
  43.         // main buffer
  44.         protected byte[] bufBytes;
  45.        
  46.         // output stream
  47.         protected Stream stream;
  48.        
  49.         // encoding of the stream or text writer
  50.         protected Encoding encoding;
  51.        
  52.         // char type tables
  53.         protected XmlCharType xmlCharType = XmlCharType.Instance;
  54.        
  55.         // buffer positions
  56.         protected int bufPos = 1;
  57.         // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
  58.         // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
  59.         protected int textPos = 1;
  60.         // text end position; don't indent first element, pi, or comment
  61.         protected int contentPos;
  62.         // element content end position
  63.         protected int cdataPos;
  64.         // cdata end position
  65.         protected int attrEndPos;
  66.         // end of the last attribute
  67.         protected int bufLen = BUFSIZE;
  68.        
  69.         // flags
  70.         protected bool writeToNull;
  71.         protected bool hadDoubleBracket;
  72.         protected bool inAttributeValue;
  73.        
  74.        
  75.         protected int bufBytesUsed;
  76.         protected char[] bufChars;
  77.        
  78.         // encoder for encoding chars in specified encoding when writing to stream
  79.         protected Encoder encoder;
  80.        
  81.         // output text writer
  82.         protected TextWriter writer;
  83.        
  84.         // escaping of characters invalid in the output encoding
  85.         protected bool trackTextContent;
  86.         protected bool inTextContent;
  87.         private int lastMarkPos;
  88.         private int[] textContentMarks;
  89.         // even indices contain text content start positions
  90.         // odd indices contain markup start positions
  91.         private CharEntityEncoderFallback charEntityFallback;
  92.        
  93.        
  94.         // writer settings
  95.         protected NewLineHandling newLineHandling;
  96.         protected bool closeOutput;
  97.         protected bool omitXmlDeclaration;
  98.         protected bool autoXmlDeclaration;
  99.         protected string newLineChars;
  100.         protected XmlStandalone standalone;
  101.         protected XmlOutputMethod outputMethod;
  102.         protected bool checkCharacters;
  103.         protected bool mergeCDataSections;
  104.        
  105.         //
  106.         // Constants
  107.         //
  108.         private const int BUFSIZE = 2048 * 3;
  109.         // Should be greater than default FileStream size (4096), otherwise the FileStream will try to cache the data
  110.         private const int OVERFLOW = 32;
  111.         // Allow overflow in order to reduce checks when writing out constant size markup
  112.         private const int INIT_MARKS_COUNT = 64;
  113.        
  114.         //
  115.         // Constructors
  116.         //
  117.         // Construct and initialize an instance of this class.
  118.         protected XmlEncodedRawTextWriter(XmlWriterSettings settings, bool closeOutput)
  119.         {
  120.             // copy settings
  121.             newLineHandling = settings.NewLineHandling;
  122.             omitXmlDeclaration = settings.OmitXmlDeclaration;
  123.             newLineChars = settings.NewLineChars;
  124.             standalone = settings.Standalone;
  125.             outputMethod = settings.OutputMethod;
  126.             checkCharacters = settings.CheckCharacters;
  127.             mergeCDataSections = settings.MergeCDataSections;
  128.             this.closeOutput = closeOutput;
  129.            
  130.             if (checkCharacters && newLineHandling == NewLineHandling.Replace) {
  131.                 ValidateContentChars(newLineChars, "NewLineChars", false);
  132.             }
  133.         }
  134.        
  135.        
  136.         // Construct an instance of this class that outputs text to the TextWriter interface.
  137.         public XmlEncodedRawTextWriter(TextWriter writer, XmlWriterSettings settings) : this(settings, settings.CloseOutput)
  138.         {
  139.             Debug.Assert(writer != null && settings != null);
  140.            
  141.             this.writer = writer;
  142.             this.encoding = writer.Encoding;
  143.             // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
  144.             this.bufChars = new char[BUFSIZE + OVERFLOW];
  145.            
  146.             // Write the xml declaration
  147.             if (settings.AutoXmlDeclaration) {
  148.                 WriteXmlDeclaration(standalone);
  149.                 autoXmlDeclaration = true;
  150.             }
  151.         }
  152.        
  153.        
  154.         // Construct an instance of this class that serializes to a Stream interface.
  155.         public XmlEncodedRawTextWriter(Stream stream, Encoding encoding, XmlWriterSettings settings, bool closeOutput) : this(settings, closeOutput)
  156.         {
  157.             Debug.Assert(stream != null && settings != null);
  158.            
  159.             this.stream = stream;
  160.             this.encoding = encoding;
  161.            
  162.            
  163.            
  164.            
  165.            
  166.            
  167.            
  168.            
  169.            
  170.            
  171.            
  172.            
  173.            
  174.            
  175.            
  176.             // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
  177.             bufChars = new char[BUFSIZE + OVERFLOW];
  178.             bufBytes = new byte[bufChars.Length];
  179.             bufBytesUsed = 0;
  180.            
  181.             // Init escaping of characters not fitting into the target encoding
  182.             trackTextContent = true;
  183.             inTextContent = false;
  184.             lastMarkPos = 0;
  185.             textContentMarks = new int[INIT_MARKS_COUNT];
  186.             textContentMarks[0] = 1;
  187.            
  188.             charEntityFallback = new CharEntityEncoderFallback();
  189.             encoding = (Encoding)encoding.Clone();
  190.             encoding.EncoderFallback = charEntityFallback;
  191.             this.encoding = encoding;
  192.            
  193.             encoder = encoding.GetEncoder();
  194.            
  195.             if (!stream.CanSeek || stream.Position == 0) {
  196.                 byte[] bom = encoding.GetPreamble();
  197.                 if (bom.Length != 0) {
  198.                     this.stream.Write(bom, 0, bom.Length);
  199.                 }
  200.             }
  201.            
  202.            
  203.             // Write the xml declaration
  204.             if (settings.AutoXmlDeclaration) {
  205.                 WriteXmlDeclaration(standalone);
  206.                 autoXmlDeclaration = true;
  207.             }
  208.         }
  209.        
  210.         //
  211.         // XmlWriter implementation
  212.         //
  213.         // Returns settings the writer currently applies.
  214.         public override XmlWriterSettings Settings {
  215.             get {
  216.                 XmlWriterSettings settings = new XmlWriterSettings();
  217.                
  218.                 settings.Encoding = encoding;
  219.                 settings.OmitXmlDeclaration = omitXmlDeclaration;
  220.                 settings.NewLineHandling = newLineHandling;
  221.                 settings.NewLineChars = newLineChars;
  222.                 settings.CloseOutput = closeOutput;
  223.                 settings.ConformanceLevel = ConformanceLevel.Auto;
  224.                 settings.AutoXmlDeclaration = autoXmlDeclaration;
  225.                 settings.Standalone = standalone;
  226.                 settings.OutputMethod = outputMethod;
  227.                 settings.CheckCharacters = checkCharacters;
  228.                
  229.                 settings.ReadOnly = true;
  230.                
  231.                 return settings;
  232.             }
  233.         }
  234.        
  235.         // Write the xml declaration. This must be the first call.
  236.         internal override void WriteXmlDeclaration(XmlStandalone standalone)
  237.         {
  238.             // Output xml declaration only if user allows it and it was not already output
  239.             if (!omitXmlDeclaration && !autoXmlDeclaration) {
  240.                
  241.                 if (trackTextContent && inTextContent != false) {
  242.                     ChangeTextContentMark(false);
  243.                 }
  244.                
  245.                 RawText("<?xml version=\"");
  246.                
  247.                 // Version
  248.                 RawText("1.0");
  249.                
  250.                 // Encoding
  251.                 if (encoding != null) {
  252.                     RawText("\" encoding=\"");
  253.                     RawText((encoding.CodePage == 1201) ? "UTF-16BE" : encoding.WebName);
  254.                 }
  255.                
  256.                 // Standalone
  257.                 if (standalone != XmlStandalone.Omit) {
  258.                     RawText("\" standalone=\"");
  259.                     RawText(standalone == XmlStandalone.Yes ? "yes" : "no");
  260.                 }
  261.                
  262.                 RawText("\"?>");
  263.             }
  264.         }
  265.        
  266.         internal override void WriteXmlDeclaration(string xmldecl)
  267.         {
  268.             // Output xml declaration only if user allows it and it was not already output
  269.             if (!omitXmlDeclaration && !autoXmlDeclaration) {
  270.                 WriteProcessingInstruction("xml", xmldecl);
  271.             }
  272.         }
  273.        
  274.         // Serialize the document type declaration.
  275.         public override void WriteDocType(string name, string pubid, string sysid, string subset)
  276.         {
  277.             Debug.Assert(name != null && name.Length > 0);
  278.            
  279.             if (trackTextContent && inTextContent != false) {
  280.                 ChangeTextContentMark(false);
  281.             }
  282.            
  283.             RawText("<!DOCTYPE ");
  284.             RawText(name);
  285.             if (pubid != null) {
  286.                 RawText(" PUBLIC \"");
  287.                 RawText(pubid);
  288.                 RawText("\" \"");
  289.                 if (sysid != null) {
  290.                     RawText(sysid);
  291.                 }
  292.                 bufChars[bufPos++] = (char)'"';
  293.             }
  294.             else if (sysid != null) {
  295.                 RawText(" SYSTEM \"");
  296.                 RawText(sysid);
  297.                 bufChars[bufPos++] = (char)'"';
  298.             }
  299.             else {
  300.                 bufChars[bufPos++] = (char)' ';
  301.             }
  302.            
  303.             if (subset != null) {
  304.                 bufChars[bufPos++] = (char)'[';
  305.                 RawText(subset);
  306.                 bufChars[bufPos++] = (char)']';
  307.             }
  308.            
  309.             bufChars[this.bufPos++] = (char)'>';
  310.         }
  311.        
  312.         // Serialize the beginning of an element start tag: "<prefix:localName"
  313.         public override void WriteStartElement(string prefix, string localName, string ns)
  314.         {
  315.             Debug.Assert(localName != null && localName.Length > 0);
  316.             Debug.Assert(prefix != null);
  317.            
  318.             if (trackTextContent && inTextContent != false) {
  319.                 ChangeTextContentMark(false);
  320.             }
  321.            
  322.             bufChars[bufPos++] = (char)'<';
  323.             if (prefix != null && prefix.Length != 0) {
  324.                 RawText(prefix);
  325.                 bufChars[this.bufPos++] = (char)':';
  326.             }
  327.            
  328.             RawText(localName);
  329.            
  330.             attrEndPos = bufPos;
  331.         }
  332.        
  333.         // Serialize the end of an element start tag in preparation for content serialization: ">"
  334.         internal override void StartElementContent()
  335.         {
  336.             bufChars[bufPos++] = (char)'>';
  337.            
  338.             // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the
  339.             // position of the '>' character. If WriteEndElement is called and no other characters have been
  340.             // output, then the '>' character can be be overwritten with the shortcut syntax " />".
  341.             contentPos = bufPos;
  342.         }
  343.        
  344.         // Serialize an element end tag: "</prefix:localName>", if content was output. Otherwise, serialize
  345.         // the shortcut syntax: " />".
  346.         internal override void WriteEndElement(string prefix, string localName, string ns)
  347.         {
  348.             Debug.Assert(localName != null && localName.Length > 0);
  349.             Debug.Assert(prefix != null);
  350.            
  351.             if (trackTextContent && inTextContent != false) {
  352.                 ChangeTextContentMark(false);
  353.             }
  354.            
  355.             if (contentPos != bufPos) {
  356.                 // Content has been output, so can't use shortcut syntax
  357.                 bufChars[bufPos++] = (char)'<';
  358.                 bufChars[bufPos++] = (char)'/';
  359.                
  360.                 if (prefix != null && prefix.Length != 0) {
  361.                     RawText(prefix);
  362.                     bufChars[bufPos++] = (char)':';
  363.                 }
  364.                 RawText(localName);
  365.                 bufChars[bufPos++] = (char)'>';
  366.             }
  367.             else {
  368.                 // Use shortcut syntax; overwrite the already output '>' character
  369.                 bufPos--;
  370.                 bufChars[bufPos++] = (char)' ';
  371.                 bufChars[bufPos++] = (char)'/';
  372.                 bufChars[bufPos++] = (char)'>';
  373.             }
  374.         }
  375.        
  376.         // Serialize a full element end tag: "</prefix:localName>"
  377.         internal override void WriteFullEndElement(string prefix, string localName, string ns)
  378.         {
  379.             Debug.Assert(localName != null && localName.Length > 0);
  380.             Debug.Assert(prefix != null);
  381.            
  382.             if (trackTextContent && inTextContent != false) {
  383.                 ChangeTextContentMark(false);
  384.             }
  385.            
  386.             bufChars[bufPos++] = (char)'<';
  387.             bufChars[bufPos++] = (char)'/';
  388.            
  389.             if (prefix != null && prefix.Length != 0) {
  390.                 RawText(prefix);
  391.                 bufChars[bufPos++] = (char)':';
  392.             }
  393.             RawText(localName);
  394.             bufChars[bufPos++] = (char)'>';
  395.         }
  396.        
  397.         // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="'
  398.         public override void WriteStartAttribute(string prefix, string localName, string ns)
  399.         {
  400.             Debug.Assert(localName != null && localName.Length > 0);
  401.             Debug.Assert(prefix != null);
  402.            
  403.             if (trackTextContent && inTextContent != false) {
  404.                 ChangeTextContentMark(false);
  405.             }
  406.            
  407.             if (attrEndPos == bufPos) {
  408.                 bufChars[bufPos++] = (char)' ';
  409.             }
  410.            
  411.             if (prefix != null && prefix.Length > 0) {
  412.                 RawText(prefix);
  413.                 bufChars[bufPos++] = (char)':';
  414.             }
  415.             RawText(localName);
  416.             bufChars[bufPos++] = (char)'=';
  417.             bufChars[bufPos++] = (char)'"';
  418.            
  419.             inAttributeValue = true;
  420.         }
  421.        
  422.         // Serialize the end of an attribute value using double quotes: '"'
  423.         public override void WriteEndAttribute()
  424.         {
  425.             if (trackTextContent && inTextContent != false) {
  426.                 ChangeTextContentMark(false);
  427.             }
  428.             bufChars[bufPos++] = (char)'"';
  429.             inAttributeValue = false;
  430.             attrEndPos = bufPos;
  431.         }
  432.        
  433.         internal override void WriteNamespaceDeclaration(string prefix, string namespaceName)
  434.         {
  435.             Debug.Assert(prefix != null && namespaceName != null);
  436.            
  437.             if (trackTextContent && inTextContent != false) {
  438.                 ChangeTextContentMark(false);
  439.             }
  440.            
  441.             if (prefix.Length == 0) {
  442.                 RawText(" xmlns=\"");
  443.             }
  444.             else {
  445.                 RawText(" xmlns:");
  446.                 RawText(prefix);
  447.                 bufChars[bufPos++] = (char)'=';
  448.                 bufChars[bufPos++] = (char)'"';
  449.             }
  450.            
  451.             inAttributeValue = true;
  452.             if (trackTextContent && inTextContent != true) {
  453.                 ChangeTextContentMark(true);
  454.             }
  455.             WriteString(namespaceName);
  456.             if (trackTextContent && inTextContent != false) {
  457.                 ChangeTextContentMark(false);
  458.             }
  459.             inAttributeValue = false;
  460.            
  461.             bufChars[bufPos++] = (char)'"';
  462.             attrEndPos = bufPos;
  463.         }
  464.        
  465.         // Serialize a CData section. If the "]]>" pattern is found within
  466.         // the text, replace it with "]]><![CDATA[>".
  467.         public override void WriteCData(string text)
  468.         {
  469.             Debug.Assert(text != null);
  470.            
  471.             if (trackTextContent && inTextContent != false) {
  472.                 ChangeTextContentMark(false);
  473.             }
  474.            
  475.             if (mergeCDataSections && bufPos == cdataPos) {
  476.                 // Merge adjacent cdata sections - overwrite the "]]>" characters
  477.                 Debug.Assert(bufPos >= 4);
  478.                 bufPos -= 3;
  479.             }
  480.             else {
  481.                 // Start a new cdata section
  482.                 bufChars[bufPos++] = (char)'<';
  483.                 bufChars[bufPos++] = (char)'!';
  484.                 bufChars[bufPos++] = (char)'[';
  485.                 bufChars[bufPos++] = (char)'C';
  486.                 bufChars[bufPos++] = (char)'D';
  487.                 bufChars[bufPos++] = (char)'A';
  488.                 bufChars[bufPos++] = (char)'T';
  489.                 bufChars[bufPos++] = (char)'A';
  490.                 bufChars[bufPos++] = (char)'[';
  491.             }
  492.            
  493.             WriteCDataSection(text);
  494.            
  495.             bufChars[bufPos++] = (char)']';
  496.             bufChars[bufPos++] = (char)']';
  497.             bufChars[bufPos++] = (char)'>';
  498.            
  499.             textPos = bufPos;
  500.             cdataPos = bufPos;
  501.         }
  502.        
  503.         // Serialize a comment.
  504.         public override void WriteComment(string text)
  505.         {
  506.             Debug.Assert(text != null);
  507.            
  508.             if (trackTextContent && inTextContent != false) {
  509.                 ChangeTextContentMark(false);
  510.             }
  511.            
  512.             bufChars[bufPos++] = (char)'<';
  513.             bufChars[bufPos++] = (char)'!';
  514.             bufChars[bufPos++] = (char)'-';
  515.             bufChars[bufPos++] = (char)'-';
  516.            
  517.             WriteCommentOrPi(text, '-');
  518.            
  519.             bufChars[bufPos++] = (char)'-';
  520.             bufChars[bufPos++] = (char)'-';
  521.             bufChars[bufPos++] = (char)'>';
  522.         }
  523.        
  524.         // Serialize a processing instruction.
  525.         public override void WriteProcessingInstruction(string name, string text)
  526.         {
  527.             Debug.Assert(name != null && name.Length > 0);
  528.             Debug.Assert(text != null);
  529.            
  530.             if (trackTextContent && inTextContent != false) {
  531.                 ChangeTextContentMark(false);
  532.             }
  533.            
  534.             bufChars[bufPos++] = (char)'<';
  535.             bufChars[bufPos++] = (char)'?';
  536.             RawText(name);
  537.            
  538.             if (text.Length > 0) {
  539.                 bufChars[bufPos++] = (char)' ';
  540.                 WriteCommentOrPi(text, '?');
  541.             }
  542.            
  543.             bufChars[bufPos++] = (char)'?';
  544.             bufChars[bufPos++] = (char)'>';
  545.         }
  546.        
  547.         // Serialize an entity reference.
  548.         public override void WriteEntityRef(string name)
  549.         {
  550.             Debug.Assert(name != null && name.Length > 0);
  551.            
  552.             if (trackTextContent && inTextContent != false) {
  553.                 ChangeTextContentMark(false);
  554.             }
  555.            
  556.             bufChars[bufPos++] = (char)'&';
  557.             RawText(name);
  558.             bufChars[bufPos++] = (char)';';
  559.            
  560.             if (bufPos > bufLen) {
  561.                 FlushBuffer();
  562.             }
  563.            
  564.             textPos = bufPos;
  565.         }
  566.        
  567.         // Serialize a character entity reference.
  568.         public override void WriteCharEntity(char ch)
  569.         {
  570.             string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo);
  571.            
  572.             if (checkCharacters && !xmlCharType.IsCharData(ch)) {
  573.                 throw XmlConvert.CreateInvalidCharException(ch);
  574.             }
  575.            
  576.             if (trackTextContent && inTextContent != false) {
  577.                 ChangeTextContentMark(false);
  578.             }
  579.            
  580.             bufChars[bufPos++] = (char)'&';
  581.             bufChars[bufPos++] = (char)'#';
  582.             bufChars[bufPos++] = (char)'x';
  583.             RawText(strVal);
  584.             bufChars[bufPos++] = (char)';';
  585.            
  586.             if (bufPos > bufLen) {
  587.                 FlushBuffer();
  588.             }
  589.            
  590.             textPos = bufPos;
  591.         }
  592.        
  593.         // Serialize a whitespace node.
  594.         unsafe public override void WriteWhitespace(string ws)
  595.         {
  596.             Debug.Assert(ws != null);
  597.             if (trackTextContent && inTextContent != false) {
  598.                 ChangeTextContentMark(false);
  599.             }
  600.            
  601.             fixed (char* pSrc = ws) {
  602.                 char* pSrcEnd = pSrc + ws.Length;
  603.                 if (inAttributeValue) {
  604.                     WriteAttributeTextBlock(pSrc, pSrcEnd);
  605.                 }
  606.                 else {
  607.                     WriteElementTextBlock(pSrc, pSrcEnd);
  608.                 }
  609.             }
  610.         }
  611.        
  612.         // Serialize either attribute or element text using XML rules.
  613.         unsafe public override void WriteString(string text)
  614.         {
  615.             Debug.Assert(text != null);
  616.             if (trackTextContent && inTextContent != true) {
  617.                 ChangeTextContentMark(true);
  618.             }
  619.            
  620.             fixed (char* pSrc = text) {
  621.                 char* pSrcEnd = pSrc + text.Length;
  622.                 if (inAttributeValue) {
  623.                     WriteAttributeTextBlock(pSrc, pSrcEnd);
  624.                 }
  625.                 else {
  626.                     WriteElementTextBlock(pSrc, pSrcEnd);
  627.                 }
  628.             }
  629.         }
  630.        
  631.         // Serialize surrogate character entity.
  632.         public override void WriteSurrogateCharEntity(char lowChar, char highChar)
  633.         {
  634.             if (trackTextContent && inTextContent != false) {
  635.                 ChangeTextContentMark(false);
  636.             }
  637.             int surrogateChar = ((int)lowChar - SurLowStart) | (((int)highChar - SurHighStart) << 10) + 65536;
  638.            
  639.             bufChars[bufPos++] = (char)'&';
  640.             bufChars[bufPos++] = (char)'#';
  641.             bufChars[bufPos++] = (char)'x';
  642.             RawText(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo));
  643.             bufChars[bufPos++] = (char)';';
  644.             textPos = bufPos;
  645.         }
  646.        
  647.         // Serialize either attribute or element text using XML rules.
  648.         unsafe public override void WriteChars(char[] buffer, int index, int count)
  649.         {
  650.             Debug.Assert(buffer != null);
  651.             Debug.Assert(index >= 0);
  652.             Debug.Assert(count >= 0 && index + count <= buffer.Length);
  653.            
  654.             if (trackTextContent && inTextContent != true) {
  655.                 ChangeTextContentMark(true);
  656.             }
  657.            
  658.             fixed (char* pSrcBegin = &buffer[index]) {
  659.                 if (inAttributeValue) {
  660.                     WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count);
  661.                 }
  662.                 else {
  663.                     WriteElementTextBlock(pSrcBegin, pSrcBegin + count);
  664.                 }
  665.             }
  666.         }
  667.        
  668.         // Serialize raw data.
  669.         unsafe public override void WriteRaw(char[] buffer, int index, int count)
  670.         {
  671.             Debug.Assert(buffer != null);
  672.             Debug.Assert(index >= 0);
  673.             Debug.Assert(count >= 0 && index + count <= buffer.Length);
  674.            
  675.             if (trackTextContent && inTextContent != false) {
  676.                 ChangeTextContentMark(false);
  677.             }
  678.            
  679.             fixed (char* pSrcBegin = &buffer[index]) {
  680.                 WriteRawWithCharChecking(pSrcBegin, pSrcBegin + count);
  681.             }
  682.             textPos = bufPos;
  683.         }
  684.        
  685.         // Serialize raw data.
  686.         unsafe public override void WriteRaw(string data)
  687.         {
  688.             Debug.Assert(data != null);
  689.            
  690.             if (trackTextContent && inTextContent != false) {
  691.                 ChangeTextContentMark(false);
  692.             }
  693.            
  694.             fixed (char* pSrcBegin = data) {
  695.                 WriteRawWithCharChecking(pSrcBegin, pSrcBegin + data.Length);
  696.             }
  697.             textPos = bufPos;
  698.         }
  699.        
  700.         // Flush all bytes in the buffer to output and close the output stream or writer.
  701.         public override void Close()
  702.         {
  703.             FlushBuffer();
  704.             FlushEncoder();
  705.            
  706.             // Future calls to Close or Flush shouldn't write to Stream or Writer
  707.             writeToNull = true;
  708.            
  709.             if (stream != null) {
  710.                 stream.Flush();
  711.                 if (closeOutput) {
  712.                     stream.Close();
  713.                 }
  714.                 stream = null;
  715.             }
  716.            
  717.             else if (writer != null) {
  718.                 writer.Flush();
  719.                 if (closeOutput) {
  720.                     writer.Close();
  721.                 }
  722.                 writer = null;
  723.             }
  724.            
  725.         }
  726.        
  727.         // Flush all characters in the buffer to output and call Flush() on the output object.
  728.         public override void Flush()
  729.         {
  730.             FlushBuffer();
  731.             FlushEncoder();
  732.            
  733.            
  734.            
  735.            
  736.            
  737.             if (stream != null) {
  738.                 stream.Flush();
  739.             }
  740.             else if (writer != null) {
  741.                 writer.Flush();
  742.             }
  743.            
  744.         }
  745.        
  746.         //
  747.         // Implementation methods
  748.         //
  749.         // Flush all characters in the buffer to output. Do not flush the output object.
  750.         protected virtual void FlushBuffer()
  751.         {
  752.             try {
  753.                 // Output all characters (except for previous characters stored at beginning of buffer)
  754.                 if (!writeToNull) {
  755.                    
  756.                    
  757.                    
  758.                    
  759.                     Debug.Assert(stream != null || writer != null);
  760.                    
  761.                     if (stream != null) {
  762.                         if (trackTextContent) {
  763.                             charEntityFallback.Reset(textContentMarks, lastMarkPos);
  764.                             // reset text content tracking
  765.                             lastMarkPos = 0;
  766.                             Debug.Assert(textContentMarks[0] == 1);
  767.                         }
  768.                         EncodeChars(1, bufPos, true);
  769.                     }
  770.                     else {
  771.                         // Write text to TextWriter
  772.                         writer.Write(bufChars, 1, bufPos - 1);
  773.                     }
  774.                    
  775.                 }
  776.             }
  777.             catch {
  778.                 // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream
  779.                 writeToNull = true;
  780.                 throw;
  781.             }
  782.             finally {
  783.                 // Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
  784.                 bufChars[0] = bufChars[bufPos - 1];
  785.                
  786.                
  787.                
  788.                
  789.                
  790.                
  791.                
  792.                
  793.                
  794.                
  795.                
  796.                 // Reset buffer position
  797.                 textPos = (textPos == bufPos) ? 1 : 0;
  798.                 attrEndPos = (attrEndPos == bufPos) ? 1 : 0;
  799.                 contentPos = 0;
  800.                 // Needs to be zero, since overwriting '>' character is no longer possible
  801.                 cdataPos = 0;
  802.                 // Needs to be zero, since overwriting ']]>' characters is no longer possible
  803.                 bufPos = 1;
  804.                 // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
  805.                 // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
  806.             }
  807.         }
  808.        
  809.        
  810.        
  811.        
  812.        
  813.        
  814.         private void EncodeChars(int startOffset, int endOffset, bool writeAllToStream)
  815.         {
  816.             // Write encoded text to stream
  817.             int chEnc;
  818.             int bEnc;
  819.             bool completed;
  820.             while (startOffset < endOffset) {
  821.                 if (charEntityFallback != null) {
  822.                     charEntityFallback.StartOffset = startOffset;
  823.                 }
  824.                 encoder.Convert(bufChars, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed
  825.                 );
  826.                 startOffset += chEnc;
  827.                 bufBytesUsed += bEnc;
  828.                 if (bufBytesUsed >= (bufBytes.Length - 16)) {
  829.                     stream.Write(bufBytes, 0, bufBytesUsed);
  830.                     bufBytesUsed = 0;
  831.                 }
  832.             }
  833.             if (writeAllToStream && bufBytesUsed > 0) {
  834.                 stream.Write(bufBytes, 0, bufBytesUsed);
  835.                 bufBytesUsed = 0;
  836.             }
  837.         }
  838.        
  839.         private void FlushEncoder()
  840.         {
  841.             Debug.Assert(bufPos == 1);
  842.             if (stream != null) {
  843.                 int chEnc;
  844.                 int bEnc;
  845.                 bool completed;
  846.                 // decode no chars, just flush
  847.                 encoder.Convert(bufChars, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed
  848.                 );
  849.                 if (bEnc != 0) {
  850.                     stream.Write(bufBytes, 0, bEnc);
  851.                 }
  852.             }
  853.         }
  854.        
  855.        
  856.         // Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
  857.         // are entitized.
  858.         unsafe protected void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd)
  859.         {
  860.             fixed (char* pDstBegin = bufChars) {
  861.                 char* pDst = pDstBegin + this.bufPos;
  862.                
  863.                 int ch = 0;
  864.                 for (;;) {
  865.                     char* pDstEnd = pDst + (pSrcEnd - pSrc);
  866.                     if (pDstEnd > pDstBegin + bufLen) {
  867.                         pDstEnd = pDstBegin + bufLen;
  868.                     }
  869.                    
  870.                    
  871.                    
  872.                    
  873.                     while (pDst < pDstEnd && (((xmlCharType.charProperties[(ch = *pSrc)] & XmlCharType.fAttrValue) != 0))) {
  874.                        
  875.                         *pDst = (char)ch;
  876.                         pDst++;
  877.                         pSrc++;
  878.                     }
  879.                     Debug.Assert(pSrc <= pSrcEnd);
  880.                    
  881.                     // end of value
  882.                     if (pSrc >= pSrcEnd) {
  883.                         break;
  884.                     }
  885.                    
  886.                     // end of buffer
  887.                     if (pDst >= pDstEnd) {
  888.                         bufPos = (int)(pDst - pDstBegin);
  889.                         FlushBuffer();
  890.                         pDst = pDstBegin + 1;
  891.                         continue;
  892.                     }
  893.                    
  894.                     // some character needs to be escaped
  895.                     switch (ch) {
  896.                         case '&':
  897.                             pDst = AmpEntity(pDst);
  898.                             break;
  899.                         case '<':
  900.                             pDst = LtEntity(pDst);
  901.                             break;
  902.                         case '>':
  903.                             pDst = GtEntity(pDst);
  904.                             break;
  905.                         case '"':
  906.                             pDst = QuoteEntity(pDst);
  907.                             break;
  908.                         case '\'':
  909.                             *pDst = (char)ch;
  910.                             pDst++;
  911.                             break;
  912.                         case (char)9:
  913.                             if (newLineHandling == NewLineHandling.None) {
  914.                                 *pDst = (char)ch;
  915.                                 pDst++;
  916.                             }
  917.                             else {
  918.                                 // escape tab in attributes
  919.                                 pDst = TabEntity(pDst);
  920.                             }
  921.                             break;
  922.                         case (char)13:
  923.                             if (newLineHandling == NewLineHandling.None) {
  924.                                 *pDst = (char)ch;
  925.                                 pDst++;
  926.                             }
  927.                             else {
  928.                                 // escape new lines in attributes
  929.                                 pDst = CarriageReturnEntity(pDst);
  930.                             }
  931.                             break;
  932.                         case (char)10:
  933.                             if (newLineHandling == NewLineHandling.None) {
  934.                                 *pDst = (char)ch;
  935.                                 pDst++;
  936.                             }
  937.                             else {
  938.                                 // escape new lines in attributes
  939.                                 pDst = LineFeedEntity(pDst);
  940.                             }
  941.                             break;
  942.                         default:
  943.                             if (InRange(ch, SurHighStart, SurLowEnd)) {
  944.                                 pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  945.                                 pSrc += 2;
  946.                             }
  947.                             else if (ch <= 127 || ch >= 65534) {
  948.                                 pDst = InvalidXmlChar(ch, pDst, true);
  949.                                 pSrc++;
  950.                             }
  951.                             else {
  952.                                 *pDst = (char)ch;
  953.                                 pDst++;
  954.                                 pSrc++;
  955.                             }
  956.                             ;
  957.                             continue;
  958.                     }
  959.                     pSrc++;
  960.                 }
  961.                 bufPos = (int)(pDst - pDstBegin);
  962.             }
  963.         }
  964.        
  965.         // Serialize text that is part of element content. The '&', '<', and '>' characters
  966.         // are entitized.
  967.         unsafe protected void WriteElementTextBlock(char* pSrc, char* pSrcEnd)
  968.         {
  969.             fixed (char* pDstBegin = bufChars) {
  970.                 char* pDst = pDstBegin + this.bufPos;
  971.                
  972.                 int ch = 0;
  973.                 for (;;) {
  974.                     char* pDstEnd = pDst + (pSrcEnd - pSrc);
  975.                     if (pDstEnd > pDstBegin + bufLen) {
  976.                         pDstEnd = pDstBegin + bufLen;
  977.                     }
  978.                    
  979.                    
  980.                    
  981.                    
  982.                     while (pDst < pDstEnd && (((xmlCharType.charProperties[(ch = *pSrc)] & XmlCharType.fAttrValue) != 0))) {
  983.                        
  984.                         *pDst = (char)ch;
  985.                         pDst++;
  986.                         pSrc++;
  987.                     }
  988.                     Debug.Assert(pSrc <= pSrcEnd);
  989.                    
  990.                     // end of value
  991.                     if (pSrc >= pSrcEnd) {
  992.                         break;
  993.                     }
  994.                    
  995.                     // end of buffer
  996.                     if (pDst >= pDstEnd) {
  997.                         bufPos = (int)(pDst - pDstBegin);
  998.                         FlushBuffer();
  999.                         pDst = pDstBegin + 1;
  1000.                         continue;
  1001.                     }
  1002.                    
  1003.                     // some character needs to be escaped
  1004.                     switch (ch) {
  1005.                         case '&':
  1006.                             pDst = AmpEntity(pDst);
  1007.                             break;
  1008.                         case '<':
  1009.                             pDst = LtEntity(pDst);
  1010.                             break;
  1011.                         case '>':
  1012.                             pDst = GtEntity(pDst);
  1013.                             break;
  1014.                         case '"':
  1015.                         case '\'':
  1016.                         case (char)9:
  1017.                             *pDst = (char)ch;
  1018.                             pDst++;
  1019.                             break;
  1020.                         case (char)10:
  1021.                             if (newLineHandling == NewLineHandling.Replace) {
  1022.                                 pDst = WriteNewLine(pDst);
  1023.                             }
  1024.                             else {
  1025.                                 *pDst = (char)ch;
  1026.                                 pDst++;
  1027.                             }
  1028.                             break;
  1029.                         case (char)13:
  1030.                             switch (newLineHandling) {
  1031.                                 case NewLineHandling.Replace:
  1032.                                     // Replace "\r\n", or "\r" with NewLineChars
  1033.                                     if (pSrc[1] == '\n') {
  1034.                                         pSrc++;
  1035.                                     }
  1036.                                     pDst = WriteNewLine(pDst);
  1037.                                     break;
  1038.                                 case NewLineHandling.Entitize:
  1039.                                     // Entitize 0xD
  1040.                                     pDst = CarriageReturnEntity(pDst);
  1041.                                     break;
  1042.                                 case NewLineHandling.None:
  1043.                                     *pDst = (char)ch;
  1044.                                     pDst++;
  1045.                                     break;
  1046.                             }
  1047.                             break;
  1048.                         default:
  1049.                             if (InRange(ch, SurHighStart, SurLowEnd)) {
  1050.                                 pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1051.                                 pSrc += 2;
  1052.                             }
  1053.                             else if (ch <= 127 || ch >= 65534) {
  1054.                                 pDst = InvalidXmlChar(ch, pDst, true);
  1055.                                 pSrc++;
  1056.                             }
  1057.                             else {
  1058.                                 *pDst = (char)ch;
  1059.                                 pDst++;
  1060.                                 pSrc++;
  1061.                             }
  1062.                             ;
  1063.                             continue;
  1064.                     }
  1065.                     pSrc++;
  1066.                 }
  1067.                 bufPos = (int)(pDst - pDstBegin);
  1068.                 textPos = bufPos;
  1069.                 contentPos = 0;
  1070.             }
  1071.         }
  1072.        
  1073.         unsafe protected void RawText(string s)
  1074.         {
  1075.             Debug.Assert(s != null);
  1076.             fixed (char* pSrcBegin = s) {
  1077.                 RawText(pSrcBegin, pSrcBegin + s.Length);
  1078.             }
  1079.         }
  1080.        
  1081.         unsafe protected void RawText(char* pSrcBegin, char* pSrcEnd)
  1082.         {
  1083.             fixed (char* pDstBegin = bufChars) {
  1084.                 char* pDst = pDstBegin + this.bufPos;
  1085.                 char* pSrc = pSrcBegin;
  1086.                
  1087.                 int ch = 0;
  1088.                 for (;;) {
  1089.                     char* pDstEnd = pDst + (pSrcEnd - pSrc);
  1090.                     if (pDstEnd > pDstBegin + this.bufLen) {
  1091.                         pDstEnd = pDstBegin + this.bufLen;
  1092.                     }
  1093.                    
  1094.                    
  1095.                    
  1096.                    
  1097.                     while (pDst < pDstEnd && ((ch = *pSrc) < SurHighStart)) {
  1098.                        
  1099.                         pSrc++;
  1100.                         *pDst = (char)ch;
  1101.                         pDst++;
  1102.                     }
  1103.                     Debug.Assert(pSrc <= pSrcEnd);
  1104.                    
  1105.                     // end of value
  1106.                     if (pSrc >= pSrcEnd) {
  1107.                         break;
  1108.                     }
  1109.                    
  1110.                     // end of buffer
  1111.                     if (pDst >= pDstEnd) {
  1112.                         bufPos = (int)(pDst - pDstBegin);
  1113.                         FlushBuffer();
  1114.                         pDst = pDstBegin + 1;
  1115.                         continue;
  1116.                     }
  1117.                    
  1118.                     if (InRange(ch, SurHighStart, SurLowEnd)) {
  1119.                         pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1120.                         pSrc += 2;
  1121.                     }
  1122.                     else if (ch <= 127 || ch >= 65534) {
  1123.                         pDst = InvalidXmlChar(ch, pDst, false);
  1124.                         pSrc++;
  1125.                     }
  1126.                     else {
  1127.                         *pDst = (char)ch;
  1128.                         pDst++;
  1129.                         pSrc++;
  1130.                     }
  1131.                     ;
  1132.                 }
  1133.                
  1134.                 bufPos = (int)(pDst - pDstBegin);
  1135.             }
  1136.         }
  1137.        
  1138.         unsafe protected void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd)
  1139.         {
  1140.             fixed (char* pDstBegin = bufChars) {
  1141.                 char* pSrc = pSrcBegin;
  1142.                 char* pDst = pDstBegin + bufPos;
  1143.                
  1144.                 int ch = 0;
  1145.                 for (;;) {
  1146.                     char* pDstEnd = pDst + (pSrcEnd - pSrc);
  1147.                     if (pDstEnd > pDstBegin + bufLen) {
  1148.                         pDstEnd = pDstBegin + bufLen;
  1149.                     }
  1150.                    
  1151.                    
  1152.                    
  1153.                    
  1154.                     while (pDst < pDstEnd && (((xmlCharType.charProperties[(ch = *pSrc)] & XmlCharType.fText) != 0))) {
  1155.                        
  1156.                         *pDst = (char)ch;
  1157.                         pDst++;
  1158.                         pSrc++;
  1159.                     }
  1160.                    
  1161.                     Debug.Assert(pSrc <= pSrcEnd);
  1162.                    
  1163.                     // end of value
  1164.                     if (pSrc >= pSrcEnd) {
  1165.                         break;
  1166.                     }
  1167.                    
  1168.                     // end of buffer
  1169.                     if (pDst >= pDstEnd) {
  1170.                         bufPos = (int)(pDst - pDstBegin);
  1171.                         FlushBuffer();
  1172.                         pDst = pDstBegin + 1;
  1173.                         continue;
  1174.                     }
  1175.                    
  1176.                     // handle special characters
  1177.                     switch (ch) {
  1178.                         case ']':
  1179.                         case '<':
  1180.                         case '&':
  1181.                         case (char)9:
  1182.                             *pDst = (char)ch;
  1183.                             pDst++;
  1184.                             break;
  1185.                         case (char)13:
  1186.                             if (newLineHandling == NewLineHandling.Replace) {
  1187.                                 // Normalize "\r\n", or "\r" to NewLineChars
  1188.                                 if (pSrc[1] == '\n') {
  1189.                                     pSrc++;
  1190.                                 }
  1191.                                 pDst = WriteNewLine(pDst);
  1192.                             }
  1193.                             else {
  1194.                                 *pDst = (char)ch;
  1195.                                 pDst++;
  1196.                             }
  1197.                             break;
  1198.                         case (char)10:
  1199.                             if (newLineHandling == NewLineHandling.Replace) {
  1200.                                 pDst = WriteNewLine(pDst);
  1201.                             }
  1202.                             else {
  1203.                                 *pDst = (char)ch;
  1204.                                 pDst++;
  1205.                             }
  1206.                             break;
  1207.                         default:
  1208.                             if (InRange(ch, SurHighStart, SurLowEnd)) {
  1209.                                 pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1210.                                 pSrc += 2;
  1211.                             }
  1212.                             else if (ch <= 127 || ch >= 65534) {
  1213.                                 pDst = InvalidXmlChar(ch, pDst, false);
  1214.                                 pSrc++;
  1215.                             }
  1216.                             else {
  1217.                                 *pDst = (char)ch;
  1218.                                 pDst++;
  1219.                                 pSrc++;
  1220.                             }
  1221.                             ;
  1222.                             continue;
  1223.                     }
  1224.                     pSrc++;
  1225.                 }
  1226.                 bufPos = (int)(pDst - pDstBegin);
  1227.             }
  1228.         }
  1229.        
  1230.         unsafe protected void WriteCommentOrPi(string text, int stopChar)
  1231.         {
  1232.             // write text
  1233.             fixed (char* pSrcBegin = text)
  1234.                 fixed (char* pDstBegin = bufChars) {
  1235.                     char* pSrc = pSrcBegin;
  1236.                     char* pSrcEnd = pSrcBegin + text.Length;
  1237.                     char* pDst = pDstBegin + bufPos;
  1238.                    
  1239.                     int ch = 0;
  1240.                     for (;;) {
  1241.                         char* pDstEnd = pDst + (pSrcEnd - pSrc);
  1242.                         if (pDstEnd > pDstBegin + bufLen) {
  1243.                             pDstEnd = pDstBegin + bufLen;
  1244.                         }
  1245.                        
  1246.                        
  1247.                        
  1248.                        
  1249.                         while (pDst < pDstEnd && (((xmlCharType.charProperties[(ch = *pSrc)] & XmlCharType.fText) != 0) && ch != stopChar)) {
  1250.                            
  1251.                             *pDst = (char)ch;
  1252.                             pDst++;
  1253.                             pSrc++;
  1254.                         }
  1255.                        
  1256.                         Debug.Assert(pSrc <= pSrcEnd);
  1257.                        
  1258.                         // end of value
  1259.                         if (pSrc >= pSrcEnd) {
  1260.                             break;
  1261.                         }
  1262.                        
  1263.                         // end of buffer
  1264.                         if (pDst >= pDstEnd) {
  1265.                             bufPos = (int)(pDst - pDstBegin);
  1266.                             FlushBuffer();
  1267.                             pDst = pDstBegin + 1;
  1268.                             continue;
  1269.                         }
  1270.                        
  1271.                         // handle special characters
  1272.                         switch (ch) {
  1273.                             case '-':
  1274.                                 *pDst = (char)'-';
  1275.                                 pDst++;
  1276.                                 if (ch == stopChar) {
  1277.                                     // Insert space between adjacent dashes or before comment's end dashes
  1278.                                     if (pSrc + 1 == pSrcEnd || *(pSrc + 1) == '-') {
  1279.                                         *pDst = (char)' ';
  1280.                                         pDst++;
  1281.                                     }
  1282.                                 }
  1283.                                 break;
  1284.                             case '?':
  1285.                                 *pDst = (char)'?';
  1286.                                 pDst++;
  1287.                                 if (ch == stopChar) {
  1288.                                     // Processing instruction: insert space between adjacent '?' and '>'
  1289.                                     if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>') {
  1290.                                         *pDst = (char)' ';
  1291.                                         pDst++;
  1292.                                     }
  1293.                                 }
  1294.                                 break;
  1295.                             case ']':
  1296.                                 *pDst = (char)']';
  1297.                                 pDst++;
  1298.                                 break;
  1299.                             case (char)13:
  1300.                                 if (newLineHandling == NewLineHandling.Replace) {
  1301.                                     // Normalize "\r\n", or "\r" to NewLineChars
  1302.                                     if (pSrc[1] == '\n') {
  1303.                                         pSrc++;
  1304.                                     }
  1305.                                     pDst = WriteNewLine(pDst);
  1306.                                 }
  1307.                                 else {
  1308.                                     *pDst = (char)ch;
  1309.                                     pDst++;
  1310.                                 }
  1311.                                 break;
  1312.                             case (char)10:
  1313.                                 if (newLineHandling == NewLineHandling.Replace) {
  1314.                                     pDst = WriteNewLine(pDst);
  1315.                                 }
  1316.                                 else {
  1317.                                     *pDst = (char)ch;
  1318.                                     pDst++;
  1319.                                 }
  1320.                                 break;
  1321.                             case '<':
  1322.                             case '&':
  1323.                             case (char)9:
  1324.                                 *pDst = (char)ch;
  1325.                                 pDst++;
  1326.                                 break;
  1327.                             default:
  1328.                                 if (InRange(ch, SurHighStart, SurLowEnd)) {
  1329.                                     pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1330.                                     pSrc += 2;
  1331.                                 }
  1332.                                 else if (ch <= 127 || ch >= 65534) {
  1333.                                     pDst = InvalidXmlChar(ch, pDst, false);
  1334.                                     pSrc++;
  1335.                                 }
  1336.                                 else {
  1337.                                     *pDst = (char)ch;
  1338.                                     pDst++;
  1339.                                     pSrc++;
  1340.                                 }
  1341.                                 ;
  1342.                                 continue;
  1343.                         }
  1344.                         pSrc++;
  1345.                     }
  1346.                     bufPos = (int)(pDst - pDstBegin);
  1347.                 }
  1348.         }
  1349.        
  1350.         unsafe protected void WriteCDataSection(string text)
  1351.         {
  1352.             // write text
  1353.             fixed (char* pSrcBegin = text)
  1354.                 fixed (char* pDstBegin = bufChars) {
  1355.                     char* pSrc = pSrcBegin;
  1356.                     char* pSrcEnd = pSrcBegin + text.Length;
  1357.                     char* pDst = pDstBegin + bufPos;
  1358.                    
  1359.                     int ch = 0;
  1360.                     for (;;) {
  1361.                         char* pDstEnd = pDst + (pSrcEnd - pSrc);
  1362.                         if (pDstEnd > pDstBegin + bufLen) {
  1363.                             pDstEnd = pDstBegin + bufLen;
  1364.                         }
  1365.                        
  1366.                        
  1367.                        
  1368.                        
  1369.                         while (pDst < pDstEnd && (((xmlCharType.charProperties[(ch = *pSrc)] & XmlCharType.fAttrValue) != 0) && ch != ']')) {
  1370.                            
  1371.                             *pDst = (char)ch;
  1372.                             pDst++;
  1373.                             pSrc++;
  1374.                         }
  1375.                        
  1376.                         Debug.Assert(pSrc <= pSrcEnd);
  1377.                        
  1378.                         // end of value
  1379.                         if (pSrc >= pSrcEnd) {
  1380.                             break;
  1381.                         }
  1382.                        
  1383.                         // end of buffer
  1384.                         if (pDst >= pDstEnd) {
  1385.                             bufPos = (int)(pDst - pDstBegin);
  1386.                             FlushBuffer();
  1387.                             pDst = pDstBegin + 1;
  1388.                             continue;
  1389.                         }
  1390.                        
  1391.                         // handle special characters
  1392.                         switch (ch) {
  1393.                             case '>':
  1394.                                 if (hadDoubleBracket && pDst[-1] == (char)']') {
  1395.                                     // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
  1396.                                     // The characters "]]>" were found within the CData text
  1397.                                     pDst = RawEndCData(pDst);
  1398.                                     pDst = RawStartCData(pDst);
  1399.                                 }
  1400.                                 *pDst = (char)'>';
  1401.                                 pDst++;
  1402.                                 break;
  1403.                             case ']':
  1404.                                 if (pDst[-1] == (char)']') {
  1405.                                     // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
  1406.                                     hadDoubleBracket = true;
  1407.                                 }
  1408.                                 else {
  1409.                                     hadDoubleBracket = false;
  1410.                                 }
  1411.                                 *pDst = (char)']';
  1412.                                 pDst++;
  1413.                                 break;
  1414.                             case (char)13:
  1415.                                 if (newLineHandling == NewLineHandling.Replace) {
  1416.                                     // Normalize "\r\n", or "\r" to NewLineChars
  1417.                                     if (pSrc[1] == '\n') {
  1418.                                         pSrc++;
  1419.                                     }
  1420.                                     pDst = WriteNewLine(pDst);
  1421.                                 }
  1422.                                 else {
  1423.                                     *pDst = (char)ch;
  1424.                                     pDst++;
  1425.                                 }
  1426.                                 break;
  1427.                             case (char)10:
  1428.                                 if (newLineHandling == NewLineHandling.Replace) {
  1429.                                     pDst = WriteNewLine(pDst);
  1430.                                 }
  1431.                                 else {
  1432.                                     *pDst = (char)ch;
  1433.                                     pDst++;
  1434.                                 }
  1435.                                 break;
  1436.                             case '&':
  1437.                             case '<':
  1438.                             case '"':
  1439.                             case '\'':
  1440.                             case (char)9:
  1441.                                 *pDst = (char)ch;
  1442.                                 pDst++;
  1443.                                 break;
  1444.                             default:
  1445.                                 if (InRange(ch, SurHighStart, SurLowEnd)) {
  1446.                                     pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1447.                                     pSrc += 2;
  1448.                                 }
  1449.                                 else if (ch <= 127 || ch >= 65534) {
  1450.                                     pDst = InvalidXmlChar(ch, pDst, false);
  1451.                                     pSrc++;
  1452.                                 }
  1453.                                 else {
  1454.                                     *pDst = (char)ch;
  1455.                                     pDst++;
  1456.                                     pSrc++;
  1457.                                 }
  1458.                                 ;
  1459.                                 continue;
  1460.                         }
  1461.                         pSrc++;
  1462.                     }
  1463.                     bufPos = (int)(pDst - pDstBegin);
  1464.                 }
  1465.         }
  1466.        
  1467.        
  1468.        
  1469.        
  1470.        
  1471.        
  1472.        
  1473.        
  1474.        
  1475.         unsafe private static char* EncodeSurrogate(char* pSrc, char* pSrcEnd, char* pDst)
  1476.         {
  1477.             Debug.Assert(InRange(*pSrc, SurHighStart, SurLowEnd));
  1478.            
  1479.             int ch = *pSrc;
  1480.             if (ch <= SurHighEnd) {
  1481.                 if (pSrc + 1 < pSrcEnd) {
  1482.                     int lowChar = pSrc[1];
  1483.                     if (lowChar >= SurLowStart) {
  1484.                        
  1485.                        
  1486.                        
  1487.                        
  1488.                        
  1489.                        
  1490.                        
  1491.                        
  1492.                        
  1493.                        
  1494.                        
  1495.                        
  1496.                         pDst[0] = (char)ch;
  1497.                         pDst[1] = (char)lowChar;
  1498.                         pDst += 2;
  1499.                        
  1500.                         return pDst;
  1501.                     }
  1502.                     throw XmlConvert.CreateInvalidSurrogatePairException((char)lowChar, (char)ch);
  1503.                 }
  1504.                 throw new ArgumentException(Res.GetString(Res.Xml_InvalidSurrogateMissingLowChar));
  1505.             }
  1506.             throw XmlConvert.CreateInvalidHighSurrogateCharException((char)ch);
  1507.         }
  1508.        
  1509.         unsafe private char* InvalidXmlChar(int ch, char* pDst, bool entitize)
  1510.         {
  1511.             Debug.Assert(!xmlCharType.IsWhiteSpace((char)ch));
  1512.             Debug.Assert(!xmlCharType.IsAttributeValueChar((char)ch));
  1513.            
  1514.             if (checkCharacters) {
  1515.                 throw XmlConvert.CreateInvalidCharException((char)ch);
  1516.             }
  1517.             else {
  1518.                 if (entitize) {
  1519.                     return CharEntity(pDst, (char)ch);
  1520.                 }
  1521.                 else {
  1522.                    
  1523.                    
  1524.                    
  1525.                     *pDst = (char)ch;
  1526.                     pDst++;
  1527.                    
  1528.                    
  1529.                    
  1530.                    
  1531.                    
  1532.                    
  1533.                     return pDst;
  1534.                 }
  1535.             }
  1536.         }
  1537.        
  1538.         unsafe internal void EncodeChar(ref char* pSrc, char* pSrcEnd, ref char* pDst)
  1539.         {
  1540.             int ch = *pSrc;
  1541.             if (InRange(ch, SurHighStart, SurLowEnd)) {
  1542.                 pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
  1543.                 pSrc += 2;
  1544.             }
  1545.             else if (ch <= 127 || ch >= 65534) {
  1546.                 pDst = InvalidXmlChar(ch, pDst, false);
  1547.                 pSrc++;
  1548.             }
  1549.             else {
  1550.                 *pDst = (char)ch;
  1551.                 pDst++;
  1552.                 pSrc++;
  1553.             }
  1554.             ;
  1555.         }
  1556.        
  1557.        
  1558.        
  1559.        
  1560.        
  1561.        
  1562.        
  1563.        
  1564.        
  1565.        
  1566.        
  1567.        
  1568.        
  1569.        
  1570.        
  1571.        
  1572.        
  1573.        
  1574.        
  1575.        
  1576.        
  1577.        
  1578.        
  1579.        
  1580.        
  1581.        
  1582.        
  1583.        
  1584.        
  1585.        
  1586.        
  1587.        
  1588.        
  1589.        
  1590.        
  1591.        
  1592.        
  1593.        
  1594.        
  1595.        
  1596.        
  1597.         protected void ChangeTextContentMark(bool value)
  1598.         {
  1599.             Debug.Assert(inTextContent != value);
  1600.             inTextContent = value;
  1601.             if (lastMarkPos + 1 == textContentMarks.Length) {
  1602.                 GrowTextContentMarks();
  1603.             }
  1604.             textContentMarks[++lastMarkPos] = this.bufPos;
  1605.         }
  1606.        
  1607.         private void GrowTextContentMarks()
  1608.         {
  1609.             Debug.Assert(lastMarkPos + 1 == textContentMarks.Length);
  1610.             int[] newTextContentMarks = new int[textContentMarks.Length * 2];
  1611.             Array.Copy(textContentMarks, newTextContentMarks, textContentMarks.Length);
  1612.             textContentMarks = newTextContentMarks;
  1613.         }
  1614.        
  1615.        
  1616.         // Write NewLineChars to the specified buffer position and return an updated position.
  1617.         unsafe protected char* WriteNewLine(char* pDst)
  1618.         {
  1619.             fixed (char* pDstBegin = bufChars) {
  1620.                 bufPos = (int)(pDst - pDstBegin);
  1621.                 // Let RawText do the real work
  1622.                 RawText(newLineChars);
  1623.                 return pDstBegin + bufPos;
  1624.             }
  1625.         }
  1626.        
  1627.         // Following methods do not check whether pDst is beyond the bufSize because the buffer was allocated with a OVERFLOW to accomodate
  1628.         // for the writes of small constant-length string as below.
  1629.        
  1630.         // Entitize '<' as "&lt;". Return an updated pointer.
  1631.         unsafe protected static char* LtEntity(char* pDst)
  1632.         {
  1633.             pDst[0] = (char)'&';
  1634.             pDst[1] = (char)'l';
  1635.             pDst[2] = (char)'t';
  1636.             pDst[3] = (char)';';
  1637.             return pDst + 4;
  1638.         }
  1639.        
  1640.         // Entitize '>' as "&gt;". Return an updated pointer.
  1641.         unsafe protected static char* GtEntity(char* pDst)
  1642.         {
  1643.             pDst[0] = (char)'&';
  1644.             pDst[1] = (char)'g';
  1645.             pDst[2] = (char)'t';
  1646.             pDst[3] = (char)';';
  1647.             return pDst + 4;
  1648.         }
  1649.        
  1650.         // Entitize '&' as "&amp;". Return an updated pointer.
  1651.         unsafe protected static char* AmpEntity(char* pDst)
  1652.         {
  1653.             pDst[0] = (char)'&';
  1654.             pDst[1] = (char)'a';
  1655.             pDst[2] = (char)'m';
  1656.             pDst[3] = (char)'p';
  1657.             pDst[4] = (char)';';
  1658.             return pDst + 5;
  1659.         }
  1660.        
  1661.         // Entitize '"' as "&quot;". Return an updated pointer.
  1662.         unsafe protected static char* QuoteEntity(char* pDst)
  1663.         {
  1664.             pDst[0] = (char)'&';
  1665.             pDst[1] = (char)'q';
  1666.             pDst[2] = (char)'u';
  1667.             pDst[3] = (char)'o';
  1668.             pDst[4] = (char)'t';
  1669.             pDst[5] = (char)';';
  1670.             return pDst + 6;
  1671.         }
  1672.        
  1673.         // Entitize '\t' as "&#x9;". Return an updated pointer.
  1674.         unsafe protected static char* TabEntity(char* pDst)
  1675.         {
  1676.             pDst[0] = (char)'&';
  1677.             pDst[1] = (char)'#';
  1678.             pDst[2] = (char)'x';
  1679.             pDst[3] = (char)'9';
  1680.             pDst[4] = (char)';';
  1681.             return pDst + 5;
  1682.         }
  1683.        
  1684.         // Entitize 0xa as "&#xA;". Return an updated pointer.
  1685.         unsafe protected static char* LineFeedEntity(char* pDst)
  1686.         {
  1687.             pDst[0] = (char)'&';
  1688.             pDst[1] = (char)'#';
  1689.             pDst[2] = (char)'x';
  1690.             pDst[3] = (char)'A';
  1691.             pDst[4] = (char)';';
  1692.             return pDst + 5;
  1693.         }
  1694.        
  1695.         // Entitize 0xd as "&#xD;". Return an updated pointer.
  1696.         unsafe protected static char* CarriageReturnEntity(char* pDst)
  1697.         {
  1698.             pDst[0] = (char)'&';
  1699.             pDst[1] = (char)'#';
  1700.             pDst[2] = (char)'x';
  1701.             pDst[3] = (char)'D';
  1702.             pDst[4] = (char)';';
  1703.             return pDst + 5;
  1704.         }
  1705.        
  1706.         unsafe private static char* CharEntity(char* pDst, char ch)
  1707.         {
  1708.             string s = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo);
  1709.             pDst[0] = (char)'&';
  1710.             pDst[1] = (char)'#';
  1711.             pDst[2] = (char)'x';
  1712.             pDst += 3;
  1713.            
  1714.             fixed (char* pSrc = s) {
  1715.                 char* pS = pSrc;
  1716.                 while ((*pDst++ = (char)*pS++) != 0)
  1717.                     ;
  1718.             }
  1719.            
  1720.             pDst[-1] = (char)';';
  1721.             return pDst;
  1722.         }
  1723.        
  1724.         // Write "<![CDATA[" to the specified buffer. Return an updated pointer.
  1725.         unsafe protected static char* RawStartCData(char* pDst)
  1726.         {
  1727.             pDst[0] = (char)'<';
  1728.             pDst[1] = (char)'!';
  1729.             pDst[2] = (char)'[';
  1730.             pDst[3] = (char)'C';
  1731.             pDst[4] = (char)'D';
  1732.             pDst[5] = (char)'A';
  1733.             pDst[6] = (char)'T';
  1734.             pDst[7] = (char)'A';
  1735.             pDst[8] = (char)'[';
  1736.             return pDst + 9;
  1737.         }
  1738.        
  1739.         // Write "]]>" to the specified buffer. Return an updated pointer.
  1740.         unsafe protected static char* RawEndCData(char* pDst)
  1741.         {
  1742.             pDst[0] = (char)']';
  1743.             pDst[1] = (char)']';
  1744.             pDst[2] = (char)'>';
  1745.             return pDst + 3;
  1746.         }
  1747.        
  1748.         // This method tests whether a character is in a given range with just one test; start and end should be constants
  1749.         private static bool InRange(int ch, int start, int end)
  1750.         {
  1751.             return (uint)(ch - start) <= (uint)(end - start);
  1752.         }
  1753.        
  1754.         unsafe protected void ValidateContentChars(string chars, string propertyName, bool allowOnlyWhitespace)
  1755.         {
  1756.             if (allowOnlyWhitespace) {
  1757.                 if (!xmlCharType.IsOnlyWhitespace(chars)) {
  1758.                     throw new ArgumentException(Res.GetString(Res.Xml_IndentCharsNotWhitespace, propertyName));
  1759.                 }
  1760.             }
  1761.             else {
  1762.                 string error = null;
  1763.                 for (int i = 0; i < chars.Length; i++) {
  1764.                     if (!xmlCharType.IsTextChar(chars[i])) {
  1765.                         switch (chars[i]) {
  1766.                             case '\n':
  1767.                             case '\r':
  1768.                             case '\t':
  1769.                                 continue;
  1770.                             case '<':
  1771.                             case '&':
  1772.                             case ']':
  1773.                                 error = Res.GetString(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionStr(chars[i]));
  1774.                                 goto Error;
  1775.                                 break;
  1776.                             default:
  1777.                                 if ((int)chars[i] >= SurHighStart && (int)chars[i] <= SurHighEnd) {
  1778.                                     if (i + 1 < chars.Length) {
  1779.                                         if ((int)chars[i + 1] >= SurLowStart && (int)chars[i + 1] <= SurLowEnd) {
  1780.                                             i++;
  1781.                                             continue;
  1782.                                         }
  1783.                                     }
  1784.                                     error = Res.GetString(Res.Xml_InvalidSurrogateMissingLowChar);
  1785.                                     goto Error;
  1786.                                 }
  1787.                                 else if ((int)chars[i] >= SurLowStart && (int)chars[i] <= SurLowEnd) {
  1788.                                     error = Res.GetString(Res.Xml_InvalidSurrogateHighChar, ((uint)chars[i]).ToString("X", CultureInfo.InvariantCulture));
  1789.                                     goto Error;
  1790.                                 }
  1791.                                 continue;
  1792.                         }
  1793.                     }
  1794.                 }
  1795.                 return;
  1796.                 Error:
  1797.                
  1798.                 throw new ArgumentException(Res.GetString(Res.Xml_InvalidCharsInIndent, new string[] {propertyName, error}));
  1799.             }
  1800.         }
  1801.     }
  1802.    
  1803.     // Same as base text writer class except that elements, attributes, comments, and pi's are indented.
  1804.     internal class XmlEncodedRawTextWriterIndent : XmlEncodedRawTextWriter
  1805.     {
  1806.         //
  1807.         // Fields
  1808.         //
  1809.         protected int indentLevel;
  1810.         protected bool newLineOnAttributes;
  1811.         protected string indentChars;
  1812.        
  1813.         protected bool mixedContent;
  1814.         private BitStack mixedContentStack;
  1815.        
  1816.         //
  1817.         // Constructors
  1818.         //
  1819.        
  1820.        
  1821.         public XmlEncodedRawTextWriterIndent(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
  1822.         {
  1823.             Init(settings);
  1824.         }
  1825.        
  1826.        
  1827.         public XmlEncodedRawTextWriterIndent(Stream stream, Encoding encoding, XmlWriterSettings settings, bool closeOutput) : base(stream, encoding, settings, closeOutput)
  1828.         {
  1829.             Init(settings);
  1830.         }
  1831.        
  1832.         //
  1833.         // XmlWriter methods
  1834.         //
  1835.         // Returns settings the writer currently applies.
  1836.         public override XmlWriterSettings Settings {
  1837.             get {
  1838.                 XmlWriterSettings settings = base.Settings;
  1839.                
  1840.                 settings.ReadOnly = false;
  1841.                 settings.Indent = true;
  1842.                 settings.IndentChars = indentChars;
  1843.                 settings.NewLineOnAttributes = newLineOnAttributes;
  1844.                 settings.ReadOnly = true;
  1845.                
  1846.                 return settings;
  1847.             }
  1848.         }
  1849.        
  1850.         public override void WriteDocType(string name, string pubid, string sysid, string subset)
  1851.         {
  1852.             // Add indentation
  1853.             if (!mixedContent && base.textPos != base.bufPos) {
  1854.                 WriteIndent();
  1855.             }
  1856.             base.WriteDocType(name, pubid, sysid, subset);
  1857.         }
  1858.        
  1859.         public override void WriteStartElement(string prefix, string localName, string ns)
  1860.         {
  1861.             Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
  1862.            
  1863.             // Add indentation
  1864.             if (!mixedContent && base.textPos != base.bufPos) {
  1865.                 WriteIndent();
  1866.             }
  1867.             indentLevel++;
  1868.             mixedContentStack.PushBit(mixedContent);
  1869.            
  1870.             base.WriteStartElement(prefix, localName, ns);
  1871.         }
  1872.        
  1873.         internal override void StartElementContent()
  1874.         {
  1875.             mixedContent = mixedContentStack.PeekBit();
  1876.             base.StartElementContent();
  1877.         }
  1878.        
  1879.         internal override void WriteEndElement(string prefix, string localName, string ns)
  1880.         {
  1881.             // Add indentation
  1882.             indentLevel--;
  1883.             if (!mixedContent && base.contentPos != base.bufPos) {
  1884.                 // There was content, so try to indent
  1885.                 if (base.textPos != base.bufPos) {
  1886.                     WriteIndent();
  1887.                 }
  1888.             }
  1889.             mixedContent = mixedContentStack.PopBit();
  1890.            
  1891.             base.WriteEndElement(prefix, localName, ns);
  1892.         }
  1893.        
  1894.         internal override void WriteFullEndElement(string prefix, string localName, string ns)
  1895.         {
  1896.             // Add indentation
  1897.             indentLevel--;
  1898.             if (!mixedContent && base.contentPos != base.bufPos) {
  1899.                 // There was content, so try to indent
  1900.                 if (base.textPos != base.bufPos) {
  1901.                     WriteIndent();
  1902.                 }
  1903.             }
  1904.             mixedContent = mixedContentStack.PopBit();
  1905.            
  1906.             base.WriteFullEndElement(prefix, localName, ns);
  1907.         }
  1908.        
  1909.         // Same as base class, plus possible indentation.
  1910.         public override void WriteStartAttribute(string prefix, string localName, string ns)
  1911.         {
  1912.             // Add indentation
  1913.             if (newLineOnAttributes) {
  1914.                 WriteIndent();
  1915.             }
  1916.            
  1917.             base.WriteStartAttribute(prefix, localName, ns);
  1918.         }
  1919.        
  1920.         public override void WriteCData(string text)
  1921.         {
  1922.             mixedContent = true;
  1923.             base.WriteCData(text);
  1924.         }
  1925.        
  1926.         public override void WriteComment(string text)
  1927.         {
  1928.             if (!mixedContent && base.textPos != base.bufPos) {
  1929.                 WriteIndent();
  1930.             }
  1931.            
  1932.             base.WriteComment(text);
  1933.         }
  1934.        
  1935.         public override void WriteProcessingInstruction(string target, string text)
  1936.         {
  1937.             if (!mixedContent && base.textPos != base.bufPos) {
  1938.                 WriteIndent();
  1939.             }
  1940.            
  1941.             base.WriteProcessingInstruction(target, text);
  1942.         }
  1943.        
  1944.         public override void WriteEntityRef(string name)
  1945.         {
  1946.             mixedContent = true;
  1947.             base.WriteEntityRef(name);
  1948.         }
  1949.        
  1950.         public override void WriteCharEntity(char ch)
  1951.         {
  1952.             mixedContent = true;
  1953.             base.WriteCharEntity(ch);
  1954.         }
  1955.        
  1956.         public override void WriteSurrogateCharEntity(char lowChar, char highChar)
  1957.         {
  1958.             mixedContent = true;
  1959.             base.WriteSurrogateCharEntity(lowChar, highChar);
  1960.         }
  1961.        
  1962.         public override void WriteWhitespace(string ws)
  1963.         {
  1964.             mixedContent = true;
  1965.             base.WriteWhitespace(ws);
  1966.         }
  1967.        
  1968.         public override void WriteString(string text)
  1969.         {
  1970.             mixedContent = true;
  1971.             base.WriteString(text);
  1972.         }
  1973.        
  1974.         public override void WriteChars(char[] buffer, int index, int count)
  1975.         {
  1976.             mixedContent = true;
  1977.             base.WriteChars(buffer, index, count);
  1978.         }
  1979.        
  1980.         public override void WriteRaw(char[] buffer, int index, int count)
  1981.         {
  1982.             mixedContent = true;
  1983.             base.WriteRaw(buffer, index, count);
  1984.         }
  1985.        
  1986.         public override void WriteRaw(string data)
  1987.         {
  1988.             mixedContent = true;
  1989.             base.WriteRaw(data);
  1990.         }
  1991.        
  1992.         public override void WriteBase64(byte[] buffer, int index, int count)
  1993.         {
  1994.             mixedContent = true;
  1995.             base.WriteBase64(buffer, index, count);
  1996.         }
  1997.        
  1998.         //
  1999.         // Private methods
  2000.         //
  2001.         private void Init(XmlWriterSettings settings)
  2002.         {
  2003.             indentLevel = 0;
  2004.             indentChars = settings.IndentChars;
  2005.             newLineOnAttributes = settings.NewLineOnAttributes;
  2006.             mixedContentStack = new BitStack();
  2007.            
  2008.             // check indent characters that they are valid XML characters
  2009.             if (base.checkCharacters) {
  2010.                 if (newLineOnAttributes) {
  2011.                     base.ValidateContentChars(indentChars, "IndentChars", true);
  2012.                     base.ValidateContentChars(newLineChars, "NewLineChars", true);
  2013.                 }
  2014.                 else {
  2015.                     base.ValidateContentChars(indentChars, "IndentChars", false);
  2016.                     if (base.newLineHandling != NewLineHandling.Replace) {
  2017.                         base.ValidateContentChars(newLineChars, "NewLineChars", false);
  2018.                     }
  2019.                 }
  2020.             }
  2021.         }
  2022.        
  2023.         // Add indentation to output. Write newline and then repeat IndentChars for each indent level.
  2024.         private void WriteIndent()
  2025.         {
  2026.             RawText(base.newLineChars);
  2027.             for (int i = indentLevel; i > 0; i--) {
  2028.                 RawText(indentChars);
  2029.             }
  2030.         }
  2031.     }
  2032. }

Developer Fusion