InternalEncoderBestFitFallbackBuffer
using System.Threading;
namespace System.Text
{
    internal sealed class InternalEncoderBestFitFallbackBuffer : EncoderFallbackBuffer
    {
        private char _cBestFit;
        private readonly InternalEncoderBestFitFallback _oFallback;
        private int _iCount = -1;
        private int _iSize;
        private static object s_InternalSyncObject;
        private static object InternalSyncObject {
            get {
                if (s_InternalSyncObject == null) {
                    object value = new object();
                    Interlocked.CompareExchange<object>(ref s_InternalSyncObject, value, (object)null);
                }
                return s_InternalSyncObject;
            }
        }
        public override int Remaining {
            get {
                if (_iCount <= 0)
                    return 0;
                return _iCount;
            }
        }
        public InternalEncoderBestFitFallbackBuffer(InternalEncoderBestFitFallback fallback)
        {
            _oFallback = fallback;
            if (_oFallback.arrayBestFit == null) {
                lock (InternalSyncObject) {
                    InternalEncoderBestFitFallback oFallback = _oFallback;
                    if (oFallback.arrayBestFit == null)
                        oFallback.arrayBestFit = fallback.encoding.GetBestFitUnicodeToBytesData();
                }
            }
        }
        public override bool Fallback(char charUnknown, int index)
        {
            _iCount = (_iSize = 1);
            _cBestFit = TryBestFit(charUnknown);
            if (_cBestFit == ' ')
                _cBestFit = '?';
            return true;
        }
        public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
        {
            if (!char.IsHighSurrogate(charUnknownHigh))
                throw new ArgumentOutOfRangeException("charUnknownHigh", System.SR.Format(System.SR.ArgumentOutOfRange_Range, 55296, 56319));
            if (!char.IsLowSurrogate(charUnknownLow))
                throw new ArgumentOutOfRangeException("charUnknownLow", System.SR.Format(System.SR.ArgumentOutOfRange_Range, 56320, 57343));
            _cBestFit = '?';
            _iCount = (_iSize = 2);
            return true;
        }
        public override char GetNextChar()
        {
            _iCount--;
            if (_iCount < 0)
                return ' ';
            if (_iCount == 2147483647) {
                _iCount = -1;
                return ' ';
            }
            return _cBestFit;
        }
        public override bool MovePrevious()
        {
            if (_iCount >= 0)
                _iCount++;
            if (_iCount >= 0)
                return _iCount <= _iSize;
            return false;
        }
        public override void Reset()
        {
            _iCount = -1;
        }
        private char TryBestFit(char cUnknown)
        {
            int num = 0;
            int num2 = _oFallback.arrayBestFit.Length;
            int num3;
            while ((num3 = num2 - num) > 6) {
                int num4 = (num3 / 2 + num) & 65534;
                char c = _oFallback.arrayBestFit[num4];
                if (c == cUnknown)
                    return _oFallback.arrayBestFit[num4 + 1];
                if (c < cUnknown)
                    num = num4;
                else
                    num2 = num4;
            }
            for (int num4 = num; num4 < num2; num4 += 2) {
                if (_oFallback.arrayBestFit[num4] == cUnknown)
                    return _oFallback.arrayBestFit[num4 + 1];
            }
            return ' ';
        }
    }
}