This source file includes following definitions.
- mc_search__cond_struct_new
- mc_search__cond_struct_free
- mc_search_new
- mc_search_new_len
- mc_search_free
- mc_search_prepare
- mc_search_run
- mc_search_is_type_avail
- mc_search_types_list_get
- mc_search_prepare_replace_str
- mc_search_prepare_replace_str2
- mc_search_is_fixed_search_str
- mc_search
- mc_search_getstart_result_by_num
- mc_search_getend_result_by_num
- mc_search_set_error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #include <config.h>
29
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33
34 #include "lib/global.h"
35 #include "lib/strutil.h"
36 #include "lib/search.h"
37 #include "lib/util.h"
38 #ifdef HAVE_CHARSET
39 # include "lib/charsets.h"
40 #endif
41
42 #include "internal.h"
43
44
45
46
47
48
49
50
51
52
53
54 static const mc_search_type_str_t mc_search__list_types[] = {
55 { N_ ("No&rmal"), MC_SEARCH_T_NORMAL },
56 { N_ ("Re&gular expression"), MC_SEARCH_T_REGEX },
57 { N_ ("He&xadecimal"), MC_SEARCH_T_HEX },
58 { N_ ("Wil&dcard search"), MC_SEARCH_T_GLOB },
59 { NULL, MC_SEARCH_T_INVALID }
60 };
61
62
63
64
65
66 static mc_search_cond_t *
67 mc_search__cond_struct_new (mc_search_t *lc_mc_search, const GString *str, const char *charset)
68 {
69 mc_search_cond_t *mc_search_cond;
70
71 mc_search_cond = g_malloc0 (sizeof (mc_search_cond_t));
72 mc_search_cond->str = mc_g_string_dup (str);
73 mc_search_cond->charset = g_strdup (charset);
74 #ifdef HAVE_PCRE2
75 lc_mc_search->regex_match_info = pcre2_match_data_create (MC_SEARCH__NUM_REPLACE_ARGS, NULL);
76 lc_mc_search->iovector = pcre2_get_ovector_pointer (lc_mc_search->regex_match_info);
77 #endif
78 switch (lc_mc_search->search_type)
79 {
80 case MC_SEARCH_T_GLOB:
81 mc_search__cond_struct_new_init_glob (charset, lc_mc_search, mc_search_cond);
82 break;
83 case MC_SEARCH_T_NORMAL:
84 mc_search__cond_struct_new_init_normal (charset, lc_mc_search, mc_search_cond);
85 break;
86 case MC_SEARCH_T_REGEX:
87 mc_search__cond_struct_new_init_regex (charset, lc_mc_search, mc_search_cond);
88 break;
89 case MC_SEARCH_T_HEX:
90 mc_search__cond_struct_new_init_hex (charset, lc_mc_search, mc_search_cond);
91 break;
92 default:
93 break;
94 }
95 return mc_search_cond;
96 }
97
98
99
100 static void
101 mc_search__cond_struct_free (gpointer data)
102 {
103 mc_search_cond_t *mc_search_cond = (mc_search_cond_t *) data;
104
105 if (mc_search_cond->upper != NULL)
106 g_string_free (mc_search_cond->upper, TRUE);
107
108 if (mc_search_cond->lower != NULL)
109 g_string_free (mc_search_cond->lower, TRUE);
110
111 g_string_free (mc_search_cond->str, TRUE);
112 g_free (mc_search_cond->charset);
113
114 #ifdef SEARCH_TYPE_GLIB
115 if (mc_search_cond->regex_handle != NULL)
116 g_regex_unref (mc_search_cond->regex_handle);
117 #else
118 g_free (mc_search_cond->regex_handle);
119 #endif
120
121 g_free (mc_search_cond);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135 mc_search_t *
136 mc_search_new (const gchar *original, const gchar *original_charset)
137 {
138 if (original == NULL)
139 return NULL;
140
141 return mc_search_new_len (original, strlen (original), original_charset);
142 }
143
144
145
146
147
148
149
150
151
152
153
154 mc_search_t *
155 mc_search_new_len (const gchar *original, gsize original_len, const gchar *original_charset)
156 {
157 mc_search_t *lc_mc_search;
158
159 if (original == NULL || original_len == 0)
160 return NULL;
161
162 lc_mc_search = g_new0 (mc_search_t, 1);
163 lc_mc_search->original.str = g_string_new_len (original, original_len);
164 #ifdef HAVE_CHARSET
165 lc_mc_search->original.charset = g_strdup (
166 original_charset != NULL && *original_charset != '\0' ? original_charset : cp_display);
167 #else
168 (void) original_charset;
169 #endif
170
171 return lc_mc_search;
172 }
173
174
175
176 void
177 mc_search_free (mc_search_t *lc_mc_search)
178 {
179 if (lc_mc_search == NULL)
180 return;
181
182 g_string_free (lc_mc_search->original.str, TRUE);
183 #ifdef HAVE_CHARSET
184 g_free (lc_mc_search->original.charset);
185 #endif
186 g_free (lc_mc_search->error_str);
187
188 if (lc_mc_search->prepared.conditions != NULL)
189 g_ptr_array_free (lc_mc_search->prepared.conditions, TRUE);
190
191 #ifdef SEARCH_TYPE_GLIB
192 if (lc_mc_search->regex_match_info != NULL)
193 g_match_info_free (lc_mc_search->regex_match_info);
194 #else
195 g_free (lc_mc_search->regex_match_info);
196 #endif
197
198 if (lc_mc_search->regex_buffer != NULL)
199 g_string_free (lc_mc_search->regex_buffer, TRUE);
200
201 g_free (lc_mc_search);
202 }
203
204
205
206 gboolean
207 mc_search_prepare (mc_search_t *lc_mc_search)
208 {
209 GPtrArray *ret;
210
211 if (lc_mc_search->prepared.conditions != NULL)
212 return lc_mc_search->prepared.result;
213
214 ret = g_ptr_array_new_with_free_func (mc_search__cond_struct_free);
215 #ifdef HAVE_CHARSET
216 if (!lc_mc_search->is_all_charsets)
217 g_ptr_array_add (ret,
218 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original.str,
219 lc_mc_search->original.charset));
220 else
221 {
222 gsize loop1;
223
224 for (loop1 = 0; loop1 < codepages->len; loop1++)
225 {
226 const char *id;
227
228 id = ((codepage_desc *) g_ptr_array_index (codepages, loop1))->id;
229 if (g_ascii_strcasecmp (id, lc_mc_search->original.charset) == 0)
230 g_ptr_array_add (ret,
231 mc_search__cond_struct_new (lc_mc_search,
232 lc_mc_search->original.str,
233 lc_mc_search->original.charset));
234 else
235 {
236 GString *buffer;
237
238 buffer = mc_search__recode_str (lc_mc_search->original.str->str,
239 lc_mc_search->original.str->len,
240 lc_mc_search->original.charset, id);
241 g_ptr_array_add (ret, mc_search__cond_struct_new (lc_mc_search, buffer, id));
242 g_string_free (buffer, TRUE);
243 }
244 }
245 }
246 #else
247 g_ptr_array_add (ret,
248 mc_search__cond_struct_new (lc_mc_search, lc_mc_search->original.str,
249 str_detect_termencoding ()));
250 #endif
251 lc_mc_search->prepared.conditions = ret;
252 lc_mc_search->prepared.result = (lc_mc_search->error == MC_SEARCH_E_OK);
253
254 return lc_mc_search->prepared.result;
255 }
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 gboolean
273 mc_search_run (mc_search_t *lc_mc_search, const void *user_data, off_t start_search,
274 off_t end_search, gsize *found_len)
275 {
276 gboolean ret = FALSE;
277
278 if (lc_mc_search == NULL || user_data == NULL)
279 return FALSE;
280 if (!mc_search_is_type_avail (lc_mc_search->search_type))
281 {
282 mc_search_set_error (lc_mc_search, MC_SEARCH_E_INPUT, "%s", _ (STR_E_UNKNOWN_TYPE));
283 return FALSE;
284 }
285 #ifdef SEARCH_TYPE_GLIB
286 if (lc_mc_search->regex_match_info != NULL)
287 {
288 g_match_info_free (lc_mc_search->regex_match_info);
289 lc_mc_search->regex_match_info = NULL;
290 }
291 #endif
292
293 mc_search_set_error (lc_mc_search, MC_SEARCH_E_OK, NULL);
294
295 if (!mc_search_prepare (lc_mc_search))
296 return FALSE;
297
298 switch (lc_mc_search->search_type)
299 {
300 case MC_SEARCH_T_NORMAL:
301 ret = mc_search__run_normal (lc_mc_search, user_data, start_search, end_search, found_len);
302 break;
303 case MC_SEARCH_T_REGEX:
304 ret = mc_search__run_regex (lc_mc_search, user_data, start_search, end_search, found_len);
305 break;
306 case MC_SEARCH_T_GLOB:
307 ret = mc_search__run_glob (lc_mc_search, user_data, start_search, end_search, found_len);
308 break;
309 case MC_SEARCH_T_HEX:
310 ret = mc_search__run_hex (lc_mc_search, user_data, start_search, end_search, found_len);
311 break;
312 default:
313 break;
314 }
315 return ret;
316 }
317
318
319
320 gboolean
321 mc_search_is_type_avail (mc_search_type_t search_type)
322 {
323 switch (search_type)
324 {
325 case MC_SEARCH_T_GLOB:
326 case MC_SEARCH_T_NORMAL:
327 case MC_SEARCH_T_REGEX:
328 case MC_SEARCH_T_HEX:
329 return TRUE;
330 default:
331 break;
332 }
333 return FALSE;
334 }
335
336
337
338 const mc_search_type_str_t *
339 mc_search_types_list_get (size_t *num)
340 {
341
342 if (num != NULL)
343 *num = G_N_ELEMENTS (mc_search__list_types) - 1;
344
345 return mc_search__list_types;
346 }
347
348
349
350 GString *
351 mc_search_prepare_replace_str (mc_search_t *lc_mc_search, GString *replace_str)
352 {
353 GString *ret;
354
355 if (replace_str == NULL || replace_str->len == 0)
356 return g_string_new ("");
357
358 if (lc_mc_search == NULL)
359 return mc_g_string_dup (replace_str);
360
361 switch (lc_mc_search->search_type)
362 {
363 case MC_SEARCH_T_REGEX:
364 ret = mc_search_regex_prepare_replace_str (lc_mc_search, replace_str);
365 break;
366 case MC_SEARCH_T_GLOB:
367 ret = mc_search_glob_prepare_replace_str (lc_mc_search, replace_str);
368 break;
369 case MC_SEARCH_T_NORMAL:
370 ret = mc_search_normal_prepare_replace_str (lc_mc_search, replace_str);
371 break;
372 case MC_SEARCH_T_HEX:
373 ret = mc_search_hex_prepare_replace_str (lc_mc_search, replace_str);
374 break;
375 default:
376 ret = mc_g_string_dup (replace_str);
377 break;
378 }
379 return ret;
380 }
381
382
383
384 char *
385 mc_search_prepare_replace_str2 (mc_search_t *lc_mc_search, const char *replace_str)
386 {
387 GString *ret;
388 GString *replace_str2;
389
390 replace_str2 = g_string_new (replace_str);
391 ret = mc_search_prepare_replace_str (lc_mc_search, replace_str2);
392 g_string_free (replace_str2, TRUE);
393 return (ret != NULL) ? g_string_free (ret, FALSE) : NULL;
394 }
395
396
397
398 gboolean
399 mc_search_is_fixed_search_str (const mc_search_t *lc_mc_search)
400 {
401 if (lc_mc_search == NULL)
402 return FALSE;
403 switch (lc_mc_search->search_type)
404 {
405 case MC_SEARCH_T_REGEX:
406 case MC_SEARCH_T_GLOB:
407 return FALSE;
408 default:
409 return TRUE;
410 }
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424 gboolean
425 mc_search (const gchar *pattern, const gchar *pattern_charset, const gchar *str,
426 mc_search_type_t type)
427 {
428 gboolean ret;
429 mc_search_t *search;
430
431 if (str == NULL)
432 return FALSE;
433
434 search = mc_search_new (pattern, pattern_charset);
435 if (search == NULL)
436 return FALSE;
437
438 search->search_type = type;
439 search->is_case_sensitive = TRUE;
440
441 if (type == MC_SEARCH_T_GLOB)
442 search->is_entire_line = TRUE;
443
444 ret = mc_search_run (search, str, 0, strlen (str), NULL);
445 mc_search_free (search);
446 return ret;
447 }
448
449
450
451 int
452 mc_search_getstart_result_by_num (mc_search_t *lc_mc_search, int lc_index)
453 {
454 if (lc_mc_search == NULL)
455 return 0;
456 if (lc_mc_search->search_type == MC_SEARCH_T_NORMAL)
457 return 0;
458 #ifdef SEARCH_TYPE_GLIB
459 {
460 gint start_pos;
461 gint end_pos;
462
463 g_match_info_fetch_pos (lc_mc_search->regex_match_info, lc_index, &start_pos, &end_pos);
464 return (int) start_pos;
465 }
466 #else
467 return lc_mc_search->iovector[lc_index * 2];
468 #endif
469 }
470
471
472
473 int
474 mc_search_getend_result_by_num (mc_search_t *lc_mc_search, int lc_index)
475 {
476 if (lc_mc_search == NULL)
477 return 0;
478 if (lc_mc_search->search_type == MC_SEARCH_T_NORMAL)
479 return 0;
480 #ifdef SEARCH_TYPE_GLIB
481 {
482 gint start_pos;
483 gint end_pos;
484
485 g_match_info_fetch_pos (lc_mc_search->regex_match_info, lc_index, &start_pos, &end_pos);
486 return (int) end_pos;
487 }
488 #else
489 return lc_mc_search->iovector[lc_index * 2 + 1];
490 #endif
491 }
492
493
494
495
496
497
498
499
500
501
502 void
503 mc_search_set_error (mc_search_t *lc_mc_search, mc_search_error_t code, const gchar *format, ...)
504 {
505 lc_mc_search->error = code;
506
507 MC_PTR_FREE (lc_mc_search->error_str);
508
509 if (format != NULL)
510 {
511 va_list args;
512
513 va_start (args, format);
514 lc_mc_search->error_str = g_strdup_vprintf (format, args);
515 va_end (args);
516 }
517 }
518
519