59 #include <sys/resource.h>
67 #include <amxc/amxc.h>
68 #include <amxc/amxc_macros.h>
71 #include "amxp_expr.tab.h"
73 #define REGEXP_STORE_SIZE 40
97 amxc_htable_it_clean(&amxp_regexp->
hit, NULL);
98 regfree(&amxp_regexp->
regexp);
104 amxc_htable_it_t* it = amxc_htable_get(&
regexp_store, regexp_str);
124 amxc_htable_it_t* it) {
130 amxc_htable_it_t* it) {
139 result = amxc_rbuffer_read(&expr->
rbuffer, (
char*) buf, max_size);
147 amxc_var_t* rvalue) {
150 char* regexp_str = NULL;
151 char* value_str = NULL;
153 regexp_str = amxc_var_dyncast(cstring_t, rvalue);
154 value_str = amxc_var_dyncast(cstring_t, lvalue);
160 if(regcomp(®exp->
regexp, regexp_str, REG_EXTENDED) != 0) {
174 if(regexec(®exp->
regexp, value_str, 0, NULL, 0) == 0) {
193 when_true(rlength > llength, exit);
198 offset = llength - rlength;
200 retval = strncmp(lstr + offset, rstr, rlength) == 0;
210 char* lstr = amxc_var_dyncast(cstring_t, lvalue);
212 size_t llength = strlen(lstr);
214 if(amxc_var_type_of(rvalue) == AMXC_VAR_ID_LIST) {
215 amxc_var_for_each(var, rvalue) {
217 rstr = amxc_var_dyncast(cstring_t, var);
218 rlength = strlen(rstr);
227 rstr = amxc_var_dyncast(cstring_t, rvalue);
228 rlength = strlen(rstr);
237 amxc_var_t* rvalue) {
238 const amxc_llist_t* list = amxc_var_constcast(amxc_llist_t, rvalue);
242 amxc_llist_for_each(it, list) {
243 amxc_var_t* item = amxc_var_from_llist_it(it);
244 int amxc_rv = amxc_var_compare(lvalue, item, &result);
245 if((amxc_rv == 0) && (result == 0)) {
255 amxc_var_t* rvalue) {
256 const char*
string = amxc_var_constcast(cstring_t, rvalue);
257 int rlength = strlen(
string);
258 char* lstr = amxc_var_dyncast(cstring_t, lvalue);
259 int llength = strlen(lstr);
262 if(llength <= rlength) {
263 for(
int i = 0; i <= rlength - llength; i++) {
264 if(strncmp(lstr,
string + i, llength) == 0) {
276 amxc_var_t* rvalue) {
278 char* lvalue_str = NULL;
279 char* rvalue_str = NULL;
281 lvalue_str = amxc_var_dyncast(cstring_t, lvalue);
282 rvalue_str = amxc_var_dyncast(cstring_t, rvalue);
284 retval = 0 == strcasecmp(lvalue_str, rvalue_str);
293 int type = amxc_var_type_of(value);
294 return !(type == AMXC_VAR_ID_HTABLE || type == AMXC_VAR_ID_LIST);
298 amxc_var_t* rvalue) {
305 amxc_var_t* rvalue) {
306 int rtype = amxc_var_type_of(rvalue);
315 case AMXC_VAR_ID_LIST:
318 case AMXC_VAR_ID_CSTRING:
321 case AMXC_VAR_ID_SSV_STRING:
322 case AMXC_VAR_ID_CSV_STRING:
323 amxc_var_cast(rvalue, AMXC_VAR_ID_LIST);
326 case AMXC_VAR_ID_BOOL:
344 retval = (result == 0);
347 retval = (result != 0);
350 retval = (result < 0);
353 retval = (result > 0);
356 retval = (result <= 0);
359 retval = (result >= 0);
371 amxc_var_t* data = NULL;
372 amxc_llist_for_each(it, (&args->data.vl)) {
373 data = amxc_var_from_llist_it(it);
374 if(!amxc_var_is_null(data)) {
380 when_null(data, exit);
381 amxc_var_copy(ret, data);
392 amxc_llist_it_t* it = amxc_llist_get_first(&args->data.vl);
393 amxc_var_t* data = amxc_var_from_llist_it(it);
395 if(amxc_var_is_null(data)) {
399 if((amxc_var_type_of(data) == AMXC_VAR_ID_LIST) &&
400 amxc_llist_is_empty(&data->data.vl)) {
404 if((amxc_var_type_of(data) == AMXC_VAR_ID_HTABLE) &&
405 amxc_htable_is_empty(&data->data.vm)) {
415 amxc_var_t* data = (amxc_var_t*) expr->
priv;
416 const char*
path = NULL;
417 amxc_var_t field_value;
420 amxc_var_init(&field_value);
421 when_null(data, exit);
424 amxc_var_for_each(field_var, args) {
425 if(amxc_var_type_of(field_var) != AMXC_VAR_ID_CSTRING) {
429 path = amxc_var_constcast(cstring_t, field_var);
439 amxc_var_clean(&field_value);
447 for(
const char* c =
string; *c !=
'\0'; c++) {
448 bool is_whitelisted =
451 || (*c >=
'#' && *c <=
'&')
452 || (*c >=
'(' && *c <=
'[')
453 || (*c >=
']' && *c <=
'_')
454 || (*c >=
'a' && *c <=
'~');
455 if(!is_whitelisted) {
465 when_null(expr, exit);
473 amxc_rbuffer_write(&expr->
rbuffer,
477 amxc_rbuffer_write(&expr->
rbuffer,
";", 2);
484 yyparse_rv = yyparse(expr->
scanner);
487 if(yyparse_rv != 0) {
491 while(node != NULL) {
497 amxc_rbuffer_clean(&expr->
rbuffer);
506 va_start(args, format);
507 amxc_string_vsetf(&expr->
msg, format, args);
513 va_start(args, format);
514 vfprintf(stderr, format, args);
554 amxc_var_compare(lvalue, rvalue, &result);
571 amxc_htable_it_t* it = amxc_htable_get(&
value_funcs, func);
579 expr->
status = fn->
fn(expr, args, ret);
590 amxc_htable_it_t* it = amxc_htable_get(&
bool_funcs, func);
599 retval = fn->
fn(expr, args);
612 amxc_var_clean(value);
614 amxc_var_set(
bool, value,
true);
620 retval = fn(expr, value,
path, expr->
priv);
623 if(amxc_var_is_null(value)) {
635 when_null(expr, exit);
636 when_null(expression, exit);
639 when_null((*expr), exit);
644 if((retval != 0) && (expr != NULL) && (*expr != NULL)) {
653 when_null(expr, exit);
654 when_null(*expr, exit);
665 const char* expr_fmt,
668 when_null(expr, exit);
669 when_null(expr_fmt, exit);
672 when_null((*expr), exit);
677 if((retval != 0) && (expr != NULL) && (*expr != NULL)) {
686 const char* expr_fmt,
690 va_start(args, expr_fmt);
697 const char* expression) {
699 when_null(expr, exit);
705 amxc_rbuffer_init(&expr->
rbuffer, 0);
706 amxc_string_init(&expr->
msg, 0);
707 amxc_lstack_init(&expr->
nodes);
709 when_null(expression, exit);
726 amxc_lqueue_clean(&expr->
nodes, NULL);
733 const char* expr_fmt,
737 amxc_string_t expression;
739 amxc_string_init(&expression, 0);
741 when_null(expr, exit);
742 when_null(expr_fmt, exit);
751 amxc_string_clean(&expression);
756 const char* expr_fmt,
760 va_start(args, expr_fmt);
768 when_null(expr, exit);
775 amxc_lstack_clean(&expr->
nodes, NULL);
776 amxc_rbuffer_clean(&expr->
rbuffer);
777 amxc_string_clean(&expr->
msg);
794 when_null_status(expr, exit, rv =
false);
808 if((status != NULL) && (expr != NULL)) {
828 when_true(amxc_htable_contains(&
value_funcs, fn_name), exit);
830 when_null(vfn, exit);
847 when_true(amxc_htable_contains(&
bool_funcs, fn_name), exit);
849 when_null(bfn, exit);
851 retval = amxc_htable_insert(&
bool_funcs, fn_name, &bfn->
hit);
PRIVATE void amxp_expr_create_lex(amxp_expr_t *expr)
PRIVATE amxp_expr_node_t * amxp_expr_get_node(amxp_expr_t *expr)
enum _amxp_expr_comp amxp_expr_comp_t
PRIVATE void amxp_expr_node_delete(amxp_expr_node_t **node)
PRIVATE void amxp_expr_node_dump(amxp_expr_t *expr, amxp_expr_node_t *node, uint32_t level, uint32_t parent_id)
PRIVATE void amxp_expr_destroy_lex(amxp_expr_t *expr)
PRIVATE amxp_expr_node_t * amxp_expr_node_pop(amxc_lstack_t *stack)
PRIVATE bool amxp_expr_node_eval(amxp_expr_t *expr, amxp_expr_node_t *node)
@ amxp_expr_comp_bigger_equal
@ amxp_expr_comp_ends_with
@ amxp_expr_comp_starts_with
@ amxp_expr_comp_equals_ignorecase
@ amxp_expr_comp_not_equal
@ amxp_expr_comp_contains
@ amxp_expr_comp_lesser_equal
static bool amxp_expr_in_string(amxc_var_t *lvalue, amxc_var_t *rvalue)
struct _amxp_expr_vfunc amxp_expr_vfunc_t
static bool amxp_expr_equals_ignorecase(amxc_var_t *lvalue, amxc_var_t *rvalue)
static bool amxp_expr_string_head_tail_check(amxc_var_t *lvalue, amxc_var_t *rvalue, amxp_expr_comp_t comperator)
static bool amxp_expr_in_list(amxc_var_t *lvalue, amxc_var_t *rvalue)
void amxp_expr_msg(amxp_expr_t *expr, const char *format,...)
amxp_expr_status_t amxp_expr_buildf_new(amxp_expr_t **expr, const char *expr_fmt,...)
static void amxp_expr_bfunc_hit_free(UNUSED const char *key, amxc_htable_it_t *it)
struct _amxp_regexp amxp_regexp_t
static bool _bool_contains(amxp_expr_t *expr, amxc_var_t *args)
int amxp_expr_printf(const char *format,...)
static bool amxp_expr_in(amxp_expr_t *expr, amxc_var_t *lvalue, amxc_var_t *rvalue)
static void amxp_expr_vfunc_hit_free(UNUSED const char *key, amxc_htable_it_t *it)
bool amxp_expr_compare(amxp_expr_t *expr, amxc_var_t *lvalue, amxc_var_t *rvalue, amxp_expr_comp_t comperator)
static bool amxp_expr_is_simple_type(amxc_var_t *value)
static bool amxp_expr_is_safe_value(const char *string)
static amxc_htable_t value_funcs
static amxp_expr_status_t _value_first_of(UNUSED amxp_expr_t *expr, amxc_var_t *args, amxc_var_t *ret)
static void amxp_regexp_clean(amxc_llist_it_t *it)
static amxp_expr_status_t amxp_expr_parse(amxp_expr_t *expr)
static amxc_htable_t bool_funcs
static ssize_t amxp_expr_string_reader(amxp_expr_t *expr, void *buf, size_t max_size)
amxp_expr_status_t amxp_expr_call_value_func(amxp_expr_t *expr, const char *func, amxc_var_t *args, amxc_var_t *ret)
static bool amxp_expr_are_simple_types(amxc_var_t *lvalue, amxc_var_t *rvalue)
static bool _bool_is_empty(UNUSED amxp_expr_t *expr, amxc_var_t *args)
static amxc_htable_t regexp_store
struct _amxp_expr_bfunc amxp_expr_bfunc_t
static amxp_regexp_t * amxp_regexp_get(const char *regexp_str)
static DESTRUCTOR void amxp_regexp_store_cleanup(void)
amxp_expr_status_t amxp_expr_get_field(amxp_expr_t *expr, amxc_var_t *value, const char *path)
amxp_expr_status_t amxp_expr_buildf(amxp_expr_t *expr, const char *expr_fmt,...)
static CONSTRUCTOR void amxp_regexp_store_init(void)
static bool amxp_expr_match_regexp(amxp_expr_t *expr, amxc_var_t *lvalue, amxc_var_t *rvalue)
static bool amxp_expr_comperator(int result, amxp_expr_comp_t type)
static bool amxp_expr_string_check(const char *lstr, size_t llength, const char *rstr, size_t rlength, amxp_expr_comp_t comperator)
bool amxp_expr_call_bool_func(amxp_expr_t *expr, const char *func, amxc_var_t *args)
#define REGEXP_STORE_SIZE
static amxc_llist_t regexp_store_list
const char * amxp_expr_get_string(amxp_expr_t *expr)
Returns the string representation of the given expression.
amxp_expr_status_t amxp_expr_new(amxp_expr_t **expr, const char *expression)
Allocates and initializes an expression.
bool amxp_expr_eval(amxp_expr_t *expr, amxp_expr_status_t *status)
Evaluates an expression.
amxp_expr_status_t amxp_expr_vbuildf(amxp_expr_t *expr, const char *expr_fmt, va_list args)
va_list version of amxp_expr_buildf
void amxp_expr_clean(amxp_expr_t *expr)
Clean-up the expression structure.
amxp_expr_status_t amxp_expr_vbuildf_new(amxp_expr_t **expr, const char *expr_fmt, va_list args)
va_list version of amxp_expr_buildf_new
amxp_expr_status_t(* amxp_expr_get_field_t)(amxp_expr_t *expr, amxc_var_t *value, const char *path, void *priv)
Field fetcher function signature.
bool(* amxp_expr_bool_func_t)(amxp_expr_t *expr, amxc_var_t *args)
Callback function that evaluates to true or false.
int amxp_expr_add_value_fn(const char *fn_name, amxp_expr_value_func_t fn)
Adds a value calculation function.
amxp_expr_status_t(* amxp_expr_value_func_t)(amxp_expr_t *expr, amxc_var_t *args, amxc_var_t *ret)
Callback function that can "calculate" a value.
amxp_expr_status_t amxp_expr_init(amxp_expr_t *expr, const char *expression)
Initializes an expression structure.
bool amxp_expr_evaluate(amxp_expr_t *expr, amxp_expr_get_field_t fn, void *priv, amxp_expr_status_t *status)
Evaluates an expression.
int amxp_expr_add_bool_fn(const char *fn_name, amxp_expr_bool_func_t fn)
Adds a boolean evaluation function.
void amxp_expr_dump_tree(amxp_expr_t *expr)
Dumps the binary tree in dot formatted text file to stdout.
enum _expr_status amxp_expr_status_t
Expression status/error codes.
void amxp_expr_delete(amxp_expr_t **expr)
Deletes a previously allocated expression structure.
@ amxp_expr_status_syntax_error
@ amxp_expr_status_invalid_value
@ amxp_expr_status_field_not_found
@ amxp_expr_status_unknown_error
@ amxp_expr_status_function_not_found
@ amxp_expr_status_invalid_regexp
amxp_expr_value_func_t fn
amxp_expr_get_field_t get_field
amxp_expr_reader_t reader
amxp_expr_status_t status
static amxc_string_t path