Stepper

  • 334
  • 0

摘要:Stepper

public class Stepper
{
    private readonly Digit _digit;
    private char[] _buf;

    public string Value
    {
        get
        {
            _digit.FillValue(_buf);
            return new string(_buf);
        }
        set { _digit.SetValue(value); }
    }

    public Stepper(string chars)
    {
        _buf = new char[]{};
        _digit = new Digit(chars);
    }

    public string Next()
    {
        _digit.Next();
        return Value;
    }

    public void ForEach(string start, string end, Action callback)
    {
        _buf = new char[start.Length];
        Value = start;
        while (true)
        {
            var s = Value;
            callback(s);
            if (s == end) break;
            Next();
        }
    }

    private class Digit
    {
        private int _current;
        private Digit _next;
        private readonly int _len;
        private readonly string _chars;

        public Digit(string chars)
        {
            _current = 0;
            _chars = chars;
            _len = _chars.Length;
        }

        public void Next()
        {
            _current++;
            if (_current < _len) return;
            if (_next == null) _next = new Digit(_chars);
            _next.Next();
            _current = 0;
        }

        public void FillValue(IList list)
        {
            Fill(list, list.Count - 1);
        }

        public void SetValue(string value)
        {
            SetValue(value, value.Length - 1);
        }

        private void SetValue(string value, int index)
        {
            var i = _chars.IndexOf(value[index]);
            if (i < 0) throw new ArgumentOutOfRangeException();
            _current = i;
            if (index == 0)
            {
                _next = null;
                return;
            }
            if (_next == null) _next = new Digit(_chars);
            _next.SetValue(value, index - 1);
        }

        private void Fill(IList list, int index)
        {
            if (index < 0) return;
            list[index] = _chars[_current];
            if (_next != null) _next.Fill(list, index-1);
        }
    }
}