<Compile Include="System\Xml\Bits.cs" />
<Compile Include="System\Xml\BitStack.cs" />
<Compile Include="System\Xml\ByteStack.cs" />
+ <Compile Include="System\Xml\Core\HtmlEncodedRawTextWriter.cs">
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ <DependentUpon>HtmlEncodedRawTextWriter.tt</DependentUpon>
+ </Compile>
+ <Compile Include="System\Xml\Core\HtmlUtf8RawTextWriter.cs">
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ <DependentUpon>HtmlUtf8RawTextWriter.tt</DependentUpon>
+ </Compile>
+ <Compile Include="System\Xml\Core\TextEncodedRawTextWriter.cs">
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ <DependentUpon>TextEncodedRawTextWriter.tt</DependentUpon>
+ </Compile>
+ <Compile Include="System\Xml\Core\TextUtf8RawTextWriter.cs">
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ <DependentUpon>TextUtf8RawTextWriter.tt</DependentUpon>
+ </Compile>
+ <None Include="System\Xml\Core\HtmlEncodedRawTextWriter.tt">
+ <Generator>TextTemplatingFileGenerator</Generator>
+ <LastGenOutput>HtmlEncodedRawTextWriter.cs</LastGenOutput>
+ </None>
+ <None Include="System\Xml\Core\HtmlRawTextWriterGenerator.ttinclude" />
+ <None Include="System\Xml\Core\HtmlUtf8RawTextWriter.tt">
+ <Generator>TextTemplatingFileGenerator</Generator>
+ <LastGenOutput>HtmlUtf8RawTextWriter.cs</LastGenOutput>
+ </None>
+ <None Include="System\Xml\Core\RawTextWriter.ttinclude" />
+ <None Include="System\Xml\Core\TextEncodedRawTextWriter.tt">
+ <Generator>TextTemplatingFileGenerator</Generator>
+ <LastGenOutput>TextEncodedRawTextWriter.cs</LastGenOutput>
+ </None>
+ <None Include="System\Xml\Core\TextRawTextWriterGenerator.ttinclude" />
+ <None Include="System\Xml\Core\TextUtf8RawTextWriter.tt">
+ <Generator>TextTemplatingFileGenerator</Generator>
+ <LastGenOutput>TextUtf8RawTextWriter.cs</LastGenOutput>
+ </None>
+ <None Include="System\Xml\Core\XmlRawTextWriterGeneratorAsync.ttinclude" />
+ <None Include="System\Xml\Core\XmlRawTextWriterGenerator.ttinclude" />
+ <None Include="System\Xml\Core\RawTextWriterEncoded.ttinclude" />
+ <Content Include="System\Xml\Core\XmlEncodedRawTextWriter.tt">
+ <LastGenOutput>XmlEncodedRawTextWriter.cs</LastGenOutput>
+ <Generator>TextTemplatingFileGenerator</Generator>
+ </Content>
+ <Compile Include="System\Xml\Core\XmlEncodedRawTextWriter.cs">
+ <DependentUpon>XmlEncodedRawTextWriter.tt</DependentUpon>
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ </Compile>
+ <Content Include="System\Xml\Core\XmlEncodedRawTextWriterAsync.tt">
+ <LastGenOutput>XmlEncodedRawTextWriterAsync.cs</LastGenOutput>
+ <Generator>TextTemplatingFileGenerator</Generator>
+ </Content>
+ <Compile Include="System\Xml\Core\XmlEncodedRawTextWriterAsync.cs">
+ <DependentUpon>XmlEncodedRawTextWriterAsync.tt</DependentUpon>
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ </Compile>
+ <None Include="System\Xml\Core\RawTextWriterUtf8.ttinclude" />
+ <Content Include="System\Xml\Core\XmlUtf8RawTextWriter.tt">
+ <LastGenOutput>XmlUtf8RawTextWriter.cs</LastGenOutput>
+ <Generator>TextTemplatingFileGenerator</Generator>
+ </Content>
+ <Compile Include="System\Xml\Core\XmlUtf8RawTextWriter.cs">
+ <DependentUpon>XmlUtf8RawTextWriter.tt</DependentUpon>
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ </Compile>
+ <Content Include="System\Xml\Core\XmlUtf8RawTextWriterAsync.tt">
+ <LastGenOutput>XmlUtf8RawTextWriterAsync.cs</LastGenOutput>
+ <Generator>TextTemplatingFileGenerator</Generator>
+ </Content>
+ <Compile Include="System\Xml\Core\XmlUtf8RawTextWriterAsync.cs">
+ <DependentUpon>XmlUtf8RawTextWriterAsync.tt</DependentUpon>
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ </Compile>
<Compile Include="System\Xml\DiagnosticsSwitches.cs" />
<Compile Include="System\Xml\Dom\XmlNamedNodeMap.SmallXmlNodeList.cs" />
<Compile Include="System\Xml\EmptyEnumerator.cs" />
<Compile Include="System\Xml\Core\ConformanceLevel.cs" />
<Compile Include="System\Xml\Core\DtdProcessing.cs" />
<Compile Include="System\Xml\Core\EntityHandling.cs" />
- <Compile Include="System\Xml\Core\HtmlEncodedRawTextWriter.cs" />
- <None Include="System\Xml\Core\HtmlRawTextWriterGenerator.cxx" />
<Compile Include="System\Xml\Core\HtmlTernaryTree.cs" />
- <Compile Include="System\Xml\Core\HtmlUtf8RawTextWriter.cs" />
<Compile Include="System\Xml\Core\IDtdInfo.cs" />
<Compile Include="System\Xml\Core\IDtdParser.cs" />
<Compile Include="System\Xml\Core\IDtdParserAsync.cs" />
<Compile Include="System\Xml\Core\ReadOnlyTernaryTree.cs" />
<Compile Include="System\Xml\Core\ReadState.cs" />
<Compile Include="System\Xml\Core\SecureStringHasher.cs" />
- <Compile Include="System\Xml\Core\TextEncodedRawTextWriter.cs" />
- <None Include="System\Xml\Core\TextRawTextWriterGenerator.cxx" />
- <Compile Include="System\Xml\Core\TextUtf8RawTextWriter.cs" />
<Compile Include="System\Xml\Core\ValidatingReaderNodeData.cs" />
<Compile Include="System\Xml\Core\ValidationType.cs" />
<Compile Include="System\Xml\Core\WhitespaceHandling.cs" />
<Compile Include="System\Xml\Core\XmlCharCheckingReaderAsync.cs" />
<Compile Include="System\Xml\Core\XmlCharCheckingWriter.cs" />
<Compile Include="System\Xml\Core\XmlCharCheckingWriterAsync.cs" />
- <Compile Include="System\Xml\Core\XmlEncodedRawTextWriter.cs" />
- <Compile Include="System\Xml\Core\XmlEncodedRawTextWriterAsync.cs" />
<Compile Include="System\Xml\Core\XmlEventCache.cs" />
<Compile Include="System\Xml\Core\XmlParserContext.cs" />
- <None Include="System\Xml\Core\XmlRawTextWriterGenerator.cxx" />
<Compile Include="System\Xml\Core\XmlRawWriter.cs" />
<Compile Include="System\Xml\Core\XmlRawWriterAsync.cs" />
<Compile Include="System\Xml\Core\XmlReader.cs" />
<Compile Include="System\Xml\Core\XmlTextReaderImplHelpers.cs" />
<Compile Include="System\Xml\Core\XmlTextReaderImplHelpersAsync.cs" />
<Compile Include="System\Xml\Core\XmlTextWriter.cs" />
- <Compile Include="System\Xml\Core\XmlUtf8RawTextWriter.cs" />
- <Compile Include="System\Xml\Core\XmlUtf8RawTextWriterAsync.cs" />
<Compile Include="System\Xml\Core\XmlValidatingReader.cs" />
<Compile Include="System\Xml\Core\XmlValidatingReaderImpl.cs" />
<Compile Include="System\Xml\Core\XmlValidatingReaderImplAsync.cs" />
+++ /dev/null
-@echo off
-
-pushd %_NTDRIVE%%_NTROOT%\ndp\fx\src\Xml\System\Xml\Core
-echo.
-echo Checking files out..
-echo.
-
-sd edit XmlUtf8RawTextWriter.cs
-sd edit XmlEncodedRawTextWriter.cs
-sd edit XmlUtf8RawTextWriter_SL.cs
-sd edit XmlEncodedRawTextWriter_SL.cs
-
-rem Make read-only in case user is offline and sd edit fails
-attrib -r XmlUtf8RawTextWriter.cs
-attrib -r XmlEncodedRawTextWriter.cs
-attrib -r XmlUtf8RawTextWriter_SL.cs
-attrib -r XmlEncodedRawTextWriter_SL.cs
-
-
-echo.
-echo Generating writers..
-echo.
-
-cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter.cs
-cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter.cs
-
-cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER /D SILVERLIGHT XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter_SL.cs
-cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER /D SILVERLIGHT XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter_SL.cs
-
-popd
\ No newline at end of file
+++ /dev/null
-@echo off
-
-pushd %_NTDRIVE%%_NTROOT%\ndp\fx\src\Xml\System\Xml\Core
-echo.
-echo Checking files out..
-echo.
-
-call tf edit XmlUtf8RawTextWriter.cs
-call tf edit XmlEncodedRawTextWriter.cs
-call tf edit XmlUtf8RawTextWriter_SL.cs
-call tf edit XmlEncodedRawTextWriter_SL.cs
-
-rem Make read-only in case user is offline and sd edit fails
-attrib -r XmlUtf8RawTextWriter.cs
-attrib -r XmlEncodedRawTextWriter.cs
-attrib -r XmlUtf8RawTextWriter_SL.cs
-attrib -r XmlEncodedRawTextWriter_SL.cs
-
-
-echo.
-echo Generating writers..
-echo.
-
-cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter.cs
-cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter.cs
-
-cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER /D SILVERLIGHT XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter_SL.cs
-cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER /D SILVERLIGHT XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter_SL.cs
-
-popd
\ No newline at end of file
+++ /dev/null
-@echo off
-
-pushd %_NTDRIVE%%_NTROOT%\ndp\fx\src\Xml\System\Xml\Core
-
-call GenerateCoreWriters.bat
-
-echo.
-echo Checking files out..
-echo.
-
-sd edit HtmlUtf8RawTextWriter.cs
-sd edit HtmlEncodedRawTextWriter.cs
-sd edit TextUtf8RawTextWriter.cs
-sd edit TextEncodedRawTextWriter.cs
-
-rem Make read-only in case user is offline and sd edit fails
-
-attrib -r HtmlUtf8RawTextWriter.cs
-attrib -r HtmlEncodedRawTextWriter.cs
-attrib -r TextUtf8RawTextWriter.cs
-attrib -r TextEncodedRawTextWriter.cs
-
-echo.
-echo Generating writers..
-echo.
-
-cl.exe /C /EP /D _HTML_UTF8_TEXT_WRITER HtmlRawTextWriterGenerator.cxx > HtmlUtf8RawTextWriter.cs
-cl.exe /C /EP /D _HTML_ENCODED_TEXT_WRITER HtmlRawTextWriterGenerator.cxx > HtmlEncodedRawTextWriter.cs
-cl.exe /C /EP /D _UTF8_TEXT_WRITER TextRawTextWriterGenerator.cxx > TextUtf8RawTextWriter.cs
-cl.exe /C /EP /D _ENCODED_TEXT_WRITER TextRawTextWriterGenerator.cxx > TextEncodedRawTextWriter.cs
-
-popd
+++ /dev/null
-@echo off
-
-pushd %_NTDRIVE%%_NTROOT%\ndp\fx\src\Xml\System\Xml\Core
-
-call GenerateCoreWriters.bat
-
-echo.
-echo Checking files out..
-echo.
-
-call tf edit HtmlUtf8RawTextWriter.cs
-call tf edit HtmlEncodedRawTextWriter.cs
-call tf edit TextUtf8RawTextWriter.cs
-call tf edit TextEncodedRawTextWriter.cs
-
-rem Make read-only in case user is offline and sd edit fails
-
-attrib -r HtmlUtf8RawTextWriter.cs
-attrib -r HtmlEncodedRawTextWriter.cs
-attrib -r TextUtf8RawTextWriter.cs
-attrib -r TextEncodedRawTextWriter.cs
-
-echo.
-echo Generating writers..
-echo.
-
-cl.exe /C /EP /D _HTML_UTF8_TEXT_WRITER HtmlRawTextWriterGenerator.cxx > HtmlUtf8RawTextWriter.cs
-cl.exe /C /EP /D _HTML_ENCODED_TEXT_WRITER HtmlRawTextWriterGenerator.cxx > HtmlEncodedRawTextWriter.cs
-cl.exe /C /EP /D _UTF8_TEXT_WRITER TextRawTextWriterGenerator.cxx > TextUtf8RawTextWriter.cs
-cl.exe /C /EP /D _ENCODED_TEXT_WRITER TextRawTextWriterGenerator.cxx > TextEncodedRawTextWriter.cs
-
-popd
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// Following comment might not be valid anymore as this code is fairly old and a lot happened since it was written...
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlUtf8TextWriter.cs
-// cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlEncodedTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify HtmlRawTextWriterGenerator.ttinclude
using System;
using System.IO;
Init(settings);
}
-
public HtmlEncodedRawTextWriter(Stream stream, XmlWriterSettings settings) : base(stream, settings)
{
Init(settings);
bufChars[bufPos++] = (char)']';
}
- bufChars[this.bufPos++] = (char)'>';
+ bufChars[bufPos++] = (char)'>';
}
// For the HTML element, it should call this method with ns and prefix as String.Empty
Debug.Assert(prefix.Length == 0);
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName);
base.bufChars[bufPos++] = (char)'<';
base.RawText(localName);
base.bufChars[base.bufPos++] = (char)'>';
// Detect whether content is output
- this.contentPos = this.bufPos;
+ contentPos = bufPos;
if ((currentElementProperties & ElementProperties.HEAD) != 0)
{
if (ns.Length == 0)
{
Debug.Assert(prefix.Length == 0);
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
if (base.attrEndPos == bufPos)
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
char ch = (char)0;
for (;;)
}
else if (pSrc[1] != '{')
{
- pDst = XmlEncodedRawTextWriter.AmpEntity(pDst);
+ pDst = AmpEntity(pDst);
break;
}
*pDst++ = (char)ch;
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
char ch = (char)0;
for (;;)
}
else if (pSrc[1] != '{')
{
- pDst = XmlEncodedRawTextWriter.AmpEntity(pDst);
+ pDst = AmpEntity(pDst);
break;
}
*pDst++ = (char)ch;
break;
default:
const string hexDigits = "0123456789ABCDEF";
+ Debug.Assert(_uriEscapingBuffer?.Length > 0);
fixed (byte* pUriEscapingBuffer = _uriEscapingBuffer)
{
byte* pByte = pUriEscapingBuffer;
}
}
-
//
// Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
//
// Constructors
//
-
public HtmlEncodedRawTextWriterIndent(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
{
Init(settings);
}
-
public HtmlEncodedRawTextWriterIndent(Stream stream, XmlWriterSettings settings) : base(stream, settings)
{
Init(settings);
}
}
-
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterEncoded.ttinclude" #>
+<#
+ ClassName = "HtmlEncodedRawTextWriter";
+ ClassNameIndent = "HtmlEncodedRawTextWriterIndent";
+ BaseClassName = "XmlEncodedRawTextWriter";
+#>
+<#@ include file="HtmlRawTextWriterGenerator.ttinclude" #>
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlUtf8TextWriter.cs
-// cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlEncodedTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-#ifdef _HTML_UTF8_TEXT_WRITER
-#define _CLASS_NAME HtmlUtf8RawTextWriter
-#define _BASE_CLASS_NAME XmlUtf8RawTextWriter
-#define _CLASS_NAME_INDENT HtmlUtf8RawTextWriterIndent
-#define _BUFFER bufBytes
-#define _BUFFER_TYPE byte
-#define _SET_TEXT_CONTENT_MARK(value)
-#endif
-
-#ifdef _HTML_ENCODED_TEXT_WRITER
-#define _CLASS_NAME HtmlEncodedRawTextWriter
-#define _BASE_CLASS_NAME XmlEncodedRawTextWriter
-#define _CLASS_NAME_INDENT HtmlEncodedRawTextWriterIndent
-#define _BUFFER bufChars
-#define _BUFFER_TYPE char
-#define _SET_TEXT_CONTENT_MARK(value) \
- if ( trackTextContent && inTextContent != value ) { \
- ChangeTextContentMark( value ); \
- }
-#endif
-
-#define XMLCHARTYPE_TEST(ch, flag) ( ( xmlCharType.charProperties[ch] & XmlCharType.##flag ) != 0 )
-#define XMLCHARTYPE_ISATTRIBUTEVALUECHAR(ch) XMLCHARTYPE_TEST(ch, fAttrValue)
-
-using System;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Schema;
-//using System.Xml.Query;
-using System.Diagnostics;
-using MS.Internal.Xml;
-
-namespace System.Xml {
-
- internal class _CLASS_NAME : _BASE_CLASS_NAME {
-//
-// Fields
-//
- protected ByteStack elementScope;
- protected ElementProperties currentElementProperties;
- private AttributeProperties currentAttributeProperties;
-
- private bool endsWithAmpersand;
- private byte [] uriEscapingBuffer;
-
- // settings
- private string mediaType;
- private bool doNotEscapeUriAttributes;
-
-//
-// Static fields
-//
- protected static TernaryTreeReadOnly elementPropertySearch;
- protected static TernaryTreeReadOnly attributePropertySearch;
-
-//
-// Constants
-//
- private const int StackIncrement = 10;
-
-//
-// Constructors
-//
-
-#ifdef _HTML_ENCODED_TEXT_WRITER
-
- public _CLASS_NAME( TextWriter writer, XmlWriterSettings settings ) : base( writer, settings ) {
- Init( settings );
- }
-#endif
-
- public _CLASS_NAME( Stream stream, XmlWriterSettings settings ) : base( stream, settings ) {
- Init( settings );
- }
-
-//
-// XmlRawWriter implementation
-//
- internal override void WriteXmlDeclaration( XmlStandalone standalone ) {
- // Ignore xml declaration
- }
-
- internal override void WriteXmlDeclaration( string xmldecl ) {
- // Ignore xml declaration
- }
-
- /// Html rules allow public ID without system ID and always output "html"
- public override void WriteDocType( string name, string pubid, string sysid, string subset ) {
- Debug.Assert( name != null && name.Length > 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- RawText( "<!DOCTYPE ");
-
- // Bug 114337: Always output "html" or "HTML" in doc-type, even if "name" is something else
- if ( name == "HTML" )
- RawText( "HTML" );
- else
- RawText( "html" );
-
- if ( pubid != null ) {
- RawText( " PUBLIC \"" );
- RawText( pubid );
- if ( sysid != null ) {
- RawText( "\" \"" );
- RawText( sysid );
- }
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- else if ( sysid != null ) {
- RawText( " SYSTEM \"" );
- RawText( sysid );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- else {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- }
-
- if ( subset != null ) {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '[';
- RawText( subset );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ']';
- }
-
- _BUFFER[this.bufPos++] = (_BUFFER_TYPE) '>';
- }
-
- // For the HTML element, it should call this method with ns and prefix as String.Empty
- public override void WriteStartElement( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length != 0 && prefix != null && ns != null );
-
- elementScope.Push( (byte)currentElementProperties );
-
- if ( ns.Length == 0 ) {
- Debug.Assert( prefix.Length == 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
- currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString( localName );
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- base.RawText( localName );
- base.attrEndPos = bufPos;
- }
- else {
- // Since the HAS_NS has no impact to the ElementTextBlock behavior,
- // we don't need to push it into the stack.
- currentElementProperties = ElementProperties.HAS_NS;
- base.WriteStartElement( prefix, localName, ns );
- }
- }
-
- // Output >. For HTML needs to output META info
- internal override void StartElementContent() {
- base._BUFFER[base.bufPos++] = (_BUFFER_TYPE) '>';
-
- // Detect whether content is output
- this.contentPos = this.bufPos;
-
- if ( ( currentElementProperties & ElementProperties.HEAD ) != 0 ) {
- WriteMetaElement();
- }
- }
-
- // end element with />
- // for HTML(ns.Length == 0)
- // not an empty tag <h1></h1>
- // empty tag <basefont>
- internal override void WriteEndElement( string prefix, string localName, string ns ) {
- if ( ns.Length == 0 ) {
- Debug.Assert( prefix.Length == 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( ( currentElementProperties & ElementProperties.EMPTY ) == 0 ) {
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '/';
- base.RawText( localName );
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '>';
- }
- }
- else {
- //xml content
- base.WriteEndElement( prefix, localName, ns );
- }
-
- currentElementProperties = (ElementProperties)elementScope.Pop();
- }
-
- internal override void WriteFullEndElement( string prefix, string localName, string ns ) {
- if ( ns.Length == 0 ) {
- Debug.Assert( prefix.Length == 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( ( currentElementProperties & ElementProperties.EMPTY ) == 0 ) {
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '/';
- base.RawText( localName );
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '>';
- }
- }
- else {
- //xml content
- base.WriteFullEndElement( prefix, localName, ns );
- }
-
- currentElementProperties = (ElementProperties)elementScope.Pop();
- }
-
- // 1. How the outputBooleanAttribute(fBOOL) and outputHtmlUriText(fURI) being set?
- // When SA is called.
- //
- // BOOL_PARENT URI_PARENT Others
- // fURI
- // URI att false true false
- //
- // fBOOL
- // BOOL att true false false
- //
- // How they change the attribute output behaviors?
- //
- // 1) fURI=true fURI=false
- // SA a=" a="
- // AT HtmlURIText HtmlText
- // EA " "
- //
- // 2) fBOOL=true fBOOL=false
- // SA a a="
- // AT HtmlText output nothing
- // EA output nothing "
- //
- // When they get reset?
- // At the end of attribute.
-
- // 2. How the outputXmlTextElementScoped(fENs) and outputXmlTextattributeScoped(fANs) are set?
- // fANs is in the scope of the fENs.
- //
- // SE(localName) SE(ns, pre, localName) SA(localName) SA(ns, pre, localName)
- // fENs false(default) true(action)
- // fANs false(default) false(default) false(default) true(action)
-
- // how they get reset?
- //
- // EE(localName) EE(ns, pre, localName) EENC(ns, pre, localName) EA(localName) EA(ns, pre, localName)
- // fENs false(action)
- // fANs false(action)
-
- // How they change the TextOutput?
- //
- // fENs | fANs Else
- // AT XmlText HtmlText
- //
- //
- // 3. Flags for processing &{ split situations
- //
- // When the flag is set?
- //
- // AT src[lastchar]='&' flag&{ = true;
- //
- // when it get result?
- //
- // AT method.
- //
- // How it changes the behaviors?
- //
- // flag&{=true
- //
- // AT if (src[0] == '{') {
- // output "&{"
- // }
- // else {
- // output &
- // }
- //
- // EA output amp;
- //
-
- // SA if (flagBOOL == false) { output =";}
- //
- // AT if (flagBOOL) { return};
- // if (flagNS) {XmlText;} {
- // }
- // else if (flagURI) {
- // HtmlURIText;
- // }
- // else {
- // HtmlText;
- // }
- //
-
- // AT if (flagNS) {XmlText;} {
- // }
- // else if (flagURI) {
- // HtmlURIText;
- // }
- // else if (!flagBOOL) {
- // HtmlText; //flag&{ handling
- // }
- //
- //
- // EA if (flagBOOL == false) { output "
- // }
- // else if (flag&{) {
- // output amp;
- // }
- //
- public override void WriteStartAttribute( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length != 0 && prefix != null && ns != null );
-
- if ( ns.Length == 0 ) {
- Debug.Assert( prefix.Length == 0 );
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( base.attrEndPos == bufPos ) {
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- }
- base.RawText( localName );
-
- if ( ( currentElementProperties & ( ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT ) ) != 0 ) {
- currentAttributeProperties = (AttributeProperties)attributePropertySearch.FindCaseInsensitiveString( localName ) &
- (AttributeProperties)currentElementProperties;
-
- if ( ( currentAttributeProperties & AttributeProperties.BOOLEAN ) != 0 ) {
- base.inAttributeValue = true;
- return;
- }
- }
- else {
- currentAttributeProperties = AttributeProperties.DEFAULT;
- }
-
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) '=';
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- else {
- base.WriteStartAttribute( prefix, localName, ns );
- currentAttributeProperties = AttributeProperties.DEFAULT;
- }
-
- base.inAttributeValue = true;
- }
-
- // Output the amp; at end of EndAttribute
- public override void WriteEndAttribute() {
-
- if ( ( currentAttributeProperties & AttributeProperties.BOOLEAN ) != 0 ) {
- base.attrEndPos = bufPos;
- }
- else {
- if ( endsWithAmpersand ) {
- OutputRestAmps();
- endsWithAmpersand = false;
- }
-
- _SET_TEXT_CONTENT_MARK(false)
-
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- base.inAttributeValue = false;
- base.attrEndPos = bufPos;
- }
-
- // HTML PI's use ">" to terminate rather than "?>".
- public override void WriteProcessingInstruction( string target, string text ) {
- Debug.Assert( target != null && target.Length != 0 && text != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) '?';
- base.RawText( target );
- _BUFFER[base.bufPos++] = (_BUFFER_TYPE) ' ';
-
- base.WriteCommentOrPi( text, '?' );
-
- base._BUFFER[base.bufPos++] = (_BUFFER_TYPE) '>';
-
- if ( base.bufPos > base.bufLen ) {
- FlushBuffer();
- }
- }
-
- // Serialize either attribute or element text using HTML rules.
- public override unsafe void WriteString( string text ) {
- Debug.Assert( text != null );
-
- _SET_TEXT_CONTENT_MARK(true)
-
- fixed ( char * pSrc = text ) {
- char * pSrcEnd = pSrc + text.Length;
- if ( base.inAttributeValue) {
- WriteHtmlAttributeTextBlock( pSrc, pSrcEnd );
- }
- else {
- WriteHtmlElementTextBlock( pSrc, pSrcEnd );
- }
- }
- }
-
- public override void WriteEntityRef( string name ) {
- throw new InvalidOperationException( string.Format( SR.Xml_InvalidOperation ) );
- }
-
- public override void WriteCharEntity( char ch ) {
- throw new InvalidOperationException( string.Format( SR.Xml_InvalidOperation ) );
- }
-
- public override void WriteSurrogateCharEntity( char lowChar, char highChar ) {
- throw new InvalidOperationException( string.Format( SR.Xml_InvalidOperation ) );
- }
-
- public override unsafe void WriteChars( char[] buffer, int index, int count ) {
- Debug.Assert( buffer != null );
- Debug.Assert( index >= 0 );
- Debug.Assert( count >= 0 && index + count <= buffer.Length );
-
- _SET_TEXT_CONTENT_MARK(true)
-
- fixed ( char * pSrcBegin = &buffer[index] ) {
- if ( inAttributeValue ) {
- WriteAttributeTextBlock( pSrcBegin, pSrcBegin + count );
- }
- else {
- WriteElementTextBlock( pSrcBegin, pSrcBegin + count );
- }
- }
- }
-
-//
-// Private methods
-//
-
- private void Init( XmlWriterSettings settings ) {
- Debug.Assert( (int)ElementProperties.URI_PARENT == (int)AttributeProperties.URI );
- Debug.Assert( (int)ElementProperties.BOOL_PARENT == (int)AttributeProperties.BOOLEAN );
- Debug.Assert( (int)ElementProperties.NAME_PARENT == (int)AttributeProperties.NAME );
-
- if ( elementPropertySearch == null ) {
- //elementPropertySearch should be init last for the mutli thread safe situation.
- attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes );
- elementPropertySearch = new TernaryTreeReadOnly( HtmlTernaryTree.htmlElements );
- }
-
- elementScope = new ByteStack( StackIncrement );
- uriEscapingBuffer = new byte[5];
- currentElementProperties = ElementProperties.DEFAULT;
-
- mediaType = settings.MediaType;
- doNotEscapeUriAttributes = settings.DoNotEscapeUriAttributes;
- }
-
- protected void WriteMetaElement() {
- base.RawText("<META http-equiv=\"Content-Type\"");
-
- if ( mediaType == null ) {
- mediaType = "text/html";
- }
-
- base.RawText( " content=\"" );
- base.RawText( mediaType );
- base.RawText( "; charset=" );
- base.RawText( base.encoding.WebName );
- base.RawText( "\">" );
- }
-
- // Justify the stack usage:
- //
- // Nested elements has following possible position combinations
- // 1. <E1>Content1<E2>Content2</E2></E1>
- // 2. <E1><E2>Content2</E2>Content1</E1>
- // 3. <E1>Content<E2>Cotent2</E2>Content1</E1>
- //
- // In the situation 2 and 3, the stored currentElementProrperties will be E2's,
- // only the top of the stack is the real E1 element properties.
- protected unsafe void WriteHtmlElementTextBlock( char * pSrc, char * pSrcEnd ) {
- if ( ( currentElementProperties & ElementProperties.NO_ENTITIES ) != 0 ) {
- base.RawText( pSrc, pSrcEnd );
- } else {
- base.WriteElementTextBlock( pSrc, pSrcEnd );
- }
-
- }
-
- protected unsafe void WriteHtmlAttributeTextBlock( char * pSrc, char * pSrcEnd ) {
- if ( ( currentAttributeProperties & ( AttributeProperties.BOOLEAN | AttributeProperties.URI | AttributeProperties.NAME ) ) != 0 ) {
- if ( ( currentAttributeProperties & AttributeProperties.BOOLEAN ) != 0 ) {
- //if output boolean attribute, ignore this call.
- return;
- }
-
- if ( ( currentAttributeProperties & ( AttributeProperties.URI | AttributeProperties.NAME ) ) != 0 && !doNotEscapeUriAttributes ) {
- WriteUriAttributeText( pSrc, pSrcEnd );
- }
- else {
- WriteHtmlAttributeText( pSrc, pSrcEnd );
- }
- }
- else if ( ( currentElementProperties & ElementProperties.HAS_NS ) != 0 ) {
- base.WriteAttributeTextBlock( pSrc, pSrcEnd );
- }
- else {
- WriteHtmlAttributeText( pSrc, pSrcEnd );
- }
- }
-
- //
- // &{ split cases
- // 1). HtmlAttributeText("a&");
- // HtmlAttributeText("{b}");
- //
- // 2). HtmlAttributeText("a&");
- // EndAttribute();
-
- // 3).split with Flush by the user
- // HtmlAttributeText("a&");
- // FlushBuffer();
- // HtmlAttributeText("{b}");
-
- //
- // Solutions:
- // case 1)hold the & output as &
- // if the next income character is {, output {
- // else output amp;
- //
-
- private unsafe void WriteHtmlAttributeText( char * pSrc, char *pSrcEnd ) {
- if ( endsWithAmpersand ) {
- if ( pSrcEnd - pSrc > 0 && pSrc[0] != '{' ) {
- OutputRestAmps();
- }
- endsWithAmpersand = false;
- }
-
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- _BUFFER_TYPE * pDst = pDstBegin + this.bufPos;
-
- char ch = (char)0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#if _HTML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) ) ) {
-#endif
- *pDst++ = (_BUFFER_TYPE)ch;
- pSrc++;
- }
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // some character needs to be escaped
- switch ( ch ) {
- case '&':
- if ( pSrc + 1 == pSrcEnd ) {
- endsWithAmpersand = true;
- }
- else if ( pSrc[1] != '{' ) {
- pDst = _BASE_CLASS_NAME.AmpEntity(pDst);
- break;
- }
- *pDst++ = (_BUFFER_TYPE)ch;
- break;
- case '"':
- pDst = QuoteEntity( pDst );
- break;
- case '<':
- case '>':
- case '\'':
- case (char)0x9:
- *pDst++ = (_BUFFER_TYPE)ch;
- break;
- case (char)0xD:
- // do not normalize new lines in attributes - just escape them
- pDst = CarriageReturnEntity( pDst );
- break;
- case (char)0xA:
- // do not normalize new lines in attributes - just escape them
- pDst = LineFeedEntity( pDst );
- break;
- default:
- EncodeChar( ref pSrc, pSrcEnd, ref pDst);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- private unsafe void WriteUriAttributeText( char * pSrc, char * pSrcEnd ) {
- if ( endsWithAmpersand ) {
- if ( pSrcEnd - pSrc > 0 && pSrc[0] != '{' ) {
- OutputRestAmps();
- }
- this.endsWithAmpersand = false;
- }
-
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- _BUFFER_TYPE * pDst = pDstBegin + this.bufPos;
-
- char ch = (char)0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch < 0x80 ) ) {
- *pDst++ = (_BUFFER_TYPE)ch;
- pSrc++;
- }
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // some character needs to be escaped
- switch ( ch ) {
- case '&':
- if ( pSrc + 1 == pSrcEnd ) {
- endsWithAmpersand = true;
- }
- else if ( pSrc[1] != '{' ) {
- pDst = _BASE_CLASS_NAME.AmpEntity(pDst);
- break;
- }
- *pDst++ = (_BUFFER_TYPE)ch;
- break;
- case '"':
- pDst = QuoteEntity( pDst );
- break;
- case '<':
- case '>':
- case '\'':
- case (char)0x9:
- *pDst++ = (_BUFFER_TYPE)ch;
- break;
- case (char)0xD:
- // do not normalize new lines in attributes - just escape them
- pDst = CarriageReturnEntity( pDst );
- break;
- case (char)0xA:
- // do not normalize new lines in attributes - just escape them
- pDst = LineFeedEntity( pDst );
- break;
- default:
- const string hexDigits = "0123456789ABCDEF";
- fixed ( byte * pUriEscapingBuffer = uriEscapingBuffer ) {
- byte * pByte = pUriEscapingBuffer;
- byte * pEnd = pByte;
-
- XmlUtf8RawTextWriter.CharToUTF8( ref pSrc, pSrcEnd, ref pEnd );
-
- while ( pByte < pEnd ) {
- *pDst++ = (_BUFFER_TYPE) '%';
- *pDst++ = (_BUFFER_TYPE) hexDigits[*pByte >> 4];
- *pDst++ = (_BUFFER_TYPE) hexDigits[*pByte & 0xF];
- pByte++;
- }
- }
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- // For handling &{ in Html text field. If & is not followed by {, it still needs to be escaped.
- private void OutputRestAmps() {
- base._BUFFER[bufPos++] = (_BUFFER_TYPE)'a';
- base._BUFFER[bufPos++] = (_BUFFER_TYPE)'m';
- base._BUFFER[bufPos++] = (_BUFFER_TYPE)'p';
- base._BUFFER[bufPos++] = (_BUFFER_TYPE)';';
- }
- }
-
-
- //
- // Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
- //
- // Here are all the cases:
- // ELEMENT1 actions ELEMENT2 actions SC EE
- // 1). SE SC store SE blockPro SE a). check ELEMENT1 blockPro <A> </A>
- // EE if SE, EE are blocks b). true: check ELEMENT2 blockPro <B> <B>
- // c). detect ELEMENT is SE, SC
- // d). increase the indexlevel
- //
- // 2). SE SC, Store EE blockPro EE a). check stored blockPro <A></A> </A>
- // EE if SE, EE are blocks b). true: indexLevel same </B>
- //
-
-
- //
- // This is an alternative way to make the output looks better
- //
- // Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
- //
- // Here are all the cases:
- // ELEMENT1 actions ELEMENT2 actions Samples
- // 1). SE SC store SE blockPro SE a). check ELEMENT1 blockPro <A>(blockPos)
- // b). true: check ELEMENT2 blockPro <B>
- // c). detect ELEMENT is SE, SC
- // d). increase the indentLevel
- //
- // 2). EE Store EE blockPro SE a). check stored blockPro </A>
- // b). true: indentLevel same <B>
- // c). output block2
- //
- // 3). EE same as above EE a). check stored blockPro </A>
- // b). true: --indentLevel </B>
- // c). output block2
- //
- // 4). SE SC same as above EE a). check stored blockPro <A></A>
- // b). true: indentLevel no change
- internal class _CLASS_NAME_INDENT : _CLASS_NAME {
-//
-// Fields
-//
- int indentLevel;
-
- // for detecting SE SC situation
- int endBlockPos;
-
- // settings
- string indentChars;
- bool newLineOnAttributes;
-
-//
-// Constructors
-//
-#ifdef _HTML_ENCODED_TEXT_WRITER
-
- public _CLASS_NAME_INDENT( TextWriter writer, XmlWriterSettings settings ) : base( writer, settings ) {
- Init( settings );
- }
-#endif
-
- public _CLASS_NAME_INDENT( Stream stream, XmlWriterSettings settings ) : base( stream, settings ) {
- Init( settings );
- }
-
-//
-// XmlRawWriter overrides
-//
- /// <summary>
- /// Serialize the document type declaration.
- /// </summary>
- public override void WriteDocType( string name, string pubid, string sysid, string subset ) {
- base.WriteDocType( name, pubid, sysid, subset );
-
- // Allow indentation after DocTypeDecl
- endBlockPos = base.bufPos;
- }
-
- public override void WriteStartElement(string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length != 0 && prefix != null && ns != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- base.elementScope.Push( (byte)base.currentElementProperties );
-
- if ( ns.Length == 0 ) {
- Debug.Assert( prefix.Length == 0 );
-
- base.currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString( localName );
-
- if ( endBlockPos == base.bufPos && ( base.currentElementProperties & ElementProperties.BLOCK_WS ) != 0 ) {
- WriteIndent();
- }
- indentLevel++;
-
- base._BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- }
- else {
- base.currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS;
-
- if ( endBlockPos == base.bufPos ) {
- WriteIndent();
- }
- indentLevel++;
-
- base._BUFFER[base.bufPos++] = (_BUFFER_TYPE) '<';
- if ( prefix.Length != 0 ) {
- base.RawText( prefix );
- base._BUFFER[base.bufPos++] = (_BUFFER_TYPE) ':';
- }
- }
- base.RawText( localName );
- base.attrEndPos = bufPos;
- }
-
- internal override void StartElementContent() {
- base._BUFFER[base.bufPos++] = (_BUFFER_TYPE) '>';
-
- // Detect whether content is output
- base.contentPos = base.bufPos;
-
- if ( ( currentElementProperties & ElementProperties.HEAD ) != 0) {
- WriteIndent();
- WriteMetaElement();
- endBlockPos = base.bufPos;
- }
- else if ( ( base.currentElementProperties & ElementProperties.BLOCK_WS ) != 0 ) {
- // store the element block position
- endBlockPos = base.bufPos;
- }
- }
-
- internal override void WriteEndElement( string prefix, string localName, string ns ) {
- bool isBlockWs;
- Debug.Assert( localName != null && localName.Length != 0 && prefix != null && ns != null );
-
- indentLevel--;
-
- // If this element has block whitespace properties,
- isBlockWs = ( base.currentElementProperties & ElementProperties.BLOCK_WS ) != 0;
- if ( isBlockWs ) {
- // And if the last node to be output had block whitespace properties,
- // And if content was output within this element,
- if ( endBlockPos == base.bufPos && base.contentPos != base.bufPos ) {
- // Then indent
- WriteIndent();
- }
- }
-
- base.WriteEndElement(prefix, localName, ns);
-
- // Reset contentPos in case of empty elements
- base.contentPos = 0;
-
- // Mark end of element in buffer for element's with block whitespace properties
- if ( isBlockWs ) {
- endBlockPos = base.bufPos;
- }
- }
-
- public override void WriteStartAttribute( string prefix, string localName, string ns ) {
- if ( newLineOnAttributes ) {
- RawText( base.newLineChars );
- indentLevel++;
- WriteIndent();
- indentLevel--;
- }
- base.WriteStartAttribute( prefix, localName, ns );
- }
-
- protected override void FlushBuffer() {
- // Make sure the buffer will reset the block position
- endBlockPos = ( endBlockPos == base.bufPos ) ? 1 : 0;
- base.FlushBuffer();
- }
-
-//
-// Private methods
-//
- private void Init( XmlWriterSettings settings ) {
- indentLevel = 0;
- indentChars = settings.IndentChars;
- newLineOnAttributes = settings.NewLineOnAttributes;
- }
-
- private void WriteIndent() {
- // <block><inline> -- suppress ws betw <block> and <inline>
- // <block><block> -- don't suppress ws betw <block> and <block>
- // <block>text -- suppress ws betw <block> and text (handled by wcharText method)
- // <block><?PI?> -- suppress ws betw <block> and PI
- // <block><!-- --> -- suppress ws betw <block> and comment
-
- // <inline><block> -- suppress ws betw <inline> and <block>
- // <inline><inline> -- suppress ws betw <inline> and <inline>
- // <inline>text -- suppress ws betw <inline> and text (handled by wcharText method)
- // <inline><?PI?> -- suppress ws betw <inline> and PI
- // <inline><!-- --> -- suppress ws betw <inline> and comment
-
- RawText( base.newLineChars );
- for ( int i = indentLevel; i > 0; i-- ) {
- RawText( indentChars );
- }
- }
- }
-}
-
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriter.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify HtmlRawTextWriterGenerator.ttinclude
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using System.Diagnostics;
+using MS.Internal.Xml;
+
+namespace System.Xml
+{
+ internal class <#= ClassName #> : <#= BaseClassName #>
+ {
+ protected ByteStack elementScope;
+ protected ElementProperties currentElementProperties;
+ private AttributeProperties _currentAttributeProperties;
+
+ private bool _endsWithAmpersand;
+ private byte[] _uriEscapingBuffer;
+
+ private string _mediaType;
+ private bool _doNotEscapeUriAttributes;
+
+ protected static TernaryTreeReadOnly elementPropertySearch;
+ protected static TernaryTreeReadOnly attributePropertySearch;
+
+ private const int StackIncrement = 10;
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+
+ public <#= ClassName #>(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
+ {
+ Init(settings);
+ }
+<# } #>
+
+ public <#= ClassName #>(Stream stream, XmlWriterSettings settings) : base(stream, settings)
+ {
+ Init(settings);
+ }
+
+ internal override void WriteXmlDeclaration(XmlStandalone standalone)
+ {
+ // Ignore xml declaration
+ }
+
+ internal override void WriteXmlDeclaration(string xmldecl)
+ {
+ // Ignore xml declaration
+ }
+
+ /// Html rules allow public ID without system ID and always output "html"
+ public override void WriteDocType(string name, string pubid, string sysid, string subset)
+ {
+ Debug.Assert(name != null && name.Length > 0);<#
+/* Code block is to squash extra line. */
+#><#= SetTextContentMark(3, false) #>
+
+ RawText("<!DOCTYPE ");
+
+ // Bug: Always output "html" or "HTML" in doc-type, even if "name" is something else
+ if (name == "HTML")
+ RawText("HTML");
+ else
+ RawText("html");
+
+ if (pubid != null)
+ {
+ RawText(" PUBLIC \"");
+ RawText(pubid);
+ if (sysid != null)
+ {
+ RawText("\" \"");
+ RawText(sysid);
+ }
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else if (sysid != null)
+ {
+ RawText(" SYSTEM \"");
+ RawText(sysid);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+
+ if (subset != null)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ RawText(subset);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ }
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // For the HTML element, it should call this method with ns and prefix as String.Empty
+ public override void WriteStartElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
+
+ elementScope.Push((byte)currentElementProperties);
+
+ if (ns.Length == 0)
+ {
+ Debug.Assert(prefix.Length == 0);<#
+
+#><#= SetTextContentMark(4, false) #>
+
+ currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName);
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ base.RawText(localName);
+ base.attrEndPos = bufPos;
+ }
+ else
+ {
+ // Since the HAS_NS has no impact to the ElementTextBlock behavior,
+ // we don't need to push it into the stack.
+ currentElementProperties = ElementProperties.HAS_NS;
+ base.WriteStartElement(prefix, localName, ns);
+ }
+ }
+
+ // Output >. For HTML needs to output META info
+ internal override void StartElementContent()
+ {
+ base.<#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'>';
+
+ // Detect whether content is output
+ contentPos = bufPos;
+
+ if ((currentElementProperties & ElementProperties.HEAD) != 0)
+ {
+ WriteMetaElement();
+ }
+ }
+
+ // end element with />
+ // for HTML(ns.Length == 0)
+ // not an empty tag <h1></h1>
+ // empty tag <basefont>
+ internal override void WriteEndElement(string prefix, string localName, string ns)
+ {
+ if (ns.Length == 0)
+ {
+ Debug.Assert(prefix.Length == 0);<#
+
+#><#= SetTextContentMark(4, false) #>
+
+ if ((currentElementProperties & ElementProperties.EMPTY) == 0)
+ {
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'/';
+ base.RawText(localName);
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'>';
+ }
+ }
+ else
+ {
+ //xml content
+ base.WriteEndElement(prefix, localName, ns);
+ }
+
+ currentElementProperties = (ElementProperties)elementScope.Pop();
+ }
+
+ internal override void WriteFullEndElement(string prefix, string localName, string ns)
+ {
+ if (ns.Length == 0)
+ {
+ Debug.Assert(prefix.Length == 0);<#
+
+#><#= SetTextContentMark(4, false) #>
+
+ if ((currentElementProperties & ElementProperties.EMPTY) == 0)
+ {
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'/';
+ base.RawText(localName);
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'>';
+ }
+ }
+ else
+ {
+ //xml content
+ base.WriteFullEndElement(prefix, localName, ns);
+ }
+
+ currentElementProperties = (ElementProperties)elementScope.Pop();
+ }
+
+ // 1. How the outputBooleanAttribute(fBOOL) and outputHtmlUriText(fURI) being set?
+ // When SA is called.
+ //
+ // BOOL_PARENT URI_PARENT Others
+ // fURI
+ // URI att false true false
+ //
+ // fBOOL
+ // BOOL att true false false
+ //
+ // How they change the attribute output behaviors?
+ //
+ // 1) fURI=true fURI=false
+ // SA a=" a="
+ // AT HtmlURIText HtmlText
+ // EA " "
+ //
+ // 2) fBOOL=true fBOOL=false
+ // SA a a="
+ // AT HtmlText output nothing
+ // EA output nothing "
+ //
+ // When they get reset?
+ // At the end of attribute.
+
+ // 2. How the outputXmlTextElementScoped(fENs) and outputXmlTextattributeScoped(fANs) are set?
+ // fANs is in the scope of the fENs.
+ //
+ // SE(localName) SE(ns, pre, localName) SA(localName) SA(ns, pre, localName)
+ // fENs false(default) true(action)
+ // fANs false(default) false(default) false(default) true(action)
+
+ // how they get reset?
+ //
+ // EE(localName) EE(ns, pre, localName) EENC(ns, pre, localName) EA(localName) EA(ns, pre, localName)
+ // fENs false(action)
+ // fANs false(action)
+
+ // How they change the TextOutput?
+ //
+ // fENs | fANs Else
+ // AT XmlText HtmlText
+ //
+ //
+ // 3. Flags for processing &{ split situations
+ //
+ // When the flag is set?
+ //
+ // AT src[lastchar]='&' flag&{ = true;
+ //
+ // when it get result?
+ //
+ // AT method.
+ //
+ // How it changes the behaviors?
+ //
+ // flag&{=true
+ //
+ // AT if (src[0] == '{') {
+ // output "&{"
+ // }
+ // else {
+ // output &
+ // }
+ //
+ // EA output amp;
+ //
+
+ // SA if (flagBOOL == false) { output =";}
+ //
+ // AT if (flagBOOL) { return};
+ // if (flagNS) {XmlText;} {
+ // }
+ // else if (flagURI) {
+ // HtmlURIText;
+ // }
+ // else {
+ // HtmlText;
+ // }
+ //
+
+ // AT if (flagNS) {XmlText;} {
+ // }
+ // else if (flagURI) {
+ // HtmlURIText;
+ // }
+ // else if (!flagBOOL) {
+ // HtmlText; //flag&{ handling
+ // }
+ //
+ //
+ // EA if (flagBOOL == false) { output "
+ // }
+ // else if (flag&{) {
+ // output amp;
+ // }
+ //
+ public override void WriteStartAttribute(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
+
+ if (ns.Length == 0)
+ {
+ Debug.Assert(prefix.Length == 0);<#
+
+#><#= SetTextContentMark(4, false) #>
+
+ if (base.attrEndPos == bufPos)
+ {
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+ base.RawText(localName);
+
+ if ((currentElementProperties & (ElementProperties.BOOL_PARENT | ElementProperties.URI_PARENT | ElementProperties.NAME_PARENT)) != 0)
+ {
+ _currentAttributeProperties = (AttributeProperties)attributePropertySearch.FindCaseInsensitiveString(localName) &
+ (AttributeProperties)currentElementProperties;
+
+ if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0)
+ {
+ base.inAttributeValue = true;
+ return;
+ }
+ }
+ else
+ {
+ _currentAttributeProperties = AttributeProperties.DEFAULT;
+ }
+
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'=';
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else
+ {
+ base.WriteStartAttribute(prefix, localName, ns);
+ _currentAttributeProperties = AttributeProperties.DEFAULT;
+ }
+
+ base.inAttributeValue = true;
+ }
+
+ // Output the amp; at end of EndAttribute
+ public override void WriteEndAttribute()
+ {
+ if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0)
+ {
+ base.attrEndPos = bufPos;
+ }
+ else
+ {
+ if (_endsWithAmpersand)
+ {
+ OutputRestAmps();
+ _endsWithAmpersand = false;
+ }<#
+
+#><#= SetTextContentMark(4, false) #>
+
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ base.inAttributeValue = false;
+ base.attrEndPos = bufPos;
+ }
+
+ // HTML PI's use ">" to terminate rather than "?>".
+ public override void WriteProcessingInstruction(string target, string text)
+ {
+ Debug.Assert(target != null && target.Length != 0 && text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'?';
+ base.RawText(target);
+ <#= BufferName #>[base.bufPos++] = (<#= BufferType #>)' ';
+
+ base.WriteCommentOrPi(text, '?');
+
+ base.<#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'>';
+
+ if (base.bufPos > base.bufLen)
+ {
+ FlushBuffer();
+ }
+ }
+
+ // Serialize either attribute or element text using HTML rules.
+ public override unsafe void WriteString(string text)
+ {
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, true) #>
+
+ fixed (char* pSrc = text)
+ {
+ char* pSrcEnd = pSrc + text.Length;
+ if (base.inAttributeValue)
+ {
+ WriteHtmlAttributeTextBlock(pSrc, pSrcEnd);
+ }
+ else
+ {
+ WriteHtmlElementTextBlock(pSrc, pSrcEnd);
+ }
+ }
+ }
+
+ public override void WriteEntityRef(string name)
+ {
+ throw new InvalidOperationException(SR.Xml_InvalidOperation);
+ }
+
+ public override void WriteCharEntity(char ch)
+ {
+ throw new InvalidOperationException(SR.Xml_InvalidOperation);
+ }
+
+ public override void WriteSurrogateCharEntity(char lowChar, char highChar)
+ {
+ throw new InvalidOperationException(SR.Xml_InvalidOperation);
+ }
+
+ public override unsafe void WriteChars(char[] buffer, int index, int count)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(index >= 0);
+ Debug.Assert(count >= 0 && index + count <= buffer.Length);<#
+
+#><#= SetTextContentMark(3, true) #>
+
+ fixed (char* pSrcBegin = &buffer[index])
+ {
+ if (inAttributeValue)
+ {
+ WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count);
+ }
+ else
+ {
+ WriteElementTextBlock(pSrcBegin, pSrcBegin + count);
+ }
+ }
+ }
+
+ //
+ // Private methods
+ //
+
+ private void Init(XmlWriterSettings settings)
+ {
+ Debug.Assert((int)ElementProperties.URI_PARENT == (int)AttributeProperties.URI);
+ Debug.Assert((int)ElementProperties.BOOL_PARENT == (int)AttributeProperties.BOOLEAN);
+ Debug.Assert((int)ElementProperties.NAME_PARENT == (int)AttributeProperties.NAME);
+
+ if (elementPropertySearch == null)
+ {
+ //elementPropertySearch should be init last for the mutli thread safe situation.
+ attributePropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlAttributes);
+ elementPropertySearch = new TernaryTreeReadOnly(HtmlTernaryTree.htmlElements);
+ }
+
+ elementScope = new ByteStack(StackIncrement);
+ _uriEscapingBuffer = new byte[5];
+ currentElementProperties = ElementProperties.DEFAULT;
+
+ _mediaType = settings.MediaType;
+ _doNotEscapeUriAttributes = settings.DoNotEscapeUriAttributes;
+ }
+
+ protected void WriteMetaElement()
+ {
+ base.RawText("<META http-equiv=\"Content-Type\"");
+
+ if (_mediaType == null)
+ {
+ _mediaType = "text/html";
+ }
+
+ base.RawText(" content=\"");
+ base.RawText(_mediaType);
+ base.RawText("; charset=");
+ base.RawText(base.encoding.WebName);
+ base.RawText("\">");
+ }
+
+ // Justify the stack usage:
+ //
+ // Nested elements has following possible position combinations
+ // 1. <E1>Content1<E2>Content2</E2></E1>
+ // 2. <E1><E2>Content2</E2>Content1</E1>
+ // 3. <E1>Content<E2>Cotent2</E2>Content1</E1>
+ //
+ // In the situation 2 and 3, the stored currentElementProrperties will be E2's,
+ // only the top of the stack is the real E1 element properties.
+ protected unsafe void WriteHtmlElementTextBlock(char* pSrc, char* pSrcEnd)
+ {
+ if ((currentElementProperties & ElementProperties.NO_ENTITIES) != 0)
+ {
+ base.RawText(pSrc, pSrcEnd);
+ }
+ else
+ {
+ base.WriteElementTextBlock(pSrc, pSrcEnd);
+ }
+ }
+
+ protected unsafe void WriteHtmlAttributeTextBlock(char* pSrc, char* pSrcEnd)
+ {
+ if ((_currentAttributeProperties & (AttributeProperties.BOOLEAN | AttributeProperties.URI | AttributeProperties.NAME)) != 0)
+ {
+ if ((_currentAttributeProperties & AttributeProperties.BOOLEAN) != 0)
+ {
+ //if output boolean attribute, ignore this call.
+ return;
+ }
+
+ if ((_currentAttributeProperties & (AttributeProperties.URI | AttributeProperties.NAME)) != 0 && !_doNotEscapeUriAttributes)
+ {
+ WriteUriAttributeText(pSrc, pSrcEnd);
+ }
+ else
+ {
+ WriteHtmlAttributeText(pSrc, pSrcEnd);
+ }
+ }
+ else if ((currentElementProperties & ElementProperties.HAS_NS) != 0)
+ {
+ base.WriteAttributeTextBlock(pSrc, pSrcEnd);
+ }
+ else
+ {
+ WriteHtmlAttributeText(pSrc, pSrcEnd);
+ }
+ }
+
+ //
+ // &{ split cases
+ // 1). HtmlAttributeText("a&");
+ // HtmlAttributeText("{b}");
+ //
+ // 2). HtmlAttributeText("a&");
+ // EndAttribute();
+
+ // 3).split with Flush by the user
+ // HtmlAttributeText("a&");
+ // FlushBuffer();
+ // HtmlAttributeText("{b}");
+
+ //
+ // Solutions:
+ // case 1)hold the & output as &
+ // if the next income character is {, output {
+ // else output amp;
+ //
+
+ private unsafe void WriteHtmlAttributeText(char* pSrc, char* pSrcEnd)
+ {
+ if (_endsWithAmpersand)
+ {
+ if (pSrcEnd - pSrc > 0 && pSrc[0] != '{')
+ {
+ OutputRestAmps();
+ }
+ _endsWithAmpersand = false;
+ }
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ char ch = (char)0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst++ = (<#= BufferType #>)ch;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ if (pSrc + 1 == pSrcEnd)
+ {
+ _endsWithAmpersand = true;
+ }
+ else if (pSrc[1] != '{')
+ {
+ pDst = AmpEntity(pDst);
+ break;
+ }
+ *pDst++ = (<#= BufferType #>)ch;
+ break;
+ case '"':
+ pDst = QuoteEntity(pDst);
+ break;
+ case '<':
+ case '>':
+ case '\'':
+ case (char)0x9:
+ *pDst++ = (<#= BufferType #>)ch;
+ break;
+ case (char)0xD:
+ // do not normalize new lines in attributes - just escape them
+ pDst = CarriageReturnEntity(pDst);
+ break;
+ case (char)0xA:
+ // do not normalize new lines in attributes - just escape them
+ pDst = LineFeedEntity(pDst);
+ break;
+ default:
+ EncodeChar(ref pSrc, pSrcEnd, ref pDst);
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ private unsafe void WriteUriAttributeText(char* pSrc, char* pSrcEnd)
+ {
+ if (_endsWithAmpersand)
+ {
+ if (pSrcEnd - pSrc > 0 && pSrc[0] != '{')
+ {
+ OutputRestAmps();
+ }
+ _endsWithAmpersand = false;
+ }
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ char ch = (char)0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch < 0x80))
+ {
+ *pDst++ = (<#= BufferType #>)ch;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ if (pSrc + 1 == pSrcEnd)
+ {
+ _endsWithAmpersand = true;
+ }
+ else if (pSrc[1] != '{')
+ {
+ pDst = AmpEntity(pDst);
+ break;
+ }
+ *pDst++ = (<#= BufferType #>)ch;
+ break;
+ case '"':
+ pDst = QuoteEntity(pDst);
+ break;
+ case '<':
+ case '>':
+ case '\'':
+ case (char)0x9:
+ *pDst++ = (<#= BufferType #>)ch;
+ break;
+ case (char)0xD:
+ // do not normalize new lines in attributes - just escape them
+ pDst = CarriageReturnEntity(pDst);
+ break;
+ case (char)0xA:
+ // do not normalize new lines in attributes - just escape them
+ pDst = LineFeedEntity(pDst);
+ break;
+ default:
+ const string hexDigits = "0123456789ABCDEF";
+ Debug.Assert(_uriEscapingBuffer?.Length > 0);
+ fixed (byte* pUriEscapingBuffer = _uriEscapingBuffer)
+ {
+ byte* pByte = pUriEscapingBuffer;
+ byte* pEnd = pByte;
+
+ XmlUtf8RawTextWriter.CharToUTF8(ref pSrc, pSrcEnd, ref pEnd);
+
+ while (pByte < pEnd)
+ {
+ *pDst++ = (<#= BufferType #>)'%';
+ *pDst++ = (<#= BufferType #>)hexDigits[*pByte >> 4];
+ *pDst++ = (<#= BufferType #>)hexDigits[*pByte & 0xF];
+ pByte++;
+ }
+ }
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ // For handling &{ in Html text field. If & is not followed by {, it still needs to be escaped.
+ private void OutputRestAmps()
+ {
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'a';
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'m';
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'p';
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+ }
+ }
+
+ //
+ // Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
+ //
+ // Here are all the cases:
+ // ELEMENT1 actions ELEMENT2 actions SC EE
+ // 1). SE SC store SE blockPro SE a). check ELEMENT1 blockPro <A> </A>
+ // EE if SE, EE are blocks b). true: check ELEMENT2 blockPro <B> <B>
+ // c). detect ELEMENT is SE, SC
+ // d). increase the indexlevel
+ //
+ // 2). SE SC, Store EE blockPro EE a). check stored blockPro <A></A> </A>
+ // EE if SE, EE are blocks b). true: indexLevel same </B>
+ //
+
+
+ //
+ // This is an alternative way to make the output looks better
+ //
+ // Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
+ //
+ // Here are all the cases:
+ // ELEMENT1 actions ELEMENT2 actions Samples
+ // 1). SE SC store SE blockPro SE a). check ELEMENT1 blockPro <A>(blockPos)
+ // b). true: check ELEMENT2 blockPro <B>
+ // c). detect ELEMENT is SE, SC
+ // d). increase the indentLevel
+ //
+ // 2). EE Store EE blockPro SE a). check stored blockPro </A>
+ // b). true: indentLevel same <B>
+ // c). output block2
+ //
+ // 3). EE same as above EE a). check stored blockPro </A>
+ // b). true: --indentLevel </B>
+ // c). output block2
+ //
+ // 4). SE SC same as above EE a). check stored blockPro <A></A>
+ // b). true: indentLevel no change
+ internal class <#= ClassNameIndent #> : <#= ClassName #>
+ {
+ //
+ // Fields
+ //
+ private int _indentLevel;
+
+ // for detecting SE SC sitution
+ private int _endBlockPos;
+
+ // settings
+ private string _indentChars;
+ private bool _newLineOnAttributes;
+
+ //
+ // Constructors
+ //
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+
+ public <#= ClassNameIndent #>(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
+ {
+ Init(settings);
+ }
+<# } #>
+
+ public <#= ClassNameIndent #>(Stream stream, XmlWriterSettings settings) : base(stream, settings)
+ {
+ Init(settings);
+ }
+
+ //
+ // XmlRawWriter overrides
+ //
+ /// <summary>
+ /// Serialize the document type declaration.
+ /// </summary>
+ public override void WriteDocType(string name, string pubid, string sysid, string subset)
+ {
+ base.WriteDocType(name, pubid, sysid, subset);
+
+ // Allow indentation after DocTypeDecl
+ _endBlockPos = base.bufPos;
+ }
+
+ public override void WriteStartElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ base.elementScope.Push((byte)base.currentElementProperties);
+
+ if (ns.Length == 0)
+ {
+ Debug.Assert(prefix.Length == 0);
+
+ base.currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName);
+
+ if (_endBlockPos == base.bufPos && (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0)
+ {
+ WriteIndent();
+ }
+ _indentLevel++;
+
+ base.<#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ }
+ else
+ {
+ base.currentElementProperties = ElementProperties.HAS_NS | ElementProperties.BLOCK_WS;
+
+ if (_endBlockPos == base.bufPos)
+ {
+ WriteIndent();
+ }
+ _indentLevel++;
+
+ base.<#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'<';
+ if (prefix.Length != 0)
+ {
+ base.RawText(prefix);
+ base.<#= BufferName #>[base.bufPos++] = (<#= BufferType #>)':';
+ }
+ }
+ base.RawText(localName);
+ base.attrEndPos = bufPos;
+ }
+
+ internal override void StartElementContent()
+ {
+ base.<#= BufferName #>[base.bufPos++] = (<#= BufferType #>)'>';
+
+ // Detect whether content is output
+ base.contentPos = base.bufPos;
+
+ if ((currentElementProperties & ElementProperties.HEAD) != 0)
+ {
+ WriteIndent();
+ WriteMetaElement();
+ _endBlockPos = base.bufPos;
+ }
+ else if ((base.currentElementProperties & ElementProperties.BLOCK_WS) != 0)
+ {
+ // store the element block position
+ _endBlockPos = base.bufPos;
+ }
+ }
+
+ internal override void WriteEndElement(string prefix, string localName, string ns)
+ {
+ bool isBlockWs;
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
+
+ _indentLevel--;
+
+ // If this element has block whitespace properties,
+ isBlockWs = (base.currentElementProperties & ElementProperties.BLOCK_WS) != 0;
+ if (isBlockWs)
+ {
+ // And if the last node to be output had block whitespace properties,
+ // And if content was output within this element,
+ if (_endBlockPos == base.bufPos && base.contentPos != base.bufPos)
+ {
+ // Then indent
+ WriteIndent();
+ }
+ }
+
+ base.WriteEndElement(prefix, localName, ns);
+
+ // Reset contentPos in case of empty elements
+ base.contentPos = 0;
+
+ // Mark end of element in buffer for element's with block whitespace properties
+ if (isBlockWs)
+ {
+ _endBlockPos = base.bufPos;
+ }
+ }
+
+ public override void WriteStartAttribute(string prefix, string localName, string ns)
+ {
+ if (_newLineOnAttributes)
+ {
+ RawText(base.newLineChars);
+ _indentLevel++;
+ WriteIndent();
+ _indentLevel--;
+ }
+ base.WriteStartAttribute(prefix, localName, ns);
+ }
+
+ protected override void FlushBuffer()
+ {
+ // Make sure the buffer will reset the block position
+ _endBlockPos = (_endBlockPos == base.bufPos) ? 1 : 0;
+ base.FlushBuffer();
+ }
+
+ //
+ // Private methods
+ //
+ private void Init(XmlWriterSettings settings)
+ {
+ _indentLevel = 0;
+ _indentChars = settings.IndentChars;
+ _newLineOnAttributes = settings.NewLineOnAttributes;
+ }
+
+ private void WriteIndent()
+ {
+ // <block><inline> -- suppress ws betw <block> and <inline>
+ // <block><block> -- don't suppress ws betw <block> and <block>
+ // <block>text -- suppress ws betw <block> and text (handled by wcharText method)
+ // <block><?PI?> -- suppress ws betw <block> and PI
+ // <block><!-- --> -- suppress ws betw <block> and comment
+
+ // <inline><block> -- suppress ws betw <inline> and <block>
+ // <inline><inline> -- suppress ws betw <inline> and <inline>
+ // <inline>text -- suppress ws betw <inline> and text (handled by wcharText method)
+ // <inline><?PI?> -- suppress ws betw <inline> and PI
+ // <inline><!-- --> -- suppress ws betw <inline> and comment
+
+ RawText(base.newLineChars);
+ for (int i = _indentLevel; i > 0; i--)
+ {
+ RawText(_indentChars);
+ }
+ }
+ }
+}
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// Following comment might not be valid anymore as this code is fairly old and a lot happened since it was written...
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlUtf8TextWriter.cs
-// cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER HtmlTextWriterGenerator.cxx > HtmlEncodedTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify HtmlRawTextWriterGenerator.ttinclude
using System;
using System.IO;
RawText("<!DOCTYPE ");
- // Bug 114337: Always output "html" or "HTML" in doc-type, even if "name" is something else
+ // Bug: Always output "html" or "HTML" in doc-type, even if "name" is something else
if (name == "HTML")
RawText("HTML");
else
bufBytes[bufPos++] = (byte)']';
}
- bufBytes[this.bufPos++] = (byte)'>';
+ bufBytes[bufPos++] = (byte)'>';
}
// For the HTML element, it should call this method with ns and prefix as String.Empty
{
Debug.Assert(prefix.Length == 0);
-
currentElementProperties = (ElementProperties)elementPropertySearch.FindCaseInsensitiveString(localName);
base.bufBytes[bufPos++] = (byte)'<';
base.RawText(localName);
base.bufBytes[base.bufPos++] = (byte)'>';
// Detect whether content is output
- this.contentPos = this.bufPos;
+ contentPos = bufPos;
if ((currentElementProperties & ElementProperties.HEAD) != 0)
{
{
Debug.Assert(prefix.Length == 0);
-
-
if ((currentElementProperties & ElementProperties.EMPTY) == 0)
{
bufBytes[base.bufPos++] = (byte)'<';
{
Debug.Assert(prefix.Length == 0);
-
-
if ((currentElementProperties & ElementProperties.EMPTY) == 0)
{
bufBytes[base.bufPos++] = (byte)'<';
{
Debug.Assert(prefix.Length == 0);
-
if (base.attrEndPos == bufPos)
{
base.bufBytes[bufPos++] = (byte)' ';
_endsWithAmpersand = false;
}
-
-
base.bufBytes[bufPos++] = (byte)'"';
}
base.inAttributeValue = false;
{
Debug.Assert(target != null && target.Length != 0 && text != null);
-
-
bufBytes[base.bufPos++] = (byte)'<';
bufBytes[base.bufPos++] = (byte)'?';
base.RawText(target);
{
Debug.Assert(text != null);
-
-
fixed (char* pSrc = text)
{
char* pSrcEnd = pSrc + text.Length;
Debug.Assert(index >= 0);
Debug.Assert(count >= 0 && index + count <= buffer.Length);
-
-
fixed (char* pSrcBegin = &buffer[index])
{
if (inAttributeValue)
}
}
+ //
+ // Private methods
+ //
+
private void Init(XmlWriterSettings settings)
{
Debug.Assert((int)ElementProperties.URI_PARENT == (int)AttributeProperties.URI);
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
char ch = (char)0;
for (;;)
}
else if (pSrc[1] != '{')
{
- pDst = XmlUtf8RawTextWriter.AmpEntity(pDst);
+ pDst = AmpEntity(pDst);
break;
}
*pDst++ = (byte)ch;
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
char ch = (char)0;
for (;;)
}
else if (pSrc[1] != '{')
{
- pDst = XmlUtf8RawTextWriter.AmpEntity(pDst);
+ pDst = AmpEntity(pDst);
break;
}
*pDst++ = (byte)ch;
default:
const string hexDigits = "0123456789ABCDEF";
Debug.Assert(_uriEscapingBuffer?.Length > 0);
- fixed (byte* pUriEscapingBuffer = &_uriEscapingBuffer[0])
+ fixed (byte* pUriEscapingBuffer = _uriEscapingBuffer)
{
byte* pByte = pUriEscapingBuffer;
byte* pEnd = pByte;
}
}
-
//
// Indentation HtmlWriter only indent <BLOCK><BLOCK> situations
//
// Constructors
//
-
-
-
-
-
-
public HtmlUtf8RawTextWriterIndent(Stream stream, XmlWriterSettings settings) : base(stream, settings)
{
Init(settings);
{
Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
-
-
base.elementScope.Push((byte)base.currentElementProperties);
if (ns.Length == 0)
}
}
-
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterUtf8.ttinclude" #>
+<#
+ ClassName = "HtmlUtf8RawTextWriter";
+ ClassNameIndent = "HtmlUtf8RawTextWriterIndent";
+ BaseClassName = "XmlUtf8RawTextWriter";
+#>
+<#@ include file="HtmlRawTextWriterGenerator.ttinclude" #>
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ import namespace="System" #>
+<#@ import namespace="System.Text" #>
+<#
+switch (WriterType)
+{
+ case RawTextWriterType.Utf8:
+ case RawTextWriterType.Encoded:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(
+ "WriterType", WriterType,
+ "Unknown value for WriterType.");
+}
+#>
+<#+
+ private const string newline = "\r\n";
+
+ public enum RawTextWriterType {
+ Unknown, Utf8, Encoded
+ }
+
+ public RawTextWriterType WriterType;
+ public string ClassName;
+ public string ClassNameIndent;
+ public string BaseClassName;
+ public string BufferName;
+ public string BufferType;
+ public string EncodeCharBody;
+ public string SetTextContentMarkBody;
+
+ public string SetTextContentMark(int indentAmount, bool value)
+ {
+ return SetTextContentMark(indentAmount, 2, value);
+ }
+
+ public string SetTextContentMark(int indentAmount, int linesPrefix, bool value)
+ {
+ string prefixed = LinesPrefix(linesPrefix, SetTextContentMarkBody);
+
+ return ReIndent(indentAmount, prefixed)
+ .Replace("_value_", BoolString(value));
+ }
+
+ public string EncodeChar(int indentAmount, bool entitizeInvalidChars)
+ {
+ return ReIndent(indentAmount, EncodeCharBody)
+ .Replace("_entitizeInvalidChars_", BoolString(entitizeInvalidChars));
+ }
+
+ public static string LinesPrefix(int amount, string code)
+ {
+ if (string.IsNullOrWhiteSpace(code))
+ {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(code.Length);
+
+ for (int i = 0; i < amount; ++i)
+ {
+ sb.Append(newline);
+ }
+
+ sb.Append(code);
+
+ return sb.ToString();
+ }
+
+ public static string LinesPostfix(int amount, string code)
+ {
+ if (string.IsNullOrWhiteSpace(code))
+ {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(code);
+
+ for (int i = 0; i < amount; ++i)
+ {
+ sb.Append(newline);
+ }
+
+ return sb.ToString();
+ }
+
+ private static string ReIndent(int indentAmount, string code)
+ {
+ if (string.IsNullOrWhiteSpace(code))
+ {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(code.Length);
+ string[] lines = code.Split(new string[] { newline }, StringSplitOptions.None);
+ string indentation = new string(' ', indentAmount * 4);
+
+ for (int i = 0; i < lines.Length; ++i)
+ {
+ string line = lines[i];
+
+ // Do not make lines that have "trailing space."
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ sb.Append(newline);
+ continue;
+ }
+
+ bool lastLine = i == lines.Length - 1;
+
+ sb.Append(indentation);
+ sb.Append(line);
+
+ if (!lastLine)
+ {
+ sb.Append(newline);
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ private static string BoolString(bool value)
+ {
+ return value ? "true" : "false";
+ }
+#>
\ No newline at end of file
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #><#
+ WriterType = RawTextWriterType.Encoded;
+ ClassName = "XmlEncodedRawTextWriter";
+ ClassNameIndent = "XmlEncodedRawTextWriterIndent";
+ BufferName = "bufChars";
+ BufferType = "char";
+ EncodeCharBody = @"/* Surrogate character */
+if (XmlCharType.IsSurrogate(ch))
+{
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+}
+/* Invalid XML character */
+else if (ch <= 0x7F || ch >= 0xFFFE)
+{
+ pDst = InvalidXmlChar(ch, pDst, _entitizeInvalidChars_);
+ pSrc++;
+}
+/* Other character between SurLowEnd and 0xFFFE */
+else
+{
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+}";
+ SetTextContentMarkBody = @"if (trackTextContent && inTextContent != _value_) { ChangeTextContentMark(_value_); }";
+#>
\ No newline at end of file
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #><#
+ WriterType = RawTextWriterType.Utf8;
+ ClassName = "XmlUtf8RawTextWriter";
+ ClassNameIndent = "XmlUtf8RawTextWriterIndent";
+ BufferName = "bufBytes";
+ BufferType = "byte";
+ EncodeCharBody = @"/* Surrogate character */
+if (XmlCharType.IsSurrogate(ch))
+{
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+}
+/* Invalid XML character */
+else if (ch <= 0x7F || ch >= 0xFFFE)
+{
+ pDst = InvalidXmlChar(ch, pDst, _entitizeInvalidChars_);
+ pSrc++;
+}
+/* Multibyte UTF8 character */
+else
+{
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+}";
+ SetTextContentMarkBody = "";
+#>
\ No newline at end of file
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify TextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _UTF8_TEXT_WRITER TextWriterGenerator.cxx > Utf8TextWriter.cs
-// cl.exe /C /EP /D _ENCODED_TEXT_WRITER TextWriterGenerator.cxx > EncodedTextWriter.cs
-//
-// Because these two implementations of TextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-
-
-
-
-
-
-
-
-
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify TextRawTextWriterGenerator.ttinclude
using System;
using System.IO;
using System.Text;
-//using System.Xml.Query;
using System.Xml.Schema;
using System.Diagnostics;
using System.Globalization;
{
}
-
// Construct an instance of this class that serializes to a Stream interface.
public TextEncodedRawTextWriter(Stream stream, XmlWriterSettings settings) : base(stream, settings)
{
}
-
//
// XmlRawWriter
//
}
}
}
+
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterEncoded.ttinclude" #>
+<#
+ ClassName = "TextEncodedRawTextWriter";
+ BaseClassName = "XmlEncodedRawTextWriter";
+#>
+<#@ include file="TextRawTextWriterGenerator.ttinclude" #>
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify TextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _UTF8_TEXT_WRITER TextWriterGenerator.cxx > Utf8TextWriter.cs
-// cl.exe /C /EP /D _ENCODED_TEXT_WRITER TextWriterGenerator.cxx > EncodedTextWriter.cs
-//
-// Because these two implementations of TextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-#ifdef _UTF8_TEXT_WRITER
-#define _CLASS_NAME TextUtf8RawTextWriter
-#define _BASE_CLASS_NAME XmlUtf8RawTextWriter
-#endif
-
-#ifdef _ENCODED_TEXT_WRITER
-#define _CLASS_NAME TextEncodedRawTextWriter
-#define _BASE_CLASS_NAME XmlEncodedRawTextWriter
-#endif
-
-using System;
-using System.IO;
-using System.Text;
-//using System.Xml.Query;
-using System.Xml.Schema;
-using System.Diagnostics;
-using System.Globalization;
-
-namespace System.Xml {
- // Concrete implementation of XmlRawWriter interface that serializes text events as encoded
- // text. All other non-text events are ignored. The general-purpose TextEncodedRawTextWriter uses the
- // Encoder class to output to any encoding. The TextUtf8RawTextWriter class combined the encoding
- // operation with serialization in order to achieve better performance.
- // </summary>
- internal class _CLASS_NAME : _BASE_CLASS_NAME {
-
-#ifdef _ENCODED_TEXT_WRITER
- // Construct an instance of this class that outputs text to the TextWriter interface.
- public _CLASS_NAME( TextWriter writer, XmlWriterSettings settings ) : base ( writer, settings ) {
- }
-#endif
-
- // Construct an instance of this class that serializes to a Stream interface.
- public _CLASS_NAME( Stream stream, XmlWriterSettings settings ) : base( stream, settings ) {
- }
-
-
-//
-// XmlRawWriter
-//
- // Ignore Xml declaration
- internal override void WriteXmlDeclaration( XmlStandalone standalone ) {
- }
- internal override void WriteXmlDeclaration( string xmldecl ) {
- }
-
- // Ignore DTD
- public override void WriteDocType( string name, string pubid, string sysid, string subset ) {
- }
-
- // Ignore Elements
- public override void WriteStartElement( string prefix, string localName, string ns ) {
- }
-
- internal override void WriteEndElement( string prefix, string localName, string ns ) {
- }
-
- internal override void WriteFullEndElement( string prefix, string localName, string ns ) {
- }
-
- internal override void StartElementContent() {
- }
-
- // Ignore attributes
- public override void WriteStartAttribute( string prefix, string localName, string ns ) {
- base.inAttributeValue = true;
- }
-
- public override void WriteEndAttribute() {
- base.inAttributeValue = false;
- }
-
- // Ignore namespace declarations
- internal override void WriteNamespaceDeclaration( string prefix, string ns ) {
- }
-
- internal override bool SupportsNamespaceDeclarationInChunks {
- get {
- return false;
- }
- }
-
- // Output content of CDATA sections as plain text without escaping
- public override void WriteCData( string text ) {
- base.WriteRaw( text );
- }
-
- // Ignore comments
- public override void WriteComment( string text ) {
- }
-
- // Ignore processing instructions
- public override void WriteProcessingInstruction( string name, string text ) {
- }
-
- // Ignore entities
- public override void WriteEntityRef( string name ) {
- }
- public override void WriteCharEntity( char ch ) {
- }
- public override void WriteSurrogateCharEntity( char lowChar, char highChar ) {
- }
-
- // Output text content without any escaping; ignore attribute values
- public override void WriteWhitespace( string ws ) {
- if ( !base.inAttributeValue ) {
- base.WriteRaw( ws );
- }
- }
-
- // Output text content without any escaping; ignore attribute values
- public override void WriteString( string textBlock ) {
- if ( !base.inAttributeValue ) {
- base.WriteRaw( textBlock );
- }
- }
-
- // Output text content without any escaping; ignore attribute values
- public override void WriteChars( char[] buffer, int index, int count ) {
- if ( !base.inAttributeValue ) {
- base.WriteRaw( buffer, index, count );
- }
- }
-
- // Output text content without any escaping; ignore attribute values
- public override void WriteRaw( char[] buffer, int index, int count ) {
- if ( !base.inAttributeValue ) {
- base.WriteRaw( buffer, index, count );
- }
- }
-
- // Output text content without any escaping; ignore attribute values
- public override void WriteRaw( string data ) {
- if ( !base.inAttributeValue ) {
- base.WriteRaw( data );
- }
- }
- }
-}
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriter.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify TextRawTextWriterGenerator.ttinclude
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml.Schema;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace System.Xml
+{
+ // Concrete implementation of XmlRawWriter interface that serializes text events as encoded
+ // text. All other non-text events are ignored. The general-purpose TextEncodedRawTextWriter uses the
+ // Encoder class to output to any encoding. The TextUtf8RawTextWriter class combined the encoding
+ // operation with serialization in order to achieve better performance.
+ // </summary>
+ internal class <#= ClassName #> : <#= BaseClassName #>
+ {
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ // Construct an instance of this class that outputs text to the TextWriter interface.
+ public <#= ClassName #>(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
+ {
+ }
+
+<# } #>
+ // Construct an instance of this class that serializes to a Stream interface.
+ public <#= ClassName #>(Stream stream, XmlWriterSettings settings) : base(stream, settings)
+ {
+ }
+
+ //
+ // XmlRawWriter
+ //
+ // Ignore Xml declaration
+ internal override void WriteXmlDeclaration(XmlStandalone standalone)
+ {
+ }
+ internal override void WriteXmlDeclaration(string xmldecl)
+ {
+ }
+
+ // Ignore DTD
+ public override void WriteDocType(string name, string pubid, string sysid, string subset)
+ {
+ }
+
+ // Ignore Elements
+ public override void WriteStartElement(string prefix, string localName, string ns)
+ {
+ }
+
+ internal override void WriteEndElement(string prefix, string localName, string ns)
+ {
+ }
+
+ internal override void WriteFullEndElement(string prefix, string localName, string ns)
+ {
+ }
+
+ internal override void StartElementContent()
+ {
+ }
+
+ // Ignore attributes
+ public override void WriteStartAttribute(string prefix, string localName, string ns)
+ {
+ base.inAttributeValue = true;
+ }
+
+ public override void WriteEndAttribute()
+ {
+ base.inAttributeValue = false;
+ }
+
+ // Ignore namespace declarations
+ internal override void WriteNamespaceDeclaration(string prefix, string ns)
+ {
+ }
+
+ internal override bool SupportsNamespaceDeclarationInChunks
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // Output content of CDATA sections as plain text without escaping
+ public override void WriteCData(string text)
+ {
+ base.WriteRaw(text);
+ }
+
+ // Ignore comments
+ public override void WriteComment(string text)
+ {
+ }
+
+ // Ignore processing instructions
+ public override void WriteProcessingInstruction(string name, string text)
+ {
+ }
+
+ // Ignore entities
+ public override void WriteEntityRef(string name)
+ {
+ }
+ public override void WriteCharEntity(char ch)
+ {
+ }
+ public override void WriteSurrogateCharEntity(char lowChar, char highChar)
+ {
+ }
+
+ // Output text content without any escaping; ignore attribute values
+ public override void WriteWhitespace(string ws)
+ {
+ if (!base.inAttributeValue)
+ {
+ base.WriteRaw(ws);
+ }
+ }
+
+ // Output text content without any escaping; ignore attribute values
+ public override void WriteString(string textBlock)
+ {
+ if (!base.inAttributeValue)
+ {
+ base.WriteRaw(textBlock);
+ }
+ }
+
+ // Output text content without any escaping; ignore attribute values
+ public override void WriteChars(char[] buffer, int index, int count)
+ {
+ if (!base.inAttributeValue)
+ {
+ base.WriteRaw(buffer, index, count);
+ }
+ }
+
+ // Output text content without any escaping; ignore attribute values
+ public override void WriteRaw(char[] buffer, int index, int count)
+ {
+ if (!base.inAttributeValue)
+ {
+ base.WriteRaw(buffer, index, count);
+ }
+ }
+
+ // Output text content without any escaping; ignore attribute values
+ public override void WriteRaw(string data)
+ {
+ if (!base.inAttributeValue)
+ {
+ base.WriteRaw(data);
+ }
+ }
+ }
+}
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify TextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _UTF8_TEXT_WRITER TextWriterGenerator.cxx > Utf8TextWriter.cs
-// cl.exe /C /EP /D _ENCODED_TEXT_WRITER TextWriterGenerator.cxx > EncodedTextWriter.cs
-//
-// Because these two implementations of TextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-
-
-
-
-
-
-
-
-
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify TextRawTextWriterGenerator.ttinclude
using System;
using System.IO;
using System.Text;
-//using System.Xml.Query;
using System.Xml.Schema;
using System.Diagnostics;
using System.Globalization;
{
}
-
//
// XmlRawWriter
//
}
}
}
+
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterUtf8.ttinclude" #>
+<#
+ ClassName = "TextUtf8RawTextWriter";
+ BaseClassName = "XmlUtf8RawTextWriter";
+#>
+<#@ include file="TextRawTextWriterGenerator.ttinclude" #>
+
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// Note: Following comment is fairly old - generator might not actually work
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-// Note: This file was generated without #define SILVERLIGHT
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGenerator.ttinclude
using System;
using System.IO;
// output stream
protected Stream stream;
- // encoding of the stream or text writer
+ // encoding of the stream or text writer
protected Encoding encoding;
// char type tables
// buffer positions
protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
+ // close an empty element or in CDATA section detection of double ]; bufChars[0] will always be 0
protected int textPos = 1; // text end position; don't indent first element, pi, or comment
protected int contentPos; // element content end position
protected int cdataPos; // cdata end position
protected bool inTextContent;
private int _lastMarkPos;
private int[] _textContentMarks; // even indices contain text content start positions
- // odd indices contain markup start positions
+ // odd indices contain markup start positions
private CharEntityEncoderFallback _charEntityFallback;
// writer settings
{
bufLen = ASYNCBUFSIZE;
}
- bufChars = new char[bufLen + OVERFLOW];
+ bufChars = new char[bufLen + OVERFLOW];
bufBytes = new byte[bufChars.Length];
bufBytesUsed = 0;
// grab bom before possibly changing encoding settings
ReadOnlySpan<byte> bom = encoding.Preamble;
-
+
// the encoding instance this creates can differ from the one passed in
this.encoding = Encoding.GetEncoding(
settings.Encoding.CodePage,
{
XmlWriterSettings settings = new XmlWriterSettings();
- settings.Encoding = this.encoding;
- settings.OmitXmlDeclaration = this.omitXmlDeclaration;
- settings.NewLineHandling = this.newLineHandling;
- settings.NewLineChars = this.newLineChars;
- settings.CloseOutput = this.closeOutput;
+ settings.Encoding = encoding;
+ settings.OmitXmlDeclaration = omitXmlDeclaration;
+ settings.NewLineHandling = newLineHandling;
+ settings.NewLineChars = newLineChars;
+ settings.CloseOutput = closeOutput;
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.CheckCharacters = checkCharacters;
}
}
- // Write the xml declaration. This must be the first call.
+ // Write the xml declaration. This must be the first call.
internal override void WriteXmlDeclaration(XmlStandalone standalone)
{
// Output xml declaration only if user allows it and it was not already output
bufChars[bufPos++] = (char)']';
}
- bufChars[this.bufPos++] = (char)'>';
+ bufChars[bufPos++] = (char)'>';
}
// Serialize the beginning of an element start tag: "<prefix:localName"
if (prefix != null && prefix.Length != 0)
{
RawText(prefix);
- bufChars[this.bufPos++] = (char)':';
+ bufChars[bufPos++] = (char)':';
}
RawText(localName);
public override void WriteEndAttribute()
{
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
bufChars[bufPos++] = (char)'"';
inAttributeValue = false;
attrEndPos = bufPos;
{
Debug.Assert(prefix != null && namespaceName != null);
- this.WriteStartNamespaceDeclaration(prefix);
- this.WriteString(namespaceName);
- this.WriteEndNamespaceDeclaration();
+ WriteStartNamespaceDeclaration(prefix);
+ WriteString(namespaceName);
+ WriteEndNamespaceDeclaration();
}
internal override bool SupportsNamespaceDeclarationInChunks
}
inAttributeValue = true;
+
if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); }
}
public override unsafe void WriteWhitespace(string ws)
{
Debug.Assert(ws != null);
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
fixed (char* pSrc = ws)
public override unsafe void WriteString(string text)
{
Debug.Assert(text != null);
+
if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); }
fixed (char* pSrc = text)
}
}
}
-
else if (writer != null)
{
try
{
FlushBuffer();
FlushEncoder();
-
if (stream != null)
{
stream.Flush();
contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible
cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible
bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
+ // close an empty element or in CDATA section detection of double ]; bufChars[0] will always be 0
}
}
// Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
// are entitized.
-
protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd)
{
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
// Serialize text that is part of element content. The '&', '<', and '>' characters
// are entitized.
-
protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd)
{
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
{
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
char* pSrc = pSrcBegin;
int ch = 0;
for (;;)
{
char* pDstEnd = pDst + (pSrcEnd - pSrc);
- if (pDstEnd > pDstBegin + this.bufLen)
+ if (pDstEnd > pDstBegin + bufLen)
{
- pDstEnd = pDstBegin + this.bufLen;
+ pDstEnd = pDstBegin + bufLen;
}
while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart))
continue;
}
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
}
bufPos = (int)(pDst - pDstBegin);
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
if (ch == stopChar)
{
- // Processing instruction: insert space between adjacent '?' and '>'
+ // Processing instruction: insert space between adjacent '?' and '>'
if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
{
*pDst = (char)' ';
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
{
case '>':
if (hadDoubleBracket && pDst[-1] == (char)']')
- { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ { // pDst[-1] will always correct - there is a padding character at bufChars[0]
// The characters "]]>" were found within the CData text
pDst = RawEndCData(pDst);
pDst = RawStartCData(pDst);
break;
case ']':
if (pDst[-1] == (char)']')
- { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ { // pDst[-1] will always correct - there is a padding character at bufChars[0]
hadDoubleBracket = true;
}
else
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
}
}
+
private static unsafe char* EncodeSurrogate(char* pSrc, char* pSrcEnd, char* pDst)
{
Debug.Assert(XmlCharType.IsSurrogate(*pSrc));
}
else
{
- *pDst = (char)ch;
- pDst++;
-
+ *pDst = (char)ch;
+ pDst++;
return pDst;
}
}
internal unsafe void EncodeChar(ref char* pSrc, char* pSrcEnd, ref char* pDst)
{
int ch = *pSrc;
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
}
+
protected void ChangeTextContentMark(bool value)
{
Debug.Assert(inTextContent != value);
{
GrowTextContentMarks();
}
- _textContentMarks[++_lastMarkPos] = this.bufPos;
+ _textContentMarks[++_lastMarkPos] = bufPos;
}
private void GrowTextContentMarks()
Array.Copy(_textContentMarks, newTextContentMarks, _textContentMarks.Length);
_textContentMarks = newTextContentMarks;
}
-
// Write NewLineChars to the specified buffer position and return an updated position.
-
protected unsafe char* WriteNewLine(char* pDst)
{
fixed (char* pDstBegin = bufChars)
//
// Constructors
//
-
public XmlEncodedRawTextWriterIndent(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
{
Init(settings);
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterEncoded.ttinclude" #>
+<#@ include file="XmlRawTextWriterGenerator.ttinclude" #>
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGeneratorAsync.ttinclude
+
using System;
using System.IO;
using System.Xml;
}
}
- // Write the xml declaration. This must be the first call.
+ // Write the xml declaration. This must be the first call.
internal override async Task WriteXmlDeclarationAsync(XmlStandalone standalone)
{
CheckAsyncCall();
if (!omitXmlDeclaration && !autoXmlDeclaration)
{
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
-
await RawTextAsync("<?xml version=\"").ConfigureAwait(false);
// Version
bufChars[bufPos++] = (char)']';
}
- bufChars[this.bufPos++] = (char)'>';
+ bufChars[bufPos++] = (char)'>';
}
// Serialize the beginning of an element start tag: "<prefix:localName"
Debug.Assert(prefix != null);
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
Task task;
bufChars[bufPos++] = (char)'<';
if (prefix != null && prefix.Length != 0)
protected internal override Task WriteEndAttributeAsync()
{
CheckAsyncCall();
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
bufChars[bufPos++] = (char)'"';
inAttributeValue = false;
attrEndPos = bufPos;
CheckAsyncCall();
Debug.Assert(prefix != null && namespaceName != null);
- await this.WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false);
- await this.WriteStringAsync(namespaceName).ConfigureAwait(false);
- await this.WriteEndNamespaceDeclarationAsync().ConfigureAwait(false);
+ await WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false);
+ await WriteStringAsync(namespaceName).ConfigureAwait(false);
+ await WriteEndNamespaceDeclarationAsync().ConfigureAwait(false);
}
internal override async Task WriteStartNamespaceDeclarationAsync(string prefix)
}
inAttributeValue = true;
+
if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); }
}
internal override Task WriteEndNamespaceDeclarationAsync()
{
CheckAsyncCall();
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
inAttributeValue = false;
bufChars[bufPos++] = (char)'"';
{
CheckAsyncCall();
Debug.Assert(ws != null);
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
if (inAttributeValue)
{
CheckAsyncCall();
Debug.Assert(text != null);
+
if (trackTextContent && inTextContent != true) { ChangeTextContentMark(true); }
if (inAttributeValue)
public override async Task WriteSurrogateCharEntityAsync(char lowChar, char highChar)
{
CheckAsyncCall();
+
if (trackTextContent && inTextContent != false) { ChangeTextContentMark(false); }
+
int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar);
bufChars[bufPos++] = (char)'&';
// Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
bufChars[0] = bufChars[bufPos - 1];
+
// Reset buffer position
textPos = (textPos == bufPos) ? 1 : 0;
attrEndPos = (attrEndPos == bufPos) ? 1 : 0;
// close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
}
}
-
private async Task EncodeCharsAsync(int startOffset, int endOffset, bool writeAllToStream)
{
// Write encoded text to stream
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
return Task.CompletedTask;
}
-
private async Task _WriteAttributeTextBlockAsync(string text, int curIndex, int leftCount)
{
int writeLen;
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
fixed (char* pDstBegin = bufChars)
{
- char* pDst = pDstBegin + this.bufPos;
+ char* pDst = pDstBegin + bufPos;
char* pSrc = pSrcBegin;
int ch = 0;
for (;;)
{
char* pDstEnd = pDst + (pSrcEnd - pSrc);
- if (pDstEnd > pDstBegin + this.bufLen)
+ if (pDstEnd > pDstBegin + bufLen)
{
- pDstEnd = pDstBegin + this.bufLen;
+ pDstEnd = pDstBegin + bufLen;
}
while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart))
return (int)(pSrc - pRaw);
}
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
}
bufPos = (int)(pDst - pDstBegin);
if (writeLen >= 0)
{
// If we were only able to write out some of the second string,
- // write out the remainder and then the other strings,
+ // write out the remainder and then the other strings,
return _RawTextAsync(text2, writeLen, text2.Length - writeLen, text3, text4);
}
}
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
if (ch == stopChar)
{
- // Processing instruction: insert space between adjacent '?' and '>'
+ // Processing instruction: insert space between adjacent '?' and '>'
if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
{
*pDst = (char)' ';
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { *pDst = (char)ch; pDst++; pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Other character between SurLowEnd and 0xFFFE */
+ else
+ {
+ *pDst = (char)ch;
+ pDst++;
+ pSrc++;
+ }
continue;
}
pSrc++;
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterEncoded.ttinclude" #>
+<#@ include file="XmlRawTextWriterGeneratorAsync.ttinclude" #>
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_UTF8_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlUtf8RawTextWriter.cs
-// cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-// Note: This file was generated without #define SILVERLIGHT
-
-#ifdef _XML_UTF8_TEXT_WRITER
-#define _CLASS_NAME XmlUtf8RawTextWriter
-#define _CLASS_NAME_INDENT XmlUtf8RawTextWriterIndent
-#define _BUFFER bufBytes
-#define _BUFFER_TYPE byte
-#define _ENCODE_CHAR(entitizeInvalidChars) \
- /* Surrogate character */ \
- if ( XmlCharType.IsSurrogate( ch ) ) { \
- pDst = EncodeSurrogate( pSrc, pSrcEnd, pDst ); \
- pSrc += 2; \
- } \
- /* Invalid XML character */ \
- else if ( ch <= 0x7F || ch >= 0xFFFE ) { \
- pDst = InvalidXmlChar( ch, pDst, entitizeInvalidChars ); \
- pSrc++; \
- } \
- /* Multibyte UTF8 character */ \
- else { \
- pDst = EncodeMultibyteUTF8( ch, pDst ); \
- pSrc++; \
- }
-
-#define _SET_TEXT_CONTENT_MARK(value)
-#endif
-
-#ifdef _XML_ENCODED_TEXT_WRITER
-#define _CLASS_NAME XmlEncodedRawTextWriter
-#define _CLASS_NAME_INDENT XmlEncodedRawTextWriterIndent
-#define _BUFFER bufChars
-#define _BUFFER_TYPE char
-#define _ENCODE_CHAR(entitizeInvalidChars) \
- /* Surrogate character */ \
- if ( XmlCharType.IsSurrogate( ch ) ) { \
- pDst = EncodeSurrogate( pSrc, pSrcEnd, pDst ); \
- pSrc += 2; \
- } \
- /* Invalid XML character */ \
- else if ( ch <= 0x7F || ch >= 0xFFFE ) { \
- pDst = InvalidXmlChar( ch, pDst, entitizeInvalidChars ); \
- pSrc++; \
- } \
- /* Other character between SurLowEnd and 0xFFFE */ \
- else { \
- *pDst = (char)ch; \
- pDst++; \
- pSrc++; \
- } \
-
-#define _SET_TEXT_CONTENT_MARK(value) \
- if ( trackTextContent && inTextContent != value ) { \
- ChangeTextContentMark( value ); \
- }
-
-#endif
-
-#define XMLCHARTYPE_TEST(ch, flag) ( ( xmlCharType.charProperties[ch] & XmlCharType.##flag ) != 0 )
-#define XMLCHARTYPE_ISATTRIBUTEVALUECHAR(ch) XMLCHARTYPE_TEST(ch, fAttrValue)
-#define XMLCHARTYPE_ISTEXT(ch) XMLCHARTYPE_TEST(ch, fText)
-
-
-using System;
-using System.IO;
-using System.Xml;
-using System.Text;
-using System.Diagnostics;
-using System.Globalization;
-
-namespace System.Xml {
-
- // Concrete implementation of XmlWriter abstract class that serializes events as encoded XML
- // text. The general-purpose XmlEncodedTextWriter uses the Encoder class to output to any
- // encoding. The XmlUtf8TextWriter class combined the encoding operation with serialization
- // in order to achieve better performance.
- internal class _CLASS_NAME : XmlRawWriter {
-//
-// Fields
-//
- // main buffer
- protected byte[] bufBytes;
-
- // output stream
- protected Stream stream;
-
- // encoding of the stream or text writer
- protected Encoding encoding;
-
- // char type tables
- protected XmlCharType xmlCharType = XmlCharType.Instance;
-
- // buffer positions
- protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
- protected int textPos = 1; // text end position; don't indent first element, pi, or comment
- protected int contentPos; // element content end position
- protected int cdataPos; // cdata end position
- protected int attrEndPos; // end of the last attribute
- protected int bufLen = BUFSIZE;
-
- // flags
- protected bool writeToNull;
- protected bool hadDoubleBracket;
- protected bool inAttributeValue;
-
-#ifdef _XML_ENCODED_TEXT_WRITER
- protected int bufBytesUsed;
- protected char[] bufChars;
-
- // encoder for encoding chars in specified encoding when writing to stream
- protected Encoder encoder;
-
- // output text writer
- protected TextWriter writer;
-
- // escaping of characters invalid in the output encoding
- protected bool trackTextContent;
- protected bool inTextContent;
- private int lastMarkPos;
- private int[] textContentMarks; // even indices contain text content start positions
- // odd indices contain markup start positions
- private CharEntityEncoderFallback charEntityFallback;
-
-#endif
-
- // writer settings
- protected NewLineHandling newLineHandling;
- protected bool closeOutput;
- protected bool omitXmlDeclaration;
- protected string newLineChars;
- protected bool checkCharacters;
- protected XmlStandalone standalone;
- protected XmlOutputMethod outputMethod;
- protected bool autoXmlDeclaration;
- protected bool mergeCDataSections;
-
-//
-// Constants
-//
- private const int BUFSIZE = 2048 * 3; // Should be greater than default FileStream size (4096), otherwise the FileStream will try to cache the data
- private const int OVERFLOW = 32; // Allow overflow in order to reduce checks when writing out constant size markup
- private const int INIT_MARKS_COUNT = 64;
-
-//
-// Constructors
-//
- // Construct and initialize an instance of this class.
- protected _CLASS_NAME( XmlWriterSettings settings ) {
- // copy settings
- newLineHandling = settings.NewLineHandling;
- omitXmlDeclaration = settings.OmitXmlDeclaration;
- newLineChars = settings.NewLineChars;
- checkCharacters = settings.CheckCharacters;
- closeOutput = settings.CloseOutput;
-
- standalone = settings.Standalone;
- outputMethod = settings.OutputMethod;
- mergeCDataSections = settings.MergeCDataSections;
-
- if ( checkCharacters && newLineHandling == NewLineHandling.Replace ) {
- ValidateContentChars( newLineChars, "NewLineChars", false );
- }
- }
-
-#ifdef _XML_ENCODED_TEXT_WRITER
- // Construct an instance of this class that outputs text to the TextWriter interface.
- public _CLASS_NAME( TextWriter writer, XmlWriterSettings settings ) : this( settings ) {
- Debug.Assert( writer != null && settings != null );
-
- this.writer = writer;
- this.encoding = writer.Encoding;
- // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
- this.bufChars = new _BUFFER_TYPE[BUFSIZE + OVERFLOW];
-
- // Write the xml declaration
- if (settings.AutoXmlDeclaration ) {
- WriteXmlDeclaration( standalone );
- autoXmlDeclaration = true;
- }
- }
-#endif
-
- // Construct an instance of this class that serializes to a Stream interface.
- public _CLASS_NAME( Stream stream, XmlWriterSettings settings ) : this( settings ) {
- Debug.Assert( stream != null && settings != null );
-
- this.stream = stream;
- this.encoding = settings.Encoding;
-
-#ifdef _XML_UTF8_TEXT_WRITER
- // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
- bufBytes = new _BUFFER_TYPE[ BUFSIZE + OVERFLOW ];
-
- // Output UTF-8 byte order mark if Encoding object wants it
- if ( !stream.CanSeek || stream.Position == 0 ) {
- ReadOnlySpan<byte> bom = encoding.Preamble;
- if ( bom.Length != 0 ) {
- bom.CopyTo(new Span<byte>(bufBytes).Slice(1));
- bufPos += bom.Length;
- textPos += bom.Length;
- }
- }
-#else
- // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
- bufChars = new _BUFFER_TYPE[ BUFSIZE + OVERFLOW ];
- bufBytes = new byte[ bufChars.Length ];
- bufBytesUsed = 0;
-
- // Init escaping of characters not fitting into the target encoding
- trackTextContent = true;
- inTextContent = false;
- lastMarkPos = 0;
- textContentMarks = new int[INIT_MARKS_COUNT];
- textContentMarks[0] = 1;
-
- charEntityFallback = new CharEntityEncoderFallback();
- this.encoding = (Encoding)settings.Encoding.Clone();
- encoding.EncoderFallback = charEntityFallback;
-
- encoder = encoding.GetEncoder();
-
- if ( !stream.CanSeek || stream.Position == 0 ) {
- ReadOnlySpan<byte> bom = encoding.Preamble;
- if ( bom.Length != 0 ) {
- this.stream.Write( bom );
- }
- }
-#endif
-
- // Write the xml declaration
- if ( settings.AutoXmlDeclaration ) {
- WriteXmlDeclaration( standalone );
- autoXmlDeclaration = true;
- }
- }
-
-//
-// XmlWriter implementation
-//
- // Returns settings the writer currently applies.
- public override XmlWriterSettings Settings {
- get {
- XmlWriterSettings settings = new XmlWriterSettings();
-
- settings.Encoding = this.encoding;
- settings.OmitXmlDeclaration = this.omitXmlDeclaration;
- settings.NewLineHandling = this.newLineHandling;
- settings.NewLineChars = this.newLineChars;
- settings.CloseOutput = this.closeOutput;
- settings.ConformanceLevel = ConformanceLevel.Auto;
- settings.CheckCharacters = checkCharacters;
-
- settings.AutoXmlDeclaration = autoXmlDeclaration;
- settings.Standalone = standalone;
- settings.OutputMethod = outputMethod;
- settings.ReadOnly = true;
- return settings;
-
- }
- }
-
- // Write the xml declaration. This must be the first call.
- internal override void WriteXmlDeclaration( XmlStandalone standalone ) {
- // Output xml declaration only if user allows it and it was not already output
- if ( !omitXmlDeclaration && !autoXmlDeclaration ) {
-
- _SET_TEXT_CONTENT_MARK(false)
-
- RawText( "<?xml version=\"" );
-
- // Version
- RawText( "1.0" );
-
- // Encoding
- if ( encoding != null ) {
- RawText( "\" encoding=\"" );
- RawText( encoding.WebName );
- }
-
- // Standalone
- if ( standalone != XmlStandalone.Omit ) {
- RawText( "\" standalone=\"" );
- RawText( standalone == XmlStandalone.Yes ? "yes" : "no" );
- }
-
- RawText( "\"?>" );
- }
- }
-
- internal override void WriteXmlDeclaration( string xmldecl ) {
- // Output xml declaration only if user allows it and it was not already output
- if ( !omitXmlDeclaration && !autoXmlDeclaration ) {
- WriteProcessingInstruction( "xml", xmldecl );
- }
- }
-
- // Serialize the document type declaration.
- public override void WriteDocType( string name, string pubid, string sysid, string subset ) {
- Debug.Assert( name != null && name.Length > 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- RawText( "<!DOCTYPE ");
- RawText(name);
- if ( pubid != null ) {
- RawText( " PUBLIC \"" );
- RawText( pubid );
- RawText( "\" \"");
- if ( sysid != null ) {
- RawText( sysid );
- }
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- else if ( sysid != null ) {
- RawText( " SYSTEM \"" );
- RawText( sysid );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- }
- else {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- }
-
- if ( subset != null ) {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '[';
- RawText( subset );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ']';
- }
-
- _BUFFER[this.bufPos++] = (_BUFFER_TYPE) '>';
- }
-
- // Serialize the beginning of an element start tag: "<prefix:localName"
- public override void WriteStartElement( string prefix, string localName, string ns) {
- Debug.Assert( localName != null && localName.Length > 0 );
- Debug.Assert( prefix != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- if ( prefix != null && prefix.Length != 0 ) {
- RawText( prefix );
- _BUFFER[this.bufPos++] = (_BUFFER_TYPE) ':';
- }
-
- RawText( localName );
-
- attrEndPos = bufPos;
- }
-
- // Serialize the end of an element start tag in preparation for content serialization: ">"
- internal override void StartElementContent() {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
-
- // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the
- // position of the '>' character. If WriteEndElement is called and no other characters have been
- // output, then the '>' character can be overwritten with the shortcut syntax " />".
- contentPos = bufPos;
- }
-
- // Serialize an element end tag: "</prefix:localName>", if content was output. Otherwise, serialize
- // the shortcut syntax: " />".
- internal override void WriteEndElement( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length > 0 );
- Debug.Assert( prefix != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( contentPos != bufPos ) {
- // Content has been output, so can't use shortcut syntax
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '/';
-
- if ( prefix != null && prefix.Length != 0) {
- RawText( prefix );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ':';
- }
- RawText( localName );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
- }
- else {
- // Use shortcut syntax; overwrite the already output '>' character
- bufPos--;
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '/';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
- }
- }
-
- // Serialize a full element end tag: "</prefix:localName>"
- internal override void WriteFullEndElement( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length > 0 );
- Debug.Assert( prefix != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '/';
-
- if ( prefix != null && prefix.Length != 0) {
- RawText( prefix );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ':';
- }
- RawText( localName );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
- }
-
- // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="'
- public override void WriteStartAttribute( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length > 0 );
- Debug.Assert( prefix != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( attrEndPos == bufPos ) {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- }
-
- if ( prefix != null && prefix.Length > 0 ) {
- RawText( prefix );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ':';
- }
- RawText( localName );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '=';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
-
- inAttributeValue = true;
- }
-
- // Serialize the end of an attribute value using double quotes: '"'
- public override void WriteEndAttribute() {
- _SET_TEXT_CONTENT_MARK(false)
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '"';
- inAttributeValue = false;
- attrEndPos = bufPos;
- }
-
- internal override void WriteNamespaceDeclaration( string prefix, string namespaceName ) {
- Debug.Assert( prefix != null && namespaceName != null );
-
- this.WriteStartNamespaceDeclaration( prefix );
- this.WriteString( namespaceName );
- this.WriteEndNamespaceDeclaration();
- }
-
- internal override bool SupportsNamespaceDeclarationInChunks {
- get {
- return true;
- }
- }
-
- internal override void WriteStartNamespaceDeclaration(string prefix) {
- Debug.Assert( prefix != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- // VSTFDEVDIV bug #583965: Inconsistency between Silverlight 2 and Dev10 in the way a single xmlns attribute is serialized
- // Resolved as: Won't fix (breaking change)
- if ( prefix.Length == 0 ) {
- RawText( " xmlns=\"" );
- }
- else {
- RawText( " xmlns:" );
- RawText( prefix );
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'=';
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'"';
- }
-
- inAttributeValue = true;
- _SET_TEXT_CONTENT_MARK(true)
- }
-
- internal override void WriteEndNamespaceDeclaration() {
- _SET_TEXT_CONTENT_MARK(false)
- inAttributeValue = false;
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'"';
- attrEndPos = bufPos;
- }
-
- // Serialize a CData section. If the "]]>" pattern is found within
- // the text, replace it with "]]><![CDATA[>".
- public override void WriteCData( string text ) {
- Debug.Assert( text != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- if ( mergeCDataSections && bufPos == cdataPos ) {
- // Merge adjacent cdata sections - overwrite the "]]>" characters
- Debug.Assert( bufPos >= 4 );
- bufPos -= 3;
- }
- else {
- // Start a new cdata section
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '!';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '[';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) 'C';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) 'D';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) 'A';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) 'T';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) 'A';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '[';
- }
-
- WriteCDataSection( text );
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ']';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ']';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
-
- textPos = bufPos;
- cdataPos = bufPos;
- }
-
- // Serialize a comment.
- public override void WriteComment( string text ) {
- Debug.Assert( text != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '!';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '-';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '-';
-
- WriteCommentOrPi( text, '-' );
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '-';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '-';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
- }
-
- // Serialize a processing instruction.
- public override void WriteProcessingInstruction( string name, string text ) {
- Debug.Assert( name != null && name.Length > 0 );
- Debug.Assert( text != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '<';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '?';
- RawText( name );
-
- if ( text.Length > 0 ) {
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ' ';
- WriteCommentOrPi( text, '?' );
- }
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '?';
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '>';
- }
-
- // Serialize an entity reference.
- public override void WriteEntityRef( string name ) {
- Debug.Assert( name != null && name.Length > 0 );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE) '&';
- RawText( name );
- _BUFFER[bufPos++] = (_BUFFER_TYPE) ';';
-
- if ( bufPos > bufLen ) {
- FlushBuffer();
- }
-
- textPos = bufPos;
- }
-
- // Serialize a character entity reference.
- public override void WriteCharEntity( char ch ) {
- string strVal = ((int)ch).ToString( "X", NumberFormatInfo.InvariantInfo );
-
- if ( checkCharacters && !xmlCharType.IsCharData( ch ) ) {
- // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char
- throw XmlConvert.CreateInvalidCharException( ch, '\0' );
- }
-
- _SET_TEXT_CONTENT_MARK(false)
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'&';
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'#';
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'x';
- RawText( strVal );
- _BUFFER[bufPos++] = (_BUFFER_TYPE)';';
-
- if ( bufPos > bufLen ) {
- FlushBuffer();
- }
-
- textPos = bufPos;
- }
-
- // Serialize a whitespace node.
- public override unsafe void WriteWhitespace( string ws ) {
- Debug.Assert( ws != null );
- _SET_TEXT_CONTENT_MARK(false)
-
- fixed ( char * pSrc = ws ) {
- char * pSrcEnd = pSrc + ws.Length;
- if ( inAttributeValue) {
- WriteAttributeTextBlock( pSrc, pSrcEnd );
- }
- else {
- WriteElementTextBlock( pSrc, pSrcEnd );
- }
- }
- }
-
- // Serialize either attribute or element text using XML rules.
- public override unsafe void WriteString( string text ) {
- Debug.Assert( text != null );
- _SET_TEXT_CONTENT_MARK(true)
-
- fixed ( char * pSrc = text ) {
- char * pSrcEnd = pSrc + text.Length;
- if ( inAttributeValue) {
- WriteAttributeTextBlock( pSrc, pSrcEnd );
- }
- else {
- WriteElementTextBlock( pSrc, pSrcEnd );
- }
- }
- }
-
- // Serialize surrogate character entity.
- public override void WriteSurrogateCharEntity( char lowChar, char highChar ) {
- _SET_TEXT_CONTENT_MARK(false)
- int surrogateChar = XmlCharType.CombineSurrogateChar( lowChar, highChar );
-
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'&';
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'#';
- _BUFFER[bufPos++] = (_BUFFER_TYPE)'x';
- RawText( surrogateChar.ToString( "X", NumberFormatInfo.InvariantInfo ) );
- _BUFFER[bufPos++] = (_BUFFER_TYPE)';';
- textPos = bufPos;
- }
-
- // Serialize either attribute or element text using XML rules.
- // Arguments are validated in the XmlWellformedWriter layer.
- public override unsafe void WriteChars( char[] buffer, int index, int count ) {
- Debug.Assert( buffer != null );
- Debug.Assert( index >= 0 );
- Debug.Assert( count >= 0 && index + count <= buffer.Length );
-
- _SET_TEXT_CONTENT_MARK(true)
-
- fixed ( char * pSrcBegin = &buffer[index] ) {
- if ( inAttributeValue ) {
- WriteAttributeTextBlock( pSrcBegin, pSrcBegin + count );
- }
- else {
- WriteElementTextBlock( pSrcBegin, pSrcBegin + count );
- }
- }
- }
-
- // Serialize raw data.
- // Arguments are validated in the XmlWellformedWriter layer
- public override unsafe void WriteRaw( char[] buffer, int index, int count ) {
- Debug.Assert( buffer != null );
- Debug.Assert( index >= 0 );
- Debug.Assert( count >= 0 && index + count <= buffer.Length );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- fixed ( char * pSrcBegin = &buffer[index] ) {
- WriteRawWithCharChecking( pSrcBegin, pSrcBegin + count );
- }
- textPos = bufPos;
- }
-
- // Serialize raw data.
- public override unsafe void WriteRaw( string data ) {
- Debug.Assert( data != null );
-
- _SET_TEXT_CONTENT_MARK(false)
-
- fixed ( char * pSrcBegin = data ) {
- WriteRawWithCharChecking( pSrcBegin, pSrcBegin + data.Length );
- }
- textPos = bufPos;
- }
-
- // Flush all bytes in the buffer to output and close the output stream or writer.
- public override void Close() {
- try {
- FlushBuffer();
- FlushEncoder();
- }
- finally {
- // Future calls to Close or Flush shouldn't write to Stream or Writer
- writeToNull = true;
-
- if ( stream != null ) {
- try {
- stream.Flush();
- }
- finally {
- try {
- if ( closeOutput ) {
- stream.Close();
- }
- }
- finally {
- stream = null;
- }
- }
- }
-#ifndef _XML_UTF8_TEXT_WRITER
- else if ( writer != null ) {
- try {
- writer.Flush();
- }
- finally {
- try {
- if ( closeOutput ) {
- writer.Close();
- }
- }
- finally {
- writer = null;
- }
- }
- }
-#endif
- }
- }
-
- // Flush all characters in the buffer to output and call Flush() on the output object.
- public override void Flush() {
- FlushBuffer();
- FlushEncoder();
-#ifdef _XML_UTF8_TEXT_WRITER
- if ( stream != null ) {
- stream.Flush();
- }
-#else
- if ( stream != null ) {
- stream.Flush();
- }
- else if ( writer != null ) {
- writer.Flush();
- }
-#endif
- }
-
-//
-// Implementation methods
-//
- // Flush all characters in the buffer to output. Do not flush the output object.
- protected virtual void FlushBuffer() {
- try {
- // Output all characters (except for previous characters stored at beginning of buffer)
- if ( !writeToNull ) {
-#ifdef _XML_UTF8_TEXT_WRITER
- Debug.Assert( stream != null);
- stream.Write( bufBytes, 1, bufPos - 1 );
-#else
- Debug.Assert( stream != null || writer != null );
-
- if ( stream != null ) {
- if ( trackTextContent ) {
- charEntityFallback.Reset( textContentMarks, lastMarkPos );
- // reset text content tracking
-
- if ((lastMarkPos & 1) != 0) {
- // If the previous buffer ended inside a text content we need to preserve that info
- // which means the next index to which we write has to be even
- textContentMarks[1] = 1;
- lastMarkPos = 1;
- }
- else {
- lastMarkPos = 0;
- }
- Debug.Assert( textContentMarks[0] == 1 );
- }
- EncodeChars( 1, bufPos, true );
- }
- else {
- // Write text to TextWriter
- writer.Write( bufChars, 1, bufPos - 1 );
- }
-#endif
- }
- }
- catch {
- // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream
- writeToNull = true;
- throw;
- }
- finally {
- // Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
- _BUFFER[0] = _BUFFER[bufPos - 1];
-
-#ifdef _XML_UTF8_TEXT_WRITER
- if ( IsSurrogateByte( _BUFFER[0] ) ) {
- // Last character was the first byte in a surrogate encoding, so move last three
- // bytes of encoding to the beginning of the buffer.
- _BUFFER[1] = _BUFFER[bufPos];
- _BUFFER[2] = _BUFFER[bufPos + 1];
- _BUFFER[3] = _BUFFER[bufPos + 2];
- }
-#endif
-
- // Reset buffer position
- textPos = (textPos == bufPos) ? 1 : 0;
- attrEndPos = (attrEndPos == bufPos) ? 1 : 0;
- contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible
- cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible
- bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
- }
- }
-
-#if _XML_UTF8_TEXT_WRITER
- private void FlushEncoder() {
- // intentionally empty
- }
-#else
- private void EncodeChars( int startOffset, int endOffset, bool writeAllToStream ) {
- // Write encoded text to stream
- int chEnc;
- int bEnc;
- bool completed;
- while ( startOffset < endOffset ) {
- if ( charEntityFallback != null ) {
- charEntityFallback.StartOffset = startOffset;
- }
- encoder.Convert( bufChars, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed );
- startOffset += chEnc;
- bufBytesUsed += bEnc;
- if ( bufBytesUsed >= ( bufBytes.Length - 16 ) ) {
- stream.Write( bufBytes, 0, bufBytesUsed );
- bufBytesUsed = 0;
- }
- }
- if ( writeAllToStream && bufBytesUsed > 0 ) {
- stream.Write( bufBytes, 0, bufBytesUsed );
- bufBytesUsed = 0;
- }
- }
-
- private void FlushEncoder() {
- Debug.Assert( bufPos == 1 );
- if ( stream != null ) {
- int chEnc;
- int bEnc;
- bool completed;
- // decode no chars, just flush
- encoder.Convert( bufChars, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed );
- if ( bEnc != 0 ) {
- stream.Write( bufBytes, 0, bEnc );
- }
- }
- }
-#endif
-
- // Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
- // are entitized.
- protected unsafe void WriteAttributeTextBlock( char *pSrc, char *pSrcEnd ) {
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- _BUFFER_TYPE * pDst = pDstBegin + this.bufPos;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#if _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) ) ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- pSrc++;
- }
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // some character needs to be escaped
- switch ( ch ) {
- case '&':
- pDst = AmpEntity( pDst );
- break;
- case '<':
- pDst = LtEntity( pDst );
- break;
- case '>':
- pDst = GtEntity( pDst );
- break;
- case '"':
- pDst = QuoteEntity( pDst );
- break;
- case '\'':
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- case (char)0x9:
- if ( newLineHandling == NewLineHandling.None ) {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- else {
- // escape tab in attributes
- pDst = TabEntity( pDst );
- }
- break;
- case (char)0xD:
- if ( newLineHandling == NewLineHandling.None ) {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- else {
- // escape new lines in attributes
- pDst = CarriageReturnEntity( pDst );
- }
- break;
- case (char)0xA:
- if ( newLineHandling == NewLineHandling.None ) {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- else {
- // escape new lines in attributes
- pDst = LineFeedEntity( pDst );
- }
- break;
- default:
- _ENCODE_CHAR(true);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- // Serialize text that is part of element content. The '&', '<', and '>' characters
- // are entitized.
- protected unsafe void WriteElementTextBlock( char *pSrc, char *pSrcEnd ) {
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- _BUFFER_TYPE * pDst = pDstBegin + this.bufPos;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#if _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) ) ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- pSrc++;
- }
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // some character needs to be escaped
- switch ( ch ) {
- case '&':
- pDst = AmpEntity( pDst );
- break;
- case '<':
- pDst = LtEntity( pDst );
- break;
- case '>':
- pDst = GtEntity( pDst );
- break;
- case '"':
- case '\'':
- case (char)0x9:
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- case (char)0xA:
- if ( newLineHandling == NewLineHandling.Replace ) {
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case (char)0xD:
- switch ( newLineHandling ) {
- case NewLineHandling.Replace:
- // Replace "\r\n", or "\r" with NewLineChars
- if ( pSrc[1] == '\n' ) {
- pSrc++;
- }
- pDst = WriteNewLine( pDst );
- break;
- case NewLineHandling.Entitize:
- // Entitize 0xD
- pDst = CarriageReturnEntity( pDst );
- break;
- case NewLineHandling.None:
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- }
- break;
- default:
- _ENCODE_CHAR(true);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- textPos = bufPos;
- contentPos = 0;
- }
- }
-
- protected unsafe void RawText( string s ) {
- Debug.Assert( s != null );
- fixed ( char * pSrcBegin = s ) {
- RawText( pSrcBegin, pSrcBegin + s.Length );
- }
- }
-
- protected unsafe void RawText( char * pSrcBegin, char * pSrcEnd ) {
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- _BUFFER_TYPE * pDst = pDstBegin + this.bufPos;
- char * pSrc = pSrcBegin;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + this.bufLen ) {
- pDstEnd = pDstBegin + this.bufLen;
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( ( ch = *pSrc ) <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( ( ch = *pSrc ) < XmlCharType.SurHighStart ) ) {
-#endif
- pSrc++;
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- _ENCODE_CHAR(false);
- }
-
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- protected unsafe void WriteRawWithCharChecking( char * pSrcBegin, char * pSrcEnd ) {
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- char * pSrc = pSrcBegin;
- _BUFFER_TYPE * pDst = pDstBegin + bufPos;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISTEXT( ( ch = *pSrc ) ) && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISTEXT( ( ch = *pSrc ) ) ) ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- pSrc++;
- }
-
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // handle special characters
- switch ( ch ) {
- case ']':
- case '<':
- case '&':
- case (char)0x9:
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- case (char)0xD:
- if ( newLineHandling == NewLineHandling.Replace ) {
- // Normalize "\r\n", or "\r" to NewLineChars
- if ( pSrc[1] == '\n' ) {
- pSrc++;
- }
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case (char)0xA:
- if ( newLineHandling == NewLineHandling.Replace ) {
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- default:
- _ENCODE_CHAR(false);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- protected unsafe void WriteCommentOrPi( string text, int stopChar ) {
- if ( text.Length == 0 ) {
- if ( bufPos >= bufLen ) {
- FlushBuffer();
- }
- return;
- }
- // write text
- fixed ( char * pSrcBegin = text )
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- char * pSrc = pSrcBegin;
- char * pSrcEnd = pSrcBegin + text.Length;
- _BUFFER_TYPE * pDst = pDstBegin + bufPos;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISTEXT( ( ch = *pSrc ) ) && ch != stopChar && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISTEXT( ( ch = *pSrc ) ) && ch != stopChar ) ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- pSrc++;
- }
-
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // handle special characters
- switch ( ch ) {
- case '-':
- *pDst = (_BUFFER_TYPE) '-';
- pDst++;
- if ( ch == stopChar ) {
- // Insert space between adjacent dashes or before comment's end dashes
- if ( pSrc + 1 == pSrcEnd || *(pSrc + 1)== '-' ) {
- *pDst = (_BUFFER_TYPE) ' ';
- pDst++;
- }
- }
- break;
- case '?':
- *pDst = (_BUFFER_TYPE) '?';
- pDst++;
- if ( ch == stopChar ) {
- // Processing instruction: insert space between adjacent '?' and '>'
- if ( pSrc + 1 < pSrcEnd && *(pSrc + 1)== '>' ) {
- *pDst = (_BUFFER_TYPE) ' ';
- pDst++;
- }
- }
- break;
- case ']':
- *pDst = (_BUFFER_TYPE) ']';
- pDst++;
- break;
- case (char)0xD:
- if ( newLineHandling == NewLineHandling.Replace ) {
- // Normalize "\r\n", or "\r" to NewLineChars
- if ( pSrc[1] == '\n' ) {
- pSrc++;
- }
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case (char)0xA:
- if ( newLineHandling == NewLineHandling.Replace ) {
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case '<':
- case '&':
- case (char)0x9:
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- default:
- _ENCODE_CHAR(false);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
- protected unsafe void WriteCDataSection( string text ) {
- if ( text.Length == 0 ) {
- if ( bufPos >= bufLen ) {
- FlushBuffer();
- }
- return;
- }
- // write text
- fixed ( char * pSrcBegin = text )
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- char * pSrc = pSrcBegin;
- char * pSrcEnd = pSrcBegin + text.Length;
- _BUFFER_TYPE * pDst = pDstBegin + bufPos;
-
- int ch = 0;
- for (;;) {
- _BUFFER_TYPE * pDstEnd = pDst + ( pSrcEnd - pSrc );
- if ( pDstEnd > pDstBegin + bufLen ) {
- pDstEnd = pDstBegin + bufLen;
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch != ']' && ch <= 0x7F ) ) {
-#else
- while ( pDst < pDstEnd && ( XMLCHARTYPE_ISATTRIBUTEVALUECHAR( ( ch = *pSrc ) ) && ch != ']' ) ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- pSrc++;
- }
-
- Debug.Assert( pSrc <= pSrcEnd );
-
- // end of value
- if ( pSrc >= pSrcEnd ) {
- break;
- }
-
- // end of buffer
- if ( pDst >= pDstEnd ) {
- bufPos = (int)(pDst - pDstBegin);
- FlushBuffer();
- pDst = pDstBegin + 1;
- continue;
- }
-
- // handle special characters
- switch ( ch ) {
- case '>':
- if ( hadDoubleBracket && pDst[-1] == (_BUFFER_TYPE) ']') { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
- // The characters "]]>" were found within the CData text
- pDst = RawEndCData( pDst );
- pDst = RawStartCData( pDst );
- }
- *pDst = (_BUFFER_TYPE) '>';
- pDst++;
- break;
- case ']':
- if ( pDst[-1] == (_BUFFER_TYPE)']' ) { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
- hadDoubleBracket = true;
- }
- else {
- hadDoubleBracket = false;
- }
- *pDst = (_BUFFER_TYPE)']';
- pDst++;
- break;
- case (char)0xD:
- if ( newLineHandling == NewLineHandling.Replace ) {
- // Normalize "\r\n", or "\r" to NewLineChars
- if ( pSrc[1] == '\n' ) {
- pSrc++;
- }
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case (char)0xA:
- if ( newLineHandling == NewLineHandling.Replace ) {
- pDst = WriteNewLine( pDst );
- }
- else {
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- }
- break;
- case '&':
- case '<':
- case '"':
- case '\'':
- case (char)0x9:
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
- break;
- default:
- _ENCODE_CHAR(false);
- continue;
- }
- pSrc++;
- }
- bufPos = (int)(pDst - pDstBegin);
- }
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- // Returns true if UTF8 encoded byte is first of four bytes that encode a surrogate pair.
- // To do this, detect the bit pattern 11110xxx.
- private static bool IsSurrogateByte( byte b ) {
- return (b & 0xF8) == 0xF0;
- }
-#endif
-
- private static unsafe _BUFFER_TYPE* EncodeSurrogate( char* pSrc, char* pSrcEnd, _BUFFER_TYPE* pDst ) {
- Debug.Assert( XmlCharType.IsSurrogate( *pSrc ) );
-
- int ch = *pSrc;
- if ( ch <= XmlCharType.SurHighEnd ) {
- if ( pSrc + 1 < pSrcEnd ) {
- int lowChar = pSrc[1];
- if ( lowChar >= XmlCharType.SurLowStart ) {
-#ifdef _XML_UTF8_TEXT_WRITER
- // Calculate Unicode scalar value for easier manipulations (see section 3.7 in Unicode spec)
- // The scalar value repositions surrogate values to start at 0x10000.
-
- ch = XmlCharType.CombineSurrogateChar( lowChar, ch );
-
- pDst[0] = (byte)( 0xF0 | ( ch >> 18 ) );
- pDst[1] = (byte)( 0x80 | ( ch >> 12 ) & 0x3F );
- pDst[2] = (byte)( 0x80 | ( ch >> 6 ) & 0x3F );
- pDst[3] = (byte)( 0x80 | ch & 0x3F);
- pDst += 4;
-#else
- pDst[0] = (char)ch;
- pDst[1] = (char)lowChar;
- pDst += 2;
-#endif
- return pDst;
- }
- throw XmlConvert.CreateInvalidSurrogatePairException( (char)lowChar, (char)ch );
- }
- throw new ArgumentException( string.Format( SR.Xml_InvalidSurrogateMissingLowChar ) );
- }
- throw XmlConvert.CreateInvalidHighSurrogateCharException( (char)ch );
- }
-
- private unsafe _BUFFER_TYPE* InvalidXmlChar( int ch, _BUFFER_TYPE* pDst, bool entitize ) {
- Debug.Assert( !xmlCharType.IsWhiteSpace( (char)ch ) );
- Debug.Assert( !xmlCharType.IsAttributeValueChar( (char)ch ) );
-
- if ( checkCharacters ) {
- // This method will never be called on surrogates, so it is ok to pass in '\0' to the CreateInvalidCharException
- throw XmlConvert.CreateInvalidCharException( (char)ch, '\0' );
- }
- else {
- if ( entitize ) {
- return CharEntity( pDst, (char)ch );
- }
- else {
-#ifdef _XML_UTF8_TEXT_WRITER
- if ( ch < 0x80 ) {
-#endif
- *pDst = (_BUFFER_TYPE)ch;
- pDst++;
-#ifdef _XML_UTF8_TEXT_WRITER
- }
- else {
- pDst = EncodeMultibyteUTF8( ch, pDst );
- }
-#endif
- return pDst;
- }
- }
- }
-
- internal unsafe void EncodeChar(ref char* pSrc, char*pSrcEnd, ref _BUFFER_TYPE* pDst) {
- int ch = *pSrc;
- _ENCODE_CHAR(false);
- }
-
-#ifdef _XML_UTF8_TEXT_WRITER
- internal static unsafe byte* EncodeMultibyteUTF8( int ch, byte* pDst ) {
- Debug.Assert( ch >= 0x80 && !XmlCharType.IsSurrogate( ch ) );
-
- unchecked {
- /* UTF8-2: If ch is in 0x80-0x7ff range, then use 2 bytes to encode it */ \
- if ( ch < 0x800 ) {
- *pDst = (byte)( (sbyte)0xC0 | (ch >> 6) );
- }
- /* UTF8-3: If ch is anything else, then default to using 3 bytes to encode it. */
- else {
- *pDst = (byte)( (sbyte)0xE0 | ( ch >> 12 ) );
- pDst++;
-
- *pDst = (byte)( (sbyte)0x80 | ( ch >> 6 ) & 0x3F);
- }
- }
-
- pDst++;
- *pDst = (byte)( 0x80 | ch & 0x3F );
- return pDst + 1;
- }
-
- // Encode *pSrc as a sequence of UTF8 bytes. Write the bytes to pDst and return an updated pointer.
- internal static unsafe void CharToUTF8( ref char * pSrc, char * pSrcEnd, ref byte * pDst ) {
- int ch = *pSrc;
- if ( ch <= 0x7F ) {
- *pDst = (byte)ch;
- pDst++;
- pSrc++;
- }
- else if ( XmlCharType.IsSurrogate( ch ) ) {
- pDst = EncodeSurrogate( pSrc, pSrcEnd, pDst );
- pSrc += 2;
- }
- else {
- pDst = EncodeMultibyteUTF8( ch, pDst );
- pSrc++;
- }
- }
-
-#endif
-
-#ifdef _XML_ENCODED_TEXT_WRITER
-
- protected void ChangeTextContentMark( bool value ) {
- Debug.Assert( inTextContent != value );
- Debug.Assert( inTextContent || ((lastMarkPos & 1) == 0) );
- inTextContent = value;
- if ( lastMarkPos + 1 == textContentMarks.Length ) {
- GrowTextContentMarks();
- }
- textContentMarks[++lastMarkPos] = this.bufPos;
- }
-
- private void GrowTextContentMarks() {
- Debug.Assert( lastMarkPos + 1 == textContentMarks.Length );
- int[] newTextContentMarks = new int[ textContentMarks.Length * 2 ];
- Array.Copy( textContentMarks, newTextContentMarks, textContentMarks.Length );
- textContentMarks = newTextContentMarks;
- }
-
-#endif
-
- // Write NewLineChars to the specified buffer position and return an updated position.
- protected unsafe _BUFFER_TYPE * WriteNewLine( _BUFFER_TYPE * pDst ) {
- fixed ( _BUFFER_TYPE * pDstBegin = _BUFFER ) {
- bufPos = (int) (pDst - pDstBegin);
- // Let RawText do the real work
- RawText( newLineChars );
- return pDstBegin + bufPos;
- }
- }
-
- // Following methods do not check whether pDst is beyond the bufSize because the buffer was allocated with a OVERFLOW to accommodate
- // for the writes of small constant-length string as below.
-
- // Entitize '<' as "<". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * LtEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'l';
- pDst[2] = (_BUFFER_TYPE)'t';
- pDst[3] = (_BUFFER_TYPE)';';
- return pDst + 4;
- }
-
- // Entitize '>' as ">". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * GtEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'g';
- pDst[2] = (_BUFFER_TYPE)'t';
- pDst[3] = (_BUFFER_TYPE)';';
- return pDst + 4;
- }
-
- // Entitize '&' as "&". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * AmpEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'a';
- pDst[2] = (_BUFFER_TYPE)'m';
- pDst[3] = (_BUFFER_TYPE)'p';
- pDst[4] = (_BUFFER_TYPE)';';
- return pDst + 5;
- }
-
- // Entitize '"' as """. Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * QuoteEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'q';
- pDst[2] = (_BUFFER_TYPE)'u';
- pDst[3] = (_BUFFER_TYPE)'o';
- pDst[4] = (_BUFFER_TYPE)'t';
- pDst[5] = (_BUFFER_TYPE)';';
- return pDst + 6;
- }
-
- // Entitize '\t' as "	". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * TabEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'#';
- pDst[2] = (_BUFFER_TYPE)'x';
- pDst[3] = (_BUFFER_TYPE)'9';
- pDst[4] = (_BUFFER_TYPE)';';
- return pDst + 5;
- }
-
- // Entitize 0xa as "
". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * LineFeedEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'#';
- pDst[2] = (_BUFFER_TYPE)'x';
- pDst[3] = (_BUFFER_TYPE)'A';
- pDst[4] = (_BUFFER_TYPE)';';
- return pDst + 5;
- }
-
- // Entitize 0xd as "
". Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * CarriageReturnEntity( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'#';
- pDst[2] = (_BUFFER_TYPE)'x';
- pDst[3] = (_BUFFER_TYPE)'D';
- pDst[4] = (_BUFFER_TYPE)';';
- return pDst + 5;
- }
-
- private static unsafe _BUFFER_TYPE * CharEntity( _BUFFER_TYPE * pDst, char ch ) {
- string s = ((int)ch).ToString( "X",NumberFormatInfo.InvariantInfo );
- pDst[0] = (_BUFFER_TYPE)'&';
- pDst[1] = (_BUFFER_TYPE)'#';
- pDst[2] = (_BUFFER_TYPE)'x';
- pDst += 3;
-
- fixed ( char *pSrc = s ) {
- char *pS = pSrc;
- while ( ( *pDst++ = (_BUFFER_TYPE)*pS++ ) != 0 );
- }
-
- pDst[-1] = (_BUFFER_TYPE)';';
- return pDst;
- }
-
- // Write "<![CDATA[" to the specified buffer. Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * RawStartCData( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)'<';
- pDst[1] = (_BUFFER_TYPE)'!';
- pDst[2] = (_BUFFER_TYPE)'[';
- pDst[3] = (_BUFFER_TYPE)'C';
- pDst[4] = (_BUFFER_TYPE)'D';
- pDst[5] = (_BUFFER_TYPE)'A';
- pDst[6] = (_BUFFER_TYPE)'T';
- pDst[7] = (_BUFFER_TYPE)'A';
- pDst[8] = (_BUFFER_TYPE)'[';
- return pDst + 9;
- }
-
- // Write "]]>" to the specified buffer. Return an updated pointer.
- protected static unsafe _BUFFER_TYPE * RawEndCData( _BUFFER_TYPE * pDst ) {
- pDst[0] = (_BUFFER_TYPE)']';
- pDst[1] = (_BUFFER_TYPE)']';
- pDst[2] = (_BUFFER_TYPE)'>';
- return pDst + 3;
- }
-
- protected unsafe void ValidateContentChars( string chars, string propertyName, bool allowOnlyWhitespace ) {
- if ( allowOnlyWhitespace ) {
- if ( !xmlCharType.IsOnlyWhitespace( chars ) ) {
- throw new ArgumentException( string.Format( SR.Xml_IndentCharsNotWhitespace, propertyName ) );
- }
- }
- else {
- string error = null;
- for ( int i = 0; i < chars.Length; i++ ) {
- if ( !xmlCharType.IsTextChar( chars[i] ) ) {
- switch ( chars[i] ) {
- case '\n':
- case '\r':
- case '\t':
- continue;
- case '<':
- case '&':
- case ']':
- error = string.Format( SR.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs( chars, i ) );
- goto Error;
- default:
- if ( XmlCharType.IsHighSurrogate(chars[i]) ) {
- if ( i + 1 < chars.Length ) {
- if ( XmlCharType.IsLowSurrogate(chars[i + 1]) ) {
- i++;
- continue;
- }
- }
- error = string.Format( SR.Xml_InvalidSurrogateMissingLowChar );
- goto Error;
- }
- else if ( XmlCharType.IsLowSurrogate(chars[i]) ) {
- error = string.Format( SR.Xml_InvalidSurrogateHighChar, ((uint)chars[i]).ToString( "X", CultureInfo.InvariantCulture ) );
- goto Error;
- }
- continue;
- }
- }
- }
- return;
-
- Error:
- throw new ArgumentException( string.Format( SR.Xml_InvalidCharsInIndent, new string[] { propertyName, error } ) );
- }
- }
- }
-
- // Same as base text writer class except that elements, attributes, comments, and pi's are indented.
- internal class _CLASS_NAME_INDENT : _CLASS_NAME {
-//
-// Fields
-//
- protected int indentLevel;
- protected bool newLineOnAttributes;
- protected string indentChars;
-
- protected bool mixedContent;
- private BitStack mixedContentStack;
-
- protected ConformanceLevel conformanceLevel = ConformanceLevel.Auto;
-
-//
-// Constructors
-//
-
-#ifdef _XML_ENCODED_TEXT_WRITER
- public _CLASS_NAME_INDENT( TextWriter writer, XmlWriterSettings settings ) : base( writer, settings ) {
- Init( settings );
- }
-#endif
-
- public _CLASS_NAME_INDENT( Stream stream, XmlWriterSettings settings ) : base( stream, settings ) {
- Init( settings );
- }
-
-//
-// XmlWriter methods
-//
- public override XmlWriterSettings Settings {
- get {
- XmlWriterSettings settings = base.Settings;
-
- settings.ReadOnly = false;
- settings.Indent = true;
- settings.IndentChars = indentChars;
- settings.NewLineOnAttributes = newLineOnAttributes;
- settings.ReadOnly = true;
-
- return settings;
- }
- }
-
- public override void WriteDocType( string name, string pubid, string sysid, string subset ) {
- // Add indentation
- if ( !mixedContent && base.textPos != base.bufPos) {
- WriteIndent();
- }
- base.WriteDocType( name, pubid, sysid, subset );
- }
-
- public override void WriteStartElement( string prefix, string localName, string ns ) {
- Debug.Assert( localName != null && localName.Length != 0 && prefix != null && ns != null );
-
- // Add indentation
- if ( !mixedContent && base.textPos != base.bufPos) {
- WriteIndent();
- }
- indentLevel++;
- mixedContentStack.PushBit( mixedContent );
-
- base.WriteStartElement( prefix, localName, ns );
- }
-
- internal override void StartElementContent() {
- // If this is the root element and we're writing a document
- // do not inherit the mixedContent flag into the root element.
- // This is to allow for whitespace nodes on root level
- // without disabling indentation for the whole document.
- if (indentLevel == 1 && conformanceLevel == ConformanceLevel.Document) {
- mixedContent = false;
- }
- else {
- mixedContent = mixedContentStack.PeekBit();
- }
- base.StartElementContent();
- }
-
- internal override void OnRootElement(ConformanceLevel currentConformanceLevel) {
- // Just remember the current conformance level
- conformanceLevel = currentConformanceLevel;
- }
-
- internal override void WriteEndElement(string prefix, string localName, string ns) {
- // Add indentation
- indentLevel--;
- if ( !mixedContent && base.contentPos != base.bufPos ) {
- // There was content, so try to indent
- if ( base.textPos != base.bufPos ) {
- WriteIndent();
- }
- }
- mixedContent = mixedContentStack.PopBit();
-
- base.WriteEndElement( prefix, localName, ns );
- }
-
- internal override void WriteFullEndElement(string prefix, string localName, string ns) {
- // Add indentation
- indentLevel--;
- if ( !mixedContent && base.contentPos != base.bufPos ) {
- // There was content, so try to indent
- if ( base.textPos != base.bufPos ) {
- WriteIndent();
- }
- }
- mixedContent = mixedContentStack.PopBit();
-
- base.WriteFullEndElement( prefix, localName, ns );
- }
-
- // Same as base class, plus possible indentation.
- public override void WriteStartAttribute( string prefix, string localName, string ns ) {
- // Add indentation
- if ( newLineOnAttributes ) {
- WriteIndent();
- }
-
- base.WriteStartAttribute( prefix, localName, ns );
- }
-
- public override void WriteCData( string text ) {
- mixedContent = true;
- base.WriteCData( text );
- }
-
- public override void WriteComment( string text ) {
- if ( !mixedContent && base.textPos != base.bufPos ) {
- WriteIndent();
- }
-
- base.WriteComment( text );
- }
-
- public override void WriteProcessingInstruction( string target, string text ) {
- if ( !mixedContent && base.textPos != base.bufPos ) {
- WriteIndent();
- }
-
- base.WriteProcessingInstruction( target, text );
- }
-
- public override void WriteEntityRef( string name ) {
- mixedContent = true;
- base.WriteEntityRef( name );
- }
-
- public override void WriteCharEntity( char ch ) {
- mixedContent = true;
- base.WriteCharEntity( ch );
- }
-
- public override void WriteSurrogateCharEntity( char lowChar, char highChar ) {
- mixedContent = true;
- base.WriteSurrogateCharEntity( lowChar, highChar );
- }
-
- public override void WriteWhitespace( string ws ) {
- mixedContent = true;
- base.WriteWhitespace( ws );
- }
-
- public override void WriteString( string text ) {
- mixedContent = true;
- base.WriteString( text );
- }
-
- public override void WriteChars( char[] buffer, int index, int count ) {
- mixedContent = true;
- base.WriteChars( buffer, index, count );
- }
-
- public override void WriteRaw( char[] buffer, int index, int count ) {
- mixedContent = true;
- base.WriteRaw( buffer, index, count );
- }
-
- public override void WriteRaw( string data ) {
- mixedContent = true;
- base.WriteRaw( data );
- }
-
- public override void WriteBase64( byte[] buffer, int index, int count ) {
- mixedContent = true;
- base.WriteBase64( buffer, index, count );
- }
-
-//
-// Private methods
-//
- private void Init( XmlWriterSettings settings ) {
- indentLevel = 0;
- indentChars = settings.IndentChars;
- newLineOnAttributes = settings.NewLineOnAttributes;
- mixedContentStack = new BitStack();
-
- // check indent characters that they are valid XML characters
- if ( base.checkCharacters ) {
- if ( newLineOnAttributes ) {
- base.ValidateContentChars( indentChars, "IndentChars", true );
- base.ValidateContentChars( newLineChars, "NewLineChars", true );
- }
- else {
- base.ValidateContentChars( indentChars, "IndentChars", false );
- if ( base.newLineHandling != NewLineHandling.Replace ) {
- base.ValidateContentChars( newLineChars, "NewLineChars", false );
- }
- }
- }
- }
-
- // Add indentation to output. Write newline and then repeat IndentChars for each indent level.
- private void WriteIndent() {
- RawText( base.newLineChars );
- for ( int i = indentLevel; i > 0; i-- ) {
- RawText( indentChars );
- }
- }
- }
-}
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriter.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGenerator.ttinclude
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Text;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace System.Xml
+{
+ // Concrete implementation of XmlWriter abstract class that serializes events as encoded XML
+ // text. The general-purpose XmlEncodedTextWriter uses the Encoder class to output to any
+ // encoding. The XmlUtf8TextWriter class combined the encoding operation with serialization
+ // in order to achieve better performance.
+ internal partial class <#= ClassName #> : XmlRawWriter
+ {
+ //
+ // Fields
+ //
+ private readonly bool _useAsync;
+
+ // main buffer
+ protected byte[] bufBytes;
+
+ // output stream
+ protected Stream stream;
+
+ // encoding of the stream or text writer
+ protected Encoding encoding;
+
+ // char type tables
+ protected XmlCharType xmlCharType = XmlCharType.Instance;
+
+ // buffer positions
+ protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
+ // close an empty element or in CDATA section detection of double ]; <#= BufferName #>[0] will always be 0
+ protected int textPos = 1; // text end position; don't indent first element, pi, or comment
+ protected int contentPos; // element content end position
+ protected int cdataPos; // cdata end position
+ protected int attrEndPos; // end of the last attribute
+ protected int bufLen = BUFSIZE;
+
+ // flags
+ protected bool writeToNull;
+ protected bool hadDoubleBracket;
+ protected bool inAttributeValue;
+
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ protected int bufBytesUsed;
+ protected char[] bufChars;
+
+ // encoder for encoding chars in specified encoding when writing to stream
+ protected Encoder encoder;
+
+ // output text writer
+ protected TextWriter writer;
+
+ // escaping of characters invalid in the output encoding
+ protected bool trackTextContent;
+ protected bool inTextContent;
+ private int _lastMarkPos;
+ private int[] _textContentMarks; // even indices contain text content start positions
+ // odd indices contain markup start positions
+ private CharEntityEncoderFallback _charEntityFallback;
+<# } #>
+
+ // writer settings
+ protected NewLineHandling newLineHandling;
+ protected bool closeOutput;
+ protected bool omitXmlDeclaration;
+ protected string newLineChars;
+ protected bool checkCharacters;
+
+ protected XmlStandalone standalone;
+ protected XmlOutputMethod outputMethod;
+
+ protected bool autoXmlDeclaration;
+ protected bool mergeCDataSections;
+
+ //
+ // Constants
+ //
+ private const int BUFSIZE = 2048 * 3; // Should be greater than default FileStream size (4096), otherwise the FileStream will try to cache the data
+ private const int ASYNCBUFSIZE = 64 * 1024; // Set async buffer size to 64KB
+ private const int OVERFLOW = 32; // Allow overflow in order to reduce checks when writing out constant size markup
+ private const int INIT_MARKS_COUNT = 64;
+
+ //
+ // Constructors
+ //
+ // Construct and initialize an instance of this class.
+ protected <#= ClassName #>(XmlWriterSettings settings)
+ {
+ _useAsync = settings.Async;
+
+ // copy settings
+ newLineHandling = settings.NewLineHandling;
+ omitXmlDeclaration = settings.OmitXmlDeclaration;
+ newLineChars = settings.NewLineChars;
+ checkCharacters = settings.CheckCharacters;
+ closeOutput = settings.CloseOutput;
+
+ standalone = settings.Standalone;
+ outputMethod = settings.OutputMethod;
+ mergeCDataSections = settings.MergeCDataSections;
+
+ if (checkCharacters && newLineHandling == NewLineHandling.Replace)
+ {
+ ValidateContentChars(newLineChars, "NewLineChars", false);
+ }
+ }
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+
+ // Construct an instance of this class that outputs text to the TextWriter interface.
+ public <#= ClassName #>(TextWriter writer, XmlWriterSettings settings) : this(settings)
+ {
+ Debug.Assert(writer != null && settings != null);
+
+ this.writer = writer;
+ this.encoding = writer.Encoding;
+ // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
+ if (settings.Async)
+ {
+ bufLen = ASYNCBUFSIZE;
+ }
+ this.bufChars = new <#= BufferType #>[bufLen + OVERFLOW];
+
+ // Write the xml declaration
+ if (settings.AutoXmlDeclaration)
+ {
+ WriteXmlDeclaration(standalone);
+ autoXmlDeclaration = true;
+ }
+ }
+<# } #>
+
+ // Construct an instance of this class that serializes to a Stream interface.
+ public <#= ClassName #>(Stream stream, XmlWriterSettings settings) : this(settings)
+ {
+ Debug.Assert(stream != null && settings != null);
+
+ this.stream = stream;
+ this.encoding = settings.Encoding;
+
+ // the buffer is allocated will OVERFLOW in order to reduce checks when writing out constant size markup
+ if (settings.Async)
+ {
+ bufLen = ASYNCBUFSIZE;
+ }
+
+ <#= BufferName #> = new <#= BufferType #>[bufLen + OVERFLOW];
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ // Output UTF-8 byte order mark if Encoding object wants it
+ if (!stream.CanSeek || stream.Position == 0)
+ {
+ ReadOnlySpan<byte> bom = encoding.Preamble;
+ if (bom.Length != 0)
+ {
+ bom.CopyTo(new Span<byte>(bufBytes).Slice(1));
+ bufPos += bom.Length;
+ textPos += bom.Length;
+ }
+ }
+<# } else { #>
+ bufBytes = new byte[bufChars.Length];
+ bufBytesUsed = 0;
+
+ // Init escaping of characters not fitting into the target encoding
+ trackTextContent = true;
+ inTextContent = false;
+ _lastMarkPos = 0;
+ _textContentMarks = new int[INIT_MARKS_COUNT];
+ _textContentMarks[0] = 1;
+
+ _charEntityFallback = new CharEntityEncoderFallback();
+
+ // grab bom before possibly changing encoding settings
+ ReadOnlySpan<byte> bom = encoding.Preamble;
+
+ // the encoding instance this creates can differ from the one passed in
+ this.encoding = Encoding.GetEncoding(
+ settings.Encoding.CodePage,
+ _charEntityFallback,
+ settings.Encoding.DecoderFallback);
+
+ encoder = encoding.GetEncoder();
+
+ if (!stream.CanSeek || stream.Position == 0)
+ {
+ if (bom.Length != 0)
+ {
+ this.stream.Write(bom);
+ }
+ }
+<# } #>
+
+ // Write the xml declaration
+ if (settings.AutoXmlDeclaration)
+ {
+ WriteXmlDeclaration(standalone);
+ autoXmlDeclaration = true;
+ }
+ }
+
+ //
+ // XmlWriter implementation
+ //
+ // Returns settings the writer currently applies.
+ public override XmlWriterSettings Settings
+ {
+ get
+ {
+ XmlWriterSettings settings = new XmlWriterSettings();
+
+ settings.Encoding = encoding;
+ settings.OmitXmlDeclaration = omitXmlDeclaration;
+ settings.NewLineHandling = newLineHandling;
+ settings.NewLineChars = newLineChars;
+ settings.CloseOutput = closeOutput;
+ settings.ConformanceLevel = ConformanceLevel.Auto;
+ settings.CheckCharacters = checkCharacters;
+
+ settings.AutoXmlDeclaration = autoXmlDeclaration;
+ settings.Standalone = standalone;
+ settings.OutputMethod = outputMethod;
+
+ settings.ReadOnly = true;
+ return settings;
+ }
+ }
+
+ // Write the xml declaration. This must be the first call.
+ internal override void WriteXmlDeclaration(XmlStandalone standalone)
+ {
+ // Output xml declaration only if user allows it and it was not already output
+ if (!omitXmlDeclaration && !autoXmlDeclaration)
+ {<# /* Code block is to squash extra line. */
+#><#= SetTextContentMark(4, 1, false) #>
+ RawText("<?xml version=\"");
+
+ // Version
+ RawText("1.0");
+
+ // Encoding
+ if (encoding != null)
+ {
+ RawText("\" encoding=\"");
+ RawText(encoding.WebName);
+ }
+
+ // Standalone
+ if (standalone != XmlStandalone.Omit)
+ {
+ RawText("\" standalone=\"");
+ RawText(standalone == XmlStandalone.Yes ? "yes" : "no");
+ }
+
+ RawText("\"?>");
+ }
+ }
+
+ internal override void WriteXmlDeclaration(string xmldecl)
+ {
+ // Output xml declaration only if user allows it and it was not already output
+ if (!omitXmlDeclaration && !autoXmlDeclaration)
+ {
+ WriteProcessingInstruction("xml", xmldecl);
+ }
+ }
+
+ // Serialize the document type declaration.
+ public override void WriteDocType(string name, string pubid, string sysid, string subset)
+ {
+ Debug.Assert(name != null && name.Length > 0);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ RawText("<!DOCTYPE ");
+ RawText(name);
+ if (pubid != null)
+ {
+ RawText(" PUBLIC \"");
+ RawText(pubid);
+ RawText("\" \"");
+ if (sysid != null)
+ {
+ RawText(sysid);
+ }
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else if (sysid != null)
+ {
+ RawText(" SYSTEM \"");
+ RawText(sysid);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+
+ if (subset != null)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ RawText(subset);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ }
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize the beginning of an element start tag: "<prefix:localName"
+ public override void WriteStartElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ if (prefix != null && prefix.Length != 0)
+ {
+ RawText(prefix);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)':';
+ }
+
+ RawText(localName);
+
+ attrEndPos = bufPos;
+ }
+
+ // Serialize the end of an element start tag in preparation for content serialization: ">"
+ internal override void StartElementContent()
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+
+ // StartElementContent is always called; therefore, in order to allow shortcut syntax, we save the
+ // position of the '>' character. If WriteEndElement is called and no other characters have been
+ // output, then the '>' character can be overwritten with the shortcut syntax " />".
+ contentPos = bufPos;
+ }
+
+ // Serialize an element end tag: "</prefix:localName>", if content was output. Otherwise, serialize
+ // the shortcut syntax: " />".
+ internal override void WriteEndElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (contentPos != bufPos)
+ {
+ // Content has been output, so can't use shortcut syntax
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+
+ if (prefix != null && prefix.Length != 0)
+ {
+ RawText(prefix);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)':';
+ }
+ RawText(localName);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+ else
+ {
+ // Use shortcut syntax; overwrite the already output '>' character
+ bufPos--;
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+ }
+
+ // Serialize a full element end tag: "</prefix:localName>"
+ internal override void WriteFullEndElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+
+ if (prefix != null && prefix.Length != 0)
+ {
+ RawText(prefix);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)':';
+ }
+ RawText(localName);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="'
+ public override void WriteStartAttribute(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (attrEndPos == bufPos)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+
+ if (prefix != null && prefix.Length > 0)
+ {
+ RawText(prefix);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)':';
+ }
+ RawText(localName);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'=';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+
+ inAttributeValue = true;
+ }
+
+ // Serialize the end of an attribute value using double quotes: '"'
+ public override void WriteEndAttribute()
+ {<#
+#><#= SetTextContentMark(3, 1, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ inAttributeValue = false;
+ attrEndPos = bufPos;
+ }
+
+ internal override void WriteNamespaceDeclaration(string prefix, string namespaceName)
+ {
+ Debug.Assert(prefix != null && namespaceName != null);
+
+ WriteStartNamespaceDeclaration(prefix);
+ WriteString(namespaceName);
+ WriteEndNamespaceDeclaration();
+ }
+
+ internal override bool SupportsNamespaceDeclarationInChunks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ internal override void WriteStartNamespaceDeclaration(string prefix)
+ {
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (prefix.Length == 0)
+ {
+ RawText(" xmlns=\"");
+ }
+ else
+ {
+ RawText(" xmlns:");
+ RawText(prefix);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'=';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+
+ inAttributeValue = true;<#
+#><#= SetTextContentMark(3, true) #>
+ }
+
+ internal override void WriteEndNamespaceDeclaration()
+ {<#
+#><#= SetTextContentMark(3, 1, false) #>
+ inAttributeValue = false;
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ attrEndPos = bufPos;
+ }
+
+ // Serialize a CData section. If the "]]>" pattern is found within
+ // the text, replace it with "]]><![CDATA[>".
+ public override void WriteCData(string text)
+ {
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (mergeCDataSections && bufPos == cdataPos)
+ {
+ // Merge adjacent cdata sections - overwrite the "]]>" characters
+ Debug.Assert(bufPos >= 4);
+ bufPos -= 3;
+ }
+ else
+ {
+ // Start a new cdata section
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'C';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'D';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'T';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ }
+
+ WriteCDataSection(text);
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+
+ textPos = bufPos;
+ cdataPos = bufPos;
+ }
+
+ // Serialize a comment.
+ public override void WriteComment(string text)
+ {
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+
+ WriteCommentOrPi(text, '-');
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize a processing instruction.
+ public override void WriteProcessingInstruction(string name, string text)
+ {
+ Debug.Assert(name != null && name.Length > 0);
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?';
+ RawText(name);
+
+ if (text.Length > 0)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ WriteCommentOrPi(text, '?');
+ }
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize an entity reference.
+ public override void WriteEntityRef(string name)
+ {
+ Debug.Assert(name != null && name.Length > 0);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ RawText(name);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+
+ if (bufPos > bufLen)
+ {
+ FlushBuffer();
+ }
+
+ textPos = bufPos;
+ }
+
+ // Serialize a character entity reference.
+ public override void WriteCharEntity(char ch)
+ {
+ string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo);
+
+ if (checkCharacters && !xmlCharType.IsCharData(ch))
+ {
+ // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char
+ throw XmlConvert.CreateInvalidCharException(ch, '\0');
+ }<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x';
+ RawText(strVal);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+
+ if (bufPos > bufLen)
+ {
+ FlushBuffer();
+ }
+
+ textPos = bufPos;
+ }
+
+ // Serialize a whitespace node.
+
+ public override unsafe void WriteWhitespace(string ws)
+ {
+ Debug.Assert(ws != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ fixed (char* pSrc = ws)
+ {
+ char* pSrcEnd = pSrc + ws.Length;
+ if (inAttributeValue)
+ {
+ WriteAttributeTextBlock(pSrc, pSrcEnd);
+ }
+ else
+ {
+ WriteElementTextBlock(pSrc, pSrcEnd);
+ }
+ }
+ }
+
+ // Serialize either attribute or element text using XML rules.
+
+ public override unsafe void WriteString(string text)
+ {
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, true) #>
+
+ fixed (char* pSrc = text)
+ {
+ char* pSrcEnd = pSrc + text.Length;
+ if (inAttributeValue)
+ {
+ WriteAttributeTextBlock(pSrc, pSrcEnd);
+ }
+ else
+ {
+ WriteElementTextBlock(pSrc, pSrcEnd);
+ }
+ }
+ }
+
+ // Serialize surrogate character entity.
+ public override void WriteSurrogateCharEntity(char lowChar, char highChar)
+ {<#
+#><#= SetTextContentMark(3, 1, false) #>
+ int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar);
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x';
+ RawText(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo));
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+ textPos = bufPos;
+ }
+
+ // Serialize either attribute or element text using XML rules.
+ // Arguments are validated in the XmlWellformedWriter layer.
+
+ public override unsafe void WriteChars(char[] buffer, int index, int count)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(index >= 0);
+ Debug.Assert(count >= 0 && index + count <= buffer.Length);<#
+
+#><#= SetTextContentMark(3, true) #>
+
+ fixed (char* pSrcBegin = &buffer[index])
+ {
+ if (inAttributeValue)
+ {
+ WriteAttributeTextBlock(pSrcBegin, pSrcBegin + count);
+ }
+ else
+ {
+ WriteElementTextBlock(pSrcBegin, pSrcBegin + count);
+ }
+ }
+ }
+
+ // Serialize raw data.
+ // Arguments are validated in the XmlWellformedWriter layer
+
+ public override unsafe void WriteRaw(char[] buffer, int index, int count)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(index >= 0);
+ Debug.Assert(count >= 0 && index + count <= buffer.Length);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ fixed (char* pSrcBegin = &buffer[index])
+ {
+ WriteRawWithCharChecking(pSrcBegin, pSrcBegin + count);
+ }
+
+ textPos = bufPos;
+ }
+
+ // Serialize raw data.
+
+ public override unsafe void WriteRaw(string data)
+ {
+ Debug.Assert(data != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ fixed (char* pSrcBegin = data)
+ {
+ WriteRawWithCharChecking(pSrcBegin, pSrcBegin + data.Length);
+ }
+
+ textPos = bufPos;
+ }
+
+ // Flush all bytes in the buffer to output and close the output stream or writer.
+ public override void Close()
+ {
+ try
+ {
+ FlushBuffer();
+ FlushEncoder();
+ }
+ finally
+ {
+ // Future calls to Close or Flush shouldn't write to Stream or Writer
+ writeToNull = true;
+
+ if (stream != null)
+ {
+ try
+ {
+ stream.Flush();
+ }
+ finally
+ {
+ try
+ {
+ if (closeOutput)
+ {
+ stream.Dispose();
+ }
+ }
+ finally
+ {
+ stream = null;
+ }
+ }
+ }
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ else if (writer != null)
+ {
+ try
+ {
+ writer.Flush();
+ }
+ finally
+ {
+ try
+ {
+ if (closeOutput)
+ {
+ writer.Dispose();
+ }
+ }
+ finally
+ {
+ writer = null;
+ }
+ }
+ }
+<# } #>
+ }
+ }
+
+ // Flush all characters in the buffer to output and call Flush() on the output object.
+ public override void Flush()
+ {
+ FlushBuffer();
+ FlushEncoder();
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ if (stream != null)
+ {
+ stream.Flush();
+ }
+<# } else { #>
+ if (stream != null)
+ {
+ stream.Flush();
+ }
+ else if (writer != null)
+ {
+ writer.Flush();
+ }
+<# } #>
+ }
+
+ //
+ // Implementation methods
+ //
+ // Flush all characters in the buffer to output. Do not flush the output object.
+ protected virtual void FlushBuffer()
+ {
+ try
+ {
+ // Output all characters (except for previous characters stored at beginning of buffer)
+ if (!writeToNull)
+ {
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ Debug.Assert(stream != null);
+ stream.Write(<#= BufferName #>, 1, bufPos - 1);
+<# } else { #>
+ Debug.Assert(stream != null || writer != null);
+
+ if (stream != null)
+ {
+ if (trackTextContent)
+ {
+ _charEntityFallback.Reset(_textContentMarks, _lastMarkPos);
+ // reset text content tracking
+
+ if ((_lastMarkPos & 1) != 0)
+ {
+ // If the previous buffer ended inside a text content we need to preserve that info
+ // which means the next index to which we write has to be even
+ _textContentMarks[1] = 1;
+ _lastMarkPos = 1;
+ }
+ else
+ {
+ _lastMarkPos = 0;
+ }
+ Debug.Assert(_textContentMarks[0] == 1);
+ }
+ EncodeChars(1, bufPos, true);
+ }
+ else
+ {
+ // Write text to TextWriter
+ writer.Write(<#= BufferName #>, 1, bufPos - 1);
+ }
+<# } #>
+ }
+ }
+ catch
+ {
+ // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream
+ writeToNull = true;
+ throw;
+ }
+ finally
+ {
+ // Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
+ <#= BufferName #>[0] = <#= BufferName #>[bufPos - 1];
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ if (IsSurrogateByte(<#= BufferName #>[0]))
+ {
+ // Last character was the first byte in a surrogate encoding, so move last three
+ // bytes of encoding to the beginning of the buffer.
+ <#= BufferName #>[1] = <#= BufferName #>[bufPos];
+ <#= BufferName #>[2] = <#= BufferName #>[bufPos + 1];
+ <#= BufferName #>[3] = <#= BufferName #>[bufPos + 2];
+ }
+<# } #>
+
+ // Reset buffer position
+ textPos = (textPos == bufPos) ? 1 : 0;
+ attrEndPos = (attrEndPos == bufPos) ? 1 : 0;
+ contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible
+ cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible
+ bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
+ // close an empty element or in CDATA section detection of double ]; <#= BufferName #>[0] will always be 0
+ }
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ private void FlushEncoder()
+ {
+ // intentionally empty
+
+ }
+<# } else { #>
+ private void EncodeChars(int startOffset, int endOffset, bool writeAllToStream)
+ {
+ // Write encoded text to stream
+ int chEnc;
+ int bEnc;
+ bool completed;
+ while (startOffset < endOffset)
+ {
+ if (_charEntityFallback != null)
+ {
+ _charEntityFallback.StartOffset = startOffset;
+ }
+ encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed);
+ startOffset += chEnc;
+ bufBytesUsed += bEnc;
+ if (bufBytesUsed >= (bufBytes.Length - 16))
+ {
+ stream.Write(bufBytes, 0, bufBytesUsed);
+ bufBytesUsed = 0;
+ }
+ }
+ if (writeAllToStream && bufBytesUsed > 0)
+ {
+ stream.Write(bufBytes, 0, bufBytesUsed);
+ bufBytesUsed = 0;
+ }
+ }
+
+ private void FlushEncoder()
+ {
+ Debug.Assert(bufPos == 1);
+ if (stream != null)
+ {
+ int chEnc;
+ int bEnc;
+ bool completed;
+ // decode no chars, just flush
+ encoder.Convert(<#= BufferName #>, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed);
+ if (bEnc != 0)
+ {
+ stream.Write(bufBytes, 0, bEnc);
+ }
+ }
+ }
+<# } #>
+
+ // Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
+ // are entitized.
+ protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd)
+ {
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ pDst = AmpEntity(pDst);
+ break;
+ case '<':
+ pDst = LtEntity(pDst);
+ break;
+ case '>':
+ pDst = GtEntity(pDst);
+ break;
+ case '"':
+ pDst = QuoteEntity(pDst);
+ break;
+ case '\'':
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0x9:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape tab in attributes
+ pDst = TabEntity(pDst);
+ }
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape new lines in attributes
+ pDst = CarriageReturnEntity(pDst);
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape new lines in attributes
+ pDst = LineFeedEntity(pDst);
+ }
+ break;
+ default:
+<#= EncodeChar(7, true) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ // Serialize text that is part of element content. The '&', '<', and '>' characters
+ // are entitized.
+ protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd)
+ {
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ pDst = AmpEntity(pDst);
+ break;
+ case '<':
+ pDst = LtEntity(pDst);
+ break;
+ case '>':
+ pDst = GtEntity(pDst);
+ break;
+ case '"':
+ case '\'':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xD:
+ switch (newLineHandling)
+ {
+ case NewLineHandling.Replace:
+ // Replace "\r\n", or "\r" with NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ pDst = WriteNewLine(pDst);
+ break;
+
+ case NewLineHandling.Entitize:
+ // Entitize 0xD
+ pDst = CarriageReturnEntity(pDst);
+ break;
+ case NewLineHandling.None:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ }
+ break;
+ default:
+<#= EncodeChar(7, true) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ textPos = bufPos;
+ contentPos = 0;
+ }
+ }
+
+ protected unsafe void RawText(string s)
+ {
+ Debug.Assert(s != null);
+
+ fixed (char* pSrcBegin = s)
+ {
+ RawText(pSrcBegin, pSrcBegin + s.Length);
+ }
+ }
+
+ protected unsafe void RawText(char* pSrcBegin, char* pSrcEnd)
+ {
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+ char* pSrc = pSrcBegin;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart))
+<# } #>
+ {
+ pSrc++;
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+<#= EncodeChar(5, false) #>
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ protected unsafe void WriteRawWithCharChecking(char* pSrcBegin, char* pSrcEnd)
+ {
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case ']':
+ case '<':
+ case '&':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ default:
+<#= EncodeChar(7, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ protected unsafe void WriteCommentOrPi(string text, int stopChar)
+ {
+ if (text.Length == 0)
+ {
+ if (bufPos >= bufLen)
+ {
+ FlushBuffer();
+ }
+ return;
+ }
+ // write text
+ fixed (char* pSrcBegin = text)
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+
+ char* pSrcEnd = pSrcBegin + text.Length;
+
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case '-':
+ *pDst = (<#= BufferType #>)'-';
+ pDst++;
+ if (ch == stopChar)
+ {
+ // Insert space between adjacent dashes or before comment's end dashes
+ if (pSrc + 1 == pSrcEnd || *(pSrc + 1) == '-')
+ {
+ *pDst = (<#= BufferType #>)' ';
+ pDst++;
+ }
+ }
+ break;
+ case '?':
+ *pDst = (<#= BufferType #>)'?';
+ pDst++;
+ if (ch == stopChar)
+ {
+ // Processing instruction: insert space between adjacent '?' and '>'
+ if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
+ {
+ *pDst = (<#= BufferType #>)' ';
+ pDst++;
+ }
+ }
+ break;
+ case ']':
+ *pDst = (<#= BufferType #>)']';
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case '<':
+ case '&':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ default:
+<#= EncodeChar(7, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+ protected unsafe void WriteCDataSection(string text)
+ {
+ if (text.Length == 0)
+ {
+ if (bufPos >= bufLen)
+ {
+ FlushBuffer();
+ }
+ return;
+ }
+
+ // write text
+
+ fixed (char* pSrcBegin = text)
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+
+ char* pSrcEnd = pSrcBegin + text.Length;
+
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']'))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ FlushBuffer();
+ pDst = pDstBegin + 1;
+ continue;
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case '>':
+ if (hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']')
+ { // pDst[-1] will always correct - there is a padding character at <#= BufferName #>[0]
+ // The characters "]]>" were found within the CData text
+ pDst = RawEndCData(pDst);
+ pDst = RawStartCData(pDst);
+ }
+ *pDst = (<#= BufferType #>)'>';
+ pDst++;
+ break;
+ case ']':
+ if (pDst[-1] == (<#= BufferType #>)']')
+ { // pDst[-1] will always correct - there is a padding character at <#= BufferName #>[0]
+ hadDoubleBracket = true;
+ }
+ else
+ {
+ hadDoubleBracket = false;
+ }
+ *pDst = (<#= BufferType #>)']';
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ pDst = WriteNewLine(pDst);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case '&':
+ case '<':
+ case '"':
+ case '\'':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ default:
+<#= EncodeChar(7, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ // Returns true if UTF8 encoded byte is first of four bytes that encode a surrogate pair.
+ // To do this, detect the bit pattern 11110xxx.
+ private static bool IsSurrogateByte(byte b)
+ {
+ return (b & 0xF8) == 0xF0;
+ }
+<# } #>
+
+ private static unsafe <#= BufferType #>* EncodeSurrogate(char* pSrc, char* pSrcEnd, <#= BufferType #>* pDst)
+ {
+ Debug.Assert(XmlCharType.IsSurrogate(*pSrc));
+
+ int ch = *pSrc;
+ if (ch <= XmlCharType.SurHighEnd)
+ {
+ if (pSrc + 1 < pSrcEnd)
+ {
+ int lowChar = pSrc[1];
+ if (lowChar >= XmlCharType.SurLowStart &&
+ (LocalAppContextSwitches.DontThrowOnInvalidSurrogatePairs || lowChar <= XmlCharType.SurLowEnd))
+ {
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ // Calculate Unicode scalar value for easier manipulations (see section 3.7 in Unicode spec)
+ // The scalar value repositions surrogate values to start at 0x10000.
+
+ ch = XmlCharType.CombineSurrogateChar(lowChar, ch);
+
+ pDst[0] = (byte)(0xF0 | (ch >> 18));
+ pDst[1] = (byte)(0x80 | (ch >> 12) & 0x3F);
+ pDst[2] = (byte)(0x80 | (ch >> 6) & 0x3F);
+ pDst[3] = (byte)(0x80 | ch & 0x3F);
+ pDst += 4;
+<# } else { #>
+ pDst[0] = (<#= BufferType #>)ch;
+ pDst[1] = (<#= BufferType #>)lowChar;
+ pDst += 2;
+<# } #>
+
+ return pDst;
+ }
+ throw XmlConvert.CreateInvalidSurrogatePairException((char)lowChar, (char)ch);
+ }
+ throw new ArgumentException(SR.Xml_InvalidSurrogateMissingLowChar);
+ }
+ throw XmlConvert.CreateInvalidHighSurrogateCharException((char)ch);
+ }
+
+ private unsafe <#= BufferType #>* InvalidXmlChar(int ch, <#= BufferType #>* pDst, bool entitize)
+ {
+ Debug.Assert(!xmlCharType.IsWhiteSpace((char)ch));
+ Debug.Assert(!xmlCharType.IsAttributeValueChar((char)ch));
+
+ if (checkCharacters)
+ {
+ // This method will never be called on surrogates, so it is ok to pass in '\0' to the CreateInvalidCharException
+ throw XmlConvert.CreateInvalidCharException((char)ch, '\0');
+ }
+ else
+ {
+ if (entitize)
+ {
+ return CharEntity(pDst, (char)ch);
+ }
+ else
+ {
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ if (ch < 0x80)
+ {
+<# } #>
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ }
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ }
+<# } #>
+ return pDst;
+ }
+ }
+ }
+
+ internal unsafe void EncodeChar(ref char* pSrc, char* pSrcEnd, ref <#= BufferType #>* pDst)
+ {
+ int ch = *pSrc;
+<#= EncodeChar(3, false) #>
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ internal static unsafe byte* EncodeMultibyteUTF8(int ch, byte* pDst)
+ {
+ Debug.Assert(ch >= 0x80 && !XmlCharType.IsSurrogate(ch));
+
+ unchecked
+ {
+ /* UTF8-2: If ch is in 0x80-0x7ff range, then use 2 bytes to encode it */
+ if (ch < 0x800)
+ {
+ *pDst = (byte)((sbyte)0xC0 | (ch >> 6));
+ }
+ /* UTF8-3: If ch is anything else, then default to using 3 bytes to encode it. */
+ else
+ {
+ *pDst = (byte)((sbyte)0xE0 | (ch >> 12));
+ pDst++;
+
+ *pDst = (byte)((sbyte)0x80 | (ch >> 6) & 0x3F);
+ }
+ }
+
+ pDst++;
+ *pDst = (byte)(0x80 | ch & 0x3F);
+ return pDst + 1;
+ }
+
+ // Encode *pSrc as a sequence of UTF8 bytes. Write the bytes to pDst and return an updated pointer.
+
+ internal static unsafe void CharToUTF8(ref char* pSrc, char* pSrcEnd, ref byte* pDst)
+ {
+ int ch = *pSrc;
+ if (ch <= 0x7F)
+ {
+ *pDst = (byte)ch;
+ pDst++;
+ pSrc++;
+ }
+ else if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
+ }
+<# } #>
+
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ protected void ChangeTextContentMark(bool value)
+ {
+ Debug.Assert(inTextContent != value);
+ Debug.Assert(inTextContent || ((_lastMarkPos & 1) == 0));
+ inTextContent = value;
+ if (_lastMarkPos + 1 == _textContentMarks.Length)
+ {
+ GrowTextContentMarks();
+ }
+ _textContentMarks[++_lastMarkPos] = bufPos;
+ }
+
+ private void GrowTextContentMarks()
+ {
+ Debug.Assert(_lastMarkPos + 1 == _textContentMarks.Length);
+ int[] newTextContentMarks = new int[_textContentMarks.Length * 2];
+ Array.Copy(_textContentMarks, newTextContentMarks, _textContentMarks.Length);
+ _textContentMarks = newTextContentMarks;
+ }
+<# } #>
+ // Write NewLineChars to the specified buffer position and return an updated position.
+ protected unsafe <#= BufferType #>* WriteNewLine(<#= BufferType #>* pDst)
+ {
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ // Let RawText do the real work
+ RawText(newLineChars);
+ return pDstBegin + bufPos;
+ }
+ }
+
+ // Following methods do not check whether pDst is beyond the bufSize because the buffer was allocated with a OVERFLOW to accommodate
+ // for the writes of small constant-length string as below.
+
+ // Entitize '<' as "<". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* LtEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'l';
+ pDst[2] = (<#= BufferType #>)'t';
+ pDst[3] = (<#= BufferType #>)';';
+ return pDst + 4;
+ }
+
+ // Entitize '>' as ">". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* GtEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'g';
+ pDst[2] = (<#= BufferType #>)'t';
+ pDst[3] = (<#= BufferType #>)';';
+ return pDst + 4;
+ }
+
+ // Entitize '&' as "&". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* AmpEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'a';
+ pDst[2] = (<#= BufferType #>)'m';
+ pDst[3] = (<#= BufferType #>)'p';
+ pDst[4] = (<#= BufferType #>)';';
+ return pDst + 5;
+ }
+
+ // Entitize '"' as """. Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* QuoteEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'q';
+ pDst[2] = (<#= BufferType #>)'u';
+ pDst[3] = (<#= BufferType #>)'o';
+ pDst[4] = (<#= BufferType #>)'t';
+ pDst[5] = (<#= BufferType #>)';';
+ return pDst + 6;
+ }
+
+ // Entitize '\t' as "	". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* TabEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'#';
+ pDst[2] = (<#= BufferType #>)'x';
+ pDst[3] = (<#= BufferType #>)'9';
+ pDst[4] = (<#= BufferType #>)';';
+ return pDst + 5;
+ }
+
+ // Entitize 0xa as "
". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* LineFeedEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'#';
+ pDst[2] = (<#= BufferType #>)'x';
+ pDst[3] = (<#= BufferType #>)'A';
+ pDst[4] = (<#= BufferType #>)';';
+ return pDst + 5;
+ }
+
+ // Entitize 0xd as "
". Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* CarriageReturnEntity(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'#';
+ pDst[2] = (<#= BufferType #>)'x';
+ pDst[3] = (<#= BufferType #>)'D';
+ pDst[4] = (<#= BufferType #>)';';
+ return pDst + 5;
+ }
+
+ private static unsafe <#= BufferType #>* CharEntity(<#= BufferType #>* pDst, char ch)
+ {
+ string s = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo);
+ pDst[0] = (<#= BufferType #>)'&';
+ pDst[1] = (<#= BufferType #>)'#';
+ pDst[2] = (<#= BufferType #>)'x';
+ pDst += 3;
+
+ fixed (char* pSrc = s)
+ {
+ char* pS = pSrc;
+ while ((*pDst++ = (<#= BufferType #>)*pS++) != 0) ;
+ }
+
+ pDst[-1] = (<#= BufferType #>)';';
+ return pDst;
+ }
+
+ // Write "<![CDATA[" to the specified buffer. Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* RawStartCData(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)'<';
+ pDst[1] = (<#= BufferType #>)'!';
+ pDst[2] = (<#= BufferType #>)'[';
+ pDst[3] = (<#= BufferType #>)'C';
+ pDst[4] = (<#= BufferType #>)'D';
+ pDst[5] = (<#= BufferType #>)'A';
+ pDst[6] = (<#= BufferType #>)'T';
+ pDst[7] = (<#= BufferType #>)'A';
+ pDst[8] = (<#= BufferType #>)'[';
+ return pDst + 9;
+ }
+
+ // Write "]]>" to the specified buffer. Return an updated pointer.
+
+ protected static unsafe <#= BufferType #>* RawEndCData(<#= BufferType #>* pDst)
+ {
+ pDst[0] = (<#= BufferType #>)']';
+ pDst[1] = (<#= BufferType #>)']';
+ pDst[2] = (<#= BufferType #>)'>';
+ return pDst + 3;
+ }
+
+ protected unsafe void ValidateContentChars(string chars, string propertyName, bool allowOnlyWhitespace)
+ {
+ if (allowOnlyWhitespace)
+ {
+ if (!xmlCharType.IsOnlyWhitespace(chars))
+ {
+ throw new ArgumentException(SR.Format(SR.Xml_IndentCharsNotWhitespace, propertyName));
+ }
+ }
+ else
+ {
+ string error = null;
+ for (int i = 0; i < chars.Length; i++)
+ {
+ if (!xmlCharType.IsTextChar(chars[i]))
+ {
+ switch (chars[i])
+ {
+ case '\n':
+ case '\r':
+ case '\t':
+ continue;
+ case '<':
+ case '&':
+ case ']':
+ error = SR.Format(SR.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs(chars, i));
+ goto Error;
+ default:
+ if (XmlCharType.IsHighSurrogate(chars[i]))
+ {
+ if (i + 1 < chars.Length)
+ {
+ if (XmlCharType.IsLowSurrogate(chars[i + 1]))
+ {
+ i++;
+ continue;
+ }
+ }
+ error = SR.Xml_InvalidSurrogateMissingLowChar;
+ goto Error;
+ }
+ else if (XmlCharType.IsLowSurrogate(chars[i]))
+ {
+ error = SR.Format(SR.Xml_InvalidSurrogateHighChar, ((uint)chars[i]).ToString("X", CultureInfo.InvariantCulture));
+ goto Error;
+ }
+ continue;
+ }
+ }
+ }
+ return;
+
+ Error:
+ throw new ArgumentException(SR.Format(SR.Xml_InvalidCharsInIndent, new string[] { propertyName, error }));
+ }
+ }
+ }
+
+ // Same as base text writer class except that elements, attributes, comments, and pi's are indented.
+ internal partial class <#= ClassNameIndent #> : <#= ClassName #>
+ {
+ //
+ // Fields
+ //
+ protected int indentLevel;
+ protected bool newLineOnAttributes;
+ protected string indentChars;
+
+ protected bool mixedContent;
+ private BitStack _mixedContentStack;
+
+ protected ConformanceLevel conformanceLevel = ConformanceLevel.Auto;
+
+ //
+ // Constructors
+ //
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+
+ public <#= ClassNameIndent #>(TextWriter writer, XmlWriterSettings settings) : base(writer, settings)
+ {
+ Init(settings);
+ }
+<# } #>
+
+ public <#= ClassNameIndent #>(Stream stream, XmlWriterSettings settings) : base(stream, settings)
+ {
+ Init(settings);
+ }
+
+ //
+ // XmlWriter methods
+ //
+ public override XmlWriterSettings Settings
+ {
+ get
+ {
+ XmlWriterSettings settings = base.Settings;
+
+ settings.ReadOnly = false;
+ settings.Indent = true;
+ settings.IndentChars = indentChars;
+ settings.NewLineOnAttributes = newLineOnAttributes;
+ settings.ReadOnly = true;
+
+ return settings;
+ }
+ }
+
+ public override void WriteDocType(string name, string pubid, string sysid, string subset)
+ {
+ // Add indentation
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+ base.WriteDocType(name, pubid, sysid, subset);
+ }
+
+ public override void WriteStartElement(string prefix, string localName, string ns)
+ {
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
+
+ // Add indentation
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+ indentLevel++;
+ _mixedContentStack.PushBit(mixedContent);
+
+ base.WriteStartElement(prefix, localName, ns);
+ }
+
+ internal override void StartElementContent()
+ {
+ // If this is the root element and we're writing a document
+ // do not inherit the mixedContent flag into the root element.
+ // This is to allow for whitespace nodes on root level
+ // without disabling indentation for the whole document.
+ if (indentLevel == 1 && conformanceLevel == ConformanceLevel.Document)
+ {
+ mixedContent = false;
+ }
+ else
+ {
+ mixedContent = _mixedContentStack.PeekBit();
+ }
+ base.StartElementContent();
+ }
+
+ internal override void OnRootElement(ConformanceLevel currentConformanceLevel)
+ {
+ // Just remember the current conformance level
+ conformanceLevel = currentConformanceLevel;
+ }
+
+ internal override void WriteEndElement(string prefix, string localName, string ns)
+ {
+ // Add indentation
+ indentLevel--;
+ if (!mixedContent && base.contentPos != base.bufPos)
+ {
+ // There was content, so try to indent
+ if (base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+ }
+ mixedContent = _mixedContentStack.PopBit();
+
+ base.WriteEndElement(prefix, localName, ns);
+ }
+
+ internal override void WriteFullEndElement(string prefix, string localName, string ns)
+ {
+ // Add indentation
+ indentLevel--;
+ if (!mixedContent && base.contentPos != base.bufPos)
+ {
+ // There was content, so try to indent
+ if (base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+ }
+ mixedContent = _mixedContentStack.PopBit();
+
+ base.WriteFullEndElement(prefix, localName, ns);
+ }
+
+ // Same as base class, plus possible indentation.
+ public override void WriteStartAttribute(string prefix, string localName, string ns)
+ {
+ // Add indentation
+ if (newLineOnAttributes)
+ {
+ WriteIndent();
+ }
+
+ base.WriteStartAttribute(prefix, localName, ns);
+ }
+
+ public override void WriteCData(string text)
+ {
+ mixedContent = true;
+ base.WriteCData(text);
+ }
+
+ public override void WriteComment(string text)
+ {
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+
+ base.WriteComment(text);
+ }
+
+ public override void WriteProcessingInstruction(string target, string text)
+ {
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ WriteIndent();
+ }
+
+ base.WriteProcessingInstruction(target, text);
+ }
+
+ public override void WriteEntityRef(string name)
+ {
+ mixedContent = true;
+ base.WriteEntityRef(name);
+ }
+
+ public override void WriteCharEntity(char ch)
+ {
+ mixedContent = true;
+ base.WriteCharEntity(ch);
+ }
+
+ public override void WriteSurrogateCharEntity(char lowChar, char highChar)
+ {
+ mixedContent = true;
+ base.WriteSurrogateCharEntity(lowChar, highChar);
+ }
+
+ public override void WriteWhitespace(string ws)
+ {
+ mixedContent = true;
+ base.WriteWhitespace(ws);
+ }
+
+ public override void WriteString(string text)
+ {
+ mixedContent = true;
+ base.WriteString(text);
+ }
+
+ public override void WriteChars(char[] buffer, int index, int count)
+ {
+ mixedContent = true;
+ base.WriteChars(buffer, index, count);
+ }
+
+ public override void WriteRaw(char[] buffer, int index, int count)
+ {
+ mixedContent = true;
+ base.WriteRaw(buffer, index, count);
+ }
+
+ public override void WriteRaw(string data)
+ {
+ mixedContent = true;
+ base.WriteRaw(data);
+ }
+
+ public override void WriteBase64(byte[] buffer, int index, int count)
+ {
+ mixedContent = true;
+ base.WriteBase64(buffer, index, count);
+ }
+
+ //
+ // Private methods
+ //
+ private void Init(XmlWriterSettings settings)
+ {
+ indentLevel = 0;
+ indentChars = settings.IndentChars;
+ newLineOnAttributes = settings.NewLineOnAttributes;
+ _mixedContentStack = new BitStack();
+
+ // check indent characters that they are valid XML characters
+ if (base.checkCharacters)
+ {
+ if (newLineOnAttributes)
+ {
+ base.ValidateContentChars(indentChars, "IndentChars", true);
+ base.ValidateContentChars(newLineChars, "NewLineChars", true);
+ }
+ else
+ {
+ base.ValidateContentChars(indentChars, "IndentChars", false);
+ if (base.newLineHandling != NewLineHandling.Replace)
+ {
+ base.ValidateContentChars(newLineChars, "NewLineChars", false);
+ }
+ }
+ }
+ }
+
+ // Add indentation to output. Write newline and then repeat IndentChars for each indent level.
+ private void WriteIndent()
+ {
+ RawText(base.newLineChars);
+ for (int i = indentLevel; i > 0; i--)
+ {
+ RawText(indentChars);
+ }
+ }
+ }
+}
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriter.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGeneratorAsync.ttinclude
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Text;
+using System.Diagnostics;
+using System.Globalization;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace System.Xml
+{
+ // Concrete implementation of XmlWriter abstract class that serializes events as encoded XML
+ // text. The general-purpose XmlEncodedTextWriter uses the Encoder class to output to any
+ // encoding. The XmlUtf8TextWriter class combined the encoding operation with serialization
+ // in order to achieve better performance.
+ internal partial class <#= ClassName #> : XmlRawWriter
+ {
+ protected void CheckAsyncCall()
+ {
+ if (!_useAsync)
+ {
+ throw new InvalidOperationException(SR.Xml_WriterAsyncNotSetException);
+ }
+ }
+
+ // Write the xml declaration. This must be the first call.
+ internal override async Task WriteXmlDeclarationAsync(XmlStandalone standalone)
+ {
+ CheckAsyncCall();
+ // Output xml declaration only if user allows it and it was not already output
+ if (!omitXmlDeclaration && !autoXmlDeclaration)
+ {<# /* Code block is to squash extra line. */
+#><#= SetTextContentMark(4, 1, false) #>
+ await RawTextAsync("<?xml version=\"").ConfigureAwait(false);
+
+ // Version
+ await RawTextAsync("1.0").ConfigureAwait(false);
+
+ // Encoding
+ if (encoding != null)
+ {
+ await RawTextAsync("\" encoding=\"").ConfigureAwait(false);
+ await RawTextAsync(encoding.WebName).ConfigureAwait(false);
+ }
+
+ // Standalone
+ if (standalone != XmlStandalone.Omit)
+ {
+ await RawTextAsync("\" standalone=\"").ConfigureAwait(false);
+ await RawTextAsync(standalone == XmlStandalone.Yes ? "yes" : "no").ConfigureAwait(false);
+ }
+
+ await RawTextAsync("\"?>").ConfigureAwait(false);
+ }
+ }
+
+ internal override Task WriteXmlDeclarationAsync(string xmldecl)
+ {
+ CheckAsyncCall();
+ // Output xml declaration only if user allows it and it was not already output
+ if (!omitXmlDeclaration && !autoXmlDeclaration)
+ {
+ return WriteProcessingInstructionAsync("xml", xmldecl);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ // Serialize the document type declaration.
+ public override async Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset)
+ {
+ CheckAsyncCall();
+ Debug.Assert(name != null && name.Length > 0);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ await RawTextAsync("<!DOCTYPE ").ConfigureAwait(false);
+ await RawTextAsync(name).ConfigureAwait(false);
+ if (pubid != null)
+ {
+ await RawTextAsync(" PUBLIC \"").ConfigureAwait(false);
+ await RawTextAsync(pubid).ConfigureAwait(false);
+ await RawTextAsync("\" \"").ConfigureAwait(false);
+ if (sysid != null)
+ {
+ await RawTextAsync(sysid).ConfigureAwait(false);
+ }
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else if (sysid != null)
+ {
+ await RawTextAsync(" SYSTEM \"").ConfigureAwait(false);
+ await RawTextAsync(sysid).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+ else
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+
+ if (subset != null)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ await RawTextAsync(subset).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ }
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize the beginning of an element start tag: "<prefix:localName"
+ public override Task WriteStartElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ Task task;
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ if (prefix != null && prefix.Length != 0)
+ {
+ task = RawTextAsync(prefix, ":", localName);
+ }
+ else
+ {
+ task = RawTextAsync(localName);
+ }
+ return task.CallVoidFuncWhenFinishAsync(thisRef => thisRef.WriteStartElementAsync_SetAttEndPos(), this);
+ }
+
+ private void WriteStartElementAsync_SetAttEndPos()
+ {
+ attrEndPos = bufPos;
+ }
+
+ // Serialize an element end tag: "</prefix:localName>", if content was output. Otherwise, serialize
+ // the shortcut syntax: " />".
+ internal override Task WriteEndElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (contentPos != bufPos)
+ {
+ // Content has been output, so can't use shortcut syntax
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+
+ if (prefix != null && prefix.Length != 0)
+ {
+ return RawTextAsync(prefix, ":", localName, ">");
+ }
+ else
+ {
+ return RawTextAsync(localName, ">");
+ }
+ }
+ else
+ {
+ // Use shortcut syntax; overwrite the already output '>' character
+ bufPos--;
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+ return Task.CompletedTask;
+ }
+
+ // Serialize a full element end tag: "</prefix:localName>"
+ internal override Task WriteFullEndElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'/';
+
+ if (prefix != null && prefix.Length != 0)
+ {
+ return RawTextAsync(prefix, ":", localName, ">");
+ }
+ else
+ {
+ return RawTextAsync(localName, ">");
+ }
+ }
+
+ // Serialize an attribute tag using double quotes around the attribute value: 'prefix:localName="'
+ protected internal override Task WriteStartAttributeAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ Debug.Assert(localName != null && localName.Length > 0);
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (attrEndPos == bufPos)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ }
+ Task task;
+ if (prefix != null && prefix.Length > 0)
+ {
+ task = RawTextAsync(prefix, ":", localName);
+ }
+ else
+ {
+ task = RawTextAsync(localName);
+ }
+ return task.CallVoidFuncWhenFinishAsync(thisRef => thisRef.WriteStartAttribute_SetInAttribute(), this);
+ }
+
+ private void WriteStartAttribute_SetInAttribute()
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'=';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ inAttributeValue = true;
+ }
+
+ // Serialize the end of an attribute value using double quotes: '"'
+ protected internal override Task WriteEndAttributeAsync()
+ {
+ CheckAsyncCall();<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ inAttributeValue = false;
+ attrEndPos = bufPos;
+
+ return Task.CompletedTask;
+ }
+
+ internal override async Task WriteNamespaceDeclarationAsync(string prefix, string namespaceName)
+ {
+ CheckAsyncCall();
+ Debug.Assert(prefix != null && namespaceName != null);
+
+ await WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false);
+ await WriteStringAsync(namespaceName).ConfigureAwait(false);
+ await WriteEndNamespaceDeclarationAsync().ConfigureAwait(false);
+ }
+
+ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix)
+ {
+ CheckAsyncCall();
+ Debug.Assert(prefix != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (prefix.Length == 0)
+ {
+ await RawTextAsync(" xmlns=\"").ConfigureAwait(false);
+ }
+ else
+ {
+ await RawTextAsync(" xmlns:").ConfigureAwait(false);
+ await RawTextAsync(prefix).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'=';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ }
+
+ inAttributeValue = true;<#
+#><#= SetTextContentMark(3, true) #>
+ }
+
+ internal override Task WriteEndNamespaceDeclarationAsync()
+ {
+ CheckAsyncCall();<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ inAttributeValue = false;
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'"';
+ attrEndPos = bufPos;
+
+ return Task.CompletedTask;
+ }
+
+ // Serialize a CData section. If the "]]>" pattern is found within
+ // the text, replace it with "]]><![CDATA[>".
+ public override async Task WriteCDataAsync(string text)
+ {
+ CheckAsyncCall();
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ if (mergeCDataSections && bufPos == cdataPos)
+ {
+ // Merge adjacent cdata sections - overwrite the "]]>" characters
+ Debug.Assert(bufPos >= 4);
+ bufPos -= 3;
+ }
+ else
+ {
+ // Start a new cdata section
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'C';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'D';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'T';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'A';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'[';
+ }
+
+ await WriteCDataSectionAsync(text).ConfigureAwait(false);
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)']';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+
+ textPos = bufPos;
+ cdataPos = bufPos;
+ }
+
+ // Serialize a comment.
+ public override async Task WriteCommentAsync(string text)
+ {
+ CheckAsyncCall();
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'!';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+
+ await WriteCommentOrPiAsync(text, '-').ConfigureAwait(false);
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'-';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize a processing instruction.
+ public override async Task WriteProcessingInstructionAsync(string name, string text)
+ {
+ CheckAsyncCall();
+ Debug.Assert(name != null && name.Length > 0);
+ Debug.Assert(text != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'<';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?';
+ await RawTextAsync(name).ConfigureAwait(false);
+
+ if (text.Length > 0)
+ {
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)' ';
+ await WriteCommentOrPiAsync(text, '?').ConfigureAwait(false);
+ }
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'?';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'>';
+ }
+
+ // Serialize an entity reference.
+ public override async Task WriteEntityRefAsync(string name)
+ {
+ CheckAsyncCall();
+ Debug.Assert(name != null && name.Length > 0);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ await RawTextAsync(name).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+
+ if (bufPos > bufLen)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+
+ textPos = bufPos;
+ }
+
+ // Serialize a character entity reference.
+ public override async Task WriteCharEntityAsync(char ch)
+ {
+ CheckAsyncCall();
+ string strVal = ((int)ch).ToString("X", NumberFormatInfo.InvariantInfo);
+
+ if (checkCharacters && !xmlCharType.IsCharData(ch))
+ {
+ // we just have a single char, not a surrogate, therefore we have to pass in '\0' for the second char
+ throw XmlConvert.CreateInvalidCharException(ch, '\0');
+ }<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x';
+ await RawTextAsync(strVal).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+
+ if (bufPos > bufLen)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+
+ textPos = bufPos;
+ }
+
+ // Serialize a whitespace node.
+
+ public override Task WriteWhitespaceAsync(string ws)
+ {
+ CheckAsyncCall();
+ Debug.Assert(ws != null);<#
+#><#= SetTextContentMark(3, false) #>
+
+ if (inAttributeValue)
+ {
+ return WriteAttributeTextBlockAsync(ws);
+ }
+ else
+ {
+ return WriteElementTextBlockAsync(ws);
+ }
+ }
+
+ // Serialize either attribute or element text using XML rules.
+
+ public override Task WriteStringAsync(string text)
+ {
+ CheckAsyncCall();
+ Debug.Assert(text != null);<#
+#><#= SetTextContentMark(3, true) #>
+
+ if (inAttributeValue)
+ {
+ return WriteAttributeTextBlockAsync(text);
+ }
+ else
+ {
+ return WriteElementTextBlockAsync(text);
+ }
+ }
+
+ // Serialize surrogate character entity.
+ public override async Task WriteSurrogateCharEntityAsync(char lowChar, char highChar)
+ {
+ CheckAsyncCall();<#
+#><#= SetTextContentMark(3, false) #>
+
+ int surrogateChar = XmlCharType.CombineSurrogateChar(lowChar, highChar);
+
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'&';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'#';
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)'x';
+ await RawTextAsync(surrogateChar.ToString("X", NumberFormatInfo.InvariantInfo)).ConfigureAwait(false);
+ <#= BufferName #>[bufPos++] = (<#= BufferType #>)';';
+ textPos = bufPos;
+ }
+
+ // Serialize either attribute or element text using XML rules.
+ // Arguments are validated in the XmlWellformedWriter layer.
+
+ public override Task WriteCharsAsync(char[] buffer, int index, int count)
+ {
+ CheckAsyncCall();
+ Debug.Assert(buffer != null);
+ Debug.Assert(index >= 0);
+ Debug.Assert(count >= 0 && index + count <= buffer.Length);<#
+
+#><#= SetTextContentMark(3, true) #>
+
+ if (inAttributeValue)
+ {
+ return WriteAttributeTextBlockAsync(buffer, index, count);
+ }
+ else
+ {
+ return WriteElementTextBlockAsync(buffer, index, count);
+ }
+ }
+
+ // Serialize raw data.
+ // Arguments are validated in the XmlWellformedWriter layer
+
+ public override async Task WriteRawAsync(char[] buffer, int index, int count)
+ {
+ CheckAsyncCall();
+ Debug.Assert(buffer != null);
+ Debug.Assert(index >= 0);
+ Debug.Assert(count >= 0 && index + count <= buffer.Length);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ await WriteRawWithCharCheckingAsync(buffer, index, count).ConfigureAwait(false);
+
+ textPos = bufPos;
+ }
+
+ // Serialize raw data.
+
+ public override async Task WriteRawAsync(string data)
+ {
+ CheckAsyncCall();
+ Debug.Assert(data != null);<#
+
+#><#= SetTextContentMark(3, false) #>
+
+ await WriteRawWithCharCheckingAsync(data).ConfigureAwait(false);
+
+ textPos = bufPos;
+ }
+
+ // Flush all characters in the buffer to output and call Flush() on the output object.
+ public override async Task FlushAsync()
+ {
+ CheckAsyncCall();
+ await FlushBufferAsync().ConfigureAwait(false);
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ await FlushEncoderAsync().ConfigureAwait(false);
+<# } #>
+
+ if (stream != null)
+ {
+ await stream.FlushAsync().ConfigureAwait(false);
+ }
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ else if (writer != null)
+ {
+ await writer.FlushAsync().ConfigureAwait(false);
+ }
+<# } #>
+ }
+
+ //
+ // Implementation methods
+ //
+ // Flush all characters in the buffer to output. Do not flush the output object.
+ protected virtual async Task FlushBufferAsync()
+ {
+ try
+ {
+ // Output all characters (except for previous characters stored at beginning of buffer)
+ if (!writeToNull)
+ {
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ Debug.Assert(stream != null);
+ await stream.WriteAsync(bufBytes, 1, bufPos - 1).ConfigureAwait(false);
+<# } else { #>
+ Debug.Assert(stream != null || writer != null);
+
+ if (stream != null)
+ {
+ if (trackTextContent)
+ {
+ _charEntityFallback.Reset(_textContentMarks, _lastMarkPos);
+ // reset text content tracking
+
+ if ((_lastMarkPos & 1) != 0)
+ {
+ // If the previous buffer ended inside a text content we need to preserve that info
+ // which means the next index to which we write has to be even
+ _textContentMarks[1] = 1;
+ _lastMarkPos = 1;
+ }
+ else
+ {
+ _lastMarkPos = 0;
+ }
+ Debug.Assert(_textContentMarks[0] == 1);
+ }
+ await EncodeCharsAsync(1, bufPos, true).ConfigureAwait(false);
+ }
+ else
+ {
+ // Write text to TextWriter
+ await writer.WriteAsync(<#= BufferName #>, 1, bufPos - 1).ConfigureAwait(false);
+ }
+<# } #>
+ }
+ }
+ catch
+ {
+ // Future calls to flush (i.e. when Close() is called) don't attempt to write to stream
+ writeToNull = true;
+ throw;
+ }
+ finally
+ {
+ // Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
+ <#= BufferName #>[0] = <#= BufferName #>[bufPos - 1];
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ if (IsSurrogateByte(bufBytes[0]))
+ {
+ // Last character was the first byte in a surrogate encoding, so move last three
+ // bytes of encoding to the beginning of the buffer.
+ bufBytes[1] = bufBytes[bufPos];
+ bufBytes[2] = bufBytes[bufPos + 1];
+ bufBytes[3] = bufBytes[bufPos + 2];
+ }
+<# } #>
+
+ // Reset buffer position
+ textPos = (textPos == bufPos) ? 1 : 0;
+ attrEndPos = (attrEndPos == bufPos) ? 1 : 0;
+ contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible
+ cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible
+ bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
+ // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
+ }
+ }
+<# if (WriterType == RawTextWriterType.Encoded) { #>
+ private async Task EncodeCharsAsync(int startOffset, int endOffset, bool writeAllToStream)
+ {
+ // Write encoded text to stream
+ int chEnc;
+ int bEnc;
+ bool completed;
+ while (startOffset < endOffset)
+ {
+ if (_charEntityFallback != null)
+ {
+ _charEntityFallback.StartOffset = startOffset;
+ }
+ encoder.Convert(<#= BufferName #>, startOffset, endOffset - startOffset, bufBytes, bufBytesUsed, bufBytes.Length - bufBytesUsed, false, out chEnc, out bEnc, out completed);
+ startOffset += chEnc;
+ bufBytesUsed += bEnc;
+ if (bufBytesUsed >= (bufBytes.Length - 16))
+ {
+ await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false);
+ bufBytesUsed = 0;
+ }
+ }
+ if (writeAllToStream && bufBytesUsed > 0)
+ {
+ await stream.WriteAsync(bufBytes, 0, bufBytesUsed).ConfigureAwait(false);
+ bufBytesUsed = 0;
+ }
+ }
+
+ private Task FlushEncoderAsync()
+ {
+ Debug.Assert(bufPos == 1);
+ if (stream != null)
+ {
+ int chEnc;
+ int bEnc;
+ bool completed;
+ // decode no chars, just flush
+ encoder.Convert(<#= BufferName #>, 1, 0, bufBytes, 0, bufBytes.Length, true, out chEnc, out bEnc, out completed);
+ if (bEnc != 0)
+ {
+ return stream.WriteAsync(bufBytes, 0, bEnc);
+ }
+ }
+
+ return Task.CompletedTask;
+ }
+<# } #>
+
+ // Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
+ // are entitized.
+ protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd)
+ {
+ char* pRaw = pSrc;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ pDst = AmpEntity(pDst);
+ break;
+ case '<':
+ pDst = LtEntity(pDst);
+ break;
+ case '>':
+ pDst = GtEntity(pDst);
+ break;
+ case '"':
+ pDst = QuoteEntity(pDst);
+ break;
+ case '\'':
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0x9:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape tab in attributes
+ pDst = TabEntity(pDst);
+ }
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape new lines in attributes
+ pDst = CarriageReturnEntity(pDst);
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.None)
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ else
+ {
+ // escape new lines in attributes
+ pDst = LineFeedEntity(pDst);
+ }
+ break;
+ default:
+<#= EncodeChar(7, true) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+
+ return -1;
+ }
+
+ protected unsafe int WriteAttributeTextBlockNoFlush(char[] chars, int index, int count)
+ {
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrc = &chars[index])
+ {
+ char* pSrcBeg = pSrc;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteAttributeTextBlockNoFlush(pSrcBeg, pSrcEnd);
+ }
+ }
+
+ protected unsafe int WriteAttributeTextBlockNoFlush(string text, int index, int count)
+ {
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrc = text)
+ {
+ char* pSrcBeg = pSrc + index;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteAttributeTextBlockNoFlush(pSrcBeg, pSrcEnd);
+ }
+ }
+
+ protected async Task WriteAttributeTextBlockAsync(char[] chars, int index, int count)
+ {
+ int writeLen = 0;
+ int curIndex = index;
+ int leftCount = count;
+ do
+ {
+ writeLen = WriteAttributeTextBlockNoFlush(chars, curIndex, leftCount);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0);
+ }
+
+ protected Task WriteAttributeTextBlockAsync(string text)
+ {
+ int writeLen = 0;
+ int curIndex = 0;
+ int leftCount = text.Length;
+
+ writeLen = WriteAttributeTextBlockNoFlush(text, curIndex, leftCount);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (writeLen >= 0)
+ {
+ return _WriteAttributeTextBlockAsync(text, curIndex, leftCount);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ private async Task _WriteAttributeTextBlockAsync(string text, int curIndex, int leftCount)
+ {
+ int writeLen;
+ await FlushBufferAsync().ConfigureAwait(false);
+ do
+ {
+ writeLen = WriteAttributeTextBlockNoFlush(text, curIndex, leftCount);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0);
+ }
+
+ // Serialize text that is part of element content. The '&', '<', and '>' characters
+ // are entitized.
+ protected unsafe int WriteElementTextBlockNoFlush(char* pSrc, char* pSrcEnd, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ char* pRaw = pSrc;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+ // some character needs to be escaped
+ switch (ch)
+ {
+ case '&':
+ pDst = AmpEntity(pDst);
+ break;
+ case '<':
+ pDst = LtEntity(pDst);
+ break;
+ case '>':
+ pDst = GtEntity(pDst);
+ break;
+ case '"':
+ case '\'':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xD:
+ switch (newLineHandling)
+ {
+ case NewLineHandling.Replace:
+ // Replace "\r\n", or "\r" with NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+
+ case NewLineHandling.Entitize:
+ // Entitize 0xD
+ pDst = CarriageReturnEntity(pDst);
+ break;
+ case NewLineHandling.None:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ }
+ break;
+ default:
+<#= EncodeChar(7, true) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ textPos = bufPos;
+ contentPos = 0;
+ }
+
+ return -1;
+ }
+
+ protected unsafe int WriteElementTextBlockNoFlush(char[] chars, int index, int count, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ contentPos = 0;
+ return -1;
+ }
+ fixed (char* pSrc = &chars[index])
+ {
+ char* pSrcBeg = pSrc;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteElementTextBlockNoFlush(pSrcBeg, pSrcEnd, out needWriteNewLine);
+ }
+ }
+
+ protected unsafe int WriteElementTextBlockNoFlush(string text, int index, int count, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ contentPos = 0;
+ return -1;
+ }
+ fixed (char* pSrc = text)
+ {
+ char* pSrcBeg = pSrc + index;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteElementTextBlockNoFlush(pSrcBeg, pSrcEnd, out needWriteNewLine);
+ }
+ }
+
+ protected async Task WriteElementTextBlockAsync(char[] chars, int index, int count)
+ {
+ int writeLen = 0;
+ int curIndex = index;
+ int leftCount = count;
+ bool needWriteNewLine = false;
+ do
+ {
+ writeLen = WriteElementTextBlockNoFlush(chars, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ //hit WriteNewLine
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+
+ protected Task WriteElementTextBlockAsync(string text)
+ {
+ int writeLen = 0;
+ int curIndex = 0;
+ int leftCount = text.Length;
+ bool needWriteNewLine = false;
+
+ writeLen = WriteElementTextBlockNoFlush(text, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ return _WriteElementTextBlockAsync(true, text, curIndex, leftCount);
+ }
+ else if (writeLen >= 0)
+ {
+ return _WriteElementTextBlockAsync(false, text, curIndex, leftCount);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ private async Task _WriteElementTextBlockAsync(bool newLine, string text, int curIndex, int leftCount)
+ {
+ int writeLen = 0;
+ bool needWriteNewLine = false;
+
+ if (newLine)
+ {
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+
+ do
+ {
+ writeLen = WriteElementTextBlockNoFlush(text, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ //hit WriteNewLine
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+
+ protected unsafe int RawTextNoFlush(char* pSrcBegin, char* pSrcEnd)
+ {
+ char* pRaw = pSrcBegin;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+ char* pSrc = pSrcBegin;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && ((ch = *pSrc) < XmlCharType.SurHighStart))
+<# } #>
+ {
+ pSrc++;
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+<#= EncodeChar(5, false) #>
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ }
+
+ return -1;
+ }
+
+ protected unsafe int RawTextNoFlush(string text, int index, int count)
+ {
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrc = text)
+ {
+ char* pSrcBegin = pSrc + index;
+ char* pSrcEnd = pSrcBegin + count;
+ return RawTextNoFlush(pSrcBegin, pSrcEnd);
+ }
+ }
+
+ // special-case the one string overload, as it's so common
+ protected Task RawTextAsync(string text)
+ {
+ int writeLen = RawTextNoFlush(text, 0, text.Length);
+ return writeLen >= 0 ?
+ _RawTextAsync(text, writeLen, text.Length - writeLen) :
+ Task.CompletedTask;
+ }
+
+ protected Task RawTextAsync(string text1, string text2 = null, string text3 = null, string text4 = null)
+ {
+ Debug.Assert(text1 != null);
+ Debug.Assert(text2 != null || (text3 == null && text4 == null));
+ Debug.Assert(text3 != null || (text4 == null));
+
+ int writeLen;
+
+ // Write out the first string
+ writeLen = RawTextNoFlush(text1, 0, text1.Length);
+ if (writeLen >= 0)
+ {
+ // If we were only able to partially write it, write out the remainder
+ // and then write out the other strings.
+ return _RawTextAsync(text1, writeLen, text1.Length - writeLen, text2, text3, text4);
+ }
+
+ // We wrote out the first string. Try to write out the second, if it exists.
+ if (text2 != null)
+ {
+ writeLen = RawTextNoFlush(text2, 0, text2.Length);
+ if (writeLen >= 0)
+ {
+ // If we were only able to write out some of the second string,
+ // write out the remainder and then the other strings,
+ return _RawTextAsync(text2, writeLen, text2.Length - writeLen, text3, text4);
+ }
+ }
+
+ // We wrote out the first and second strings. Try to write out the third
+ // if it exists.
+ if (text3 != null)
+ {
+ writeLen = RawTextNoFlush(text3, 0, text3.Length);
+ if (writeLen >= 0)
+ {
+ // If we were only able to write out some of the third string,
+ // write out the remainder and then the last string.
+ return _RawTextAsync(text3, writeLen, text3.Length - writeLen, text4);
+ }
+ }
+
+ // Finally, try to write out the fourth string, if it exists.
+ if (text4 != null)
+ {
+ writeLen = RawTextNoFlush(text4, 0, text4.Length);
+ if (writeLen >= 0)
+ {
+ return _RawTextAsync(text4, writeLen, text4.Length - writeLen);
+ }
+ }
+
+ // All strings written successfully.
+ return Task.CompletedTask;
+ }
+
+ private async Task _RawTextAsync(
+ string text1, int curIndex1, int leftCount1,
+ string text2 = null, string text3 = null, string text4 = null)
+ {
+ Debug.Assert(text1 != null);
+ Debug.Assert(text2 != null || (text3 == null && text4 == null));
+ Debug.Assert(text3 != null || (text4 == null));
+
+ // Write out the remainder of the first string
+ await FlushBufferAsync().ConfigureAwait(false);
+ int writeLen = 0;
+ do
+ {
+ writeLen = RawTextNoFlush(text1, curIndex1, leftCount1);
+ curIndex1 += writeLen;
+ leftCount1 -= writeLen;
+ if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0);
+
+ // If there are additional strings, write them out as well
+ if (text2 != null)
+ {
+ await RawTextAsync(text2, text3, text4).ConfigureAwait(false);
+ }
+ }
+
+ protected unsafe int WriteRawWithCharCheckingNoFlush(char* pSrcBegin, char* pSrcEnd, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ char* pRaw = pSrcBegin;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && xmlCharType.IsTextChar((char)(ch = *pSrc)))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case ']':
+ case '<':
+ case '&':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ default:
+<#= EncodeChar(7, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+
+ return -1;
+ }
+
+ protected unsafe int WriteRawWithCharCheckingNoFlush(char[] chars, int index, int count, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrc = &chars[index])
+ {
+ char* pSrcBeg = pSrc;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteRawWithCharCheckingNoFlush(pSrcBeg, pSrcEnd, out needWriteNewLine);
+ }
+ }
+
+ protected unsafe int WriteRawWithCharCheckingNoFlush(string text, int index, int count, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrc = text)
+ {
+ char* pSrcBeg = pSrc + index;
+ char* pSrcEnd = pSrcBeg + count;
+ return WriteRawWithCharCheckingNoFlush(pSrcBeg, pSrcEnd, out needWriteNewLine);
+ }
+ }
+
+ protected async Task WriteRawWithCharCheckingAsync(char[] chars, int index, int count)
+ {
+ int writeLen = 0;
+ int curIndex = index;
+ int leftCount = count;
+ bool needWriteNewLine = false;
+ do
+ {
+ writeLen = WriteRawWithCharCheckingNoFlush(chars, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+
+ protected async Task WriteRawWithCharCheckingAsync(string text)
+ {
+ int writeLen = 0;
+ int curIndex = 0;
+ int leftCount = text.Length;
+ bool needWriteNewLine = false;
+ do
+ {
+ writeLen = WriteRawWithCharCheckingNoFlush(text, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+
+ protected unsafe int WriteCommentOrPiNoFlush(string text, int index, int count, int stopChar, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ return -1;
+ }
+ fixed (char* pSrcText = text)
+ {
+ char* pSrcBegin = pSrcText + index;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+
+ char* pRaw = pSrc;
+
+ char* pSrcEnd = pSrcBegin + count;
+
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && (xmlCharType.IsTextChar((char)(ch = *pSrc)) && ch != stopChar))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case '-':
+ *pDst = (<#= BufferType #>)'-';
+ pDst++;
+ if (ch == stopChar)
+ {
+ // Insert space between adjacent dashes or before comment's end dashes
+ if (pSrc + 1 == pSrcEnd || *(pSrc + 1) == '-')
+ {
+ *pDst = (<#= BufferType #>)' ';
+ pDst++;
+ }
+ }
+ break;
+ case '?':
+ *pDst = (<#= BufferType #>)'?';
+ pDst++;
+ if (ch == stopChar)
+ {
+ // Processing instruction: insert space between adjacent '?' and '>'
+ if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
+ {
+ *pDst = (<#= BufferType #>)' ';
+ pDst++;
+ }
+ }
+ break;
+ case ']':
+ *pDst = (<#= BufferType #>)']';
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case '<':
+ case '&':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ default:
+<#= EncodeChar(8, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+
+ return -1;
+ }
+ }
+
+ protected async Task WriteCommentOrPiAsync(string text, int stopChar)
+ {
+ if (text.Length == 0)
+ {
+ if (bufPos >= bufLen)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ return;
+ }
+
+ int writeLen = 0;
+ int curIndex = 0;
+ int leftCount = text.Length;
+ bool needWriteNewLine = false;
+ do
+ {
+ writeLen = WriteCommentOrPiNoFlush(text, curIndex, leftCount, stopChar, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+
+ protected unsafe int WriteCDataSectionNoFlush(string text, int index, int count, out bool needWriteNewLine)
+ {
+ needWriteNewLine = false;
+ if (count == 0)
+ {
+ return -1;
+ }
+
+ // write text
+
+ fixed (char* pSrcText = text)
+ {
+ char* pSrcBegin = pSrcText + index;
+
+ fixed (<#= BufferType #>* pDstBegin = <#= BufferName #>)
+ {
+ char* pSrc = pSrcBegin;
+
+ char* pSrcEnd = pSrcBegin + count;
+
+ char* pRaw = pSrc;
+
+ <#= BufferType #>* pDst = pDstBegin + bufPos;
+
+ int ch = 0;
+ for (;;)
+ {
+ <#= BufferType #>* pDstEnd = pDst + (pSrcEnd - pSrc);
+ if (pDstEnd > pDstBegin + bufLen)
+ {
+ pDstEnd = pDstBegin + bufLen;
+ }
+
+<# if (WriterType == RawTextWriterType.Utf8) { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']' && ch <= 0x7F))
+<# } else { #>
+ while (pDst < pDstEnd && (xmlCharType.IsAttributeValueChar((char)(ch = *pSrc)) && ch != ']'))
+<# } #>
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ pSrc++;
+ }
+
+ Debug.Assert(pSrc <= pSrcEnd);
+
+ // end of value
+ if (pSrc >= pSrcEnd)
+ {
+ break;
+ }
+
+ // end of buffer
+ if (pDst >= pDstEnd)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ return (int)(pSrc - pRaw);
+ }
+
+ // handle special characters
+ switch (ch)
+ {
+ case '>':
+ if (hadDoubleBracket && pDst[-1] == (<#= BufferType #>)']')
+ { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ // The characters "]]>" were found within the CData text
+ pDst = RawEndCData(pDst);
+ pDst = RawStartCData(pDst);
+ }
+ *pDst = (<#= BufferType #>)'>';
+ pDst++;
+ break;
+ case ']':
+ if (pDst[-1] == (<#= BufferType #>)']')
+ { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ hadDoubleBracket = true;
+ }
+ else
+ {
+ hadDoubleBracket = false;
+ }
+ *pDst = (<#= BufferType #>)']';
+ pDst++;
+ break;
+ case (char)0xD:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ // Normalize "\r\n", or "\r" to NewLineChars
+ if (pSrc + 1 < pSrcEnd && pSrc[1] == '\n')
+ {
+ pSrc++;
+ }
+
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case (char)0xA:
+ if (newLineHandling == NewLineHandling.Replace)
+ {
+ bufPos = (int)(pDst - pDstBegin);
+ needWriteNewLine = true;
+ return (int)(pSrc - pRaw);
+ }
+ else
+ {
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ }
+ break;
+ case '&':
+ case '<':
+ case '"':
+ case '\'':
+ case (char)0x9:
+ *pDst = (<#= BufferType #>)ch;
+ pDst++;
+ break;
+ default:
+<#= EncodeChar(8, false) #>
+ continue;
+ }
+ pSrc++;
+ }
+ bufPos = (int)(pDst - pDstBegin);
+ }
+
+ return -1;
+ }
+ }
+
+ protected async Task WriteCDataSectionAsync(string text)
+ {
+ if (text.Length == 0)
+ {
+ if (bufPos >= bufLen)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ return;
+ }
+
+ int writeLen = 0;
+ int curIndex = 0;
+ int leftCount = text.Length;
+ bool needWriteNewLine = false;
+ do
+ {
+ writeLen = WriteCDataSectionNoFlush(text, curIndex, leftCount, out needWriteNewLine);
+ curIndex += writeLen;
+ leftCount -= writeLen;
+ if (needWriteNewLine)
+ {
+ await RawTextAsync(newLineChars).ConfigureAwait(false);
+ curIndex++;
+ leftCount--;
+ }
+ else if (writeLen >= 0)
+ {
+ await FlushBufferAsync().ConfigureAwait(false);
+ }
+ } while (writeLen >= 0 || needWriteNewLine);
+ }
+ }
+
+ // Same as base text writer class except that elements, attributes, comments, and pi's are indented.
+ internal partial class <#= ClassNameIndent #> : <#= ClassName #>
+ {
+ public override async Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset)
+ {
+ CheckAsyncCall();
+ // Add indentation
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+ await base.WriteDocTypeAsync(name, pubid, sysid, subset).ConfigureAwait(false);
+ }
+
+ public override async Task WriteStartElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ Debug.Assert(localName != null && localName.Length != 0 && prefix != null && ns != null);
+
+ // Add indentation
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+ indentLevel++;
+ _mixedContentStack.PushBit(mixedContent);
+
+ await base.WriteStartElementAsync(prefix, localName, ns).ConfigureAwait(false);
+ }
+
+ internal override async Task WriteEndElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ // Add indentation
+ indentLevel--;
+ if (!mixedContent && base.contentPos != base.bufPos)
+ {
+ // There was content, so try to indent
+ if (base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+ }
+ mixedContent = _mixedContentStack.PopBit();
+
+ await base.WriteEndElementAsync(prefix, localName, ns).ConfigureAwait(false);
+ }
+
+ internal override async Task WriteFullEndElementAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ // Add indentation
+ indentLevel--;
+ if (!mixedContent && base.contentPos != base.bufPos)
+ {
+ // There was content, so try to indent
+ if (base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+ }
+ mixedContent = _mixedContentStack.PopBit();
+
+ await base.WriteFullEndElementAsync(prefix, localName, ns).ConfigureAwait(false);
+ }
+
+ // Same as base class, plus possible indentation.
+ protected internal override async Task WriteStartAttributeAsync(string prefix, string localName, string ns)
+ {
+ CheckAsyncCall();
+ // Add indentation
+ if (newLineOnAttributes)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+
+ await base.WriteStartAttributeAsync(prefix, localName, ns).ConfigureAwait(false);
+ }
+
+ public override Task WriteCDataAsync(string text)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteCDataAsync(text);
+ }
+
+ public override async Task WriteCommentAsync(string text)
+ {
+ CheckAsyncCall();
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+
+ await base.WriteCommentAsync(text).ConfigureAwait(false);
+ }
+
+ public override async Task WriteProcessingInstructionAsync(string target, string text)
+ {
+ CheckAsyncCall();
+ if (!mixedContent && base.textPos != base.bufPos)
+ {
+ await WriteIndentAsync().ConfigureAwait(false);
+ }
+
+ await base.WriteProcessingInstructionAsync(target, text).ConfigureAwait(false);
+ }
+
+ public override Task WriteEntityRefAsync(string name)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteEntityRefAsync(name);
+ }
+
+ public override Task WriteCharEntityAsync(char ch)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteCharEntityAsync(ch);
+ }
+
+ public override Task WriteSurrogateCharEntityAsync(char lowChar, char highChar)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteSurrogateCharEntityAsync(lowChar, highChar);
+ }
+
+ public override Task WriteWhitespaceAsync(string ws)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteWhitespaceAsync(ws);
+ }
+
+ public override Task WriteStringAsync(string text)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteStringAsync(text);
+ }
+
+ public override Task WriteCharsAsync(char[] buffer, int index, int count)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteCharsAsync(buffer, index, count);
+ }
+
+ public override Task WriteRawAsync(char[] buffer, int index, int count)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteRawAsync(buffer, index, count);
+ }
+
+ public override Task WriteRawAsync(string data)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteRawAsync(data);
+ }
+
+ public override Task WriteBase64Async(byte[] buffer, int index, int count)
+ {
+ CheckAsyncCall();
+ mixedContent = true;
+ return base.WriteBase64Async(buffer, index, count);
+ }
+
+ // Add indentation to output. Write newline and then repeat IndentChars for each indent level.
+ private async Task WriteIndentAsync()
+ {
+ CheckAsyncCall();
+ await RawTextAsync(base.newLineChars).ConfigureAwait(false);
+ for (int i = indentLevel; i > 0; i--)
+ {
+ await RawTextAsync(indentChars).ConfigureAwait(false);
+ }
+ }
+ }
+}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// Note: This code went through some modifications and generation comment might not be fully valid
-// WARNING: This file is generated and should not be modified directly. Instead,
-// modify XmlTextWriterGenerator.cxx and run gen.bat in the same directory.
-// This batch file will execute the following commands:
-//
-// cl.exe /C /EP /D _XML_ENCODED_TEXT_WRITER XmlRawTextWriterGenerator.cxx > XmlEncodedRawTextWriter.cs
-//
-// Because these two implementations of XmlTextWriter are so similar, the C++ preprocessor
-// is used to generate each implementation from one template file, using macros and ifdefs.
-
-// Note: This file was generated without #define SILVERLIGHT
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGenerator.ttinclude
using System;
using System.IO;
// output stream
protected Stream stream;
- // encoding of the stream or text writer
+ // encoding of the stream or text writer
protected Encoding encoding;
// char type tables
// buffer positions
protected int bufPos = 1; // buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
+ // close an empty element or in CDATA section detection of double ]; bufBytes[0] will always be 0
protected int textPos = 1; // text end position; don't indent first element, pi, or comment
protected int contentPos; // element content end position
protected int cdataPos; // cdata end position
protected bool hadDoubleBracket;
protected bool inAttributeValue;
+
// writer settings
protected NewLineHandling newLineHandling;
protected bool closeOutput;
}
bufBytes = new byte[bufLen + OVERFLOW];
-
// Output UTF-8 byte order mark if Encoding object wants it
if (!stream.CanSeek || stream.Position == 0)
{
{
XmlWriterSettings settings = new XmlWriterSettings();
- settings.Encoding = this.encoding;
- settings.OmitXmlDeclaration = this.omitXmlDeclaration;
- settings.NewLineHandling = this.newLineHandling;
- settings.NewLineChars = this.newLineChars;
- settings.CloseOutput = this.closeOutput;
+ settings.Encoding = encoding;
+ settings.OmitXmlDeclaration = omitXmlDeclaration;
+ settings.NewLineHandling = newLineHandling;
+ settings.NewLineChars = newLineChars;
+ settings.CloseOutput = closeOutput;
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.CheckCharacters = checkCharacters;
}
}
- // Write the xml declaration. This must be the first call.
+ // Write the xml declaration. This must be the first call.
internal override void WriteXmlDeclaration(XmlStandalone standalone)
{
// Output xml declaration only if user allows it and it was not already output
bufBytes[bufPos++] = (byte)']';
}
- bufBytes[this.bufPos++] = (byte)'>';
+ bufBytes[bufPos++] = (byte)'>';
}
// Serialize the beginning of an element start tag: "<prefix:localName"
if (prefix != null && prefix.Length != 0)
{
RawText(prefix);
- bufBytes[this.bufPos++] = (byte)':';
+ bufBytes[bufPos++] = (byte)':';
}
RawText(localName);
// Serialize the end of an attribute value using double quotes: '"'
public override void WriteEndAttribute()
{
+
bufBytes[bufPos++] = (byte)'"';
inAttributeValue = false;
attrEndPos = bufPos;
{
Debug.Assert(prefix != null && namespaceName != null);
- this.WriteStartNamespaceDeclaration(prefix);
- this.WriteString(namespaceName);
- this.WriteEndNamespaceDeclaration();
+ WriteStartNamespaceDeclaration(prefix);
+ WriteString(namespaceName);
+ WriteEndNamespaceDeclaration();
}
internal override bool SupportsNamespaceDeclarationInChunks
{
FlushBuffer();
FlushEncoder();
-
if (stream != null)
{
stream.Flush();
{
// Move last buffer character to the beginning of the buffer (so that previous character can always be determined)
bufBytes[0] = bufBytes[bufPos - 1];
-
if (IsSurrogateByte(bufBytes[0]))
{
// Last character was the first byte in a surrogate encoding, so move last three
contentPos = 0; // Needs to be zero, since overwriting '>' character is no longer possible
cdataPos = 0; // Needs to be zero, since overwriting ']]>' characters is no longer possible
bufPos = 1; // Buffer position starts at 1, because we need to be able to safely step back -1 in case we need to
- // close an empty element or in CDATA section detection of double ]; _BUFFER[0] will always be 0
+ // close an empty element or in CDATA section detection of double ]; bufBytes[0] will always be 0
}
}
// Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
// are entitized.
-
protected unsafe void WriteAttributeTextBlock(char* pSrc, char* pSrcEnd)
{
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
// Serialize text that is part of element content. The '&', '<', and '>' characters
// are entitized.
-
protected unsafe void WriteElementTextBlock(char* pSrc, char* pSrcEnd)
{
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
{
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
char* pSrc = pSrcBegin;
int ch = 0;
for (;;)
{
byte* pDstEnd = pDst + (pSrcEnd - pSrc);
- if (pDstEnd > pDstBegin + this.bufLen)
+ if (pDstEnd > pDstBegin + bufLen)
{
- pDstEnd = pDstBegin + this.bufLen;
+ pDstEnd = pDstBegin + bufLen;
}
while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F))
continue;
}
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
}
bufPos = (int)(pDst - pDstBegin);
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
if (ch == stopChar)
{
- // Processing instruction: insert space between adjacent '?' and '>'
+ // Processing instruction: insert space between adjacent '?' and '>'
if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
{
*pDst = (byte)' ';
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
{
case '>':
if (hadDoubleBracket && pDst[-1] == (byte)']')
- { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ { // pDst[-1] will always correct - there is a padding character at bufBytes[0]
// The characters "]]>" were found within the CData text
pDst = RawEndCData(pDst);
pDst = RawStartCData(pDst);
break;
case ']':
if (pDst[-1] == (byte)']')
- { // pDst[-1] will always correct - there is a padding character at _BUFFER[0]
+ { // pDst[-1] will always correct - there is a padding character at bufBytes[0]
hadDoubleBracket = true;
}
else
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
{
pDst = EncodeMultibyteUTF8(ch, pDst);
}
-
return pDst;
}
}
internal unsafe void EncodeChar(ref char* pSrc, char* pSrcEnd, ref byte* pDst)
{
int ch = *pSrc;
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
}
internal static unsafe byte* EncodeMultibyteUTF8(int ch, byte* pDst)
}
// Write NewLineChars to the specified buffer position and return an updated position.
-
protected unsafe byte* WriteNewLine(byte* pDst)
{
fixed (byte* pDstBegin = bufBytes)
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterUtf8.ttinclude" #>
+<#@ include file="XmlRawTextWriterGenerator.ttinclude" #>
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+// WARNING: This file is generated and should not be modified directly.
+// Instead, modify XmlRawTextWriterGeneratorAsync.ttinclude
+
using System;
using System.IO;
using System.Xml;
}
}
- // Write the xml declaration. This must be the first call.
+ // Write the xml declaration. This must be the first call.
internal override async Task WriteXmlDeclarationAsync(XmlStandalone standalone)
{
CheckAsyncCall();
// Output xml declaration only if user allows it and it was not already output
if (!omitXmlDeclaration && !autoXmlDeclaration)
{
+
await RawTextAsync("<?xml version=\"").ConfigureAwait(false);
// Version
bufBytes[bufPos++] = (byte)']';
}
- bufBytes[this.bufPos++] = (byte)'>';
+ bufBytes[bufPos++] = (byte)'>';
}
// Serialize the beginning of an element start tag: "<prefix:localName"
Debug.Assert(localName != null && localName.Length > 0);
Debug.Assert(prefix != null);
- bufBytes[bufPos++] = (byte)'<';
Task task;
+ bufBytes[bufPos++] = (byte)'<';
if (prefix != null && prefix.Length != 0)
{
task = RawTextAsync(prefix, ":", localName);
{
task = RawTextAsync(localName);
}
-
return task.CallVoidFuncWhenFinishAsync(thisRef => thisRef.WriteStartElementAsync_SetAttEndPos(), this);
}
Task task;
if (prefix != null && prefix.Length > 0)
{
- task = RawTextAsync(prefix, ":", localName, "=\"");
+ task = RawTextAsync(prefix, ":", localName);
}
else
{
- task = RawTextAsync(localName, "=\"");
+ task = RawTextAsync(localName);
}
return task.CallVoidFuncWhenFinishAsync(thisRef => thisRef.WriteStartAttribute_SetInAttribute(), this);
}
private void WriteStartAttribute_SetInAttribute()
{
+ bufBytes[bufPos++] = (byte)'=';
+ bufBytes[bufPos++] = (byte)'"';
inAttributeValue = true;
}
CheckAsyncCall();
Debug.Assert(prefix != null && namespaceName != null);
- await this.WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false);
- await this.WriteStringAsync(namespaceName).ConfigureAwait(false);
- await this.WriteEndNamespaceDeclarationAsync().ConfigureAwait(false);
+ await WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false);
+ await WriteStringAsync(namespaceName).ConfigureAwait(false);
+ await WriteEndNamespaceDeclarationAsync().ConfigureAwait(false);
}
internal override async Task WriteStartNamespaceDeclarationAsync(string prefix)
{
CheckAsyncCall();
await FlushBufferAsync().ConfigureAwait(false);
- await FlushEncoderAsync().ConfigureAwait(false);
if (stream != null)
{
}
}
- private Task FlushEncoderAsync()
- {
- // intentionally empty
-
- return Task.CompletedTask;
- }
-
// Serialize text that is part of an attribute value. The '&', '<', '>', and '"' characters
// are entitized.
protected unsafe int WriteAttributeTextBlockNoFlush(char* pSrc, char* pSrcEnd)
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
int ch = 0;
for (;;)
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, true); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, true);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
fixed (byte* pDstBegin = bufBytes)
{
- byte* pDst = pDstBegin + this.bufPos;
+ byte* pDst = pDstBegin + bufPos;
char* pSrc = pSrcBegin;
int ch = 0;
for (;;)
{
byte* pDstEnd = pDst + (pSrcEnd - pSrc);
- if (pDstEnd > pDstBegin + this.bufLen)
+ if (pDstEnd > pDstBegin + bufLen)
{
- pDstEnd = pDstBegin + this.bufLen;
+ pDstEnd = pDstBegin + bufLen;
}
while (pDst < pDstEnd && ((ch = *pSrc) <= 0x7F))
return (int)(pSrc - pRaw);
}
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
}
bufPos = (int)(pDst - pDstBegin);
if (writeLen >= 0)
{
// If we were only able to write out some of the second string,
- // write out the remainder and then the other strings,
+ // write out the remainder and then the other strings,
return _RawTextAsync(text2, writeLen, text2.Length - writeLen, text3, text4);
}
}
}
private async Task _RawTextAsync(
- string text, int curIndex, int leftCount,
+ string text1, int curIndex1, int leftCount1,
string text2 = null, string text3 = null, string text4 = null)
{
- Debug.Assert(text != null);
+ Debug.Assert(text1 != null);
Debug.Assert(text2 != null || (text3 == null && text4 == null));
Debug.Assert(text3 != null || (text4 == null));
int writeLen = 0;
do
{
- writeLen = RawTextNoFlush(text, curIndex, leftCount);
- curIndex += writeLen;
- leftCount -= writeLen;
+ writeLen = RawTextNoFlush(text1, curIndex1, leftCount1);
+ curIndex1 += writeLen;
+ leftCount1 -= writeLen;
if (writeLen >= 0)
{
await FlushBufferAsync().ConfigureAwait(false);
}
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
if (ch == stopChar)
{
- // Processing instruction: insert space between adjacent '?' and '>'
+ // Processing instruction: insert space between adjacent '?' and '>'
if (pSrc + 1 < pSrcEnd && *(pSrc + 1) == '>')
{
*pDst = (byte)' ';
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
pDst++;
break;
default:
- if (XmlCharType.IsSurrogate(ch)) { pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst); pSrc += 2; } else if (ch <= 0x7F || ch >= 0xFFFE) { pDst = InvalidXmlChar(ch, pDst, false); pSrc++; } else { pDst = EncodeMultibyteUTF8(ch, pDst); pSrc++; };
+ /* Surrogate character */
+ if (XmlCharType.IsSurrogate(ch))
+ {
+ pDst = EncodeSurrogate(pSrc, pSrcEnd, pDst);
+ pSrc += 2;
+ }
+ /* Invalid XML character */
+ else if (ch <= 0x7F || ch >= 0xFFFE)
+ {
+ pDst = InvalidXmlChar(ch, pDst, false);
+ pSrc++;
+ }
+ /* Multibyte UTF8 character */
+ else
+ {
+ pDst = EncodeMultibyteUTF8(ch, pDst);
+ pSrc++;
+ }
continue;
}
pSrc++;
--- /dev/null
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ output extension=".cs" #>
+<#@ import namespace="System" #>
+<#@ include file="RawTextWriterUtf8.ttinclude" #>
+<#@ include file="XmlRawTextWriterGeneratorAsync.ttinclude" #>