Merge branch '393_damn_slow_search_viewer'

* 393_damn_slow_search_viewer:
  Ticket #393 (slow search in viewer)
This commit is contained in:
Slava Zanko 2009-07-09 09:45:41 +03:00
commit 944d1cf961
3 changed files with 216 additions and 156 deletions

View File

@ -252,7 +252,7 @@ mc_search__regex_found_cond_one (mc_search_t * mc_search, mc_search_regex_t * re
mc_search->num_rezults = g_match_info_get_match_count (mc_search->regex_match_info);
#else /* SEARCH_TYPE_GLIB */
mc_search->num_rezults = pcre_exec (regex, mc_search->regex_match_info,
search_str->str, search_str->len, 0, 0, mc_search->iovector,
search_str->str, search_str->len - 1, 0, 0, mc_search->iovector,
MC_SEARCH__NUM_REPLACE_ARGS);
if (mc_search->num_rezults < 0) {
return COND__NOT_FOUND;
@ -527,7 +527,7 @@ gboolean
mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
gsize start_search, gsize end_search, gsize * found_len)
{
gsize current_pos, start_buffer;
gsize current_pos, virtual_pos;
int current_chr = 0;
gint start_pos;
gint end_pos;
@ -537,30 +537,33 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
mc_search->regex_buffer = g_string_new ("");
current_pos = start_search;
while (current_pos <= end_search) {
virtual_pos = current_pos = start_search;
while (virtual_pos <= end_search) {
g_string_set_size (mc_search->regex_buffer, 0);
start_buffer = current_pos;
mc_search->start_buffer = current_pos;
while (1) {
current_chr = mc_search__get_char (mc_search, user_data, current_pos);
if (current_chr == -1)
if (current_chr == MC_SEARCH_CB_ABORT)
break;
current_pos++;
if (current_chr == MC_SEARCH_CB_SKIP)
continue;
virtual_pos++;
g_string_append_c (mc_search->regex_buffer, (char) current_chr);
current_pos++;
if (current_chr == 0 || (char) current_chr == '\n')
break;
if (current_pos > end_search)
if (virtual_pos > end_search)
break;
}
if (current_chr == -1)
break;
switch (mc_search__regex_found_cond (mc_search, mc_search->regex_buffer)) {
case COND__FOUND_OK:
#ifdef SEARCH_TYPE_GLIB
@ -571,7 +574,7 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
#endif /* SEARCH_TYPE_GLIB */
if (found_len)
*found_len = end_pos - start_pos;
mc_search->normal_offset = start_buffer + start_pos;
mc_search->normal_offset = mc_search->start_buffer + start_pos;
return TRUE;
break;
case COND__NOT_ALL_FOUND:
@ -582,6 +585,17 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
return FALSE;
break;
}
if (mc_search->update_fn != NULL) {
if ((mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_SKIP) {
g_string_free (mc_search->regex_buffer, TRUE);
mc_search->regex_buffer = NULL;
mc_search->error = MC_SEARCH_E_NOTFOUND;
mc_search->error_str = NULL;
return FALSE;
}
}
if (current_chr == MC_SEARCH_CB_ABORT)
break;
}
g_string_free (mc_search->regex_buffer, TRUE);
mc_search->regex_buffer = NULL;
@ -599,7 +613,7 @@ mc_search_regex_prepare_replace_str (mc_search_t * mc_search, GString * replace_
int num_replace_tokens, index;
gsize loop;
gsize len;
gsize len = 0;
gchar *prev_str;
replace_transform_type_t replace_flags = REPLACE_T_NO_TRANSFORM;

View File

@ -39,6 +39,11 @@ typedef enum {
MC_SEARCH_T_GLOB
} mc_search_type_t;
typedef enum {
MC_SEARCH_CB_ABORT = -1,
MC_SEARCH_CB_SKIP = -2
} mc_search_cbret_t;
/*** structures declarations (and typedefs of structures)*****************************************/
@ -61,6 +66,9 @@ typedef struct mc_search_struct {
/* function, used for getting data. NULL if not used */
mc_search_fn search_fn;
/* function, used for updatin current search status. NULL if not used */
mc_search_fn update_fn;
/* type of search */
mc_search_type_t search_type;
@ -70,6 +78,7 @@ typedef struct mc_search_struct {
/* some data for normal */
gsize normal_offset;
gsize start_buffer;
/* some data for regexp */
int num_rezults;
mc_search_matchinfo_t *regex_match_info;
@ -109,7 +118,7 @@ void mc_search_free (mc_search_t * mc_search);
gboolean mc_search_prepare (mc_search_t * mc_search);
gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search,
gsize end_search, gsize * founded_len);
gsize end_search, gsize * found_len);
gboolean mc_search_is_type_avail (mc_search_type_t);

View File

@ -139,6 +139,20 @@ struct cache_line {
screen_dimen left;
};
/* this structure and view_read_* functions make reading text simpler
* view need remeber 4 following charsets: actual, next and two previous */
struct read_info {
char ch[4][MB_LEN_MAX + 1];
char *cnxt;
char *cact;
char *chi1;
char *chi2;
offset_type next;
offset_type actual;
int result;
};
struct WView {
Widget widget;
@ -248,6 +262,9 @@ struct WView {
gboolean search_all_codepages;
gboolean search_case;
gboolean search_backwards;
int search_numNeedSkipChar;
struct read_info search_onechar_info;
};
@ -361,18 +378,6 @@ view_get_char (WView *view, offset_type from, char *ch, int size)
return -1;
}
/* this structure and view_read_* functions make reading text simpler
* view need remeber 4 following charsets: actual, next and two previous */
struct read_info {
char ch[4][MB_LEN_MAX + 1];
char *cnxt;
char *cact;
char *chi1;
char *chi2;
offset_type next;
offset_type actual;
int result;
};
/* set read_info into initial state and read first character to cnxt
* return how many bytes was read or -1 if end of text */
@ -2742,66 +2747,6 @@ my_define (Dlg_head *h, int idx, const char *text, void (*fn) (WView *),
/* {{{ Searching }}} */
/* read one whole line into buffer, return where line start and end */
static int
view_get_line_at (WView *view, offset_type from, GString * buffer,
offset_type *buff_start, offset_type *buff_end)
{
#define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
struct read_info info;
struct cache_line *line;
offset_type start;
offset_type end;
line = view_get_first_showed_line (view);
line = view_offset_to_line_from (view, from, line);
if (!view->search_backwards) {
start = from;
end = view_get_end_of_whole_line (view, line)->end;
if (start >= end) return 0;
} else {
start = view_get_start_of_whole_line (view, line)->start;
end = from;
}
(*buff_start) = start;
(*buff_end) = end;
g_string_set_size(buffer,0);
view_read_start (view, &info, start);
while ((info.result != -1) && (info.next < end)) {
view_read_continue (view, &info);
/* if text contains '\0' */
if (cmp (info.cact, "")) {
if (info.actual < from) {
/* '\0' before start offset, continue */
g_string_set_size(buffer,0);
(*buff_start) = info.next;
continue;
} else {
/* '\0' after start offset, end */
(*buff_end) = info.next;
return 1;
}
}
if (view_read_test_new_line (view, &info))
continue;
if (view_read_test_nroff_back (view, &info)) {
g_string_truncate (buffer, buffer->len-1);
continue;
}
g_string_append(buffer,info.cact);
}
return 1;
}
/* map search result positions to offsets in text */
void
@ -3104,10 +3049,24 @@ view__get_nroff_real_len(WView *view, offset_type start, offset_type length)
struct read_info info;
view_read_start (view, &info, start);
while((loop1 < length ) && (info.result != -1))
{
while((loop1 < length ) && (info.result != -1)) {
view_read_continue (view, &info);
if (*info.cnxt == '\b')
if (view_read_test_nroff_back (view, &info)) {
if (cmp (info.chi1, "_") && (!cmp (info.cnxt, "_") || !cmp (info.chi2, "\b")))
{
view_read_continue (view, &info);
view_read_continue (view, &info);
view_read_continue (view, &info);
view_read_continue (view, &info);
nroff_seq+=4;
} else {
view_read_continue (view, &info);
view_read_continue (view, &info);
nroff_seq+=2;
}
}
if (*info.cact == '_' && *info.cnxt == 0x8)
{
view_read_continue (view, &info);
view_read_continue (view, &info);
@ -3118,17 +3077,100 @@ view__get_nroff_real_len(WView *view, offset_type start, offset_type length)
return nroff_seq;
}
static int
view_search_update_cmd_callback(const void *user_data, gsize char_offset)
{
WView *view = (WView *) user_data;
if (char_offset >= view->update_activate) {
view->update_activate += view->update_steps;
if (verbose) {
view_percent (view, char_offset);
mc_refresh ();
}
if (got_interrupt ())
return MC_SEARCH_CB_ABORT;
}
/* may be in future return from this callback will change current position
* in searching block. Now this just constant return value.
*/
return 1;
}
static int
view_search_cmd_callback(const void *user_data, gsize char_offset)
{
int byte;
WView *view = (WView *) user_data;
byte = get_byte (view, char_offset);
if (byte == -1)
return MC_SEARCH_CB_ABORT;
view_read_continue (view, &view->search_onechar_info);
if (view->search_numNeedSkipChar) {
view->search_numNeedSkipChar--;
if (view->search_numNeedSkipChar){
return byte;
}
return MC_SEARCH_CB_SKIP;
}
if (view_read_test_nroff_back (view, &view->search_onechar_info)) {
if (
cmp (view->search_onechar_info.chi1, "_") &&
(!cmp (view->search_onechar_info.cnxt, "_") || !cmp (view->search_onechar_info.chi2, "\b"))
)
view->search_numNeedSkipChar = 2;
else
view->search_numNeedSkipChar = 1;
return MC_SEARCH_CB_SKIP;
}
if (byte == '_' && *view->search_onechar_info.cnxt == 0x8)
{
view->search_numNeedSkipChar = 1;
return MC_SEARCH_CB_SKIP;
}
return byte;
}
static gboolean
view_find (WView *view, gsize search_start, gsize *len)
{
gsize search_end;
view->search_numNeedSkipChar = 0;
if (view->search_backwards) {
search_end = view_get_filesize (view);
while ((int) search_start >= 0) {
if (search_end - search_start > view->search->original_len && mc_search_is_fixed_search_str(view->search))
search_end = search_start + view->search->original_len;
view_read_start (view, &view->search_onechar_info, search_start);
if ( mc_search_run(view->search, (void *) view, search_start, search_end, len))
return TRUE;
search_start--;
}
view->search->error_str = g_strdup(_(" Search string not found "));
return FALSE;
}
view_read_start (view, &view->search_onechar_info, search_start);
return mc_search_run(view->search, (void *) view, search_start, view_get_filesize (view), len);
}
static void
do_search (WView *view)
{
GString *buffer;
offset_type search_start;
int search_status;
gboolean isFound = FALSE;
Dlg_head *d = NULL;
offset_type line_start;
offset_type line_end;
size_t match_len;
if (verbose) {
@ -3136,9 +3178,19 @@ do_search (WView *view)
mc_refresh ();
}
buffer = g_string_new ("");
/*for avoid infinite search loop we need to increase or decrease start offset of search */
if (view->search_start)
{
search_start = (view->search_backwards) ? -2 : 2;
search_start = view->search_start + search_start +
view__get_nroff_real_len(view, view->search_start, 2) * search_start;
}
else
{
search_start = view->search_start;
}
search_start = (view->search_backwards) ? view->search_start-1 : view->search_end;
if (view->search_backwards && (int) search_start < 0 )
search_start = 0;
@ -3147,81 +3199,56 @@ do_search (WView *view)
view->update_activate = 0;
enable_interrupt_key ();
search_status = -1;
while(1){
if (search_start >= view->update_activate) {
view->update_activate += view->update_steps;
do
{
if (view_find(view, search_start, &match_len))
{
view->search_start = view->search->normal_offset +
view__get_nroff_real_len(view,
view->search->start_buffer,
view->search->normal_offset - view->search->start_buffer);
view->search_end = view->search_start + match_len +
view__get_nroff_real_len(view, view->search_start, match_len + 1);
if (view->hex_mode){
view->hex_cursor = view->search_start;
view->hexedit_lownibble = FALSE;
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
}
if (verbose) {
view_percent (view, search_start);
dlg_run_done (d);
destroy_dlg (d);
d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
mc_refresh ();
}
if (got_interrupt ())
break;
}
if (!view_get_line_at (view, search_start, buffer, &line_start, &line_end))
view_moveto_match (view);
isFound = TRUE;
break;
if (! mc_search_run( view->search, buffer->str, 0, buffer->len, &match_len )){
if (view->search->error != MC_SEARCH_E_NOTFOUND) {
search_status = -2;
break;
}
if (! view->search_backwards) {
search_start = line_end;
} else {
if (line_start > 0) search_start = line_start - 1;
else break;
}
continue;
}
search_status = 1;
if (view->search_backwards){
search_start = line_start;
}
} while (view_may_still_grow(view));
view->search_start = search_start + view->search->normal_offset +
view__get_nroff_real_len(view, search_start, view->search->normal_offset);
view->search_end = view->search_start + match_len +
view__get_nroff_real_len(view, view->search_start, match_len);
if (view->hex_mode){
view->hex_cursor = view->search_start;
view->hexedit_lownibble = FALSE;
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
}
view_moveto_match (view);
break;
if (!isFound){
if (view->search->error_str)
message (D_NORMAL, _("Search"), view->search->error_str);
}
view->dirty++;
view_update (view);
disable_interrupt_key ();
if (verbose) {
dlg_run_done (d);
destroy_dlg (d);
}
switch (search_status)
{
case -1:
message (D_NORMAL, _("Search"), _(" Search string not found "));
view->search_end = view->search_start;
break;
case -2:
message (D_NORMAL, _("Search"), "%s", view->search->error_str);
view->search_end = view->search_start;
break;
}
g_string_free (buffer, TRUE);
view->dirty++;
view_update (view);
}
/* Both views */
static void
view_search_cmd (WView *view)
@ -3234,6 +3261,7 @@ view_search_cmd (WView *view)
char *defval = g_strdup (view->last_search_string != NULL ? view->last_search_string : "");
char *exp = NULL;
GString *tmp;
int ttype_of_search = (int) view->search_type;
int tall_codepages = (int) view->search_all_codepages;
@ -3295,7 +3323,14 @@ view_search_cmd (WView *view)
if (exp == NULL || exp[0] == '\0')
goto cleanup;
convert_from_input (exp);
g_free (defval);
defval = NULL;
tmp = str_convert_to_input (exp);
if (tmp)
defval = tmp->str;
g_string_free (tmp, FALSE);
g_free (view->last_search_string);
view->last_search_string = exp;
@ -3304,13 +3339,15 @@ view_search_cmd (WView *view)
if (view->search)
mc_search_free(view->search);
view->search = mc_search_new(view->last_search_string, -1);
view->search = mc_search_new(defval, -1);
if (! view->search)
return;
goto cleanup;
view->search->search_type = view->search_type;
view->search->is_all_charsets = view->search_all_codepages;
view->search->is_case_sentitive = view->search_case;
view->search->search_fn = view_search_cmd_callback;
view->search->update_fn = view_search_update_cmd_callback;
do_search (view);