| File: FrameworkFork\Microsoft.Xml\Xml\Core\CharEntityEncoderFallback.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// 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. using System.Text; using System.Diagnostics; using System.Globalization; namespace Microsoft.Xml { using System; // // CharEntityEncoderFallback // internal class CharEntityEncoderFallback : EncoderFallback { private CharEntityEncoderFallbackBuffer _fallbackBuffer; private int[] _textContentMarks; private int _endMarkPos; private int _curMarkPos; private int _startOffset; internal CharEntityEncoderFallback() { } public override EncoderFallbackBuffer CreateFallbackBuffer() { if (_fallbackBuffer == null) { _fallbackBuffer = new CharEntityEncoderFallbackBuffer(this); } return _fallbackBuffer; } public override int MaxCharCount { get { return 12; } } internal int StartOffset { get { return _startOffset; } set { _startOffset = value; } } internal void Reset(int[] textContentMarks, int endMarkPos) { _textContentMarks = textContentMarks; _endMarkPos = endMarkPos; _curMarkPos = 0; } internal bool CanReplaceAt(int index) { int mPos = _curMarkPos; int charPos = _startOffset + index; while (mPos < _endMarkPos && charPos >= _textContentMarks[mPos + 1]) { mPos++; } _curMarkPos = mPos; return (mPos & 1) != 0; } } // // CharEntityFallbackBuffer // internal class CharEntityEncoderFallbackBuffer : EncoderFallbackBuffer { private CharEntityEncoderFallback _parent; private string _charEntity = string.Empty; private int _charEntityIndex = -1; internal CharEntityEncoderFallbackBuffer(CharEntityEncoderFallback parent) { _parent = parent; } public override bool Fallback(char charUnknown, int index) { // If we are already in fallback, throw, it's probably at the suspect character in charEntity if (_charEntityIndex >= 0) { (new EncoderExceptionFallback()).CreateFallbackBuffer().Fallback(charUnknown, index); } // find out if we can replace the character with entity if (_parent.CanReplaceAt(index)) { // Create the replacement character entity _charEntity = string.Format(CultureInfo.InvariantCulture, "&#x{0:X};", new object[] { (int)charUnknown }); _charEntityIndex = 0; return true; } else { EncoderFallbackBuffer errorFallbackBuffer = (new EncoderExceptionFallback()).CreateFallbackBuffer(); errorFallbackBuffer.Fallback(charUnknown, index); return false; } } public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index) { // check input surrogate pair if (!char.IsSurrogatePair(charUnknownHigh, charUnknownLow)) { throw XmlConvert.CreateInvalidSurrogatePairException(charUnknownHigh, charUnknownLow); } // If we are already in fallback, throw, it's probably at the suspect character in charEntity if (_charEntityIndex >= 0) { (new EncoderExceptionFallback()).CreateFallbackBuffer().Fallback(charUnknownHigh, charUnknownLow, index); } if (_parent.CanReplaceAt(index)) { // Create the replacement character entity _charEntity = string.Format(CultureInfo.InvariantCulture, "&#x{0:X};", new object[] { SurrogateCharToUtf32(charUnknownHigh, charUnknownLow) }); _charEntityIndex = 0; return true; } else { EncoderFallbackBuffer errorFallbackBuffer = (new EncoderExceptionFallback()).CreateFallbackBuffer(); errorFallbackBuffer.Fallback(charUnknownHigh, charUnknownLow, index); return false; } } public override char GetNextChar() { // Bug fix: 35637. The protocol using GetNextChar() and MovePrevious() called by Encoder is not well documented. // Here we have to to signal to Encoder that the previous read was last character. Only AFTER we can // mark ourself as done (-1). Otherwise MovePrevious() can still be called, but -1 is already incorrectly set // and return false from MovePrevious(). Then Encoder swallowing the rest of the bytes. if (_charEntityIndex == _charEntity.Length) { _charEntityIndex = -1; } if (_charEntityIndex == -1) { return (char)0; } else { Debug.Assert(_charEntityIndex < _charEntity.Length); char ch = _charEntity[_charEntityIndex++]; return ch; } } public override bool MovePrevious() { if (_charEntityIndex == -1) { return false; } else { // Could be == length if just read the last character Debug.Assert(_charEntityIndex <= _charEntity.Length); if (_charEntityIndex > 0) { _charEntityIndex--; return true; } else { return false; } } } public override int Remaining { get { if (_charEntityIndex == -1) { return 0; } else { return _charEntity.Length - _charEntityIndex; } } } public override void Reset() { _charEntityIndex = -1; } private int SurrogateCharToUtf32(char highSurrogate, char lowSurrogate) { return XmlCharType.CombineSurrogateChar(lowSurrogate, highSurrogate); } } }