1 //------------------------------------------------------------------------------
2 // <copyright file="CharEntitiesEncodingFallback.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 using System
.Diagnostics
;
10 using System
.Globalization
;
12 namespace System
.Xml
{
15 // CharEntityEncoderFallback
18 internal class CharEntityEncoderFallback
: EncoderFallback
{
19 private CharEntityEncoderFallbackBuffer fallbackBuffer
;
21 private int[] textContentMarks
;
22 private int endMarkPos
;
23 private int curMarkPos
;
24 private int startOffset
;
26 internal CharEntityEncoderFallback() {
29 public override EncoderFallbackBuffer
CreateFallbackBuffer() {
30 if ( fallbackBuffer
== null ) {
31 fallbackBuffer
= new CharEntityEncoderFallbackBuffer( this );
33 return fallbackBuffer
;
36 public override int MaxCharCount
{
42 internal int StartOffset
{
51 internal void Reset( int[] textContentMarks
, int endMarkPos
) {
52 this.textContentMarks
= textContentMarks
;
53 this.endMarkPos
= endMarkPos
;
57 internal bool CanReplaceAt( int index
) {
58 int mPos
= curMarkPos
;
59 int charPos
= startOffset
+ index
;
60 while ( mPos
< endMarkPos
&& charPos
>= textContentMarks
[mPos
+1] ) {
65 return (mPos
& 1) != 0;
70 // CharEntityFallbackBuffer
72 internal class CharEntityEncoderFallbackBuffer
: EncoderFallbackBuffer
{
73 private CharEntityEncoderFallback parent
;
75 private string charEntity
= string.Empty
;
76 private int charEntityIndex
= -1;
78 internal CharEntityEncoderFallbackBuffer( CharEntityEncoderFallback parent
) {
82 public override bool Fallback( char charUnknown
, int index
) {
83 // If we are already in fallback, throw, it's probably at the suspect character in charEntity
84 if ( charEntityIndex
>= 0 ) {
85 (new EncoderExceptionFallback()).CreateFallbackBuffer().Fallback( charUnknown
, index
);
88 // find out if we can replace the character with entity
89 if ( parent
.CanReplaceAt( index
) ) {
90 // Create the replacement character entity
91 charEntity
= string.Format( CultureInfo
.InvariantCulture
, "&#x{0:X};", new object[] { (int)charUnknown }
);
96 EncoderFallbackBuffer errorFallbackBuffer
= ( new EncoderExceptionFallback() ).CreateFallbackBuffer();
97 errorFallbackBuffer
.Fallback( charUnknown
, index
);
102 public override bool Fallback( char charUnknownHigh
, char charUnknownLow
, int index
) {
103 // check input surrogate pair
104 if ( !char.IsSurrogatePair( charUnknownHigh
, charUnknownLow
) ) {
105 throw XmlConvert
.CreateInvalidSurrogatePairException( charUnknownHigh
, charUnknownLow
);
108 // If we are already in fallback, throw, it's probably at the suspect character in charEntity
109 if ( charEntityIndex
>= 0 ) {
110 (new EncoderExceptionFallback()).CreateFallbackBuffer().Fallback( charUnknownHigh
, charUnknownLow
, index
);
113 if ( parent
.CanReplaceAt( index
) ) {
114 // Create the replacement character entity
115 charEntity
= string.Format( CultureInfo
.InvariantCulture
, "&#x{0:X};", new object[] { SurrogateCharToUtf32( charUnknownHigh, charUnknownLow ) }
);
120 EncoderFallbackBuffer errorFallbackBuffer
= ( new EncoderExceptionFallback() ).CreateFallbackBuffer();
121 errorFallbackBuffer
.Fallback( charUnknownHigh
, charUnknownLow
, index
);
126 public override char GetNextChar() {
127 // Bug fix: 35637. The protocol using GetNextChar() and MovePrevious() called by Encoder is not well documented.
128 // Here we have to to signal to Encoder that the previous read was last character. Only AFTER we can
129 // mark ourself as done (-1). Otherwise MovePrevious() can still be called, but -1 is already incorrectly set
130 // and return false from MovePrevious(). Then Encoder ----ing the rest of the bytes.
131 if (charEntityIndex
== charEntity
.Length
)
133 charEntityIndex
= -1;
135 if ( charEntityIndex
== -1 ) {
139 Debug
.Assert( charEntityIndex
< charEntity
.Length
);
140 char ch
= charEntity
[charEntityIndex
++];
145 public override bool MovePrevious() {
146 if ( charEntityIndex
== -1 ) {
150 // Could be == length if just read the last character
151 Debug
.Assert(charEntityIndex
<= charEntity
.Length
);
152 if (charEntityIndex
> 0)
164 public override int Remaining
{
166 if ( charEntityIndex
== -1 ) {
170 return charEntity
.Length
- charEntityIndex
;
175 public override void Reset() {
176 charEntityIndex
= -1;
179 private int SurrogateCharToUtf32(char highSurrogate
, char lowSurrogate
) {
180 return XmlCharType
.CombineSurrogateChar(lowSurrogate
, highSurrogate
);