/// <summary>Searches for a match, beginning from a specified position.</summary> /// <param name="text">The text to match against.</param> /// <param name="startIndex">The starting position.</param> /// <param name="anchored">Set to <c>true</c> to force matches to start from <paramref name="startIndex"/>.</param> /// <returns>Result of the search.</returns> internal Match Find(string text, int startIndex, bool anchored) { int length = text.Length; if (Anchored) anchored = true; Stack<Match> avail = new Stack<Match>(); Queue<Match> active = new Queue<Match>(nTransitions); Match best = new Match(this, text, anchored); Match start = new Match(this, text, anchored); start.StateID = 0; start.Position = startIndex; if (!anchored) Scan(start); do { Match current; if (active.Count == 0 || active.Peek().Position > start.Position) current = start; else current = active.Dequeue(); Transition[] trans = States[current.StateID]; for (int i = 0; i < trans.Length; i++) { if (Evaluate(current, trans[i].instruction, trans[i].target, true)) { // don't duplicate work or run past the end of text if (current.Position <= length && !active.Contains(current, sameFinal)) { Match next; if (avail.Count == 0) next = new Match(this, text, anchored); else next = avail.Pop(); next.Copy(current); active.Enqueue(next); } } else if (Match.PosixPriority(current, best) > 0) best.Copy(current); Unevaluate(current); } if (current != start) avail.Push(current); else if (anchored || best.IsSuccess) start.Position = length; else { start.Position++; Scan(start); } } while (active.Count > 0 || start.Position < length); return best; }