Minor optimization of translation function arguments.
[midnight-commander.git] / lib / search / glob.c
blob602146162421887614e505ccd10feecdfd03a2fa
1 /*
2 Search text engine.
3 Glob-style pattern matching
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 "lib/global.h"
32 #include "lib/strutil.h"
33 #include "lib/search.h"
34 #include "lib/strescape.h"
36 #include "src/charsets.h"
38 #include "internal.h"
40 /*** global variables ****************************************************************************/
42 /*** file scope macro definitions ****************************************************************/
44 /*** file scope type declarations ****************************************************************/
46 /*** file scope variables ************************************************************************/
48 /*** file scope functions ************************************************************************/
50 static GString *
51 mc_search__glob_translate_to_regex (const GString * astr)
53 const char *str = astr->str;
54 GString *buff = g_string_new ("");
55 gsize loop = 0;
56 gboolean inside_group = FALSE;
58 while (loop < astr->len)
60 switch (str[loop])
62 case '*':
63 if (!strutils_is_char_escaped (str, &(str[loop])))
65 g_string_append (buff, (inside_group) ? ".*" : "(.*)");
66 loop++;
67 continue;
69 break;
70 case '?':
71 if (!strutils_is_char_escaped (str, &(str[loop])))
73 g_string_append (buff, (inside_group) ? "." : "(.)");
74 loop++;
75 continue;
77 break;
78 case ',':
79 if (!strutils_is_char_escaped (str, &(str[loop])))
81 g_string_append (buff, "|");
82 loop++;
83 continue;
85 break;
86 case '{':
87 if (!strutils_is_char_escaped (str, &(str[loop])))
89 g_string_append (buff, "(");
90 inside_group = TRUE;
91 loop++;
92 continue;
94 break;
95 case '}':
96 if (!strutils_is_char_escaped (str, &(str[loop])))
98 g_string_append (buff, ")");
99 inside_group = FALSE;
100 loop++;
101 continue;
103 break;
104 case '+':
105 case '.':
106 case '$':
107 case '(':
108 case ')':
109 case '^':
110 g_string_append_c (buff, '\\');
111 g_string_append_c (buff, str[loop]);
112 loop++;
113 continue;
115 g_string_append_c (buff, str[loop]);
116 loop++;
119 return buff;
122 /* --------------------------------------------------------------------------------------------- */
124 static GString *
125 mc_search__translate_replace_glob_to_regex (gchar * str)
127 GString *buff = g_string_sized_new (32);
128 int cnt = '0';
129 gboolean escaped_mode = FALSE;
130 while (*str)
132 char c = *str++;
133 switch (c)
135 case '\\':
136 if (!escaped_mode)
138 escaped_mode = TRUE;
140 g_string_append_c (buff, c);
141 continue;
142 case '*':
143 case '?':
144 if (!escaped_mode)
146 g_string_append_c (buff, '\\');
147 c = ++cnt;
149 break;
150 case '&':
151 g_string_append_c (buff, '\\');
152 break;
154 g_string_append_c (buff, c);
155 escaped_mode = FALSE;
157 return buff;
160 /*** public functions ****************************************************************************/
162 void
163 mc_search__cond_struct_new_init_glob (const char *charset, mc_search_t * lc_mc_search,
164 mc_search_cond_t * mc_search_cond)
166 GString *tmp;
168 tmp = mc_search__glob_translate_to_regex (mc_search_cond->str);
169 g_string_free (mc_search_cond->str, TRUE);
171 if (lc_mc_search->is_entire_line)
173 g_string_prepend_c (tmp, '^');
174 g_string_append_c (tmp, '$');
176 mc_search_cond->str = tmp;
178 mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
181 /* --------------------------------------------------------------------------------------------- */
183 gboolean
184 mc_search__run_glob (mc_search_t * lc_mc_search, const void *user_data,
185 gsize start_search, gsize end_search, gsize * found_len)
187 return mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
190 /* --------------------------------------------------------------------------------------------- */
192 GString *
193 mc_search_glob_prepare_replace_str (mc_search_t * lc_mc_search, GString * replace_str)
195 GString *repl = mc_search__translate_replace_glob_to_regex (replace_str->str);
196 GString *res = mc_search_regex_prepare_replace_str (lc_mc_search, repl);
197 g_string_free (repl, TRUE);
198 return res;
201 /* --------------------------------------------------------------------------------------------- */