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