/// <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++; } } }