Moved strecape.[ch] into library
[midnight-commander.git] / lib / search / glob.c
blobd40d42a67af52ec355c080c65916e800b31b1ba4
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 (gchar * str, gsize * len)
53 GString *buff = g_string_new ("");
54 gsize orig_len = *len;
55 gsize loop = 0;
56 gboolean inside_group = FALSE;
57 while (loop < orig_len) {
58 switch (str[loop]) {
59 case '*':
60 if (!strutils_is_char_escaped (str, &(str[loop]))) {
61 g_string_append (buff, (inside_group) ? ".*" : "(.*)");
62 loop++;
63 continue;
65 break;
66 case '?':
67 if (!strutils_is_char_escaped (str, &(str[loop]))) {
68 g_string_append (buff, (inside_group) ? "." : "(.)");
69 loop++;
70 continue;
72 break;
73 case ',':
74 if (!strutils_is_char_escaped (str, &(str[loop]))) {
75 g_string_append (buff, "|");
76 loop++;
77 continue;
79 break;
80 case '{':
81 if (!strutils_is_char_escaped (str, &(str[loop]))) {
82 g_string_append (buff, "(");
83 inside_group = TRUE;
84 loop++;
85 continue;
87 break;
88 case '}':
89 if (!strutils_is_char_escaped (str, &(str[loop]))) {
90 g_string_append (buff, ")");
91 inside_group = FALSE;
92 loop++;
93 continue;
95 break;
96 case '+':
97 case '.':
98 case '$':
99 case '(':
100 case ')':
101 case '^':
102 g_string_append_c (buff, '\\');
103 g_string_append_c (buff, str[loop]);
104 loop++;
105 continue;
106 break;
108 g_string_append_c (buff, str[loop]);
109 loop++;
111 *len = buff->len;
112 return buff;
115 /* --------------------------------------------------------------------------------------------- */
117 static GString *
118 mc_search__translate_replace_glob_to_regex (gchar *str)
120 GString *buff = g_string_new ("");
121 int cnt = '0';
123 while (*str) {
124 char c = *str++;
125 switch (c) {
126 case '*':
127 case '?':
128 g_string_append_c (buff, '\\');
129 c = ++cnt;
130 break;
131 /* breaks copying: mc uses "\0" internally, it must not be changed */
132 /*case '\\':*/
133 case '&':
134 g_string_append_c (buff, '\\');
135 break;
137 g_string_append_c (buff, c);
139 return buff;
142 /*** public functions ****************************************************************************/
144 void
145 mc_search__cond_struct_new_init_glob (const char *charset, mc_search_t * lc_mc_search,
146 mc_search_cond_t * mc_search_cond)
148 GString *tmp =
149 mc_search__glob_translate_to_regex (mc_search_cond->str->str, &mc_search_cond->len);
151 g_string_free (mc_search_cond->str, TRUE);
153 if (lc_mc_search->is_entire_line) {
154 g_string_prepend_c (tmp, '^');
155 g_string_append_c (tmp, '$');
157 mc_search_cond->str = tmp;
159 mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
163 /* --------------------------------------------------------------------------------------------- */
165 gboolean
166 mc_search__run_glob (mc_search_t * lc_mc_search, const void *user_data,
167 gsize start_search, gsize end_search, gsize * found_len)
169 return mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
172 /* --------------------------------------------------------------------------------------------- */
175 GString *
176 mc_search_glob_prepare_replace_str (mc_search_t * lc_mc_search, GString * replace_str)
178 GString *repl = mc_search__translate_replace_glob_to_regex(replace_str->str);
179 GString *res = mc_search_regex_prepare_replace_str (lc_mc_search, repl);
180 g_string_free (repl, TRUE);
181 return res;
184 /* --------------------------------------------------------------------------------------------- */