/// <summary> /// Stores built automaton in pre-allocated <see cref="Automaton{TSequence,TElement,TElementDistribution,TSequenceManipulator,TThis}"/> object. /// </summary> public DataContainer GetData(bool?isDeterminized = null) { if (this.StartStateIndex < 0 || this.StartStateIndex >= this.states.Count) { throw new InvalidOperationException( $"Built automaton must have a valid start state. " + $"StartStateIndex = {this.StartStateIndex}, states.Count = {this.states.Count}"); } var hasEpsilonTransitions = false; var usesGroups = false; var hasOnlyForwardTransitions = true; var resultStates = ReadOnlyArray.CreateBuilder <StateData>(this.states.Count); var resultTransitions = ReadOnlyArray.CreateBuilder <Transition>(this.transitions.Count - this.numRemovedTransitions); var nextResultTransitionIndex = 0; for (var i = 0; i < resultStates.Count; ++i) { var firstResultTransitionIndex = nextResultTransitionIndex; var transitionIndex = this.states[i].FirstTransitionIndex; while (transitionIndex != -1) { var node = this.transitions[transitionIndex]; var transition = node.Transition; Debug.Assert( transition.DestinationStateIndex < resultStates.Count, "Destination indexes must be in valid range"); resultTransitions[nextResultTransitionIndex] = transition; ++nextResultTransitionIndex; hasEpsilonTransitions = hasEpsilonTransitions || transition.IsEpsilon; usesGroups = usesGroups || (transition.Group != 0); if (transition.DestinationStateIndex <= i) { hasOnlyForwardTransitions = false; } transitionIndex = node.Next; } resultStates[i] = new StateData( firstResultTransitionIndex, nextResultTransitionIndex - firstResultTransitionIndex, this.states[i].EndWeight); } Debug.Assert( nextResultTransitionIndex == resultTransitions.Count, "number of copied transitions must match result array size"); // Detect two very common automata shapes var isEnumerable = hasOnlyForwardTransitions ? true : (bool?)null; return(new DataContainer( this.StartStateIndex, resultStates.MoveToImmutable(), resultTransitions.MoveToImmutable(), !hasEpsilonTransitions, usesGroups, isDeterminized, isZero: null, isEnumerable: isEnumerable)); }