mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 04:22:34 +03:00
Make search module more independ (and prepare for future mclib :) )
This commit is contained in:
parent
b2442d1b1e
commit
c2455b246c
@ -10,6 +10,7 @@ set -e
|
||||
: ${AUTOMAKE=automake}
|
||||
: ${ACLOCAL=aclocal}
|
||||
: ${AUTOPOINT=autopoint}
|
||||
: ${LIBTOOLIZE=libtoolize}
|
||||
: ${XGETTEXT=xgettext}
|
||||
|
||||
srcdir=`dirname $0`
|
||||
@ -38,6 +39,8 @@ $XGETTEXT --keyword=_ --keyword=N_ --keyword=Q_ --output=- \
|
||||
/g;s/ //g;p;}' | \
|
||||
grep -v '^$' | sort | uniq | grep -v 'regex.c' >po/POTFILES.in
|
||||
|
||||
$LIBTOOLIZE
|
||||
|
||||
ACLOCAL_INCLUDES="-I m4"
|
||||
|
||||
# Some old version of GNU build tools fail to set error codes.
|
||||
|
@ -15,6 +15,9 @@ AM_MAINTAINER_MODE
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_ISC_POSIX
|
||||
|
||||
AC_PROG_CC_STDC
|
||||
@ -567,7 +570,10 @@ doc/Makefile
|
||||
vfs/Makefile
|
||||
vfs/extfs/Makefile
|
||||
lib/Makefile
|
||||
|
||||
src/Makefile
|
||||
src/search/Makefile
|
||||
|
||||
edit/Makefile
|
||||
syntax/Makefile
|
||||
m4/Makefile
|
||||
|
@ -1,3 +1,5 @@
|
||||
SUBDIRS = search
|
||||
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
@ -35,12 +37,10 @@ endif
|
||||
endif
|
||||
|
||||
mc_LDADD = $(EDITLIB) $(SLANGLIB) $(VFSLIB) \
|
||||
$(INTLLIBS) $(GLIB_LIBS) $(MCLIBS) $(LIBICONV)
|
||||
$(INTLLIBS) $(GLIB_LIBS) $(MCLIBS) $(LIBICONV) search/libsearch.la
|
||||
|
||||
CHARSET_SRC = charsets.c charsets.h selcodepage.c selcodepage.h
|
||||
|
||||
MC_MODULE_SEARCH_FILES = search/search.c search/search.h
|
||||
|
||||
SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \
|
||||
chmod.c chmod.h chown.c chown.h cmd.c cmd.h color.c color.h \
|
||||
command.c command.h complete.c cons.handler.c \
|
||||
@ -63,7 +63,7 @@ SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \
|
||||
widget.h win.c win.h wtools.c wtools.h unixcompat.h \
|
||||
x11conn.h x11conn.c ecs.h ecs.c \
|
||||
strutil.h strutil.c strutilascii.c strutil8bit.c strutilutf8.c \
|
||||
$(MC_MODULE_SEARCH_FILES)
|
||||
search/search.h
|
||||
|
||||
if CHARSET
|
||||
mc_SOURCES = $(SRCS) $(CHARSET_SRC)
|
||||
|
13
src/search/Makefile.am
Normal file
13
src/search/Makefile.am
Normal file
@ -0,0 +1,13 @@
|
||||
noinst_LTLIBRARIES = libsearch.la
|
||||
|
||||
libsearch_la_SOURCES = \
|
||||
search.c \
|
||||
search.h \
|
||||
internal.h \
|
||||
lib.c \
|
||||
normal.c \
|
||||
regex.c
|
||||
|
||||
libsearch_la_CFLAGS=-I../ -I$(top_srcdir)/src \
|
||||
$(GLIB_CFLAGS) \
|
||||
-DDATADIR=\""$(pkgdatadir)/"\" -DLOCALEDIR=\""$(localedir)"\"
|
64
src/search/internal.h
Normal file
64
src/search/internal.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef MC__SEARCH_INTERNAL_H
|
||||
#define MC__SEARCH_INTERNAL_H
|
||||
|
||||
/*** typedefs(not structures) and defined constants **********************************************/
|
||||
|
||||
#define STR_E_NOTFOUND " Search string not found "
|
||||
#define STR_E_UNKNOWN_TYPE " Unknown search type "
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
COND__NOT_FOUND,
|
||||
COND__NOT_ALL_FOUND,
|
||||
COND__FOUND_CHAR,
|
||||
COND__FOUND_CHAR_LAST,
|
||||
COND__FOUND_OK,
|
||||
COND__FOUND_ERROR
|
||||
} mc_search__found_cond_t;
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
typedef struct mc_search_cond_struct {
|
||||
GString *str;
|
||||
GString *upper;
|
||||
GString *lower;
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GRegex *regex_str;
|
||||
#endif
|
||||
gsize len;
|
||||
gchar *charset;
|
||||
} mc_search_cond_t;
|
||||
|
||||
/*** global variables defined in .c file *********************************************************/
|
||||
|
||||
/*** declarations of public functions ************************************************************/
|
||||
|
||||
|
||||
/* search/lib.c : */
|
||||
|
||||
gchar *mc_search__recode_str (const char *, gsize, const char *, const char *, gsize *);
|
||||
|
||||
gchar *mc_search__get_one_symbol (const char *, const char *, gsize, gboolean *);
|
||||
|
||||
int mc_search__get_char (mc_search_t *, const void *, gsize);
|
||||
|
||||
GString *mc_search__tolower_case_str (const char *, const char *, gsize);
|
||||
|
||||
GString *mc_search__toupper_case_str (const char *, const char *, gsize);
|
||||
|
||||
gboolean mc_search__regex_is_char_escaped (char *, char *);
|
||||
|
||||
/* search/regex.c : */
|
||||
|
||||
void mc_search__cond_struct_new_init_regex (const char *, mc_search_t *, mc_search_cond_t *);
|
||||
|
||||
gboolean mc_search__run_regex (mc_search_t *, const void *, gsize, gsize, gsize *);
|
||||
|
||||
/* search/normal.c : */
|
||||
|
||||
void mc_search__cond_struct_new_init_normal (const char *, mc_search_t *, mc_search_cond_t *);
|
||||
|
||||
gboolean mc_search__run_normal (mc_search_t *, const void *, gsize, gsize, gsize *);
|
||||
|
||||
#endif
|
195
src/search/lib.c
Normal file
195
src/search/lib.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
Search text engine.
|
||||
Common share code for module.
|
||||
|
||||
Copyright (C) 2009 The Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2009.
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander 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 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/search/search.h"
|
||||
#include "../src/search/internal.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "../src/charsets.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
gchar *
|
||||
mc_search__recode_str (const char *str, gsize str_len,
|
||||
const char *charset_from, const char *charset_to, gsize * bytes_written)
|
||||
{
|
||||
gchar *ret;
|
||||
gsize bytes_read;
|
||||
GIConv conv;
|
||||
|
||||
|
||||
if (!strcmp (charset_to, charset_from)) {
|
||||
*bytes_written = str_len;
|
||||
return g_strndup (str, str_len);
|
||||
}
|
||||
|
||||
conv = g_iconv_open (charset_to, charset_from);
|
||||
if (conv == (GIConv) - 1)
|
||||
return NULL;
|
||||
|
||||
ret = g_convert_with_iconv (str, str_len, conv, &bytes_read, bytes_written, NULL);
|
||||
g_iconv_close (conv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gchar *
|
||||
mc_search__get_one_symbol (const char *charset, const char *str, gsize str_len,
|
||||
gboolean * just_letters)
|
||||
{
|
||||
|
||||
gchar *converted_str, *next_char, *converted_str2;
|
||||
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
converted_str = mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
|
||||
|
||||
next_char = (char *) str_cget_next_char (converted_str);
|
||||
|
||||
tmp_len = next_char - converted_str;
|
||||
|
||||
converted_str[tmp_len] = '\0';
|
||||
|
||||
converted_str2 =
|
||||
mc_search__recode_str (converted_str, tmp_len, cp_display, charset, &converted_str_len);
|
||||
|
||||
if (str_isalnum (converted_str) && !str_isdigit (converted_str))
|
||||
*just_letters = TRUE;
|
||||
else
|
||||
*just_letters = FALSE;
|
||||
|
||||
|
||||
g_free (converted_str);
|
||||
return converted_str2;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
int
|
||||
mc_search__get_char (mc_search_t * mc_search, const void *user_data, gsize current_pos)
|
||||
{
|
||||
char *data;
|
||||
if (mc_search->search_fn)
|
||||
return (mc_search->search_fn) (user_data, current_pos);
|
||||
|
||||
data = (char *) user_data;
|
||||
return (int) data[current_pos];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
GString *
|
||||
mc_search__tolower_case_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
gchar *converted_str, *tmp_str1, *tmp_str2, *tmp_str3;
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
tmp_str2 = converted_str =
|
||||
mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
if (converted_str == NULL)
|
||||
return NULL;
|
||||
|
||||
tmp_len = converted_str_len + 1;
|
||||
|
||||
tmp_str3 = tmp_str1 = g_strdup (converted_str);
|
||||
|
||||
while (str_tolower (tmp_str1, &tmp_str2, &tmp_len))
|
||||
tmp_str1 += str_length_char (tmp_str1);
|
||||
|
||||
g_free (tmp_str3);
|
||||
tmp_str2 =
|
||||
mc_search__recode_str (converted_str, converted_str_len, cp_display, charset, &tmp_len);
|
||||
g_free (converted_str);
|
||||
if (tmp_str2 == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_string_new_len (tmp_str2, tmp_len);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
GString *
|
||||
mc_search__toupper_case_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
gchar *converted_str, *tmp_str1, *tmp_str2, *tmp_str3;
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
tmp_str2 = converted_str =
|
||||
mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
if (converted_str == NULL)
|
||||
return NULL;
|
||||
|
||||
tmp_len = converted_str_len + 1;
|
||||
|
||||
tmp_str3 = tmp_str1 = g_strdup (converted_str);
|
||||
|
||||
while (str_toupper (tmp_str1, &tmp_str2, &tmp_len))
|
||||
tmp_str1 += str_length_char (tmp_str1);
|
||||
|
||||
g_free (tmp_str3);
|
||||
|
||||
tmp_str2 =
|
||||
mc_search__recode_str (converted_str, converted_str_len, cp_display, charset, &tmp_len);
|
||||
g_free (converted_str);
|
||||
if (tmp_str2 == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_string_new_len (tmp_str2, tmp_len);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mc_search__regex_is_char_escaped (char *start, char *current)
|
||||
{
|
||||
int num_esc = 0;
|
||||
while (*current == '\\' && current >= start) {
|
||||
num_esc++;
|
||||
current--;
|
||||
}
|
||||
return (gboolean) num_esc % 2;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
157
src/search/normal.c
Normal file
157
src/search/normal.c
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
Search text engine.
|
||||
Plain search
|
||||
|
||||
Copyright (C) 2009 The Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2009.
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander 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 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/search/search.h"
|
||||
#include "../src/search/internal.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "../src/charsets.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__normal_found_cond (mc_search_t * mc_search, int current_chr, gsize search_pos)
|
||||
{
|
||||
gsize loop1;
|
||||
mc_search_cond_t *mc_search_cond;
|
||||
|
||||
for (loop1 = 0; loop1 < mc_search->conditions->len; loop1++) {
|
||||
mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (mc_search->conditions, loop1);
|
||||
|
||||
if (search_pos > mc_search_cond->len - 1)
|
||||
continue;
|
||||
|
||||
if (mc_search->is_case_sentitive) {
|
||||
if ((char) current_chr == mc_search_cond->str->str[search_pos])
|
||||
return (search_pos ==
|
||||
mc_search_cond->len - 1) ? COND__FOUND_CHAR_LAST : COND__FOUND_CHAR;
|
||||
} else {
|
||||
GString *upp, *low;
|
||||
upp = (mc_search_cond->upper) ? mc_search_cond->upper : mc_search_cond->str;
|
||||
low = (mc_search_cond->lower) ? mc_search_cond->lower : mc_search_cond->str;
|
||||
|
||||
if (((char) current_chr == upp->str[search_pos])
|
||||
|| ((char) current_chr == low->str[search_pos]))
|
||||
return (search_pos ==
|
||||
mc_search_cond->len - 1) ? COND__FOUND_CHAR_LAST : COND__FOUND_CHAR;
|
||||
}
|
||||
}
|
||||
return COND__NOT_ALL_FOUND;
|
||||
}
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
void
|
||||
mc_search__cond_struct_new_init_normal (const char *charset, mc_search_t * mc_search,
|
||||
mc_search_cond_t * mc_search_cond)
|
||||
{
|
||||
if (!mc_search->is_case_sentitive) {
|
||||
mc_search_cond->upper =
|
||||
mc_search__toupper_case_str (charset, mc_search_cond->str->str, mc_search_cond->len);
|
||||
mc_search_cond->lower =
|
||||
mc_search__tolower_case_str (charset, mc_search_cond->str->str, mc_search_cond->len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mc_search__run_normal (mc_search_t * mc_search, const void *user_data,
|
||||
gsize start_search, gsize end_search, gsize * found_len)
|
||||
{
|
||||
gsize current_pos, search_pos;
|
||||
int current_chr = 0;
|
||||
gboolean found;
|
||||
|
||||
if (mc_search->is_backward) {
|
||||
current_pos = end_search;
|
||||
} else {
|
||||
current_pos = start_search;
|
||||
}
|
||||
while (1) {
|
||||
search_pos = 0;
|
||||
found = TRUE;
|
||||
|
||||
while (1) {
|
||||
if (current_pos + search_pos > end_search)
|
||||
break;
|
||||
|
||||
current_chr = mc_search__get_char (mc_search, user_data, current_pos + search_pos);
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
switch (mc_search__normal_found_cond (mc_search, current_chr, search_pos)) {
|
||||
|
||||
case COND__NOT_ALL_FOUND:
|
||||
found = FALSE;
|
||||
break;
|
||||
|
||||
case COND__FOUND_CHAR_LAST:
|
||||
mc_search->normal_offset = current_pos;
|
||||
*found_len = search_pos + 1;
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
break;
|
||||
|
||||
search_pos++;
|
||||
}
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
if (mc_search->is_backward) {
|
||||
current_pos--;
|
||||
if (current_pos == start_search - 1)
|
||||
break;
|
||||
} else {
|
||||
current_pos++;
|
||||
if (current_pos == end_search + 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
330
src/search/regex.c
Normal file
330
src/search/regex.c
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
Search text engine.
|
||||
Regex search
|
||||
|
||||
Copyright (C) 2009 The Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2009.
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
The Midnight Commander 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 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The Midnight Commander 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/search/search.h"
|
||||
#include "../src/search/internal.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "../src/charsets.h"
|
||||
|
||||
/*** global variables ****************************************************************************/
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
static gboolean
|
||||
mc_search__regex_str_append_if_special (GString * copy_to, GString * regex_str, gsize * offset)
|
||||
{
|
||||
char *tmp_regex_str;
|
||||
gsize spec_chr_len;
|
||||
char **spec_chr;
|
||||
char *special_chars[] = {
|
||||
"\\s", "\\S",
|
||||
"\\d", "\\D",
|
||||
"\\B", "\\B",
|
||||
"\\w", "\\W",
|
||||
"\\t", "\\n",
|
||||
"\\r", "\\f",
|
||||
"\\a", "\\e",
|
||||
"\\x", "\\X",
|
||||
"\\c[", "\\C",
|
||||
"\\l", "\\L",
|
||||
"\\u", "\\U",
|
||||
"\\E", "\\Q",
|
||||
NULL
|
||||
};
|
||||
spec_chr = special_chars;
|
||||
|
||||
tmp_regex_str = &(regex_str->str[*offset]);
|
||||
|
||||
while (*spec_chr) {
|
||||
spec_chr_len = strlen (*spec_chr);
|
||||
if (!strncmp (tmp_regex_str, *spec_chr, spec_chr_len)) {
|
||||
if (!mc_search__regex_is_char_escaped (regex_str->str, tmp_regex_str - 1)) {
|
||||
g_string_append_len (copy_to, *spec_chr, spec_chr_len);
|
||||
*offset += spec_chr_len;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
spec_chr++;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mc_search__cond_struct_new_regex_accum_append (const char *charset, GString * str_to,
|
||||
GString * str_from)
|
||||
{
|
||||
GString *recoded_part, *tmp;
|
||||
gchar *one_char;
|
||||
gsize loop;
|
||||
gboolean just_letters;
|
||||
|
||||
loop = 0;
|
||||
recoded_part = g_string_new ("");
|
||||
|
||||
while (loop < str_from->len) {
|
||||
one_char =
|
||||
mc_search__get_one_symbol (charset, &(str_from->str[loop]),
|
||||
(str_from->len - loop > 6) ? 6 : str_from->len - loop,
|
||||
&just_letters);
|
||||
if (!strlen (one_char)) {
|
||||
loop++;
|
||||
continue;
|
||||
}
|
||||
if (just_letters) {
|
||||
g_string_append_c (recoded_part, '[');
|
||||
|
||||
tmp = mc_search__toupper_case_str (charset, one_char, strlen (one_char));
|
||||
g_string_append (recoded_part, tmp->str);
|
||||
g_string_free (tmp, TRUE);
|
||||
|
||||
tmp = mc_search__tolower_case_str (charset, one_char, strlen (one_char));
|
||||
g_string_append (recoded_part, tmp->str);
|
||||
g_string_free (tmp, TRUE);
|
||||
|
||||
g_string_append_c (recoded_part, ']');
|
||||
|
||||
} else {
|
||||
g_string_append (recoded_part, one_char);
|
||||
}
|
||||
loop += strlen (one_char);
|
||||
if (!strlen (one_char))
|
||||
loop++;
|
||||
g_free (one_char);
|
||||
}
|
||||
|
||||
g_string_append (str_to, recoded_part->str);
|
||||
g_string_free (recoded_part, TRUE);
|
||||
g_string_set_size (str_from, 0);
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static GString *
|
||||
mc_search__cond_struct_new_regex_ci_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
GString *accumulator, *spec_char, *ret_str;
|
||||
gsize loop;
|
||||
GString *tmp;
|
||||
tmp = g_string_new_len (str, str_len);
|
||||
|
||||
|
||||
ret_str = g_string_new ("");
|
||||
accumulator = g_string_new ("");
|
||||
spec_char = g_string_new ("");
|
||||
loop = 0;
|
||||
|
||||
while (loop <= str_len) {
|
||||
if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop)) {
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
g_string_append_len (ret_str, spec_char->str, spec_char->len);
|
||||
g_string_set_size (spec_char, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->str[loop] == '['
|
||||
&& !mc_search__regex_is_char_escaped (tmp->str, &(tmp->str[loop]) - 1)) {
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
|
||||
while (!
|
||||
(tmp->str[loop] == ']'
|
||||
&& !mc_search__regex_is_char_escaped (tmp->str, &(tmp->str[loop]) - 1))) {
|
||||
g_string_append_c (ret_str, tmp->str[loop]);
|
||||
loop++;
|
||||
|
||||
}
|
||||
g_string_append_c (ret_str, tmp->str[loop]);
|
||||
loop++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
TODO: handle [ and ]
|
||||
*/
|
||||
g_string_append_c (accumulator, tmp->str[loop]);
|
||||
loop++;
|
||||
}
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
|
||||
g_string_free (accumulator, TRUE);
|
||||
g_string_free (spec_char, TRUE);
|
||||
g_string_free (tmp, TRUE);
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__regex_found_cond_one (mc_search_t * mc_search, GRegex * regex, GString * search_str)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GMatchInfo *match_info;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_regex_match_full (regex, search_str->str, -1, 0, 0, &match_info, &error)) {
|
||||
g_match_info_free (match_info);
|
||||
if (error) {
|
||||
mc_search->error = MC_SEARCH_E_REGEX;
|
||||
mc_search->error_str = g_strdup (error->message);
|
||||
g_error_free (error);
|
||||
return COND__FOUND_ERROR;
|
||||
}
|
||||
return COND__NOT_FOUND;
|
||||
}
|
||||
mc_search->regex_match_info = match_info;
|
||||
return COND__FOUND_OK;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__regex_found_cond (mc_search_t * mc_search, GString * search_str)
|
||||
{
|
||||
gsize loop1;
|
||||
mc_search_cond_t *mc_search_cond;
|
||||
mc_search__found_cond_t ret;
|
||||
|
||||
for (loop1 = 0; loop1 < mc_search->conditions->len; loop1++) {
|
||||
mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (mc_search->conditions, loop1);
|
||||
|
||||
if (!mc_search_cond->regex_str)
|
||||
continue;
|
||||
|
||||
ret = mc_search__regex_found_cond_one (mc_search, mc_search_cond->regex_str, search_str);
|
||||
|
||||
if (ret != COND__NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
return COND__NOT_ALL_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
void
|
||||
mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * mc_search,
|
||||
mc_search_cond_t * mc_search_cond)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GString *tmp;
|
||||
GError *error = NULL;
|
||||
if (!mc_search->is_case_sentitive) {
|
||||
tmp = g_string_new_len (mc_search_cond->str->str, mc_search_cond->str->len);
|
||||
g_string_free (mc_search_cond->str, TRUE);
|
||||
mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp->str, tmp->len);
|
||||
g_string_free (tmp, TRUE);
|
||||
}
|
||||
|
||||
mc_search_cond->regex_str = g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE, 0, &error);
|
||||
if (error != NULL) {
|
||||
mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
|
||||
mc_search->error_str = g_strdup (error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void) mc_search_cond;
|
||||
(void) mc_search;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
gsize start_search, gsize end_search, gsize * found_len)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GString *buffer;
|
||||
gsize current_pos, start_buffer;
|
||||
int current_chr = 0;
|
||||
gint start_pos;
|
||||
gint end_pos;
|
||||
|
||||
buffer = g_string_new ("");
|
||||
|
||||
current_pos = start_search;
|
||||
while (current_pos <= end_search) {
|
||||
g_string_set_size (buffer, 0);
|
||||
start_buffer = current_pos;
|
||||
|
||||
while (1) {
|
||||
current_chr = mc_search__get_char (mc_search, user_data, current_pos);
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
g_string_append_c (buffer, (char) current_chr);
|
||||
|
||||
current_pos++;
|
||||
|
||||
if (current_chr == 0 || (char) current_chr == '\n')
|
||||
break;
|
||||
|
||||
if (current_pos > end_search)
|
||||
break;
|
||||
|
||||
}
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
switch (mc_search__regex_found_cond (mc_search, buffer)) {
|
||||
case COND__FOUND_OK:
|
||||
g_match_info_fetch_pos (mc_search->regex_match_info, 0, &start_pos, &end_pos);
|
||||
*found_len = end_pos - start_pos;
|
||||
mc_search->normal_offset = start_buffer + start_pos;
|
||||
g_string_free (buffer, TRUE);
|
||||
return TRUE;
|
||||
break;
|
||||
case COND__NOT_ALL_FOUND:
|
||||
break;
|
||||
default:
|
||||
g_string_free (buffer, TRUE);
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
g_string_free (buffer, TRUE);
|
||||
#endif
|
||||
mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
return FALSE;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
Search text engine.
|
||||
Interface functions
|
||||
|
||||
Copyright (C) 2009 The Free Software Foundation, Inc.
|
||||
|
||||
@ -28,7 +29,8 @@
|
||||
|
||||
|
||||
#include "../src/global.h"
|
||||
#include "../src/search.h"
|
||||
#include "../src/search/search.h"
|
||||
#include "../src/search/internal.h"
|
||||
#include "../src/strutil.h"
|
||||
#include "../src/charsets.h"
|
||||
|
||||
@ -36,367 +38,30 @@
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
#define STR_E_NOTFOUND " Search string not found "
|
||||
#define STR_E_UNKNOWN_TYPE " Unknown search type "
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
typedef struct mc_search_cond_struct {
|
||||
GString *str;
|
||||
GString *upper;
|
||||
GString *lower;
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GRegex *regex_str;
|
||||
#endif
|
||||
gsize len;
|
||||
gchar *charset;
|
||||
} mc_search_cond_t;
|
||||
|
||||
typedef enum {
|
||||
COND__NOT_FOUND,
|
||||
COND__NOT_ALL_FOUND,
|
||||
COND__FOUND_CHAR,
|
||||
COND__FOUND_CHAR_LAST,
|
||||
COND__FOUND_OK,
|
||||
COND__FOUND_ERROR
|
||||
} mc_search__found_cond_t;
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
|
||||
static gchar *
|
||||
mc_search__recode_str (const char *str, gsize str_len,
|
||||
const char *charset_from, const char *charset_to, gsize * bytes_written)
|
||||
{
|
||||
gchar *ret;
|
||||
gsize bytes_read;
|
||||
GIConv conv;
|
||||
|
||||
|
||||
if (!strcmp (charset_to, charset_from)) {
|
||||
*bytes_written = str_len;
|
||||
return g_strndup (str, str_len);
|
||||
}
|
||||
|
||||
conv = g_iconv_open (charset_to, charset_from);
|
||||
if (conv == (GIConv) - 1)
|
||||
return NULL;
|
||||
|
||||
ret = g_convert_with_iconv (str, str_len, conv, &bytes_read, bytes_written, NULL);
|
||||
g_iconv_close (conv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static char *
|
||||
mc_search__get_one_symbol (const char *charset, const char *str, gsize str_len,
|
||||
gboolean * just_letters)
|
||||
{
|
||||
|
||||
gchar *converted_str, *next_char, *converted_str2;
|
||||
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
converted_str = mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
|
||||
|
||||
next_char = (char *) str_cget_next_char (converted_str);
|
||||
|
||||
tmp_len = next_char - converted_str;
|
||||
|
||||
converted_str[tmp_len] = '\0';
|
||||
|
||||
converted_str2 =
|
||||
mc_search__recode_str (converted_str, tmp_len, cp_display, charset, &converted_str_len);
|
||||
|
||||
if (str_isalnum (converted_str) && !str_isdigit (converted_str))
|
||||
*just_letters = TRUE;
|
||||
else
|
||||
*just_letters = FALSE;
|
||||
|
||||
|
||||
g_free (converted_str);
|
||||
return converted_str2;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static GString *
|
||||
mc_search__tolower_case_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
gchar *converted_str, *tmp_str1, *tmp_str2, *tmp_str3;
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
tmp_str2 = converted_str =
|
||||
mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
if (converted_str == NULL)
|
||||
return NULL;
|
||||
|
||||
tmp_len = converted_str_len + 1;
|
||||
|
||||
tmp_str3 = tmp_str1 = g_strdup (converted_str);
|
||||
|
||||
while (str_tolower (tmp_str1, &tmp_str2, &tmp_len))
|
||||
tmp_str1 += str_length_char (tmp_str1);
|
||||
|
||||
g_free (tmp_str3);
|
||||
tmp_str2 =
|
||||
mc_search__recode_str (converted_str, converted_str_len, cp_display, charset, &tmp_len);
|
||||
g_free (converted_str);
|
||||
if (tmp_str2 == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_string_new_len (tmp_str2, tmp_len);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static GString *
|
||||
mc_search__toupper_case_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
gchar *converted_str, *tmp_str1, *tmp_str2, *tmp_str3;
|
||||
gsize converted_str_len;
|
||||
gsize tmp_len;
|
||||
|
||||
tmp_str2 = converted_str =
|
||||
mc_search__recode_str (str, str_len, charset, cp_display, &converted_str_len);
|
||||
if (converted_str == NULL)
|
||||
return NULL;
|
||||
|
||||
tmp_len = converted_str_len + 1;
|
||||
|
||||
tmp_str3 = tmp_str1 = g_strdup (converted_str);
|
||||
|
||||
while (str_toupper (tmp_str1, &tmp_str2, &tmp_len))
|
||||
tmp_str1 += str_length_char (tmp_str1);
|
||||
|
||||
g_free (tmp_str3);
|
||||
|
||||
tmp_str2 =
|
||||
mc_search__recode_str (converted_str, converted_str_len, cp_display, charset, &tmp_len);
|
||||
g_free (converted_str);
|
||||
if (tmp_str2 == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_string_new_len (tmp_str2, tmp_len);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mc_search__regex_is_char_escaped (char *start, char *current)
|
||||
{
|
||||
int num_esc = 0;
|
||||
while (*current == '\\' && current >= start) {
|
||||
num_esc++;
|
||||
current--;
|
||||
}
|
||||
return (gboolean) num_esc % 2;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mc_search__regex_str_append_if_special (GString * copy_to, GString * regex_str, gsize * offset)
|
||||
{
|
||||
char *tmp_regex_str;
|
||||
gsize spec_chr_len;
|
||||
char **spec_chr;
|
||||
char *special_chars[] = {
|
||||
"\\s", "\\S",
|
||||
"\\d", "\\D",
|
||||
"\\B", "\\B",
|
||||
"\\w", "\\W",
|
||||
"\\t", "\\n",
|
||||
"\\r", "\\f",
|
||||
"\\a", "\\e",
|
||||
"\\x", "\\X",
|
||||
"\\c[", "\\C",
|
||||
"\\l", "\\L",
|
||||
"\\u", "\\U",
|
||||
"\\E", "\\Q",
|
||||
NULL
|
||||
};
|
||||
spec_chr = special_chars;
|
||||
|
||||
tmp_regex_str = &(regex_str->str[*offset]);
|
||||
|
||||
while (*spec_chr) {
|
||||
spec_chr_len = strlen (*spec_chr);
|
||||
if (!strncmp (tmp_regex_str, *spec_chr, spec_chr_len)) {
|
||||
if (!mc_search__regex_is_char_escaped (regex_str->str, tmp_regex_str - 1)) {
|
||||
g_string_append_len (copy_to, *spec_chr, spec_chr_len);
|
||||
*offset += spec_chr_len;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
spec_chr++;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
static void
|
||||
|
||||
mc_search__cond_struct_new_regex_accum_append (const char *charset, GString * str_to,
|
||||
GString * str_from)
|
||||
{
|
||||
GString *recoded_part, *tmp;
|
||||
gchar *one_char;
|
||||
gsize loop;
|
||||
gboolean just_letters;
|
||||
|
||||
loop = 0;
|
||||
recoded_part = g_string_new ("");
|
||||
|
||||
while (loop < str_from->len) {
|
||||
one_char =
|
||||
mc_search__get_one_symbol (charset, &(str_from->str[loop]),
|
||||
(str_from->len - loop > 6) ? 6 : str_from->len - loop,
|
||||
&just_letters);
|
||||
if (!strlen (one_char)) {
|
||||
loop++;
|
||||
continue;
|
||||
}
|
||||
if (just_letters) {
|
||||
g_string_append_c (recoded_part, '[');
|
||||
|
||||
tmp = mc_search__toupper_case_str (charset, one_char, strlen (one_char));
|
||||
g_string_append (recoded_part, tmp->str);
|
||||
g_string_free (tmp, TRUE);
|
||||
|
||||
tmp = mc_search__tolower_case_str (charset, one_char, strlen (one_char));
|
||||
g_string_append (recoded_part, tmp->str);
|
||||
g_string_free (tmp, TRUE);
|
||||
|
||||
g_string_append_c (recoded_part, ']');
|
||||
|
||||
} else {
|
||||
g_string_append (recoded_part, one_char);
|
||||
}
|
||||
loop += strlen (one_char);
|
||||
if (!strlen (one_char))
|
||||
loop++;
|
||||
g_free (one_char);
|
||||
}
|
||||
|
||||
g_string_append (str_to, recoded_part->str);
|
||||
g_string_free (recoded_part, TRUE);
|
||||
g_string_set_size (str_from, 0);
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static GString *
|
||||
mc_search__cond_struct_new_regex_ci_str (const char *charset, const char *str, gsize str_len)
|
||||
{
|
||||
GString *accumulator, *spec_char, *ret_str;
|
||||
gsize loop;
|
||||
GString *tmp;
|
||||
tmp = g_string_new_len (str, str_len);
|
||||
|
||||
|
||||
ret_str = g_string_new ("");
|
||||
accumulator = g_string_new ("");
|
||||
spec_char = g_string_new ("");
|
||||
loop = 0;
|
||||
|
||||
while (loop <= str_len) {
|
||||
if (mc_search__regex_str_append_if_special (spec_char, tmp, &loop)) {
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
g_string_append_len (ret_str, spec_char->str, spec_char->len);
|
||||
g_string_set_size (spec_char, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->str[loop] == '['
|
||||
&& !mc_search__regex_is_char_escaped (tmp->str, &(tmp->str[loop]) - 1)) {
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
|
||||
while (!
|
||||
(tmp->str[loop] == ']'
|
||||
&& !mc_search__regex_is_char_escaped (tmp->str, &(tmp->str[loop]) - 1))) {
|
||||
g_string_append_c (ret_str, tmp->str[loop]);
|
||||
loop++;
|
||||
|
||||
}
|
||||
g_string_append_c (ret_str, tmp->str[loop]);
|
||||
loop++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
TODO: handle [ and ]
|
||||
*/
|
||||
g_string_append_c (accumulator, tmp->str[loop]);
|
||||
loop++;
|
||||
}
|
||||
mc_search__cond_struct_new_regex_accum_append (charset, ret_str, accumulator);
|
||||
|
||||
g_string_free (accumulator, TRUE);
|
||||
g_string_free (spec_char, TRUE);
|
||||
g_string_free (tmp, TRUE);
|
||||
mc_log ("!!! %s\n", ret_str->str);
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
|
||||
mc_search__cond_struct_new_init_regex (mc_search_t * mc_search, mc_search_cond_t * mc_search_cond)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GError *error = NULL;
|
||||
|
||||
mc_search_cond->regex_str = g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE, 0, &error);
|
||||
if (error != NULL) {
|
||||
mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
|
||||
mc_search->error_str = g_strdup (error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void) mc_search_cond;
|
||||
(void) mc_search;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search_cond_t *
|
||||
mc_search__cond_struct_new (mc_search_t * mc_search, const char *str,
|
||||
gsize str_len, const char *charset)
|
||||
{
|
||||
mc_search_cond_t *mc_search_cond;
|
||||
mc_search_cond = g_malloc0 (sizeof (mc_search_cond_t));
|
||||
|
||||
mc_search_cond->str = g_string_new_len (str, str_len);
|
||||
mc_search_cond->len = str_len;
|
||||
mc_search_cond->charset = g_strdup (charset);
|
||||
|
||||
switch (mc_search->search_type) {
|
||||
case MC_SEARCH_T_GLOB:
|
||||
case MC_SEARCH_T_NORMAL:
|
||||
mc_search_cond->str = g_string_new_len (str, str_len);
|
||||
mc_search_cond->len = str_len;
|
||||
mc_search_cond->charset = g_strdup (charset);
|
||||
if (!mc_search->is_case_sentitive) {
|
||||
mc_search_cond->upper = mc_search__toupper_case_str (charset, str, str_len);
|
||||
mc_search_cond->lower = mc_search__tolower_case_str (charset, str, str_len);
|
||||
}
|
||||
mc_search__cond_struct_new_init_normal (charset, mc_search, mc_search_cond);
|
||||
break;
|
||||
case MC_SEARCH_T_REGEX:
|
||||
|
||||
mc_search_cond->charset = g_strdup (charset);
|
||||
|
||||
if (mc_search->is_case_sentitive) {
|
||||
mc_search_cond->str = g_string_new_len (str, str_len);
|
||||
mc_search_cond->len = str_len;
|
||||
} else {
|
||||
mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, str, str_len);
|
||||
}
|
||||
mc_search__cond_struct_new_init_regex (mc_search, mc_search_cond);
|
||||
mc_search__cond_struct_new_init_regex (charset, mc_search, mc_search_cond);
|
||||
break;
|
||||
case MC_SEARCH_T_SCANF:
|
||||
case MC_SEARCH_T_HEX:
|
||||
@ -487,229 +152,7 @@ mc_search__conditions_free (GPtrArray * array)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
mc_search__get_char (mc_search_t * mc_search, const void *user_data, gsize current_pos)
|
||||
{
|
||||
char *data;
|
||||
if (mc_search->search_fn)
|
||||
return (mc_search->search_fn) (user_data, current_pos);
|
||||
|
||||
data = (char *) user_data;
|
||||
return (int) data[current_pos];
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__normal_found_cond (mc_search_t * mc_search, int current_chr, gsize search_pos)
|
||||
{
|
||||
gsize loop1;
|
||||
mc_search_cond_t *mc_search_cond;
|
||||
|
||||
for (loop1 = 0; loop1 < mc_search->conditions->len; loop1++) {
|
||||
mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (mc_search->conditions, loop1);
|
||||
|
||||
if (search_pos > mc_search_cond->len - 1)
|
||||
continue;
|
||||
|
||||
if (mc_search->is_case_sentitive) {
|
||||
if ((char) current_chr == mc_search_cond->str->str[search_pos])
|
||||
return (search_pos ==
|
||||
mc_search_cond->len - 1) ? COND__FOUND_CHAR_LAST : COND__FOUND_CHAR;
|
||||
} else {
|
||||
GString *upp, *low;
|
||||
upp = (mc_search_cond->upper) ? mc_search_cond->upper : mc_search_cond->str;
|
||||
low = (mc_search_cond->lower) ? mc_search_cond->lower : mc_search_cond->str;
|
||||
|
||||
if (((char) current_chr == upp->str[search_pos])
|
||||
|| ((char) current_chr == low->str[search_pos]))
|
||||
return (search_pos ==
|
||||
mc_search_cond->len - 1) ? COND__FOUND_CHAR_LAST : COND__FOUND_CHAR;
|
||||
}
|
||||
}
|
||||
return COND__NOT_ALL_FOUND;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mc_search__run_normal (mc_search_t * mc_search, const void *user_data,
|
||||
gsize start_search, gsize end_search, gsize * found_len)
|
||||
{
|
||||
gsize current_pos, search_pos;
|
||||
int current_chr = 0;
|
||||
gboolean found;
|
||||
|
||||
if (mc_search->is_backward) {
|
||||
current_pos = end_search;
|
||||
} else {
|
||||
current_pos = start_search;
|
||||
}
|
||||
while (1) {
|
||||
search_pos = 0;
|
||||
found = TRUE;
|
||||
|
||||
while (1) {
|
||||
if (current_pos + search_pos > end_search)
|
||||
break;
|
||||
|
||||
current_chr = mc_search__get_char (mc_search, user_data, current_pos + search_pos);
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
switch (mc_search__normal_found_cond (mc_search, current_chr, search_pos)) {
|
||||
|
||||
case COND__NOT_ALL_FOUND:
|
||||
found = FALSE;
|
||||
break;
|
||||
|
||||
case COND__FOUND_CHAR_LAST:
|
||||
mc_search->normal_offset = current_pos;
|
||||
*found_len = search_pos + 1;
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
break;
|
||||
|
||||
search_pos++;
|
||||
}
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
if (mc_search->is_backward) {
|
||||
current_pos--;
|
||||
if (current_pos == start_search - 1)
|
||||
break;
|
||||
} else {
|
||||
current_pos++;
|
||||
if (current_pos == end_search + 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__regex_found_cond_one (mc_search_t * mc_search, GRegex * regex, GString * search_str)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GMatchInfo *match_info;
|
||||
GError *error = NULL;
|
||||
//mc_log("%s\n",search_str->str);
|
||||
|
||||
if (!g_regex_match_full (regex, search_str->str, -1, 0, 0, &match_info, &error)) {
|
||||
//mc_log("1\n");
|
||||
g_match_info_free (match_info);
|
||||
if (error) {
|
||||
//mc_log("2\n");
|
||||
mc_search->error = MC_SEARCH_E_REGEX;
|
||||
mc_search->error_str = g_strdup (error->message);
|
||||
g_error_free (error);
|
||||
return COND__FOUND_ERROR;
|
||||
}
|
||||
//mc_log("3\n");
|
||||
return COND__NOT_FOUND;
|
||||
}
|
||||
//mc_log("4\n");
|
||||
mc_search->regex_match_info = match_info;
|
||||
return COND__FOUND_OK;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static mc_search__found_cond_t
|
||||
mc_search__regex_found_cond (mc_search_t * mc_search, GString * search_str)
|
||||
{
|
||||
gsize loop1;
|
||||
mc_search_cond_t *mc_search_cond;
|
||||
mc_search__found_cond_t ret;
|
||||
|
||||
for (loop1 = 0; loop1 < mc_search->conditions->len; loop1++) {
|
||||
mc_search_cond = (mc_search_cond_t *) g_ptr_array_index (mc_search->conditions, loop1);
|
||||
|
||||
if (!mc_search_cond->regex_str)
|
||||
continue;
|
||||
|
||||
ret = mc_search__regex_found_cond_one (mc_search, mc_search_cond->regex_str, search_str);
|
||||
|
||||
if (ret != COND__NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
return COND__NOT_ALL_FOUND;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
gsize start_search, gsize end_search, gsize * found_len)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION (2, 14, 0)
|
||||
GString *buffer;
|
||||
gsize current_pos, start_buffer;
|
||||
int current_chr = 0;
|
||||
gint start_pos;
|
||||
gint end_pos;
|
||||
|
||||
buffer = g_string_new ("");
|
||||
|
||||
current_pos = start_search;
|
||||
while (current_pos <= end_search) {
|
||||
g_string_set_size (buffer, 0);
|
||||
start_buffer = current_pos;
|
||||
|
||||
while (1) {
|
||||
current_chr = mc_search__get_char (mc_search, user_data, current_pos);
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
g_string_append_c (buffer, (char) current_chr);
|
||||
|
||||
current_pos++;
|
||||
|
||||
if (current_chr == 0 || (char) current_chr == '\n')
|
||||
break;
|
||||
|
||||
if (current_pos > end_search)
|
||||
break;
|
||||
|
||||
}
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
switch (mc_search__regex_found_cond (mc_search, buffer)) {
|
||||
case COND__FOUND_OK:
|
||||
g_match_info_fetch_pos (mc_search->regex_match_info, 0, &start_pos, &end_pos);
|
||||
*found_len = end_pos - start_pos;
|
||||
mc_search->normal_offset = start_buffer + start_pos;
|
||||
g_string_free (buffer, TRUE);
|
||||
return TRUE;
|
||||
break;
|
||||
case COND__NOT_ALL_FOUND:
|
||||
break;
|
||||
default:
|
||||
g_string_free (buffer, TRUE);
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
g_string_free (buffer, TRUE);
|
||||
#endif
|
||||
mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user