Ejemplo n.º 1
0
        /// <summary>
        /// Finds largest term accepted by this Automaton, that's
        ///  <= the provided input term.  The result is placed in
        ///  output; it's fine for output and input to point to
        ///  the same BytesRef.  The returned result is either the
        ///  provided output, or null if there is no floor term
        ///  (ie, the provided input term is before the first term
        ///  accepted by this Automaton).
        /// </summary>
        public virtual BytesRef Floor(BytesRef input, BytesRef output)
        {
            output.Offset = 0;
            //if (DEBUG) System.out.println("CA.floor input=" + input.utf8ToString());

            int state = RunAutomaton.InitialState;

            // Special case empty string:
            if (input.Length == 0)
            {
                if (RunAutomaton.IsAccept(state))
                {
                    output.Length = 0;
                    return(output);
                }
                else
                {
                    return(null);
                }
            }

            IList <int> stack = new List <int>();

            int idx = 0;

            while (true)
            {
                int label     = input.Bytes[input.Offset + idx] & 0xff;
                int nextState = RunAutomaton.Step(state, label);
                //if (DEBUG) System.out.println("  cycle label=" + (char) label + " nextState=" + nextState);

                if (idx == input.Length - 1)
                {
                    if (nextState != -1 && RunAutomaton.IsAccept(nextState))
                    {
                        // Input string is accepted
                        if (idx >= output.Bytes.Length)
                        {
                            output.Grow(1 + idx);
                        }
                        output.Bytes[idx] = (sbyte)label;
                        output.Length     = input.Length;
                        //if (DEBUG) System.out.println("  input is accepted; return term=" + output.utf8ToString());
                        return(output);
                    }
                    else
                    {
                        nextState = -1;
                    }
                }

                if (nextState == -1)
                {
                    // Pop back to a state that has a transition
                    // <= our label:
                    while (true)
                    {
                        Transition[] transitions = SortedTransitions[state];
                        if (transitions.Length == 0)
                        {
                            Debug.Assert(RunAutomaton.IsAccept(state));
                            output.Length = idx;
                            //if (DEBUG) System.out.println("  return " + output.utf8ToString());
                            return(output);
                        }
                        else if (label - 1 < transitions[0].Min_Renamed)
                        {
                            if (RunAutomaton.IsAccept(state))
                            {
                                output.Length = idx;
                                //if (DEBUG) System.out.println("  return " + output.utf8ToString());
                                return(output);
                            }
                            // pop
                            if (stack.Count == 0)
                            {
                                //if (DEBUG) System.out.println("  pop ord=" + idx + " return null");
                                return(null);
                            }
                            else
                            {
                                state = stack[stack.Count - 1];
                                stack.RemoveAt(stack.Count - 1);
                                idx--;
                                //if (DEBUG) System.out.println("  pop ord=" + (idx+1) + " label=" + (char) label + " first trans.min=" + (char) transitions[0].min);
                                label = input.Bytes[input.Offset + idx] & 0xff;
                            }
                        }
                        else
                        {
                            //if (DEBUG) System.out.println("  stop pop ord=" + idx + " first trans.min=" + (char) transitions[0].min);
                            break;
                        }
                    }

                    //if (DEBUG) System.out.println("  label=" + (char) label + " idx=" + idx);

                    return(AddTail(state, output, idx, label));
                }
                else
                {
                    if (idx >= output.Bytes.Length)
                    {
                        output.Grow(1 + idx);
                    }
                    output.Bytes[idx] = (sbyte)label;
                    stack.Add(state);
                    state = nextState;
                    idx++;
                }
            }
        }