diff --git a/bindings/python/cconfigspace/expression.py b/bindings/python/cconfigspace/expression.py index b47f31a5..58ff763f 100644 --- a/bindings/python/cconfigspace/expression.py +++ b/bindings/python/cconfigspace/expression.py @@ -24,7 +24,8 @@ class ExpressionType(CEnumeration): 'IN', 'LIST', 'LITERAL', - 'VARIABLE' ] + 'VARIABLE', + 'USER_DEFINED' ] class AssociativityType(CEnumeration): _members_ = [ @@ -476,6 +477,163 @@ def __str__(self): Expression.List = ExpressionList +ccs_user_defined_expression_del_type = ct.CFUNCTYPE(Result, ccs_expression) +ccs_user_defined_expression_eval_type = ct.CFUNCTYPE(Result, ccs_expression, ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(Datum)) +ccs_user_defined_expression_serialize_type = ct.CFUNCTYPE(Result, ccs_expression, ct.c_size_t, ct.c_void_p, ct.POINTER(ct.c_size_t)) +ccs_user_defined_expression_deserialize_type = ct.CFUNCTYPE(Result, ct.c_size_t, ct.c_void_p, ct.POINTER(ct.c_void_p)) + +class UserDefinedExpressionVector(ct.Structure): + _fields_ = [ + ('delete', ccs_user_defined_expression_del_type), + ('evaluate', ccs_user_defined_expression_eval_type), + ('serialize', ccs_user_defined_expression_serialize_type), + ('deserialize', ccs_user_defined_expression_deserialize_type) ] + +ccs_create_user_defined_expression = _ccs_get_function("ccs_create_user_defined_expression", [ct.c_char_p, ct.c_size_t, ct.POINTER(Datum), ct.POINTER(UserDefinedExpressionVector), ct.py_object, ct.POINTER(ccs_expression)]) +ccs_user_defined_expression_get_name = _ccs_get_function("ccs_user_defined_expression_get_name", [ccs_expression, ct.POINTER(ct.c_char_p)]) +ccs_user_defined_expresion_get_expression_data = _ccs_get_function("ccs_user_defined_expression_get_expression_data", [ccs_expression, ct.POINTER(ct.c_void_p)]) + +class ExpressionUserDefined(Expression): + def __init__(self, handle = None, retain = False, auto_release = True, + name = "", nodes = [], delete = None, evaluate = None, serialize = None, deserialize = None, expression_data = None): + if handle is None: + if evaluate is None: + raise Error(Result(Result.ERROR_INVALID_VALUE)) + + vec = self.get_vector(delete, evaluate, serialize, deserialize) + c_expression_data = None + if expression_data is not None: + c_expression_data = ct.py_object(expression_data) + handle = ccs_expression() + sz = len(nodes) + v = (Datum*sz)() + ss = [] + for i in range(sz): + v[i].set_value(values[i], string_store = ss) + res = ccs_create_user_defined_expression(str.encode(name), sz, v, ct.byref(vec), c_expression_data, ct.byref(handle)) + Error.check(res) + super().__init__(handle = handle, retain = False) + ct.pythonapi.Py_IncRef(ct.py_object(vec)) + if c_expression_data is not None: + ct.pythonapi.Py_IncRef(c_expression_data) + else: + super().__init__(handle = handle, retain = retain, auto_release = auto_release) + + @property + def name(self): + if hasattr(self, "_name"): + return self._name + v = ct.c_char_p() + res = ccs_expression_get_name(self.handle, ct.byref(v)) + Error.check(res) + self._name = v.value.decode() + return self._name + + @property + def expression_data(self): + if hasattr(self, "_expression_data"): + return self._expression_data + v = ct.c_void_p() + res = ccs_user_defined_expression_get_expression_data(self.handle, ct.byref(v)) + Error.check(res) + if v: + self._expression_data = ct.cast(v, ct.py_object).value + else: + self._expression_data = None + return self._expression_data + + @classmethod + def get_vector(self, delete = None, evaluate = None, serialize = None, deserialize = None): + vec = UserDefinedExpressionVector() + setattr(vec, '_string_store', list()) + setattr(vec, '_object_store', list()) + def delete_wrapper(expr): + try: + expr = ct.cast(expr, ccs_expression) + o = Object.from_handle(expr) + edata = o.expression_data + if delete is not None: + delete(o) + if edata is not None: + ct.pythonapi.Py_DecRef(ct.py_object(edata)) + ct.pythonapi.Py_DecRef(ct.py_object(vec)) + return Result.SUCCESS + except Exception as e: + return Error.set_error(e) + + def evaluate_wrapper(expr, num_values, p_values, p_value_ret): + try: + expr = ct.cast(expr, ccs_expression) + if num_values == 0: + value_ret = evaluate(Expression.from_handle(expr)) + else: + values = tuple(p_values[i] for i in range(num_values)) + value_ret = evaluate(Expression.from_handle(expr), *values) + p_value_ret[0].set_value(value_ret, string_store = getattr(vec, '_string_store'), object_store = getattr(vec, '_object_store')) + return Result.SUCCESS + except Exception as e: + return Error.set_error(e) + + if serialize is not None: + def serialize_wrapper(expr, state_size, p_state, p_state_size): + try: + expr = ct.cast(expr, ccs_expression) + p_s = ct.cast(p_state, ct.c_void_p) + p_sz = ct.cast(p_state_size, ct.c_void_p) + state = serialize(Expression.from_handle(expr), True if state_size == 0 else False) + if p_s.value is not None and state_size < ct.sizeof(state): + raise Error(Result(Result.ERROR_INVALID_VALUE)) + if p_s.value is not None: + ct.memmove(p_s, ct.byref(state), ct.sizeof(state)) + if p_sz.value is not None: + p_state_size[0] = ct.sizeof(state) + return Result.SUCCESS + except Exception as e: + return Error.set_error(e) + else: + serialize_wrapper = 0 + + if deserialize is not None: + def deserialize_wrapper(state_size, p_state, p_expression_data): + try: + p_s = ct.cast(p_state, ct.c_void_p) + p_e = ct.cast(p_expression_data, ct.c_void_p) + if p_s.value is None: + state = None + else: + state = ct.cast(p_s, POINTER(c_byte * state_size)) + expression_data = deserialize(state) + c_expression_data = ct.py_object(expression_data) + p_e[0] = c_expression_data + ct.pythonapi.Py_IncRef(c_expression_data) + return Result.SUCCESS + except Exception as e: + return Error.set_error(e) + else: + deserialize_wrapper = 0 + + delete_wrapper_func = ccs_user_defined_expression_del_type(delete_wrapper) + evaluate_wrapper_func = ccs_user_defined_expression_eval_type(evaluate_wrapper) + serialize_wrapper_func = ccs_user_defined_expression_serialize_type(serialize_wrapper) + deserialize_wrapper_func = ccs_user_defined_expression_deserialize_type(deserialize_wrapper) + vec.delete = delete_wrapper_func + vec.evaluate = evaluate_wrapper_func + vec.serialize = serialize_wrapper_func + vec.deserialize = deserialize_wrapper_func + + setattr(vec, '_wrappers', ( + delete_wrapper, + evaluate_wrapper, + serialize_wrapper, + deserialize_wrapper, + delete_wrapper_func, + evaluate_wrapper_func, + serialize_wrapper_func, + deserialize_wrapper_func)) + return vec + +Expression.UserDefined = ExpressionUserDefined + setattr(Expression, 'EXPRESSION_MAP', { ExpressionType.OR: ExpressionOr, ExpressionType.AND: ExpressionAnd, @@ -497,4 +655,5 @@ def __str__(self): ExpressionType.LIST: ExpressionList, ExpressionType.LITERAL: ExpressionLiteral, ExpressionType.VARIABLE: ExpressionVariable, + ExpressionType.USER_DEFINED: ExpressionUserDefined, }) diff --git a/bindings/ruby/lib/cconfigspace/expression.rb b/bindings/ruby/lib/cconfigspace/expression.rb index af7c980a..fab24df7 100644 --- a/bindings/ruby/lib/cconfigspace/expression.rb +++ b/bindings/ruby/lib/cconfigspace/expression.rb @@ -19,7 +19,8 @@ module CCS :CCS_EXPRESSION_TYPE_IN, :CCS_EXPRESSION_TYPE_LIST, :CCS_EXPRESSION_TYPE_LITERAL, - :CCS_EXPRESSION_TYPE_VARIABLE + :CCS_EXPRESSION_TYPE_VARIABLE, + :CCS_EXPRESSION_TYPE_USER_DEFINED, ] class MemoryPointer def read_ccs_expression_type_t @@ -115,7 +116,8 @@ def self.expression_map CCS_EXPRESSION_TYPE_IN: In, CCS_EXPRESSION_TYPE_LIST: List, CCS_EXPRESSION_TYPE_LITERAL: Literal, - CCS_EXPRESSION_TYPE_VARIABLE: Variable + CCS_EXPRESSION_TYPE_VARIABLE: Variable, +# CCS_EXPRESSION_TYPE_USER_DEFINED: UserDefined } end diff --git a/include/cconfigspace/expression.h b/include/cconfigspace/expression.h index 5ae4af4a..17c24adf 100644 --- a/include/cconfigspace/expression.h +++ b/include/cconfigspace/expression.h @@ -57,6 +57,8 @@ enum ccs_expression_type_e { CCS_EXPRESSION_TYPE_LITERAL, /** Variable */ CCS_EXPRESSION_TYPE_VARIABLE, + /** User defined */ + CCS_EXPRESSION_TYPE_USER_DEFINED, /** Guard */ CCS_EXPRESSION_TYPE_MAX, /** Try forcing 32 bits value for bindings */ @@ -79,7 +81,7 @@ typedef enum ccs_expression_type_e ccs_expression_type_t; * - 6 : POSITIVE, NEGATIVE, NOT * - 7 : IN * - max - 1: LIST - * - max : LITERAL, VARIABLE + * - max : LITERAL, VARIABLE, USER_DEFINED * * Those are similar to C's precedence */ @@ -117,7 +119,7 @@ typedef enum ccs_associativity_type_e ccs_associativity_type_t; * - right: POSITIVE, NEGATIVE, NOT * - left: IN * - left: LIST - * - none: LITERAL, VARIABLE + * - none: LITERAL, VARIABLE, USER_DEFINED */ extern const ccs_associativity_type_t ccs_expression_associativity[]; @@ -143,6 +145,7 @@ extern const ccs_associativity_type_t ccs_expression_associativity[]; * - LIST: NULL * - LITERAL: NULL * - VARIABLE: NULL + * - USER_DEFINED: NULL */ extern const char *ccs_expression_symbols[]; @@ -158,6 +161,7 @@ extern const char *ccs_expression_symbols[]; * - 2: IN * - -1: LIST * - 0: LITERAL, VARIABLE + * - -1: USER_DEFINED */ extern const int ccs_expression_arity[]; @@ -349,6 +353,87 @@ ccs_create_literal(ccs_datum_t value, ccs_expression_t *expression_ret); extern ccs_result_t ccs_create_variable(ccs_parameter_t parameter, ccs_expression_t *expression_ret); +/** + * A structure that define the callbacks the user must provide to create a user + * defined expression. + */ +struct ccs_user_defined_expression_vector_s { + /** + * The deletion callback that will be called once the reference count + * of the expression reaches 0. + */ + ccs_result_t (*del)(ccs_expression_t expression); + + /** + * The expression evaluation interface. + */ + ccs_result_t (*eval)( + ccs_expression_t expression, + size_t num_values, + ccs_datum_t *values, + ccs_datum_t *value_ret); + + /** + * The expression serialization interface, can be NULL. + */ + ccs_result_t (*serialize_user_state)( + ccs_expression_t expression, + size_t sate_size, + void *state, + size_t *state_size_ret); + + /** + * The expression deserialization interface, can be NULL. + */ + ccs_result_t (*deserialize_state)( + size_t state_size, + const void *state, + void **expression_data_ret); +}; + +/** + * a commodity type to represent a user defined expression callback vector. + */ +typedef struct ccs_user_defined_expression_vector_s + ccs_user_defined_expression_vector_t; + + +/** + * Create a new user defined expression. + * @param[in] name the name of the expression + * @param[in] num_nodes the number of the expression children nodes. Must be + * compatible with the arity of the expression + * @param[in] nodes an array of \p num_nodes expressions + * @param[in] vector the vector of callbacks implementing the expression + * interface + * @param[in] expression_data a pointer to the expression internal data + * structures. Can be NULL + * @param[out] expression_ret a pointer to the variable that will hold the newly + * created expression + * @return #CCS_RESULT_SUCCESS on success + * @return #CCS_RESULT_ERROR_INVALID_OBJECT if one the nodes given is of type + * #CCS_DATA_TYPE_OBJECT but the object is not a valid CCS object + * @return #CCS_RESULT_ERROR_INVALID_VALUE if \p name is NULL; or if one the + * nodes given is of type #CCS_DATA_TYPE_OBJECT but is neither a + * #CCS_OBJECT_TYPE_PARAMETER nor a #CCS_OBJECT_TYPE_EXPRESSION; or if one the + * nodes given node is not a type #CCS_DATA_TYPE_OBJECT, #CCS_DATA_TYPE_NONE, + * #CCS_DATA_TYPE_INT, #CCS_DATA_TYPE_FLOAT, #CCS_DATA_TYPE_BOOL, or + * #CCS_DATA_TYPE_STRING; or if \p expression_ret is NULL; or if \p vector is + * NULL; or if any non optional interface pointer is NULL + * @return #CCS_RESULT_ERROR_OUT_OF_MEMORY if there was not enough memory to + * allocate the new expression instance + * @remarks + * This function is thread-safe + */ +extern ccs_result_t +ccs_create_user_defined_expression( + const char *name, + size_t num_nodes, + ccs_datum_t *nodes, + ccs_user_defined_expression_vector_t *vector, + void *expression_data, + ccs_expression_t *expression_ret); + /** * Get the type of an expression. * @param[in] expression @@ -427,6 +512,41 @@ ccs_variable_get_parameter( ccs_expression_t expression, ccs_parameter_t *parameter_ret); +/** + * Get the name of a user defined expression. + * @param[in] expression + * @param[out] name_ret a pointer to the variable that will contain a pointer to + * the name of the expression + * @return #CCS_RESULT_SUCCESS on success + * @return #CCS_RESULT_ERROR_INVALID_VALUE if \p name_ret is NULL + * @return #CCS_RESULT_ERROR_INVALID_OBJECT if \p expression is not a valid CCS expression + * @return #CCS_RESULT_ERROR_INVALID_EXPRESSION if \p expression is not a user + * defined expression + * @remarks + * This function is thread-safe + */ +extern ccs_result_t +ccs_user_defined_expression_get_name( + ccs_expression_t expression, + const char **name_ret); + +/** + * Get the user defined expression internal data pointer. + * @param[in] expression + * @param[out] expression_data_ret + * @return #CCS_RESULT_SUCCESS on success + * @return #CCS_RESULT_ERROR_INVALID_OBJECT if \p expression is not a valid CCS expression + * @return #CCS_RESULT_ERROR_INVALID_EXPRESSION if \p expression is not a user + * defined expression + * @return #CCS_RESULT_ERROR_INVALID_VALUE if \p expression_data_ret is NULL + * @remarks + * This function is thread-safe + */ +extern ccs_result_t +ccs_user_defined_expression_get_expression_data( + ccs_expression_t expression, + void **expression_data_ret); + /** * Get the value of an expression, in a given list of bindings. * @param[in] expression diff --git a/src/expression.c b/src/expression.c index ced48729..33076471 100644 --- a/src/expression.c +++ b/src/expression.c @@ -16,7 +16,8 @@ const int ccs_expression_precedence[] = { 6, 6, 6, 7, 8, - 9, 9 + 9, 9, + 9 }; const ccs_associativity_type_t ccs_expression_associativity[] = { @@ -29,7 +30,8 @@ const ccs_associativity_type_t ccs_expression_associativity[] = { CCS_ASSOCIATIVITY_TYPE_RIGHT_TO_LEFT, CCS_ASSOCIATIVITY_TYPE_RIGHT_TO_LEFT, CCS_ASSOCIATIVITY_TYPE_RIGHT_TO_LEFT, CCS_ASSOCIATIVITY_TYPE_LEFT_TO_RIGHT, CCS_ASSOCIATIVITY_TYPE_LEFT_TO_RIGHT, - CCS_ASSOCIATIVITY_TYPE_NONE, CCS_ASSOCIATIVITY_TYPE_NONE + CCS_ASSOCIATIVITY_TYPE_NONE, CCS_ASSOCIATIVITY_TYPE_NONE, + CCS_ASSOCIATIVITY_TYPE_NONE, }; const char *ccs_expression_symbols[] = { @@ -42,7 +44,8 @@ const char *ccs_expression_symbols[] = { "+", "-", "!", "#", NULL, - NULL, NULL + NULL, NULL, + NULL, }; const int ccs_expression_arity[] = { @@ -55,7 +58,8 @@ const int ccs_expression_arity[] = { 1, 1, 1, 2, -1, - 0, 0 + 0, 0, + -1 }; const int ccs_terminal_precedence[] = { @@ -93,8 +97,8 @@ ccs_expression_get_ops(ccs_expression_t expression) static ccs_result_t _ccs_expression_del(ccs_object_t o) { - ccs_expression_t d = (ccs_expression_t)o; - _ccs_expression_data_t *data = d->data; + ccs_expression_t e = (ccs_expression_t)o; + _ccs_expression_data_t *data = e->data; for (size_t i = 0; i < data->num_nodes; i++) ccs_release_object(data->nodes[i]); return CCS_RESULT_SUCCESS; @@ -205,7 +209,7 @@ _ccs_expression_serialize( do { \ _ccs_expression_ops_t *ops = \ ccs_expression_get_ops(expression); \ - CCS_VALIDATE(ops->eval(expression->data, expr_ctx, result)); \ + CCS_VALIDATE(ops->eval(expression, expr_ctx, result)); \ } while (0) static inline ccs_result_t @@ -248,20 +252,14 @@ _ccs_expr_node_eval( static ccs_result_t _ccs_expr_or_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) -{ - ccs_datum_t left; - ccs_datum_t right; - // avoid inactive branch suppressing a parameter parameter - // if the other branch is valid. - // TODO: use EVAL_LEFT_RIGHT(data, num_bindings, bindings, left, right, - // NULL, NULL); - CCS_VALIDATE( - _ccs_expr_node_eval(data->nodes[0], expr_ctx, &left, NULL)); - CCS_VALIDATE( - _ccs_expr_node_eval(data->nodes[1], expr_ctx, &right, NULL)); + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) +{ + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); CCS_REFUTE( left.type != CCS_DATA_TYPE_BOOL && left.type != CCS_DATA_TYPE_INACTIVE, @@ -291,12 +289,13 @@ static _ccs_expression_ops_t _ccs_expr_or_ops = { static ccs_result_t _ccs_expr_and_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -432,14 +431,14 @@ _ccs_datum_cmp_generic(ccs_datum_t *a, ccs_datum_t *b, ccs_int_t *cmp) static ccs_result_t _ccs_expr_equal_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); RETURN_IF_INACTIVE(left, result); @@ -466,14 +465,14 @@ static _ccs_expression_ops_t _ccs_expr_equal_ops = { static ccs_result_t _ccs_expr_not_equal_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); RETURN_IF_INACTIVE(left, result); @@ -500,14 +499,14 @@ static _ccs_expression_ops_t _ccs_expr_not_equal_ops = { static ccs_result_t _ccs_expr_less_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); CCS_REFUTE( @@ -549,14 +548,14 @@ static _ccs_expression_ops_t _ccs_expr_less_ops = { static ccs_result_t _ccs_expr_greater_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); CCS_REFUTE( @@ -598,14 +597,14 @@ static _ccs_expression_ops_t _ccs_expr_greater_ops = { static ccs_result_t _ccs_expr_less_or_equal_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); CCS_REFUTE( @@ -647,14 +646,14 @@ static _ccs_expression_ops_t _ccs_expr_less_or_equal_ops = { static ccs_result_t _ccs_expr_greater_or_equal_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; - ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; - ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + ccs_parameter_type_t htl = CCS_PARAMETER_TYPE_MAX; + ccs_parameter_type_t htr = CCS_PARAMETER_TYPE_MAX; EVAL_LEFT_RIGHT(data, expr_ctx, left, right, &htl, &htr); CCS_REFUTE( @@ -703,11 +702,12 @@ _ccs_expression_list_eval_node( static ccs_result_t _ccs_expr_in_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_expression_type_t etype = CCS_EXPR_TYPE(data->nodes[1]); + _ccs_expression_data_t *data = e->data; + ccs_expression_type_t etype = CCS_EXPR_TYPE(data->nodes[1]); CCS_REFUTE( etype != CCS_EXPRESSION_TYPE_LIST, CCS_RESULT_ERROR_INVALID_VALUE); @@ -746,12 +746,13 @@ static _ccs_expression_ops_t _ccs_expr_in_ops = { static ccs_result_t _ccs_expr_add_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -784,12 +785,13 @@ static _ccs_expression_ops_t _ccs_expr_add_ops = { static ccs_result_t _ccs_expr_substract_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -822,12 +824,13 @@ static _ccs_expression_ops_t _ccs_expr_substract_ops = { static ccs_result_t _ccs_expr_multiply_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -860,12 +863,13 @@ static _ccs_expression_ops_t _ccs_expr_multiply_ops = { static ccs_result_t _ccs_expr_divide_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -910,12 +914,13 @@ static _ccs_expression_ops_t _ccs_expr_divide_ops = { static ccs_result_t _ccs_expr_modulo_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t left; - ccs_datum_t right; + _ccs_expression_data_t *data = e->data; + ccs_datum_t left, right; + EVAL_LEFT_RIGHT(data, expr_ctx, left, right, NULL, NULL); RETURN_IF_INACTIVE(left, result); RETURN_IF_INACTIVE(right, result); @@ -960,11 +965,13 @@ static _ccs_expression_ops_t _ccs_expr_modulo_ops = { static ccs_result_t _ccs_expr_positive_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t node; + _ccs_expression_data_t *data = e->data; + ccs_datum_t node; + EVAL_NODE(data, expr_ctx, node, NULL); RETURN_IF_INACTIVE(node, result); CCS_REFUTE( @@ -982,11 +989,13 @@ static _ccs_expression_ops_t _ccs_expr_positive_ops = { static ccs_result_t _ccs_expr_negative_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t node; + _ccs_expression_data_t *data = e->data; + ccs_datum_t node; + EVAL_NODE(data, expr_ctx, node, NULL); RETURN_IF_INACTIVE(node, result); CCS_REFUTE( @@ -1008,11 +1017,13 @@ static _ccs_expression_ops_t _ccs_expr_negative_ops = { static ccs_result_t _ccs_expr_not_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - ccs_datum_t node; + _ccs_expression_data_t *data = e->data; + ccs_datum_t node; + EVAL_NODE(data, expr_ctx, node, NULL); RETURN_IF_INACTIVE(node, result); CCS_REFUTE( @@ -1029,16 +1040,16 @@ static _ccs_expression_ops_t _ccs_expr_not_ops = { static ccs_result_t _ccs_expr_list_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - (void)data; + (void)e; (void)expr_ctx; (void)result; CCS_RAISE( CCS_RESULT_ERROR_UNSUPPORTED_OPERATION, - "Lists cannot be avaluated"); + "Lists cannot be evaluated"); } static _ccs_expression_ops_t _ccs_expr_list_ops = { @@ -1142,13 +1153,15 @@ _ccs_expression_literal_serialize( static ccs_result_t _ccs_expr_literal_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { (void)expr_ctx; - _ccs_expression_literal_data_t *d = + _ccs_expression_data_t *data = e->data; + _ccs_expression_literal_data_t *d = (_ccs_expression_literal_data_t *)data; + *result = d->value; return CCS_RESULT_SUCCESS; } @@ -1263,15 +1276,17 @@ _ccs_expression_variable_serialize( static ccs_result_t _ccs_expr_variable_eval( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result) + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) { - _ccs_expression_variable_data_t *d = + _ccs_expression_data_t *data = e->data; + _ccs_expression_variable_data_t *d = (_ccs_expression_variable_data_t *)data; size_t num_bindings = expr_ctx->num_bindings; ccs_binding_t *bindings = expr_ctx->bindings; ccs_bool_t found = CCS_FALSE; + CCS_REFUTE(!num_bindings, CCS_RESULT_ERROR_INVALID_OBJECT); for (size_t i = 0; i < num_bindings; i++) { CCS_VALIDATE(ccs_binding_get_value_by_parameter( @@ -1289,6 +1304,140 @@ static _ccs_expression_ops_t _ccs_expr_variable_ops = { &_ccs_expression_variable_serialize}, &_ccs_expr_variable_eval}; +static ccs_result_t +_ccs_expr_user_defined_del(ccs_object_t o) +{ + _ccs_expression_user_defined_data_t *d= + (_ccs_expression_user_defined_data_t *)( + (ccs_expression_t)o)->data; + + ccs_result_t err; + err = d->vector.del((ccs_expression_t)o); + for (size_t i = 0; i < d->expr.num_nodes; i++) + ccs_release_object(d->expr.nodes[i]); + return err; +} + +static inline ccs_result_t +_ccs_serialize_bin_size_ccs_expression_user_defined( + ccs_expression_t expression, + size_t *cum_size, + _ccs_object_serialize_options_t *opts) +{ + _ccs_expression_user_defined_data_t *data = + (_ccs_expression_user_defined_data_t *)(expression->data); + CCS_VALIDATE(_ccs_serialize_bin_size_ccs_expression_data( + &data->expr, cum_size, opts)); + *cum_size += _ccs_serialize_bin_size_string(data->name); + size_t state_size = 0; + if (data->vector.serialize_user_state) + CCS_VALIDATE(data->vector.serialize_user_state( + expression, 0, NULL, &state_size)); + *cum_size += _ccs_serialize_bin_size_size(state_size); + *cum_size += state_size; + return CCS_RESULT_SUCCESS; +} + +static inline ccs_result_t +_ccs_serialize_bin_ccs_expression_user_defined( + ccs_expression_t expression, + size_t *buffer_size, + char **buffer, + _ccs_object_serialize_options_t *opts) +{ + _ccs_expression_user_defined_data_t *data = + (_ccs_expression_user_defined_data_t *)(expression->data); + CCS_VALIDATE(_ccs_serialize_bin_ccs_expression_data( + &data->expr, buffer_size, buffer, opts)); + CCS_VALIDATE( + _ccs_serialize_bin_string(data->name, buffer_size, buffer)); + size_t state_size = 0; + if (data->vector.serialize_user_state) + CCS_VALIDATE(data->vector.serialize_user_state( + expression, 0, NULL, &state_size)); + CCS_VALIDATE(_ccs_serialize_bin_size(state_size, buffer_size, buffer)); + if (state_size) { + CCS_REFUTE( + *buffer_size < state_size, + CCS_RESULT_ERROR_NOT_ENOUGH_DATA); + CCS_VALIDATE(data->vector.serialize_user_state( + expression, state_size, *buffer, NULL)); + *buffer_size -= state_size; + *buffer += state_size; + } + return CCS_RESULT_SUCCESS; +} + +static ccs_result_t +_ccs_expression_user_defined_serialize_size( + ccs_object_t object, + ccs_serialize_format_t format, + size_t *cum_size, + _ccs_object_serialize_options_t *opts) +{ + switch (format) { + case CCS_SERIALIZE_FORMAT_BINARY: + CCS_VALIDATE(_ccs_serialize_bin_size_ccs_expression_user_defined( + (ccs_expression_t)object, cum_size, opts)); + break; + default: + CCS_RAISE( + CCS_RESULT_ERROR_INVALID_VALUE, + "Unsupported serialization format: %d", format); + } + return CCS_RESULT_SUCCESS; +} + +static ccs_result_t +_ccs_expression_user_defined_serialize( + ccs_object_t object, + ccs_serialize_format_t format, + size_t *buffer_size, + char **buffer, + _ccs_object_serialize_options_t *opts) +{ + switch (format) { + case CCS_SERIALIZE_FORMAT_BINARY: + CCS_VALIDATE(_ccs_serialize_bin_ccs_expression_user_defined( + (ccs_expression_t)object, buffer_size, buffer, opts)); + break; + default: + CCS_RAISE( + CCS_RESULT_ERROR_INVALID_VALUE, + "Unsupported serialization format: %d", format); + } + return CCS_RESULT_SUCCESS; +} + +static ccs_result_t +_ccs_expr_user_defined_eval( + ccs_expression_t e, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result) +{ + _ccs_expression_data_t *data = e->data; + _ccs_expression_user_defined_data_t *d = + (_ccs_expression_user_defined_data_t *)data; + ccs_datum_t *values = NULL; + + if (data->num_nodes) + values = (ccs_datum_t *)alloca( + sizeof(ccs_datum_t)*data->num_nodes); + for (size_t i = 0; i < data->num_nodes; i++) { + CCS_VALIDATE(_ccs_expr_node_eval( + data->nodes[i], expr_ctx, values + i, NULL)); + RETURN_IF_INACTIVE(values[i], result); + } + CCS_VALIDATE(d->vector.eval(e, data->num_nodes, values, result)); + return CCS_RESULT_SUCCESS; +} + +static _ccs_expression_ops_t _ccs_expr_user_defined_ops = { + {&_ccs_expr_user_defined_del, + &_ccs_expression_user_defined_serialize_size, + &_ccs_expression_user_defined_serialize}, + &_ccs_expr_user_defined_eval}; + static inline _ccs_expression_ops_t * _ccs_expression_ops_broker(ccs_expression_type_t expression_type) { @@ -1353,6 +1502,9 @@ _ccs_expression_ops_broker(ccs_expression_type_t expression_type) case CCS_EXPRESSION_TYPE_VARIABLE: return &_ccs_expr_variable_ops; break; + case CCS_EXPRESSION_TYPE_USER_DEFINED: + return &_ccs_expr_user_defined_ops; + break; default: return NULL; } @@ -1432,6 +1584,56 @@ ccs_create_variable(ccs_parameter_t parameter, ccs_expression_t *expression_ret) return err; } +static inline ccs_result_t +_ccs_validate_nodes( + size_t num_nodes, + ccs_datum_t *nodes) +{ + for (size_t i = 0; i < num_nodes; i++) { + if (nodes[i].type == CCS_DATA_TYPE_OBJECT) { + ccs_object_type_t object_type = + CCS_OBJ_TYPE(nodes[i].value.o); + CCS_REFUTE( + object_type != CCS_OBJECT_TYPE_PARAMETER && + object_type != + CCS_OBJECT_TYPE_EXPRESSION, + CCS_RESULT_ERROR_INVALID_VALUE); + } else + CCS_REFUTE( + nodes[i].type < CCS_DATA_TYPE_NONE || + nodes[i].type > CCS_DATA_TYPE_STRING, + CCS_RESULT_ERROR_INVALID_VALUE); + } + return CCS_RESULT_SUCCESS; +} + +static inline ccs_result_t +_ccs_create_nodes( + size_t num_nodes, + ccs_datum_t *nodes, + ccs_expression_t *nodes_ret) +{ + for (size_t i = 0; i < num_nodes; i++) { + if (nodes[i].type == CCS_DATA_TYPE_OBJECT) { + ccs_object_type_t t = CCS_OBJ_TYPE(nodes[i].value.o); + if (t == CCS_OBJECT_TYPE_EXPRESSION) { + CCS_VALIDATE(ccs_retain_object( + nodes[i].value.o)); + nodes_ret[i] = + (ccs_expression_t)nodes[i].value.o; + } else { + CCS_VALIDATE(ccs_create_variable( + (ccs_parameter_t)nodes[i].value.o, + nodes_ret + i)); + } + } else { + CCS_VALIDATE(ccs_create_literal( + nodes[i], nodes_ret + i)); + } + } + return CCS_RESULT_SUCCESS; +} + ccs_result_t ccs_create_expression( ccs_expression_type_t type, @@ -1449,23 +1651,9 @@ ccs_create_expression( CCS_REFUTE( arity >= 0 && num_nodes != (size_t)arity, CCS_RESULT_ERROR_INVALID_VALUE); - ccs_result_t err; - for (size_t i = 0; i < num_nodes; i++) { - if (nodes[i].type == CCS_DATA_TYPE_OBJECT) { - ccs_object_type_t object_type = - CCS_OBJ_TYPE(nodes[i].value.o); - CCS_REFUTE( - object_type != CCS_OBJECT_TYPE_PARAMETER && - object_type != - CCS_OBJECT_TYPE_EXPRESSION, - CCS_RESULT_ERROR_INVALID_VALUE); - } else - CCS_REFUTE( - nodes[i].type < CCS_DATA_TYPE_NONE || - nodes[i].type > CCS_DATA_TYPE_STRING, - CCS_RESULT_ERROR_INVALID_VALUE); - } + CCS_VALIDATE(_ccs_validate_nodes(num_nodes, nodes)); + ccs_result_t err; uintptr_t mem = (uintptr_t)calloc( 1, sizeof(struct _ccs_expression_s) + sizeof(struct _ccs_expression_data_s) + @@ -1484,33 +1672,8 @@ ccs_create_expression( expression_data->nodes = (ccs_expression_t *)(mem + sizeof(struct _ccs_expression_s) + sizeof(struct _ccs_expression_data_s)); - for (size_t i = 0; i < num_nodes; i++) { - if (nodes[i].type == CCS_DATA_TYPE_OBJECT) { - ccs_object_type_t t = CCS_OBJ_TYPE(nodes[i].value.o); - if (t == CCS_OBJECT_TYPE_EXPRESSION) { - CCS_VALIDATE_ERR_GOTO( - err, - ccs_retain_object(nodes[i].value.o), - cleanup); - expression_data->nodes[i] = - (ccs_expression_t)nodes[i].value.o; - } else { - CCS_VALIDATE_ERR_GOTO( - err, - ccs_create_variable( - (ccs_parameter_t)nodes[i] - .value.o, - expression_data->nodes + i), - cleanup); - } - } else { - CCS_VALIDATE_ERR_GOTO( - err, - ccs_create_literal( - nodes[i], expression_data->nodes + i), - cleanup); - } - } + CCS_VALIDATE_ERR_GOTO(err, _ccs_create_nodes( + num_nodes, nodes, expression_data->nodes), cleanup); expression->data = expression_data; *expression_ret = expression; return CCS_RESULT_SUCCESS; @@ -1548,6 +1711,66 @@ ccs_create_unary_expression( return CCS_RESULT_SUCCESS; } +ccs_result_t +ccs_create_user_defined_expression( + const char *name, + size_t num_nodes, + ccs_datum_t *nodes, + ccs_user_defined_expression_vector_t *vector, + void *expr_data, + ccs_expression_t *expression_ret) +{ + CCS_CHECK_ARY(num_nodes, nodes); + CCS_CHECK_PTR(expression_ret); + CCS_CHECK_PTR(vector); + CCS_CHECK_PTR(vector->del); + CCS_CHECK_PTR(vector->eval); + CCS_VALIDATE(_ccs_validate_nodes(num_nodes, nodes)); + + ccs_result_t err; + uintptr_t mem = (uintptr_t)calloc( + 1, sizeof(struct _ccs_expression_s) + + sizeof(struct _ccs_expression_user_defined_data_s) + + strlen(name) + 1); + CCS_REFUTE(!mem, CCS_RESULT_ERROR_OUT_OF_MEMORY); + + ccs_expression_t expression; + expression = (ccs_expression_t)mem; + _ccs_object_init( + &(expression->obj), CCS_OBJECT_TYPE_EXPRESSION, + (_ccs_object_ops_t *)_ccs_expression_ops_broker( + CCS_EXPRESSION_TYPE_USER_DEFINED)); + _ccs_expression_user_defined_data_t *expression_data; + expression_data = (_ccs_expression_user_defined_data_t *)(mem + sizeof(struct _ccs_expression_s)); + expression_data->expr.type = CCS_EXPRESSION_TYPE_USER_DEFINED; + expression_data->expr.num_nodes = num_nodes; + expression_data->expr.nodes = + (ccs_expression_t *)(mem + + sizeof(struct _ccs_expression_s) + + sizeof(struct _ccs_expression_user_defined_data_s)); + expression_data->name = + (const char *)(mem + + sizeof(struct _ccs_expression_s) + + sizeof(struct _ccs_expression_user_defined_data_s) + + sizeof(ccs_expression_t) * num_nodes); + expression_data->vector = *vector; + expression_data->expression_data = expr_data; + strcpy((char *)expression_data->name, name); + CCS_VALIDATE_ERR_GOTO(err, _ccs_create_nodes( + num_nodes, nodes, expression_data->expr.nodes), cleanup); + expression->data = (_ccs_expression_data_t *)expression_data; + *expression_ret = expression; + return CCS_RESULT_SUCCESS; +cleanup: + for (size_t i = 0; i < num_nodes; i++) { + if (expression_data->expr.nodes[i]) + ccs_release_object(expression_data->expr.nodes[i]); + } + _ccs_object_deinit(&(expression->obj)); + free((void *)mem); + return err; +} + ccs_result_t ccs_expression_eval( ccs_expression_t expression, @@ -1666,6 +1889,38 @@ ccs_variable_get_parameter( return CCS_RESULT_SUCCESS; } +ccs_result_t +ccs_user_defined_expression_get_expression_data( + ccs_expression_t expression, + void **expression_data_ret) +{ + CCS_CHECK_OBJ(expression, CCS_OBJECT_TYPE_EXPRESSION); + CCS_CHECK_PTR(expression_data_ret); + _ccs_expression_user_defined_data_t *d = + (_ccs_expression_user_defined_data_t *)expression->data; + CCS_REFUTE( + d->expr.type != CCS_EXPRESSION_TYPE_USER_DEFINED, + CCS_RESULT_ERROR_INVALID_EXPRESSION); + *expression_data_ret = d->expression_data; + return CCS_RESULT_SUCCESS; +} + +ccs_result_t +ccs_user_defined_expression_get_name( + ccs_expression_t expression, + const char **name_ret) +{ + CCS_CHECK_OBJ(expression, CCS_OBJECT_TYPE_EXPRESSION); + CCS_CHECK_PTR(name_ret); + _ccs_expression_user_defined_data_t *d = + (_ccs_expression_user_defined_data_t *)expression->data; + CCS_REFUTE( + d->expr.type != CCS_EXPRESSION_TYPE_USER_DEFINED, + CCS_RESULT_ERROR_INVALID_EXPRESSION); + *name_ret = d->name; + return CCS_RESULT_SUCCESS; +} + #undef utarray_oom #define utarray_oom() \ { \ diff --git a/src/expression_deserialize.h b/src/expression_deserialize.h index 8ac6e7b3..7f6e0ddf 100644 --- a/src/expression_deserialize.h +++ b/src/expression_deserialize.h @@ -151,6 +151,79 @@ _ccs_deserialize_bin_expression_general( return res; } +struct _ccs_expression_user_defined_data_mock_s { + _ccs_expression_data_mock_t expr; + const char *name; + _ccs_blob_t blob; +}; +typedef struct _ccs_expression_user_defined_data_mock_s + _ccs_expression_user_defined_data_mock_t; + +static inline ccs_result_t +_ccs_deserialize_bin_ccs_expression_user_defined_data( + _ccs_expression_user_defined_data_mock_t *data, + uint32_t version, + size_t *buffer_size, + const char **buffer) +{ + CCS_VALIDATE(_ccs_deserialize_bin_ccs_expression_data( + &data->expr, version, buffer_size, buffer, NULL)); + CCS_VALIDATE(_ccs_deserialize_bin_string( + &data->name, buffer_size, buffer)); + CCS_VALIDATE(_ccs_deserialize_bin_ccs_blob( + &data->blob, buffer_size, buffer)); + return CCS_RESULT_SUCCESS; +} + +static inline ccs_result_t +_ccs_deserialize_bin_expression_user_defined( + ccs_expression_t *expression_ret, + uint32_t version, + size_t *buffer_size, + const char **buffer, + _ccs_object_deserialize_options_t *opts) +{ + _ccs_expression_user_defined_data_mock_t data; + ccs_user_defined_expression_vector_t *vector = NULL; + void *expression_data = NULL; + ccs_result_t res = + CCS_RESULT_SUCCESS; + + CCS_VALIDATE(_ccs_deserialize_bin_ccs_expression_user_defined_data( + &data, version, buffer_size, buffer)); + + CCS_VALIDATE_ERR_GOTO( + res, + opts->deserialize_vector_callback( + CCS_OBJECT_TYPE_EXPRESSION, data.name, + opts->deserialize_vector_user_data, (void **)&vector, + &expression_data), + end); + + if (vector->deserialize_state) + CCS_VALIDATE_ERR_GOTO( + res, + vector->deserialize_state( + data.blob.sz, data.blob.blob, &expression_data), + end); + + CCS_VALIDATE_ERR_GOTO( + res, + ccs_create_user_defined_expression( + data.name, data.expr.num_nodes, data.expr.nodes, + vector, expression_data, expression_ret), + end); + +end: + if (data.expr.nodes) { + for (size_t i = 0; i < data.expr.num_nodes; i++) + if (data.expr.nodes[i].type == CCS_DATA_TYPE_OBJECT) + ccs_release_object(data.expr.nodes[i].value.o); + free(data.expr.nodes); + } + return res; +} + static inline ccs_result_t _ccs_deserialize_bin_expression( ccs_expression_t *expression_ret, @@ -175,6 +248,11 @@ _ccs_deserialize_bin_expression( expression_ret, version, buffer_size, buffer, &new_opts)); break; + case CCS_EXPRESSION_TYPE_USER_DEFINED: + CCS_VALIDATE(_ccs_deserialize_bin_expression_user_defined( + expression_ret, version, buffer_size, buffer, + &new_opts)); + break; default: CCS_REFUTE( dtype < CCS_EXPRESSION_TYPE_OR || diff --git a/src/expression_internal.h b/src/expression_internal.h index 89a905bd..640d6e76 100644 --- a/src/expression_internal.h +++ b/src/expression_internal.h @@ -15,9 +15,9 @@ struct _ccs_expression_ops_s { _ccs_object_ops_t obj_ops; ccs_result_t (*eval)( - _ccs_expression_data_t *data, - _ccs_expr_ctx_t *expr_ctx, - ccs_datum_t *result); + ccs_expression_t expression, + _ccs_expr_ctx_t *expr_ctx, + ccs_datum_t *result); }; typedef struct _ccs_expression_ops_s _ccs_expression_ops_t; @@ -44,4 +44,13 @@ struct _ccs_expression_variable_data_s { }; typedef struct _ccs_expression_variable_data_s _ccs_expression_variable_data_t; +struct _ccs_expression_user_defined_data_s { + _ccs_expression_data_t expr; + ccs_user_defined_expression_vector_t vector; + void *expression_data; + const char *name; +}; +typedef struct _ccs_expression_user_defined_data_s + _ccs_expression_user_defined_data_t; + #endif //_EXPRESSION_INTERNAL_H