33
44using System . Text ;
55using System . Diagnostics ;
6- using System . Globalization ;
6+ using System . Diagnostics . CodeAnalysis ;
77
88namespace System . Xml
99{
10- //
11- // CharEntityEncoderFallback
12- //
1310 internal sealed class CharEntityEncoderFallback : EncoderFallback
1411 {
1512 private CharEntityEncoderFallbackBuffer ? _fallbackBuffer ;
16-
1713 private int [ ] ? _textContentMarks ;
1814 private int _endMarkPos ;
1915 private int _curMarkPos ;
20- private int _startOffset ;
2116
22- internal CharEntityEncoderFallback ( )
23- {
24- }
17+ public override int MaxCharCount => 12 ;
18+ internal int StartOffset { get ; set ; }
2519
2620 public override EncoderFallbackBuffer CreateFallbackBuffer ( )
2721 {
28- if ( _fallbackBuffer == null )
29- {
30- _fallbackBuffer = new CharEntityEncoderFallbackBuffer ( this ) ;
31- }
32- return _fallbackBuffer ;
33- }
34-
35- public override int MaxCharCount
36- {
37- get
38- {
39- return 12 ;
40- }
41- }
42-
43- internal int StartOffset
44- {
45- get
46- {
47- return _startOffset ;
48- }
49- set
50- {
51- _startOffset = value ;
52- }
22+ return _fallbackBuffer ??= new CharEntityEncoderFallbackBuffer ( this ) ;
5323 }
5424
25+ [ MemberNotNull ( nameof ( _textContentMarks ) ) ]
5526 internal void Reset ( int [ ] textContentMarks , int endMarkPos )
5627 {
5728 _textContentMarks = textContentMarks ;
5829 _endMarkPos = endMarkPos ;
5930 _curMarkPos = 0 ;
6031 }
6132
62- internal bool CanReplaceAt ( int index )
33+ private bool CanReplaceAt ( int index )
6334 {
6435 Debug . Assert ( _textContentMarks != null ) ;
6536
6637 int mPos = _curMarkPos ;
67- int charPos = _startOffset + index ;
38+ int charPos = StartOffset + index ;
6839 while ( mPos < _endMarkPos && charPos >= _textContentMarks [ mPos + 1 ] )
6940 {
7041 mPos ++ ;
@@ -73,144 +44,121 @@ internal bool CanReplaceAt(int index)
7344
7445 return ( mPos & 1 ) != 0 ;
7546 }
76- }
77-
78- //
79- // CharEntityFallbackBuffer
80- //
81- internal sealed class CharEntityEncoderFallbackBuffer : EncoderFallbackBuffer
82- {
83- private readonly CharEntityEncoderFallback _parent ;
8447
85- private string _charEntity = string . Empty ;
86- private int _charEntityIndex = - 1 ;
8748
88- internal CharEntityEncoderFallbackBuffer ( CharEntityEncoderFallback parent )
49+ private sealed class CharEntityEncoderFallbackBuffer : EncoderFallbackBuffer
8950 {
90- _parent = parent ;
91- }
51+ private readonly CharEntityEncoderFallback _parent ;
9252
93- public override bool Fallback ( char charUnknown , int index )
94- {
95- // If we are already in fallback, throw, it's probably at the suspect character in charEntity
96- if ( _charEntityIndex >= 0 )
97- {
98- ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) . Fallback ( charUnknown , index ) ;
99- }
53+ private string _charEntity = string . Empty ;
54+ private int _charEntityIndex = - 1 ;
10055
101- // find out if we can replace the character with entity
102- if ( _parent . CanReplaceAt ( index ) )
56+ internal CharEntityEncoderFallbackBuffer ( CharEntityEncoderFallback parent )
10357 {
104- // Create the replacement character entity
105- _charEntity = string . Create ( null , stackalloc char [ 64 ] , $ "&#x{ ( int ) charUnknown : X} ;") ;
106- _charEntityIndex = 0 ;
107- return true ;
58+ _parent = parent ;
10859 }
109- else
60+
61+ public override int Remaining => _charEntityIndex == - 1 ? 0 : _charEntity . Length - _charEntityIndex ;
62+
63+ public override bool Fallback ( char charUnknown , int index )
11064 {
65+ // If we are already in fallback, throw, it's probably at the suspect character in charEntity
66+ if ( _charEntityIndex >= 0 )
67+ {
68+ ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) . Fallback ( charUnknown , index ) ;
69+ }
70+
71+ // find out if we can replace the character with entity
72+ if ( _parent . CanReplaceAt ( index ) )
73+ {
74+ // Create the replacement character entity
75+ _charEntity = string . Create ( null , stackalloc char [ 64 ] , $ "&#x{ ( int ) charUnknown : X} ;") ;
76+ _charEntityIndex = 0 ;
77+ return true ;
78+ }
79+
11180 EncoderFallbackBuffer errorFallbackBuffer = ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) ;
11281 errorFallbackBuffer . Fallback ( charUnknown , index ) ;
11382 return false ;
11483 }
115- }
11684
117- public override bool Fallback ( char charUnknownHigh , char charUnknownLow , int index )
118- {
119- // check input surrogate pair
120- if ( ! char . IsSurrogatePair ( charUnknownHigh , charUnknownLow ) )
85+ public override bool Fallback ( char charUnknownHigh , char charUnknownLow , int index )
12186 {
122- throw XmlConvert . CreateInvalidSurrogatePairException ( charUnknownHigh , charUnknownLow ) ;
123- }
87+ // check input surrogate pair
88+ if ( ! char . IsSurrogatePair ( charUnknownHigh , charUnknownLow ) )
89+ {
90+ throw XmlConvert . CreateInvalidSurrogatePairException ( charUnknownHigh , charUnknownLow ) ;
91+ }
12492
125- // If we are already in fallback, throw, it's probably at the suspect character in charEntity
126- if ( _charEntityIndex >= 0 )
127- {
128- ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) . Fallback ( charUnknownHigh , charUnknownLow , index ) ;
129- }
93+ // If we are already in fallback, throw, it's probably at the suspect character in charEntity
94+ if ( _charEntityIndex >= 0 )
95+ {
96+ ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) . Fallback ( charUnknownHigh , charUnknownLow , index ) ;
97+ }
98+
99+ if ( _parent . CanReplaceAt ( index ) )
100+ {
101+ // Create the replacement character entity
102+ _charEntity = string . Create ( null , stackalloc char [ 64 ] , $ "&#x{ SurrogateCharToUtf32 ( charUnknownHigh , charUnknownLow ) : X} ;") ;
103+ _charEntityIndex = 0 ;
104+ return true ;
105+ }
130106
131- if ( _parent . CanReplaceAt ( index ) )
132- {
133- // Create the replacement character entity
134- _charEntity = string . Create ( null , stackalloc char [ 64 ] , $ "&#x{ SurrogateCharToUtf32 ( charUnknownHigh , charUnknownLow ) : X} ;") ;
135- _charEntityIndex = 0 ;
136- return true ;
137- }
138- else
139- {
140107 EncoderFallbackBuffer errorFallbackBuffer = ( new EncoderExceptionFallback ( ) ) . CreateFallbackBuffer ( ) ;
141108 errorFallbackBuffer . Fallback ( charUnknownHigh , charUnknownLow , index ) ;
142109 return false ;
143110 }
144- }
145111
146- public override char GetNextChar ( )
147- {
148- // The protocol using GetNextChar() and MovePrevious() called by Encoder is not well documented.
149- // Here we have to signal to Encoder that the previous read was last character. Only AFTER we can
150- // mark ourself as done (-1). Otherwise MovePrevious() can still be called, but -1 is already incorrectly set
151- // and return false from MovePrevious(). Then Encoder swallowing the rest of the bytes.
152- if ( _charEntityIndex == _charEntity . Length )
153- {
154- _charEntityIndex = - 1 ;
155- }
156- if ( _charEntityIndex == - 1 )
157- {
158- return ( char ) 0 ;
159- }
160- else
112+ public override char GetNextChar ( )
161113 {
114+ // The protocol using GetNextChar() and MovePrevious() called by Encoder is not well documented.
115+ // Here we have to signal to Encoder that the previous read was last character. Only AFTER we can
116+ // mark our self as done (-1). Otherwise MovePrevious() can still be called, but -1 is already incorrectly set
117+ // and return false from MovePrevious(). Then Encoder swallowing the rest of the bytes.
118+ if ( _charEntityIndex == _charEntity . Length )
119+ {
120+ _charEntityIndex = - 1 ;
121+ }
122+
123+ if ( _charEntityIndex == - 1 )
124+ {
125+ return ( char ) 0 ;
126+ }
127+
162128 Debug . Assert ( _charEntityIndex < _charEntity . Length ) ;
163- char ch = _charEntity [ _charEntityIndex ++ ] ;
164- return ch ;
165- }
166- }
167129
168- public override bool MovePrevious ( )
169- {
170- if ( _charEntityIndex == - 1 )
171- {
172- return false ;
130+ return _charEntity [ _charEntityIndex ++ ] ;
173131 }
174- else
132+
133+ public override bool MovePrevious ( )
175134 {
135+ if ( _charEntityIndex == - 1 )
136+ {
137+ return false ;
138+ }
139+
176140 // Could be == length if just read the last character
177141 Debug . Assert ( _charEntityIndex <= _charEntity . Length ) ;
142+
178143 if ( _charEntityIndex > 0 )
179144 {
180145 _charEntityIndex -- ;
146+
181147 return true ;
182148 }
183- else
184- {
185- return false ;
186- }
187- }
188- }
189149
150+ return false ;
151+ }
190152
191- public override int Remaining
192- {
193- get
153+ public override void Reset ( )
194154 {
195- if ( _charEntityIndex == - 1 )
196- {
197- return 0 ;
198- }
199- else
200- {
201- return _charEntity . Length - _charEntityIndex ;
202- }
155+ _charEntityIndex = - 1 ;
203156 }
204- }
205157
206- public override void Reset ( )
207- {
208- _charEntityIndex = - 1 ;
209- }
210-
211- private int SurrogateCharToUtf32 ( char highSurrogate , char lowSurrogate )
212- {
213- return XmlCharType . CombineSurrogateChar ( lowSurrogate , highSurrogate ) ;
158+ private static int SurrogateCharToUtf32 ( char highSurrogate , char lowSurrogate )
159+ {
160+ return XmlCharType . CombineSurrogateChar ( lowSurrogate , highSurrogate ) ;
161+ }
214162 }
215163 }
216164}
0 commit comments