[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / referencesource / System.Xml / System / Xml / Core / CharEntityEncoderFallback.cs
blob00aad6ab9157f0a34fde7ba15504557226d3cf19
1 //------------------------------------------------------------------------------
2 // <copyright file="CharEntitiesEncodingFallback.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Text;
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 {
37 get {
38 return 12;
42 internal int StartOffset {
43 get {
44 return startOffset;
46 set {
47 startOffset = value;
51 internal void Reset( int[] textContentMarks, int endMarkPos ) {
52 this.textContentMarks = textContentMarks;
53 this.endMarkPos = endMarkPos;
54 curMarkPos = 0;
57 internal bool CanReplaceAt( int index ) {
58 int mPos = curMarkPos;
59 int charPos = startOffset + index;
60 while ( mPos < endMarkPos && charPos >= textContentMarks[mPos+1] ) {
61 mPos++;
63 curMarkPos = mPos;
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 ) {
79 this.parent = 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 } );
92 charEntityIndex = 0;
93 return true;
95 else {
96 EncoderFallbackBuffer errorFallbackBuffer = ( new EncoderExceptionFallback() ).CreateFallbackBuffer();
97 errorFallbackBuffer.Fallback( charUnknown, index );
98 return false;
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 ) } );
116 charEntityIndex = 0;
117 return true;
119 else {
120 EncoderFallbackBuffer errorFallbackBuffer = ( new EncoderExceptionFallback() ).CreateFallbackBuffer();
121 errorFallbackBuffer.Fallback( charUnknownHigh, charUnknownLow, index );
122 return false;
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 ) {
136 return (char)0;
138 else {
139 Debug.Assert( charEntityIndex < charEntity.Length );
140 char ch = charEntity[charEntityIndex++];
141 return ch;
145 public override bool MovePrevious() {
146 if ( charEntityIndex == -1 ) {
147 return false;
149 else {
150 // Could be == length if just read the last character
151 Debug.Assert(charEntityIndex <= charEntity.Length);
152 if (charEntityIndex > 0)
154 charEntityIndex--;
155 return true;
157 else {
158 return false;
164 public override int Remaining {
165 get {
166 if ( charEntityIndex == -1 ) {
167 return 0;
169 else {
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);