/* * Aho-Corasick * * q = root * FOR i = 1 TO n * WHILE q != fail AND g(q, text[i]) == fail * q = h(q) * ENDWHILE * IF q == fail * q = root * ELSE * q = g(q, text[i]) * ENDIF * IF isElement(q, final) * RETURN TRUE * ENDIF * ENDFOR * RETURN FALSE */ public IList <TrieHit> FindMatches(string haystack) { List <TrieHit> matches = new List <TrieHit> (); TrieState q = root; TrieMatch m = null; int idx = 0, start_idx = 0, last_idx = 0; while (idx < haystack.Length) { char c = haystack [idx++]; if (!case_sensitive) { c = Char.ToLower(c); } while (q != null) { m = FindMatchAtState(q, c); if (m == null) { q = q.Fail; } else { break; } } if (q == root) { start_idx = last_idx; } if (q == null) { q = root; start_idx = idx; } else if (m != null) { q = m.State; // Got a match! if (q.Final != 0) { string key = haystack.Substring(start_idx, idx - start_idx); TrieHit hit = new TrieHit(start_idx, idx, key, q.Id); matches.Add(hit); } } last_idx = idx; } return(matches); }
void DoHighlight(TrieHit hit, Gtk.TextIter start, Gtk.TextIter end) { // Some of these checks should be replaced with fixes to // TitleTrie.FindMatches, probably. if (hit.Value == null) { Logger.Debug("DoHighlight: null pointer error for '{0}'.", hit.Key); return; } if (Manager.Find(hit.Key) == null) { Logger.Debug("DoHighlight: '{0}' links to non-existing note.", hit.Key); return; } Note hit_note = (Note)hit.Value; if (String.Compare(hit.Key.ToString(), hit_note.Title.ToString(), true) != 0) // == 0 if same string { Logger.Debug("DoHighlight: '{0}' links wrongly to note '{1}'.", hit.Key, hit_note.Title); return; } if (hit_note == this.Note) { return; } Gtk.TextIter title_start = start; title_start.ForwardChars(hit.Start); Gtk.TextIter title_end = start; title_end.ForwardChars(hit.End); // Only link against whole words/phrases if ((!title_start.StartsWord() && !title_start.StartsSentence()) || (!title_end.EndsWord() && !title_end.EndsSentence())) { return; } // Don't create links inside URLs if (Note.TagTable.HasLinkTag(title_start)) { return; } Logger.Debug("Matching Note title '{0}' at {1}-{2}...", hit.Key, hit.Start, hit.End); Buffer.RemoveTag(Note.TagTable.BrokenLinkTag, title_start, title_end); Buffer.ApplyTag(Note.TagTable.LinkTag, title_start, title_end); }
void HighlightNoteInBlock(Note find_note, Gtk.TextIter start, Gtk.TextIter end) { string buffer_text = start.GetText(end).ToLower(); string find_title_lower = find_note.Title.ToLower(); int idx = 0; while (true) { idx = buffer_text.IndexOf(find_title_lower, idx); if (idx < 0) { break; } TrieHit hit = new TrieHit(idx, idx + find_title_lower.Length, find_title_lower, find_note); DoHighlight(hit, start, end); idx += find_title_lower.Length; } }
void HighlightNoteInBlock (Note find_note, Gtk.TextIter start, Gtk.TextIter end) { string buffer_text = start.GetText (end).ToLower(); string find_title_lower = find_note.Title.ToLower (); int idx = 0; while (true) { idx = buffer_text.IndexOf (find_title_lower, idx); if (idx < 0) break; TrieHit hit = new TrieHit (idx, idx + find_title_lower.Length, find_title_lower, find_note); DoHighlight (hit, start, end); idx += find_title_lower.Length; } }
void DoHighlight (TrieHit hit, Gtk.TextIter start, Gtk.TextIter end) { // Some of these checks should be replaced with fixes to // TitleTrie.FindMatches, probably. if (hit.Value == null) { Logger.Debug ("DoHighlight: null pointer error for '{0}'." , hit.Key); return; } if (Manager.Find(hit.Key) == null) { Logger.Debug ("DoHighlight: '{0}' links to non-existing note." , hit.Key); return; } Note hit_note = (Note) hit.Value; if (String.Compare (hit.Key.ToString(), hit_note.Title.ToString(), true ) != 0) { // == 0 if same string Logger.Debug ("DoHighlight: '{0}' links wrongly to note '{1}'." , hit.Key, hit_note.Title); return; } if (hit_note == this.Note) return; Gtk.TextIter title_start = start; title_start.ForwardChars (hit.Start); Gtk.TextIter title_end = start; title_end.ForwardChars (hit.End); // Only link against whole words/phrases if ((!title_start.StartsWord () && !title_start.StartsSentence ()) || (!title_end.EndsWord() && !title_end.EndsSentence())) return; // Don't create links inside URLs if (Note.TagTable.HasLinkTag (title_start)) return; Logger.Debug ("Matching Note title '{0}' at {1}-{2}...", hit.Key, hit.Start, hit.End); Buffer.RemoveTag (Note.TagTable.BrokenLinkTag, title_start, title_end); Buffer.ApplyTag (Note.TagTable.LinkTag, title_start, title_end); }