Skip to content

Commit 499f8e7

Browse files
authored
Merge pull request #399 from bshifter/filterx-regexp-search
Filterx regexp_search rework
2 parents f67223f + ff6d70d commit 499f8e7

File tree

5 files changed

+227
-41
lines changed

5 files changed

+227
-41
lines changed

lib/filterx/expr-regexp.c

+48-12
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@
4141
FILTERX_FUNC_REGEXP_SUBST_FLAG_NEWLINE_NAME"=(boolean)" \
4242
FILTERX_FUNC_REGEXP_SUBST_FLAG_GROUPS_NAME"=(boolean))" \
4343

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))"
4552

4653
typedef struct FilterXReMatchState_
4754
{
@@ -50,6 +57,7 @@ typedef struct FilterXReMatchState_
5057
const gchar *lhs_str;
5158
gsize lhs_str_len;
5259
gint rc;
60+
FLAGSET flags;
5361
} FilterXReMatchState;
5462

5563
static void
@@ -164,14 +172,6 @@ _match(FilterXExpr *lhs_expr, pcre2_code_8 *pattern, FilterXReMatchState *state)
164172
return FALSE;
165173
}
166174

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-
175175
static gboolean
176176
_store_matches_to_list(pcre2_code_8 *pattern, const FilterXReMatchState *state, FilterXObject *fillable)
177177
{
@@ -180,6 +180,8 @@ _store_matches_to_list(pcre2_code_8 *pattern, const FilterXReMatchState *state,
180180

181181
for (gint i = 0; i < num_matches; i++)
182182
{
183+
if (num_matches > 1 && i==0 && !check_flag(state->flags, FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO))
184+
continue;
183185
gint begin_index = matches[2 * i];
184186
gint end_index = matches[2 * i + 1];
185187
if (begin_index < 0 || end_index < 0)
@@ -209,6 +211,9 @@ _store_matches_to_dict(pcre2_code_8 *pattern, const FilterXReMatchState *state,
209211
/* First store all matches with string formatted indexes as keys. */
210212
for (guint32 i = 0; i < num_matches; i++)
211213
{
214+
if (num_matches > 1 && i==0 && !check_flag(state->flags, FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO))
215+
continue;
216+
212217
PCRE2_SIZE begin_index = matches[2 * i];
213218
PCRE2_SIZE end_index = matches[2 * i + 1];
214219
if (begin_index < 0 || end_index < 0)
@@ -385,6 +390,7 @@ typedef struct FilterXExprRegexpSearchGenerator_
385390
FilterXGeneratorFunction super;
386391
FilterXExpr *lhs;
387392
pcre2_code_8 *pattern;
393+
FLAGSET flags;
388394
} FilterXExprRegexpSearchGenerator;
389395

390396
static gboolean
@@ -395,6 +401,7 @@ _regexp_search_generator_generate(FilterXExprGenerator *s, FilterXObject *fillab
395401
gboolean result;
396402
FilterXReMatchState state;
397403
_state_init(&state);
404+
state.flags = self->flags;
398405

399406
gboolean matched = _match(self->lhs, self->pattern, &state);
400407
if (!matched)
@@ -422,10 +429,10 @@ _regexp_search_generator_create_container(FilterXExprGenerator *s, FilterXExpr *
422429
{
423430
FilterXExprRegexpSearchGenerator *self = (FilterXExprRegexpSearchGenerator *) s;
424431

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);
427434

428-
return filterx_generator_create_list_container(s, fillable_parent);
435+
return filterx_generator_create_dict_container(s, fillable_parent);
429436
}
430437

431438
static gboolean
@@ -459,6 +466,29 @@ _regexp_search_generator_free(FilterXExpr *s)
459466
filterx_generator_function_free_method(&self->super);
460467
}
461468

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+
462492
static gboolean
463493
_extract_search_args(FilterXExprRegexpSearchGenerator *self, FilterXFunctionArgs *args, GError **error)
464494
{
@@ -504,6 +534,12 @@ filterx_generator_function_regexp_search_new(FilterXFunctionArgs *args, GError *
504534
self->super.super.super.free_fn = _regexp_search_generator_free;
505535
self->super.super.create_container = _regexp_search_generator_create_container;
506536

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+
507543
if (!_extract_search_args(self, args, error) ||
508544
!filterx_function_args_check(args, error))
509545
goto error;

lib/filterx/expr-regexp.h

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "filterx/filterx-expr.h"
2828
#include "filterx/expr-generator.h"
2929
#include "filterx/expr-function.h"
30+
#include "filterx/func-flags.h"
3031

3132
#define FILTERX_FUNC_REGEXP_SUBST_FLAG_JIT_NAME "jit"
3233
#define FILTERX_FUNC_REGEXP_SUBST_FLAG_GLOBAL_NAME "global"
@@ -35,6 +36,16 @@
3536
#define FILTERX_FUNC_REGEXP_SUBST_FLAG_NEWLINE_NAME "newline"
3637
#define FILTERX_FUNC_REGEXP_SUBST_FLAG_GROUPS_NAME "groups"
3738

39+
DEFINE_FUNC_FLAGS(FilterXRegexpSearchFlags,
40+
FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO,
41+
FILTERX_REGEXP_SEARCH_LIST_MODE
42+
);
43+
44+
#define FILTERX_REGEXP_SEARCH_KEEP_GRP_ZERO_NAME "keep_zero"
45+
#define FILTERX_REGEXP_SEARCH_LIST_MODE_NAME "list_mode"
46+
47+
extern const char *FilterXRegexpSearchFlags_NAMES[];
48+
3849
typedef struct FilterXFuncRegexpSubstOpts_
3950
{
4051
gboolean global;

lib/filterx/func-flags.h

+12-5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include "syslog-ng.h"
2929

30+
#define FLAGSET guint64
31+
3032
#define MAX_ENUMS 64
3133

3234
#define STATIC_ASSERT(COND) G_STATIC_ASSERT(COND)
@@ -35,14 +37,19 @@
3537
typedef enum { __VA_ARGS__, ENUM_NAME##_MAX} ENUM_NAME; \
3638
STATIC_ASSERT(ENUM_NAME##_MAX <= MAX_ENUMS) \
3739

38-
#define FUNC_FLAGS_ITER(ENUM_NAME, CODE) for (guint64 enum_elt = 0; enum_elt < ENUM_NAME##_MAX; enum_elt++) { CODE; };
40+
#define DEFINE_FUNC_FLAG_NAMES(ENUM_NAME, ...) \
41+
const char *ENUM_NAME##_NAMES[] = { \
42+
__VA_ARGS__ \
43+
};
44+
45+
#define FUNC_FLAGS_ITER(ENUM_NAME, CODE) for (FLAGSET enum_elt = 0; enum_elt < ENUM_NAME##_MAX; enum_elt++) { CODE; };
3946

4047
#define FLAG_VAL(ID) (1 << ID)
4148

4249
#define ALL_FLAG_SET(ENUM_NAME) (FLAG_VAL(ENUM_NAME##_MAX) - 1)
4350

4451
static inline void
45-
set_flag(guint64 *flags, guint64 flag, gboolean val)
52+
set_flag(FLAGSET *flags, FLAGSET flag, gboolean val)
4653
{
4754
if (val)
4855
{
@@ -55,19 +62,19 @@ set_flag(guint64 *flags, guint64 flag, gboolean val)
5562
}
5663

5764
static inline gboolean
58-
check_flag(guint64 flags, guint64 flag)
65+
check_flag(FLAGSET flags, FLAGSET flag)
5966
{
6067
return (flags & FLAG_VAL(flag)) != 0;
6168
}
6269

6370
static inline void
64-
reset_flags(guint64 *flags, guint64 val)
71+
reset_flags(FLAGSET *flags, FLAGSET val)
6572
{
6673
*flags = val;
6774
}
6875

6976
static inline gboolean
70-
toggle_flag(guint64 *flags, guint64 flag)
77+
toggle_flag(FLAGSET *flags, FLAGSET flag)
7178
{
7279
*flags ^= FLAG_VAL(flag);
7380
return (*flags & FLAG_VAL(flag)) != 0;

0 commit comments

Comments
 (0)