view Implab/Formats/InputScanner.cs @ 236:302ca905c19e v2

JsonReader optimizations
author cin
date Tue, 21 Nov 2017 14:57:58 +0300
parents 5f7a3e1d32b9
children
line wrap: on
line source

using Implab.Automaton;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Implab.Formats {
    public class InputScanner<TTag> {
        readonly TTag[] m_tags;
        readonly int m_initialState;
        readonly int[,] m_dfa;
        readonly CharMap m_alphabet;
        readonly bool[] m_final;

        int m_position;
        int m_state;

        public InputScanner(int[,] dfaTable, bool[] finalStates, TTag[] tags, int initialState, CharMap alphabet) {
            Safe.ArgumentNotNull(dfaTable, nameof(dfaTable));
            Safe.ArgumentNotNull(finalStates, nameof(finalStates));
            Safe.ArgumentNotNull(tags, nameof(tags));
            Safe.ArgumentNotNull(alphabet, nameof(alphabet));

            m_dfa = dfaTable;
            m_final = finalStates;
            m_tags = tags;
            m_initialState = initialState;
            m_alphabet = alphabet;
        }

        public TTag Tag {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get {
                return m_tags[m_state];
            }
        }

        public int Position {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get {
                return m_position;
            }
        }

        public bool IsFinal {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get {
                return m_final[m_state];
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ResetState() {
            m_state = m_initialState;
        }

        public InputScanner<TTag> Clone() {
            var clone = new InputScanner<TTag>(m_dfa, m_final, m_tags, m_initialState, m_alphabet);
            clone.m_state = m_state;
            clone.m_position = m_position;
            return clone;
        }

        //[MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Scan(char[] data, int offset, int max) {
            var next = m_state;

            while(offset < max) {
                next = m_dfa[next, m_alphabet.Translate(data[offset])];
                if (next == AutomatonConst.UnreachableState) {
                    // scanner stops on the next position after last recognized symbol
                    m_position = offset;
                    return false;
                }
                m_state = next;
                offset++;
            }
            m_position = offset;
            return true;
        }
    }
}