﻿// Decompiled with JetBrains decompiler
// Type: System.Text.EncoderFallbackBuffer
// Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 255ABCDF-D9D6-4E3D-BAD4-F74D4CE3D7A8
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll

using System;
using System.Runtime;
using System.Security;

namespace System.Text
{
  /// <summary>
  /// Provides a buffer that allows a fallback handler to return an alternate string to an encoder when it cannot encode an input character.
  /// </summary>
  /// <filterpriority>2</filterpriority>
  public abstract class EncoderFallbackBuffer
  {
    [SecurityCritical]
    internal unsafe char* charStart;
    [SecurityCritical]
    internal unsafe char* charEnd;
    internal EncoderNLS encoder;
    internal bool setEncoder;
    internal bool bUsedEncoder;
    internal bool bFallingBack;
    internal int iRecursionCount;
    private const int iMaxRecursion = 250;

    /// <summary>
    /// When overridden in a derived class, gets the number of characters in the current <see cref="T:System.Text.EncoderFallbackBuffer"/> object that remain to be processed.
    /// </summary>
    /// 
    /// <returns>
    /// The number of characters in the current fallback buffer that have not yet been processed.
    /// </returns>
    /// <filterpriority>1</filterpriority>
    public abstract int Remaining { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="T:System.Text.EncoderFallbackBuffer"/> class.
    /// </summary>
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    protected EncoderFallbackBuffer()
    {
    }

    /// <summary>
    /// When overridden in a derived class, prepares the fallback buffer to handle the specified input character.
    /// </summary>
    /// 
    /// <returns>
    /// true if the fallback buffer can process <paramref name="charUnknown"/>; false if the fallback buffer ignores <paramref name="charUnknown"/>.
    /// </returns>
    /// <param name="charUnknown">An input character.</param><param name="index">The index position of the character in the input buffer.</param><filterpriority>1</filterpriority>
    public abstract bool Fallback(char charUnknown, int index);

    /// <summary>
    /// When overridden in a derived class, prepares the fallback buffer to handle the specified surrogate pair.
    /// </summary>
    /// 
    /// <returns>
    /// true if the fallback buffer can process <paramref name="charUnknownHigh"/> and <paramref name="charUnknownLow"/>; false if the fallback buffer ignores the surrogate pair.
    /// </returns>
    /// <param name="charUnknownHigh">The high surrogate of the input pair.</param><param name="charUnknownLow">The low surrogate of the input pair.</param><param name="index">The index position of the surrogate pair in the input buffer.</param><filterpriority>1</filterpriority>
    public abstract bool Fallback(char charUnknownHigh, char charUnknownLow, int index);

    /// <summary>
    /// When overridden in a derived class, retrieves the next character in the fallback buffer.
    /// </summary>
    /// 
    /// <returns>
    /// The next character in the fallback buffer.
    /// </returns>
    /// <filterpriority>2</filterpriority>
    public abstract char GetNextChar();

    /// <summary>
    /// When overridden in a derived class, causes the next call to the <see cref="M:System.Text.EncoderFallbackBuffer.GetNextChar"/> method to access the data buffer character position that is prior to the current character position.
    /// </summary>
    /// 
    /// <returns>
    /// true if the <see cref="M:System.Text.EncoderFallbackBuffer.MovePrevious"/> operation was successful; otherwise, false.
    /// </returns>
    /// <filterpriority>1</filterpriority>
    public abstract bool MovePrevious();

    /// <summary>
    /// Initializes all data and state information pertaining to this fallback buffer.
    /// </summary>
    /// <filterpriority>1</filterpriority>
    public virtual void Reset()
    {
      do
        ;
      while ((int) this.GetNextChar() != 0);
    }

    [SecurityCritical]
    internal unsafe void InternalReset()
    {
      this.charStart = (char*) null;
      this.bFallingBack = false;
      this.iRecursionCount = 0;
      this.Reset();
    }

    [SecurityCritical]
    internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderNLS encoder, bool setEncoder)
    {
      this.charStart = charStart;
      this.charEnd = charEnd;
      this.encoder = encoder;
      this.setEncoder = setEncoder;
      this.bUsedEncoder = false;
      this.bFallingBack = false;
      this.iRecursionCount = 0;
    }

    internal char InternalGetNextChar()
    {
      char nextChar = this.GetNextChar();
      this.bFallingBack = (int) nextChar != 0;
      if ((int) nextChar == 0)
        this.iRecursionCount = 0;
      return nextChar;
    }

    [SecurityCritical]
    internal virtual unsafe bool InternalFallback(char ch, ref char* chars)
    {
      int index = (int) (chars - this.charStart) - 1;
      if (char.IsHighSurrogate(ch))
      {
        if (chars >= this.charEnd)
        {
          if (this.encoder != null && !this.encoder.MustFlush)
          {
            if (this.setEncoder)
            {
              this.bUsedEncoder = true;
              this.encoder.charLeftOver = ch;
            }
            this.bFallingBack = false;
            return false;
          }
        }
        else
        {
          char ch1 = *chars;
          if (char.IsLowSurrogate(ch1))
          {
            if (this.bFallingBack && this.iRecursionCount++ > 250)
              this.ThrowLastCharRecursive(char.ConvertToUtf32(ch, ch1));
            ++chars;
            this.bFallingBack = this.Fallback(ch, ch1, index);
            return this.bFallingBack;
          }
        }
      }
      if (this.bFallingBack && this.iRecursionCount++ > 250)
        this.ThrowLastCharRecursive((int) ch);
      this.bFallingBack = this.Fallback(ch, index);
      return this.bFallingBack;
    }

    internal void ThrowLastCharRecursive(int charRecursive)
    {
      throw new ArgumentException(Environment.GetResourceString("Argument_RecursiveFallback", (object) charRecursive), "chars");
    }
  }
}
