root/lib/search/glob.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mc_search__glob_translate_to_regex
  2. mc_search__translate_replace_glob_to_regex
  3. mc_search__cond_struct_new_init_glob
  4. mc_search__run_glob
  5. mc_search_glob_prepare_replace_str

   1 /*
   2    Search text engine.
   3    Glob-style pattern matching
   4 
   5    Copyright (C) 2009-2024
   6    Free Software Foundation, Inc.
   7 
   8    Written by:
   9    Slava Zanko <slavazanko@gmail.com>, 2009.
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include <config.h>
  28 
  29 #include "lib/global.h"
  30 #include "lib/strutil.h"
  31 #include "lib/search.h"
  32 #include "lib/strescape.h"
  33 
  34 #include "internal.h"
  35 
  36 /*** global variables ****************************************************************************/
  37 
  38 /*** file scope macro definitions ****************************************************************/
  39 
  40 /*** file scope type declarations ****************************************************************/
  41 
  42 /*** forward declarations (file scope functions) *************************************************/
  43 
  44 /*** file scope variables ************************************************************************/
  45 
  46 /* --------------------------------------------------------------------------------------------- */
  47 /*** file scope functions ************************************************************************/
  48 /* --------------------------------------------------------------------------------------------- */
  49 
  50 static GString *
  51 mc_search__glob_translate_to_regex (const GString * astr)
     /* [previous][next][first][last][top][bottom][index][help]  */
  52 {
  53     const char *str = astr->str;
  54     GString *buff;
  55     gsize loop;
  56     gboolean inside_group = FALSE;
  57 
  58     buff = g_string_sized_new (32);
  59 
  60     for (loop = 0; loop < astr->len; loop++)
  61     {
  62         switch (str[loop])
  63         {
  64         case '*':
  65             if (!strutils_is_char_escaped (str, &(str[loop])))
  66             {
  67                 g_string_append (buff, inside_group ? ".*" : "(.*)");
  68                 continue;
  69             }
  70             break;
  71         case '?':
  72             if (!strutils_is_char_escaped (str, &(str[loop])))
  73             {
  74                 g_string_append (buff, inside_group ? "." : "(.)");
  75                 continue;
  76             }
  77             break;
  78         case ',':
  79             if (!strutils_is_char_escaped (str, &(str[loop])))
  80             {
  81                 g_string_append_c (buff, inside_group ? '|' : ',');
  82                 continue;
  83             }
  84             break;
  85         case '{':
  86             if (!strutils_is_char_escaped (str, &(str[loop])))
  87             {
  88                 g_string_append_c (buff, '(');
  89                 inside_group = TRUE;
  90                 continue;
  91             }
  92             break;
  93         case '}':
  94             if (!strutils_is_char_escaped (str, &(str[loop])))
  95             {
  96                 g_string_append_c (buff, ')');
  97                 inside_group = FALSE;
  98                 continue;
  99             }
 100             break;
 101         case '+':
 102         case '.':
 103         case '$':
 104         case '(':
 105         case ')':
 106         case '^':
 107             g_string_append_c (buff, '\\');
 108             break;
 109         default:
 110             break;
 111         }
 112         g_string_append_c (buff, str[loop]);
 113     }
 114     return buff;
 115 }
 116 
 117 /* --------------------------------------------------------------------------------------------- */
 118 
 119 static GString *
 120 mc_search__translate_replace_glob_to_regex (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 121 {
 122     GString *buff;
 123     char cnt = '0';
 124     gboolean escaped_mode = FALSE;
 125 
 126     buff = g_string_sized_new (32);
 127 
 128     while (*str != '\0')
 129     {
 130         char c = *str++;
 131 
 132         switch (c)
 133         {
 134         case '\\':
 135             if (!escaped_mode)
 136             {
 137                 escaped_mode = TRUE;
 138                 g_string_append_c (buff, '\\');
 139                 continue;
 140             }
 141             break;
 142         case '*':
 143         case '?':
 144             if (!escaped_mode)
 145             {
 146                 g_string_append_c (buff, '\\');
 147                 c = ++cnt;
 148             }
 149             break;
 150         case '&':
 151             if (!escaped_mode)
 152                 g_string_append_c (buff, '\\');
 153             break;
 154         default:
 155             break;
 156         }
 157         g_string_append_c (buff, c);
 158         escaped_mode = FALSE;
 159     }
 160     return buff;
 161 }
 162 
 163 /*** public functions ****************************************************************************/
 164 
 165 void
 166 mc_search__cond_struct_new_init_glob (const char *charset, mc_search_t * lc_mc_search,
     /* [previous][next][first][last][top][bottom][index][help]  */
 167                                       mc_search_cond_t * mc_search_cond)
 168 {
 169     GString *tmp;
 170 
 171     tmp = mc_search__glob_translate_to_regex (mc_search_cond->str);
 172     g_string_free (mc_search_cond->str, TRUE);
 173 
 174     if (lc_mc_search->is_entire_line)
 175     {
 176         g_string_prepend_c (tmp, '^');
 177         g_string_append_c (tmp, '$');
 178     }
 179     mc_search_cond->str = tmp;
 180 
 181     mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
 182 }
 183 
 184 /* --------------------------------------------------------------------------------------------- */
 185 
 186 gboolean
 187 mc_search__run_glob (mc_search_t * lc_mc_search, const void *user_data,
     /* [previous][next][first][last][top][bottom][index][help]  */
 188                      gsize start_search, gsize end_search, gsize * found_len)
 189 {
 190     return mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
 191 }
 192 
 193 /* --------------------------------------------------------------------------------------------- */
 194 
 195 GString *
 196 mc_search_glob_prepare_replace_str (mc_search_t * lc_mc_search, GString * replace_str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 197 {
 198     GString *repl, *res;
 199 
 200     repl = mc_search__translate_replace_glob_to_regex (replace_str->str);
 201     res = mc_search_regex_prepare_replace_str (lc_mc_search, repl);
 202     g_string_free (repl, TRUE);
 203 
 204     return res;
 205 }
 206 
 207 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */