41
41
FILTERX_FUNC_REGEXP_SUBST_FLAG_NEWLINE_NAME"=(boolean)" \
42
42
FILTERX_FUNC_REGEXP_SUBST_FLAG_GROUPS_NAME"=(boolean))" \
43
43
44
- #define FILTERX_FUNC_REGEXP_SEARCH_USAGE "Usage: regexp_search(string, pattern)"
44
+ DEFINE_FUNC_FLAG_NAMES (FilterXRegexpSearchFlags ,
45
+ FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO_NAME ,
46
+ FILTERX_REGEXP_SEARCH_LIST_MODE_NAME
47
+ );
48
+
49
+ #define FILTERX_FUNC_REGEXP_SEARCH_USAGE "Usage: regexp_search(string, pattern, " \
50
+ FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO_NAME"=(boolean), "\
51
+ FILTERX_REGEXP_SEARCH_LIST_MODE_NAME"=(boolean))"
45
52
46
53
typedef struct FilterXReMatchState_
47
54
{
@@ -50,6 +57,7 @@ typedef struct FilterXReMatchState_
50
57
const gchar * lhs_str ;
51
58
gsize lhs_str_len ;
52
59
gint rc ;
60
+ FLAGSET flags ;
53
61
} FilterXReMatchState ;
54
62
55
63
static void
@@ -164,14 +172,6 @@ _match(FilterXExpr *lhs_expr, pcre2_code_8 *pattern, FilterXReMatchState *state)
164
172
return FALSE;
165
173
}
166
174
167
- static gboolean
168
- _has_named_capture_groups (pcre2_code_8 * pattern )
169
- {
170
- guint32 namecount = 0 ;
171
- pcre2_pattern_info (pattern , PCRE2_INFO_NAMECOUNT , & namecount );
172
- return namecount > 0 ;
173
- }
174
-
175
175
static gboolean
176
176
_store_matches_to_list (pcre2_code_8 * pattern , const FilterXReMatchState * state , FilterXObject * fillable )
177
177
{
@@ -180,6 +180,8 @@ _store_matches_to_list(pcre2_code_8 *pattern, const FilterXReMatchState *state,
180
180
181
181
for (gint i = 0 ; i < num_matches ; i ++ )
182
182
{
183
+ if (num_matches > 1 && i == 0 && !check_flag (state -> flags , FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO ))
184
+ continue ;
183
185
gint begin_index = matches [2 * i ];
184
186
gint end_index = matches [2 * i + 1 ];
185
187
if (begin_index < 0 || end_index < 0 )
@@ -209,6 +211,9 @@ _store_matches_to_dict(pcre2_code_8 *pattern, const FilterXReMatchState *state,
209
211
/* First store all matches with string formatted indexes as keys. */
210
212
for (guint32 i = 0 ; i < num_matches ; i ++ )
211
213
{
214
+ if (num_matches > 1 && i == 0 && !check_flag (state -> flags , FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO ))
215
+ continue ;
216
+
212
217
PCRE2_SIZE begin_index = matches [2 * i ];
213
218
PCRE2_SIZE end_index = matches [2 * i + 1 ];
214
219
if (begin_index < 0 || end_index < 0 )
@@ -385,6 +390,7 @@ typedef struct FilterXExprRegexpSearchGenerator_
385
390
FilterXGeneratorFunction super ;
386
391
FilterXExpr * lhs ;
387
392
pcre2_code_8 * pattern ;
393
+ FLAGSET flags ;
388
394
} FilterXExprRegexpSearchGenerator ;
389
395
390
396
static gboolean
@@ -395,6 +401,7 @@ _regexp_search_generator_generate(FilterXExprGenerator *s, FilterXObject *fillab
395
401
gboolean result ;
396
402
FilterXReMatchState state ;
397
403
_state_init (& state );
404
+ state .flags = self -> flags ;
398
405
399
406
gboolean matched = _match (self -> lhs , self -> pattern , & state );
400
407
if (!matched )
@@ -422,10 +429,10 @@ _regexp_search_generator_create_container(FilterXExprGenerator *s, FilterXExpr *
422
429
{
423
430
FilterXExprRegexpSearchGenerator * self = (FilterXExprRegexpSearchGenerator * ) s ;
424
431
425
- if (_has_named_capture_groups (self -> pattern ))
426
- return filterx_generator_create_dict_container (s , fillable_parent );
432
+ if (check_flag (self -> flags , FILTERX_REGEXP_SEARCH_LIST_MODE ))
433
+ return filterx_generator_create_list_container (s , fillable_parent );
427
434
428
- return filterx_generator_create_list_container (s , fillable_parent );
435
+ return filterx_generator_create_dict_container (s , fillable_parent );
429
436
}
430
437
431
438
static gboolean
@@ -459,6 +466,29 @@ _regexp_search_generator_free(FilterXExpr *s)
459
466
filterx_generator_function_free_method (& self -> super );
460
467
}
461
468
469
+ static gboolean
470
+ _extract_optional_arg_flag (FilterXExprRegexpSearchGenerator * self , FilterXRegexpSearchFlags flag ,
471
+ FilterXFunctionArgs * args , GError * * error )
472
+ {
473
+ gboolean exists , eval_error ;
474
+ g_assert (flag < FilterXRegexpSearchFlags_MAX );
475
+ const gchar * arg_name = FilterXRegexpSearchFlags_NAMES [flag ];
476
+ gboolean value = filterx_function_args_get_named_literal_boolean (args , arg_name , & exists , & eval_error );
477
+ if (!exists )
478
+ return TRUE;
479
+
480
+ if (eval_error )
481
+ {
482
+ g_set_error (error , FILTERX_FUNCTION_ERROR , FILTERX_FUNCTION_ERROR_CTOR_FAIL ,
483
+ "%s argument must be boolean literal. " FILTERX_FUNC_REGEXP_SEARCH_USAGE , arg_name );
484
+ return FALSE;
485
+ }
486
+
487
+ set_flag (& self -> flags , flag , value );
488
+
489
+ return TRUE;
490
+ }
491
+
462
492
static gboolean
463
493
_extract_search_args (FilterXExprRegexpSearchGenerator * self , FilterXFunctionArgs * args , GError * * error )
464
494
{
@@ -504,6 +534,12 @@ filterx_generator_function_regexp_search_new(FilterXFunctionArgs *args, GError *
504
534
self -> super .super .super .free_fn = _regexp_search_generator_free ;
505
535
self -> super .super .create_container = _regexp_search_generator_create_container ;
506
536
537
+ if (!_extract_optional_arg_flag (self , FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO , args , error ))
538
+ goto error ;
539
+
540
+ if (!_extract_optional_arg_flag (self , FILTERX_REGEXP_SEARCH_LIST_MODE , args , error ))
541
+ goto error ;
542
+
507
543
if (!_extract_search_args (self , args , error ) ||
508
544
!filterx_function_args_check (args , error ))
509
545
goto error ;
0 commit comments