/* * Copyright (C) 2015 The Lemon Man * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ namespace Gedit { namespace FindInFilesPlugin { class RegexFind : Object, IMatcher { private Regex re; public RegexFind (string pattern, bool ignore_case) throws Error { var flags = RegexCompileFlags.OPTIMIZE; if (ignore_case) flags |= RegexCompileFlags.CASELESS; re = new Regex (pattern, flags); } public bool has_match (uint8 *text, size_t text_length, size_t pos, ref Range match) { MatchInfo info; int casted_pos; // Prevent an integer overflow when downcasting from size_t to int if (pos > int.MAX) { casted_pos = 0; text += pos; } else { casted_pos = (int)pos; } // Avoid strdup-ing the whole buffer unowned string str = (string)text; // Pass the text length as str isn't null terminated try { if (!re.match_full (str, (ssize_t)text_length, casted_pos, 0, out info)) return false; } catch (RegexError err) { warning (err.message); return false; } info.fetch_pos (0, out match.from, out match.to); return true; } } class BoyerMooreHorspool : Object, IMatcher { private string pattern; private int bad_char_shift[256]; private bool ignore_case; public BoyerMooreHorspool (string pattern_, bool ignore_case_) { pattern = pattern_; ignore_case = ignore_case_; for (int i = 0; i < 256; i++) { bad_char_shift[i] = pattern.length; } for (int i = 0; i < pattern.length - 1; i++) { if (ignore_case) { bad_char_shift[Posix.toupper(pattern[i])] = pattern.length - 1 - i; bad_char_shift[Posix.tolower(pattern[i])] = pattern.length - 1 - i; } else { bad_char_shift[pattern[i]] = pattern.length - 1 - i; } } } public bool has_match (uint8 *text, size_t text_length, size_t pos, ref Range match) { uint i = 0; text += pos; text_length -= pos; if (text_length < pattern.length) return false; while (i <= text_length - pattern.length) { for (int j = pattern.length - 1; j >= 0; j--) { // Check for a match backwards if (ignore_case) { if (Posix.tolower(text[i + j]) != Posix.tolower(pattern[j])) break; } else { if (text[i + j] != pattern[j]) break; } // The whole needle has been matched! if (j == 0) { match.from = pos + i; match.to = match.from + pattern.length; return true; } } // Jump ahead in the buffer i += bad_char_shift[text[i + pattern.length - 1]]; } return false; } } } // namespace FindInFilesPlugin } // namespace Gedit