Warning fix: return discards qualifiers from pointer target type
[midnight-commander.git] / src / search / search.c
blobaa1d05415ecbb851f737e6fbbd4c8e15ce13e6e3
1 /*
2 Search text engine.
3 Interface functions
5 Copyright (C) 2009 The Free Software Foundation, Inc.
7 Written by:
8 Slava Zanko <slavazanko@gmail.com>, 2009.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software; you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be
18 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
19 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 MA 02110-1301, USA.
28 #include <config.h>
31 #include "../src/global.h"
32 #include "../src/search/search.h"
33 #include "../src/search/internal.h"
34 #include "../src/strutil.h"
35 #include "../src/charsets.h"
37 /*** global variables ****************************************************************************/
39 /*** file scope macro definitions ****************************************************************/
41 /*** file scope type declarations ****************************************************************/
43 /*** file scope variables ************************************************************************/
45 static const mc_search_type_str_t mc_search__list_types[] = {
46 {N_("Normal"), MC_SEARCH_T_NORMAL},
47 {N_("&Regular expression"), MC_SEARCH_T_REGEX},
48 {N_("Hexadecimal"), MC_SEARCH_T_HEX},
49 {N_("Wildcard search"), MC_SEARCH_T_GLOB},
50 {NULL, -1}
53 /*** file scope functions ************************************************************************/
55 static mc_search_cond_t *
56 mc_search__cond_struct_new (mc_search_t * mc_search, const char *str,
57 gsize str_len, const char *charset)
59 mc_search_cond_t *mc_search_cond;
60 mc_search_cond = g_malloc0 (sizeof (mc_search_cond_t));
62 mc_search_cond->str = g_string_new_len (str, str_len);
63 mc_search_cond->len = str_len;
64 mc_search_cond->charset = g_strdup (charset);
66 switch (mc_search->search_type) {
67 case MC_SEARCH_T_GLOB:
68 mc_search__cond_struct_new_init_glob (charset, mc_search, mc_search_cond);
69 break;
70 case MC_SEARCH_T_NORMAL:
71 mc_search__cond_struct_new_init_normal (charset, mc_search, mc_search_cond);
72 break;
73 case MC_SEARCH_T_REGEX:
74 mc_search__cond_struct_new_init_regex (charset, mc_search, mc_search_cond);
75 break;
76 case MC_SEARCH_T_HEX:
77 mc_search__cond_struct_new_init_hex (charset, mc_search, mc_search_cond);
78 break;
79 default:
80 break;
82 return mc_search_cond;
85 /* --------------------------------------------------------------------------------------------- */
87 static GPtrArray *
88 mc_search__conditions_new (mc_search_t * mc_search)
90 GPtrArray *ret;
91 ret = g_ptr_array_new ();
92 #ifdef HAVE_CHARSET
93 if (mc_search->is_all_charsets) {
94 gsize loop1, recoded_str_len;
95 gchar *buffer;
96 for (loop1 = 0; loop1 < (gsize) n_codepages; loop1++) {
97 if (!g_ascii_strcasecmp (codepages[loop1].id, cp_source)) {
98 g_ptr_array_add (ret,
99 mc_search__cond_struct_new (mc_search, mc_search->original,
100 mc_search->original_len, cp_source));
101 continue;
104 buffer =
105 mc_search__recode_str (mc_search->original, mc_search->original_len, cp_source,
106 codepages[loop1].id, &recoded_str_len);
107 if (buffer == NULL)
108 continue;
110 g_ptr_array_add (ret,
111 mc_search__cond_struct_new (mc_search, buffer,
112 recoded_str_len, codepages[loop1].id));
113 g_free (buffer);
115 } else {
116 g_ptr_array_add (ret,
117 (gpointer) mc_search__cond_struct_new (mc_search, mc_search->original,
118 mc_search->original_len,
119 cp_source));
121 #else
122 g_ptr_array_add (ret,
123 (gpointer) mc_search__cond_struct_new (mc_search, mc_search->original,
124 mc_search->original_len,
125 str_detect_termencoding()));
126 #endif
127 return ret;
130 /* --------------------------------------------------------------------------------------------- */
132 static void
133 mc_search__cond_struct_free (mc_search_cond_t * mc_search_cond)
135 if (mc_search_cond->upper)
136 g_string_free (mc_search_cond->upper, TRUE);
138 if (mc_search_cond->lower)
139 g_string_free (mc_search_cond->lower, TRUE);
141 g_string_free (mc_search_cond->str, TRUE);
142 g_free (mc_search_cond->charset);
144 #if GLIB_CHECK_VERSION (2, 14, 0)
145 if (mc_search_cond->regex_handle)
146 g_regex_unref (mc_search_cond->regex_handle);
147 #else /* GLIB_CHECK_VERSION (2, 14, 0) */
148 #if HAVE_LIBPCRE
149 if (mc_search_cond->regex_handle)
150 free (mc_search_cond->regex_handle);
151 #else /* HAVE_LIBPCRE */
152 if (mc_search_cond->regex_handle)
153 regfree (mc_search_cond->regex_handle);
154 #endif /* HAVE_LIBPCRE */
155 #endif /* GLIB_CHECK_VERSION (2, 14, 0) */
157 g_free (mc_search_cond);
160 /* --------------------------------------------------------------------------------------------- */
162 static void
163 mc_search__conditions_free (GPtrArray * array)
165 gsize loop1;
166 mc_search_cond_t *mc_search;
168 for (loop1 = 0; loop1 < array->len; loop1++) {
169 mc_search = (mc_search_cond_t *) g_ptr_array_index (array, loop1);
170 mc_search__cond_struct_free (mc_search);
172 g_ptr_array_free (array, TRUE);
175 /* --------------------------------------------------------------------------------------------- */
179 /*** public functions ****************************************************************************/
181 mc_search_t *
182 mc_search_new (const gchar * original, gsize str_len)
184 mc_search_t *mc_search;
185 if (!original)
186 return NULL;
188 if ((gssize) str_len == -1) {
189 str_len = strlen (original);
190 if (str_len == 0)
191 return NULL;
194 mc_search = g_malloc0 (sizeof (mc_search_t));
195 mc_search->original = g_strndup (original, str_len);
196 mc_search->original_len = str_len;
197 return mc_search;
200 /* --------------------------------------------------------------------------------------------- */
202 void
203 mc_search_free (mc_search_t * mc_search)
205 if (!mc_search)
206 return;
208 g_free (mc_search->original);
210 if (mc_search->error_str)
211 g_free (mc_search->error_str);
213 if (mc_search->conditions)
214 mc_search__conditions_free (mc_search->conditions);
216 #if GLIB_CHECK_VERSION (2, 14, 0)
217 if (mc_search->regex_match_info)
218 g_match_info_free (mc_search->regex_match_info);
219 #else /* GLIB_CHECK_VERSION (2, 14, 0) */
220 #if HAVE_LIBPCRE
221 if (mc_search->regex_match_info)
222 free (mc_search->regex_match_info);
223 #else /* HAVE_LIBPCRE */
224 if (mc_search->regex_match_info)
225 g_free (mc_search->regex_match_info);
226 #endif /* HAVE_LIBPCRE */
227 #endif /* GLIB_CHECK_VERSION (2, 14, 0) */
229 if (mc_search->regex_buffer != NULL)
230 g_string_free (mc_search->regex_buffer, TRUE);
232 g_free (mc_search);
235 /* --------------------------------------------------------------------------------------------- */
237 gboolean
238 mc_search_run (mc_search_t * mc_search, const void *user_data,
239 gsize start_search, gsize end_search, gsize * found_len)
241 gboolean ret = FALSE;
243 if (!mc_search)
244 return FALSE;
245 if (!mc_search_is_type_avail (mc_search->search_type)) {
246 mc_search->error = MC_SEARCH_E_INPUT;
247 mc_search->error_str = g_strdup (_(STR_E_UNKNOWN_TYPE));
248 return FALSE;
250 #if GLIB_CHECK_VERSION (2, 14, 0)
251 if (mc_search->regex_match_info) {
252 g_match_info_free (mc_search->regex_match_info);
253 mc_search->regex_match_info = NULL;
255 #endif /* GLIB_CHECK_VERSION (2, 14, 0) */
257 mc_search->error = MC_SEARCH_E_OK;
258 if (mc_search->error_str) {
259 g_free (mc_search->error_str);
260 mc_search->error_str = NULL;
263 if (!mc_search->conditions) {
264 mc_search->conditions = mc_search__conditions_new (mc_search);
266 if (mc_search->error != MC_SEARCH_E_OK)
267 return FALSE;
270 switch (mc_search->search_type) {
271 case MC_SEARCH_T_NORMAL:
272 ret = mc_search__run_normal (mc_search, user_data, start_search, end_search, found_len);
273 break;
274 case MC_SEARCH_T_REGEX:
275 ret = mc_search__run_regex (mc_search, user_data, start_search, end_search, found_len);
276 break;
277 case MC_SEARCH_T_GLOB:
278 ret = mc_search__run_glob (mc_search, user_data, start_search, end_search, found_len);
279 break;
280 case MC_SEARCH_T_HEX:
281 ret = mc_search__run_hex (mc_search, user_data, start_search, end_search, found_len);
282 break;
283 default:
284 break;
286 return ret;
289 /* --------------------------------------------------------------------------------------------- */
291 gboolean
292 mc_search_is_type_avail (mc_search_type_t search_type)
294 switch (search_type) {
295 case MC_SEARCH_T_GLOB:
296 case MC_SEARCH_T_NORMAL:
297 case MC_SEARCH_T_REGEX:
298 case MC_SEARCH_T_HEX:
299 return TRUE;
300 break;
301 default:
302 break;
304 return FALSE;
307 /* --------------------------------------------------------------------------------------------- */
309 const mc_search_type_str_t *
310 mc_search_types_list_get (void)
312 return mc_search__list_types;
315 /* --------------------------------------------------------------------------------------------- */
317 GString *
318 mc_search_prepare_replace_str (mc_search_t * mc_search, GString * replace_str)
320 GString *ret;
322 if (mc_search == NULL)
323 return g_string_new_len (replace_str->str, replace_str->len);
325 switch (mc_search->search_type) {
326 case MC_SEARCH_T_REGEX:
327 ret = mc_search_regex_prepare_replace_str (mc_search, replace_str);
328 break;
329 case MC_SEARCH_T_NORMAL:
330 case MC_SEARCH_T_HEX:
331 case MC_SEARCH_T_GLOB:
332 default:
333 ret = g_string_new_len (replace_str->str, replace_str->len);
334 break;
336 return ret;
339 /* --------------------------------------------------------------------------------------------- */
341 gboolean
342 mc_search_is_fixed_search_str (mc_search_t * mc_search)
344 if (mc_search == NULL)
345 return FALSE;
346 switch (mc_search->search_type) {
347 case MC_SEARCH_T_REGEX:
348 case MC_SEARCH_T_GLOB:
349 return FALSE;
350 break;
351 default:
352 return TRUE;
353 break;
357 /* --------------------------------------------------------------------------------------------- */
359 gboolean
360 mc_search (const gchar *pattern, const gchar *str, mc_search_type_t type)
362 gboolean ret;
363 mc_search_t *search = mc_search_new(pattern, -1);
364 if (search == NULL)
365 return FALSE;
366 search->search_type = type;
367 search->is_case_sentitive = TRUE;
368 ret = mc_search_run(search,str,0,strlen(str),NULL);
369 mc_search_free(search);
370 return ret;
373 /* --------------------------------------------------------------------------------------------- */
376 mc_search_getstart_rezult_by_num(mc_search_t *mc_search, int index)
378 if (!mc_search)
379 return 0;
380 if (mc_search->search_type == MC_SEARCH_T_NORMAL)
381 return 0;
382 #if GLIB_CHECK_VERSION (2, 14, 0)
383 gint start_pos;
384 gint end_pos;
385 g_match_info_fetch_pos (mc_search->regex_match_info, index, &start_pos, &end_pos);
386 return (int) start_pos;
387 #else /* GLIB_CHECK_VERSION (2, 14, 0) */
388 #if HAVE_LIBPCRE
389 return mc_search->iovector[index*2];
390 #else /* HAVE_LIBPCRE */
391 return mc_search->regex_match_info[index].rm_so;
392 #endif /* HAVE_LIBPCRE */
393 #endif /* GLIB_CHECK_VERSION (2, 14, 0) */
397 /* --------------------------------------------------------------------------------------------- */
400 mc_search_getend_rezult_by_num(mc_search_t *mc_search, int index)
402 if (!mc_search)
403 return 0;
404 if (mc_search->search_type == MC_SEARCH_T_NORMAL)
405 return 0;
406 #if GLIB_CHECK_VERSION (2, 14, 0)
407 gint start_pos;
408 gint end_pos;
409 g_match_info_fetch_pos (mc_search->regex_match_info, index, &start_pos, &end_pos);
410 return (int) end_pos;
411 #else /* GLIB_CHECK_VERSION (2, 14, 0) */
412 #if HAVE_LIBPCRE
413 return mc_search->iovector[index*2+1];
414 #else /* HAVE_LIBPCRE */
415 return mc_search->regex_match_info[index].rm_eo;
416 #endif /* HAVE_LIBPCRE */
417 #endif /* GLIB_CHECK_VERSION (2, 14, 0) */
421 /* --------------------------------------------------------------------------------------------- */