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 
  33 #include "internal.h"
  34 
  35 /*** global variables ****************************************************************************/
  36 
  37 /*** file scope macro definitions ****************************************************************/
  38 
  39 /*** file scope type declarations ****************************************************************/
  40 
  41 /*** forward declarations (file scope functions) *************************************************/
  42 
  43 /*** file scope variables ************************************************************************/
  44 
  45 /* --------------------------------------------------------------------------------------------- */
  46 /*** file scope functions ************************************************************************/
  47 /* --------------------------------------------------------------------------------------------- */
  48 
  49 static GString *
  50 mc_search__glob_translate_to_regex (const GString *astr)
     /* [previous][next][first][last][top][bottom][index][help]  */
  51 {
  52     GString *buff;
  53     gsize loop;
  54     gboolean inside_group = FALSE;
  55 
  56     buff = g_string_sized_new (32);
  57 
  58     for (loop = 0; loop < astr->len; loop++)
  59     {
  60         const char *str = astr->str;
  61         gboolean not_escaped;
  62 
  63         not_escaped = !str_is_char_escaped (str, str + loop);
  64 
  65         switch (str[loop])
  66         {
  67         case '*':
  68             if (not_escaped)
  69             {
  70                 g_string_append (buff, inside_group ? ".*" : "(.*)");
  71                 continue;
  72             }
  73             break;
  74         case '?':
  75             if (not_escaped)
  76             {
  77                 g_string_append (buff, inside_group ? "." : "(.)");
  78                 continue;
  79             }
  80             break;
  81         case ',':
  82             if (not_escaped)
  83             {
  84                 g_string_append_c (buff, inside_group ? '|' : ',');
  85                 continue;
  86             }
  87             break;
  88         case '{':
  89             if (not_escaped)
  90             {
  91                 g_string_append_c (buff, '(');
  92                 inside_group = TRUE;
  93                 continue;
  94             }
  95             break;
  96         case '}':
  97             if (not_escaped)
  98             {
  99                 g_string_append_c (buff, ')');
 100                 inside_group = FALSE;
 101                 continue;
 102             }
 103             break;
 104         case '+':
 105         case '.':
 106         case '$':
 107         case '(':
 108         case ')':
 109         case '^':
 110             g_string_append_c (buff, '\\');
 111             break;
 112         default:
 113             break;
 114         }
 115         g_string_append_c (buff, str[loop]);
 116     }
 117     return buff;
 118 }
 119 
 120 /* --------------------------------------------------------------------------------------------- */
 121 
 122 static GString *
 123 mc_search__translate_replace_glob_to_regex (const char *str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 124 {
 125     GString *buff;
 126     char cnt = '0';
 127     gboolean escaped_mode = FALSE;
 128 
 129     buff = g_string_sized_new (32);
 130 
 131     while (*str != '\0')
 132     {
 133         char c = *str++;
 134 
 135         switch (c)
 136         {
 137         case '\\':
 138             if (!escaped_mode)
 139             {
 140                 escaped_mode = TRUE;
 141                 g_string_append_c (buff, '\\');
 142                 continue;
 143             }
 144             break;
 145         case '*':
 146         case '?':
 147             if (!escaped_mode)
 148             {
 149                 g_string_append_c (buff, '\\');
 150                 c = ++cnt;
 151             }
 152             break;
 153         case '&':
 154             if (!escaped_mode)
 155                 g_string_append_c (buff, '\\');
 156             break;
 157         default:
 158             break;
 159         }
 160         g_string_append_c (buff, c);
 161         escaped_mode = FALSE;
 162     }
 163     return buff;
 164 }
 165 
 166 /*** public functions ****************************************************************************/
 167 
 168 void
 169 mc_search__cond_struct_new_init_glob (const char *charset, mc_search_t *lc_mc_search,
     /* [previous][next][first][last][top][bottom][index][help]  */
 170                                       mc_search_cond_t *mc_search_cond)
 171 {
 172     GString *tmp;
 173 
 174     tmp = mc_search__glob_translate_to_regex (mc_search_cond->str);
 175     g_string_free (mc_search_cond->str, TRUE);
 176 
 177     if (lc_mc_search->is_entire_line)
 178     {
 179         g_string_prepend_c (tmp, '^');
 180         g_string_append_c (tmp, '$');
 181     }
 182     mc_search_cond->str = tmp;
 183 
 184     mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
 185 }
 186 
 187 /* --------------------------------------------------------------------------------------------- */
 188 
 189 gboolean
 190 mc_search__run_glob (mc_search_t *lc_mc_search, const void *user_data,
     /* [previous][next][first][last][top][bottom][index][help]  */
 191                      gsize start_search, gsize end_search, gsize *found_len)
 192 {
 193     return mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
 194 }
 195 
 196 /* --------------------------------------------------------------------------------------------- */
 197 
 198 GString *
 199 mc_search_glob_prepare_replace_str (mc_search_t *lc_mc_search, GString *replace_str)
     /* [previous][next][first][last][top][bottom][index][help]  */
 200 {
 201     GString *repl, *res;
 202 
 203     repl = mc_search__translate_replace_glob_to_regex (replace_str->str);
 204     res = mc_search_regex_prepare_replace_str (lc_mc_search, repl);
 205     g_string_free (repl, TRUE);
 206 
 207     return res;
 208 }
 209 
 210 /* --------------------------------------------------------------------------------------------- */

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