From 6e6f05b78ff8a4bdb45f7bf0679a778c6210c17f Mon Sep 17 00:00:00 2001
From: Mooffie <mooffie@gmail.com>
Date: Tue, 6 Dec 2016 22:26:33 +0200
Subject: [PATCH 1/3] Ticket #400: search: introduce slurp mode.
(The "get around sloppy callers" comment refers to an imperfection in the
editor's backwards-search in which the 1st iteration turns out to have
start_search==(end_search+1).)
---
lib/search.h | 14 ++++++++++++++
lib/search/lib.c | 3 +++
lib/search/regex.c | 5 +++--
lib/search/search.c | 21 +++++++++++++++++++++
src/setup.c | 30 ++++++++++++++++++++++++++++++
5 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/lib/search.h b/lib/search.h
index 6e79609..d2a199f 100644
a
|
b
|
typedef enum |
37 | 37 | MC_SEARCH_E_REGEX, |
38 | 38 | MC_SEARCH_E_REGEX_REPLACE, |
39 | 39 | MC_SEARCH_E_NOTFOUND, |
| 40 | MC_SEARCH_E_SLURP_MODE_MAXED, |
40 | 41 | MC_SEARCH_E_ABORT |
41 | 42 | } mc_search_error_t; |
42 | 43 | |
… |
… |
typedef struct mc_search_struct |
81 | 82 | /* search entire string (from begin to end). Used only with GLOB search type */ |
82 | 83 | gboolean is_entire_line; |
83 | 84 | |
| 85 | /* |
| 86 | * Whether to accumulate the entire haystack (the data to search in) |
| 87 | * into one buffer before searching it. This makes it possible to |
| 88 | * search across lines. |
| 89 | * |
| 90 | * Normally the haystack is accumulated till a "\n" is encountered, |
| 91 | * repeatedly. This limits the scope of the search to one line only. |
| 92 | */ |
| 93 | gboolean slurp_mode; |
| 94 | |
84 | 95 | /* function, used for getting data. NULL if not used */ |
85 | 96 | mc_search_fn search_fn; |
86 | 97 | |
… |
… |
typedef struct mc_search_type_str_struct |
133 | 144 | /* Error messages */ |
134 | 145 | extern const char *STR_E_NOTFOUND; |
135 | 146 | extern const char *STR_E_UNKNOWN_TYPE; |
| 147 | extern const char *STR_E_SLURP_MODE_MAXED; |
136 | 148 | extern const char *STR_E_RPL_NOT_EQ_TO_FOUND; |
137 | 149 | extern const char *STR_E_RPL_INVALID_TOKEN; |
138 | 150 | |
… |
… |
gboolean mc_search (const gchar * pattern, const gchar * pattern_charset, const |
167 | 179 | int mc_search_getstart_result_by_num (mc_search_t *, int); |
168 | 180 | int mc_search_getend_result_by_num (mc_search_t *, int); |
169 | 181 | |
| 182 | void mc_search_set_slurp_mode_max (gsize max); |
| 183 | |
170 | 184 | /* *INDENT-OFF* */ |
171 | 185 | void mc_search_set_error (mc_search_t * lc_mc_search, mc_search_error_t code, const gchar * format, ...) |
172 | 186 | G_GNUC_PRINTF (3, 4); |
diff --git a/lib/search/lib.c b/lib/search/lib.c
index 5d086f1..8e6c362 100644
a
|
b
|
const char *STR_E_UNKNOWN_TYPE = N_("Not implemented yet"); |
46 | 46 | const char *STR_E_RPL_NOT_EQ_TO_FOUND = |
47 | 47 | N_("Num of replace tokens not equal to num of found tokens"); |
48 | 48 | const char *STR_E_RPL_INVALID_TOKEN = N_("Invalid token number %d"); |
| 49 | const char *STR_E_SLURP_MODE_MAXED = N_("Buffer is too large:\n" |
| 50 | "Searches across lines, or searches for 0x0A bytes,\n" |
| 51 | "are limited to buffers of size %d MB."); |
49 | 52 | |
50 | 53 | /*** file scope macro definitions ****************************************************************/ |
51 | 54 | |
diff --git a/lib/search/regex.c b/lib/search/regex.c
index e8d896c..070d463 100644
a
|
b
|
mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, |
912 | 912 | |
913 | 913 | g_string_append_c (lc_mc_search->regex_buffer, (char) current_chr); |
914 | 914 | |
915 | | if ((char) current_chr == '\n' || virtual_pos > end_search) |
| 915 | if (((char) current_chr == '\n' && !lc_mc_search->slurp_mode) |
| 916 | || virtual_pos > end_search) |
916 | 917 | break; |
917 | 918 | } |
918 | 919 | } |
… |
… |
mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data, |
931 | 932 | |
932 | 933 | current_pos++; |
933 | 934 | |
934 | | if (current_chr == '\n' || current_pos > end_search) |
| 935 | if ((current_chr == '\n' && !lc_mc_search->slurp_mode) || current_pos > end_search) |
935 | 936 | break; |
936 | 937 | } |
937 | 938 | |
diff --git a/lib/search/search.c b/lib/search/search.c
index 2e19ccf..f52dfc3 100644
a
|
b
|
static const mc_search_type_str_t mc_search__list_types[] = { |
57 | 57 | {NULL, MC_SEARCH_T_INVALID} |
58 | 58 | }; |
59 | 59 | |
| 60 | /* The maximal buffer size to allocate for slurp mode. */ |
| 61 | static gsize slurp_mode_max = 0; |
| 62 | |
60 | 63 | /*** file scope functions ************************************************************************/ |
61 | 64 | |
62 | 65 | static mc_search_cond_t * |
… |
… |
mc_search_prepare (mc_search_t * lc_mc_search) |
263 | 266 | |
264 | 267 | /* --------------------------------------------------------------------------------------------- */ |
265 | 268 | |
| 269 | void |
| 270 | mc_search_set_slurp_mode_max (gsize max) |
| 271 | { |
| 272 | slurp_mode_max = max; |
| 273 | } |
| 274 | |
| 275 | /* --------------------------------------------------------------------------------------------- */ |
| 276 | |
266 | 277 | /** |
267 | 278 | * Carries out the search. |
268 | 279 | * |
… |
… |
mc_search_run (mc_search_t * lc_mc_search, const void *user_data, |
302 | 313 | if ((lc_mc_search->conditions == NULL) && !mc_search_prepare (lc_mc_search)) |
303 | 314 | return FALSE; |
304 | 315 | |
| 316 | /* This has to come after mc_search_prepare(), as mc_search__cond_struct_new_init_XXX() |
| 317 | * may elect to turn slurp_mode on or off. */ |
| 318 | if (lc_mc_search->slurp_mode && end_search > start_search /* get around sloppy callers */ |
| 319 | && end_search - start_search > slurp_mode_max) |
| 320 | { |
| 321 | mc_search_set_error (lc_mc_search, MC_SEARCH_E_SLURP_MODE_MAXED, _(STR_E_SLURP_MODE_MAXED), |
| 322 | (int) (slurp_mode_max / 1024 / 1024)); |
| 323 | return FALSE; |
| 324 | } |
| 325 | |
305 | 326 | switch (lc_mc_search->search_type) |
306 | 327 | { |
307 | 328 | case MC_SEARCH_T_NORMAL: |
diff --git a/src/setup.c b/src/setup.c
index 951edb8..1861d9b 100644
a
|
b
|
|
37 | 37 | #include "lib/tty/tty.h" |
38 | 38 | #include "lib/tty/key.h" |
39 | 39 | #include "lib/mcconfig.h" |
| 40 | #include "lib/search.h" /* mc_search_set_slurp_mode_max() */ |
40 | 41 | #include "lib/fileloc.h" |
41 | 42 | #include "lib/timefmt.h" |
42 | 43 | #include "lib/util.h" |
… |
… |
save_panel_types (void) |
951 | 952 | } |
952 | 953 | |
953 | 954 | /* --------------------------------------------------------------------------------------------- */ |
| 955 | |
| 956 | /** |
| 957 | * Returns the user's preference for the largest buffer for some text |
| 958 | * operations. |
| 959 | * |
| 960 | * Code copied from the editor's edit.c:check_file_access(). |
| 961 | * |
| 962 | * @todo: make the editor use this function. |
| 963 | */ |
| 964 | static uintmax_t |
| 965 | get_filesize_memory_threshold (void) |
| 966 | { |
| 967 | static uintmax_t threshold = UINTMAX_MAX; |
| 968 | |
| 969 | if (threshold == UINTMAX_MAX) |
| 970 | { |
| 971 | gboolean err = FALSE; |
| 972 | |
| 973 | threshold = parse_integer (option_filesize_threshold, &err); |
| 974 | if (err) |
| 975 | threshold = 64 * 1024 * 1024; /* @todo: move edit.c's constant here. */ |
| 976 | } |
| 977 | |
| 978 | return threshold; |
| 979 | } |
| 980 | |
| 981 | /* --------------------------------------------------------------------------------------------- */ |
954 | 982 | /*** public functions ****************************************************************************/ |
955 | 983 | /* --------------------------------------------------------------------------------------------- */ |
956 | 984 | |
… |
… |
load_setup (void) |
1146 | 1174 | mc_config_get_string (mc_global.main_config, CONFIG_MISC_SECTION, "clipboard_store", ""); |
1147 | 1175 | clipboard_paste_path = |
1148 | 1176 | mc_config_get_string (mc_global.main_config, CONFIG_MISC_SECTION, "clipboard_paste", ""); |
| 1177 | |
| 1178 | mc_search_set_slurp_mode_max ((gsize) get_filesize_memory_threshold ()); |
1149 | 1179 | } |
1150 | 1180 | |
1151 | 1181 | /* --------------------------------------------------------------------------------------------- */ |