susumu.yata
null+****@clear*****
Thu Nov 12 11:20:53 JST 2015
susumu.yata 2015-11-12 11:20:53 +0900 (Thu, 12 Nov 2015) New Revision: 77ec0bdec19dbeb5d8eaf2330e16d6030524af95 https://github.com/groonga/groonga/commit/77ec0bdec19dbeb5d8eaf2330e16d6030524af95 Message: grn_ts: move definitions of grn_ts_expr_node into lib/ts/ts_expr_node Added files: lib/ts/ts_expr_node.h Copied files: lib/ts/ts_expr_node.c (from lib/ts/ts_expr.c) Modified files: lib/ts/sources.am lib/ts/ts_expr.c lib/ts/ts_expr.h lib/ts/ts_types.h Modified: lib/ts/sources.am (+2 -0) =================================================================== --- lib/ts/sources.am 2015-11-12 09:59:27 +0900 (892393b) +++ lib/ts/sources.am 2015-11-12 11:20:53 +0900 (57faefc) @@ -3,6 +3,8 @@ libgrnts_la_SOURCES = \ ts_buf.h \ ts_expr.c \ ts_expr.h \ + ts_expr_node.c \ + ts_expr_node.h \ ts_log.h \ ts_str.c \ ts_str.h \ Modified: lib/ts/ts_expr.c (+22 -4499) =================================================================== --- lib/ts/ts_expr.c 2015-11-12 09:59:27 +0900 (3c4a119) +++ lib/ts/ts_expr.c 2015-11-12 11:20:53 +0900 (b573ebe) @@ -33,27 +33,11 @@ #include "ts_log.h" #include "ts_str.h" + /*------------------------------------------------------------- * Built-in data kinds. */ -typedef union { - grn_ts_bool as_bool; - grn_ts_int as_int; - grn_ts_float as_float; - grn_ts_time as_time; - grn_ts_text as_text; - grn_ts_geo as_geo; - grn_ts_ref as_ref; - grn_ts_bool_vector as_bool_vector; - grn_ts_int_vector as_int_vector; - grn_ts_float_vector as_float_vector; - grn_ts_time_vector as_time_vector; - grn_ts_text_vector as_text_vector; - grn_ts_geo_vector as_geo_vector; - grn_ts_ref_vector as_ref_vector; -} grn_ts_any; - /* grn_ts_bool_is_valid() returns whether a value is valid or not. */ inline static grn_ts_bool grn_ts_bool_is_valid(grn_ts_bool value) { @@ -143,167 +127,6 @@ grn_ts_geo_vector_is_valid(grn_ts_geo_vector value) { } #undef GRN_TS_VECTOR_IS_VALID -/* grn_ts_bool_zero() returns a zero. */ -inline static grn_ts_bool -grn_ts_bool_zero(void) { - return GRN_FALSE; -} - -/* grn_ts_int_zero() returns a zero. */ -inline static grn_ts_int -grn_ts_int_zero(void) { - return 0; -} - -/* grn_ts_float_zero() returns a zero. */ -inline static grn_ts_float -grn_ts_float_zero(void) { - return 0.0; -} - -/* grn_ts_time_zero() returns a zero. */ -inline static grn_ts_time -grn_ts_time_zero(void) { - return 0; -} - -/* grn_ts_text_zero() returns a zero. */ -inline static grn_ts_text -grn_ts_text_zero(void) { - return (grn_ts_text){ NULL, 0 }; -} - -/* grn_ts_geo_zero() returns a zero. */ -inline static grn_ts_geo -grn_ts_geo_zero(void) { - return (grn_ts_geo){ 0, 0 }; -} - -/* grn_ts_ref_zero() returns a zero. */ -inline static grn_ts_ref -grn_ts_ref_zero(void) { - return (grn_ts_ref){ 0, 0.0 }; -} - -/* grn_ts_bool_vector_zero() returns a zero. */ -inline static grn_ts_bool_vector -grn_ts_bool_vector_zero(void) { - return (grn_ts_bool_vector){ NULL, 0 }; -} - -/* grn_ts_int_vector_zero() returns a zero. */ -inline static grn_ts_int_vector -grn_ts_int_vector_zero(void) { - return (grn_ts_int_vector){ NULL, 0 }; -} - -/* grn_ts_float_vector_zero() returns a zero. */ -inline static grn_ts_float_vector -grn_ts_float_vector_zero(void) { - return (grn_ts_float_vector){ NULL, 0 }; -} - -/* grn_ts_time_vector_zero() returns a zero. */ -inline static grn_ts_time_vector -grn_ts_time_vector_zero(void) { - return (grn_ts_time_vector){ NULL, 0 }; -} - -/* grn_ts_text_vector_zero() returns a zero. */ -inline static grn_ts_text_vector -grn_ts_text_vector_zero(void) { - return (grn_ts_text_vector){ NULL, 0 }; -} - -/* grn_ts_geo_vector_zero() returns a zero. */ -inline static grn_ts_geo_vector -grn_ts_geo_vector_zero(void) { - return (grn_ts_geo_vector){ NULL, 0 }; -} - -/* grn_ts_ref_vector_zero() returns a zero. */ -inline static grn_ts_ref_vector -grn_ts_ref_vector_zero(void) { - return (grn_ts_ref_vector){ NULL, 0 }; -} - -/* grn_ts_data_type_to_kind() returns a kind associated with a type. */ -static grn_ts_data_kind -grn_ts_data_type_to_kind(grn_ts_data_type type) { - switch (type) { - case GRN_DB_VOID: { - return GRN_TS_VOID; - } - case GRN_DB_BOOL: { - return GRN_TS_BOOL; - } - case GRN_DB_INT8: - case GRN_DB_INT16: - case GRN_DB_INT32: - case GRN_DB_INT64: - case GRN_DB_UINT8: - case GRN_DB_UINT16: - case GRN_DB_UINT32: - case GRN_DB_UINT64: { - return GRN_TS_INT; - } - case GRN_DB_FLOAT: { - return GRN_TS_FLOAT; - } - case GRN_DB_TIME: { - return GRN_TS_TIME; - } - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - return GRN_TS_TEXT; - } - case GRN_DB_TOKYO_GEO_POINT: - case GRN_DB_WGS84_GEO_POINT: { - return GRN_TS_GEO; - } - default: { - return GRN_TS_REF; - } - } -} - -/* grn_ts_data_kind_to_type() returns a type associated with a kind. */ -static grn_ts_data_type -grn_ts_data_kind_to_type(grn_ts_data_kind kind) { - switch (kind & ~GRN_TS_VECTOR_FLAG) { - case GRN_TS_BOOL: { - return GRN_DB_BOOL; - } - case GRN_TS_INT: { - return GRN_DB_INT64; - } - case GRN_TS_FLOAT: { - return GRN_DB_FLOAT; - } - case GRN_TS_TIME: { - return GRN_DB_TIME; - } - case GRN_TS_TEXT: { - return GRN_DB_TEXT; - } - case GRN_TS_GEO: { - /* GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT. */ - return GRN_DB_VOID; - } - case GRN_TS_REF: { - /* - * grn_ts_data_kind does not have enough information to get a correct - * table ID. - */ - return GRN_DB_VOID; - } - default: { - return GRN_DB_VOID; - } - } -} - /*------------------------------------------------------------- * Operators. */ @@ -412,715 +235,30 @@ grn_ts_op_get_precedence(grn_ts_op_type op_type) { } } -/* grn_ts_op_logical_not_bool() returns !arg. */ -inline static grn_ts_bool -grn_ts_op_logical_not_bool(grn_ts_bool arg) { - return !arg; -} - -/* grn_ts_op_bitwise_not_bool() returns ~arg. */ -inline static grn_ts_bool -grn_ts_op_bitwise_not_bool(grn_ts_bool arg) { - return !arg; -} - -/* grn_ts_op_bitwise_not_int() returns ~arg. */ -inline static grn_ts_int -grn_ts_op_bitwise_not_int(grn_ts_int arg) { - return ~arg; -} - -/* grn_ts_op_positive_int() returns +arg. */ -inline static grn_ts_int -grn_ts_op_positive_int(grn_ts_int arg) { - return arg; -} - -/* grn_ts_op_positive_float() returns +arg. */ -inline static grn_ts_float -grn_ts_op_positive_float(grn_ts_float arg) { - return arg; -} - -/* grn_ts_op_negative_int() returns -arg. */ -inline static grn_ts_int -grn_ts_op_negative_int(grn_ts_int arg) { - return -arg; -} - -/* grn_ts_op_negative_float() returns -arg. */ -inline static grn_ts_float -grn_ts_op_negative_float(grn_ts_float arg) { - return -arg; -} - -/* grn_ts_op_bitwise_and_bool() returns lhs & rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_and_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs & rhs; -} - -/* grn_ts_op_bitwise_and_int() returns lhs & rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_and_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs & rhs; -} - -/* grn_ts_op_bitwise_or_bool() returns lhs | rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_or_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs | rhs; -} - -/* grn_ts_op_bitwise_or_int() returns lhs | rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_or_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs | rhs; -} - -/* grn_ts_op_bitwise_xor_bool() returns lhs ^ rhs. */ -inline static grn_ts_bool -grn_ts_op_bitwise_xor_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs ^ rhs; -} - -/* grn_ts_op_bitwise_xor_int() returns lhs ^ rhs. */ -inline static grn_ts_int -grn_ts_op_bitwise_xor_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs ^ rhs; -} - -/* grn_ts_op_equal_bool() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_int() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_float() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - /* To suppress warnings, "lhs == rhs" is not used. */ - return (lhs <= rhs) && (lhs >= rhs); -} - -/* grn_ts_op_equal_time() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs == rhs; -} - -/* grn_ts_op_equal_text() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - return (lhs.size == rhs.size) && !memcmp(lhs.ptr, rhs.ptr, lhs.size); -} - -/* grn_ts_op_equal_geo() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) { - return (lhs.latitude == rhs.latitude) && (lhs.longitude == rhs.longitude); -} - -/* grn_ts_op_equal_ref() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) { - /* Ignore scores. */ - return lhs.id == rhs.id; -} - -#define GRN_TS_OP_EQUAL_VECTOR(kind)\ - size_t i;\ - if (lhs.size != rhs.size) {\ - return GRN_FALSE;\ - }\ - for (i = 0; i < lhs.size; i++) {\ - if (!grn_ts_op_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_FALSE;\ - }\ - }\ - return GRN_TRUE; -/* grn_ts_op_equal_bool_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_bool_vector(grn_ts_bool_vector lhs, grn_ts_bool_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(bool) -} - -/* grn_ts_op_equal_int_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(int) -} - -/* grn_ts_op_equal_float_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(float) -} - -/* grn_ts_op_equal_time_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(time) -} - -/* grn_ts_op_equal_text_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(text) -} - -/* grn_ts_op_equal_geo_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(geo) -} - -/* grn_ts_op_equal_ref_vector() returns lhs == rhs. */ -inline static grn_ts_bool -grn_ts_op_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) { - GRN_TS_OP_EQUAL_VECTOR(ref) -} -#undef GRN_TS_OP_EQUAL_VECTOR - -/* grn_ts_op_not_equal_bool() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_int() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_float() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - /* To suppress warnings, "lhs != rhs" is not used. */ - return (lhs < rhs) || (lhs > rhs); -} - -/* grn_ts_op_not_equal_time() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs != rhs; -} - -/* grn_ts_op_not_equal_text() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - return (lhs.size != rhs.size) || memcmp(lhs.ptr, rhs.ptr, lhs.size); -} - -/* grn_ts_op_not_equal_geo() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) { - return (lhs.latitude != rhs.latitude) || (lhs.longitude != rhs.longitude); -} - -/* grn_ts_op_not_equal_ref() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) { - /* Ignore scores. */ - return lhs.id != rhs.id; -} - -#define GRN_TS_OP_NOT_EQUAL_VECTOR(kind)\ - size_t i;\ - if (lhs.size != rhs.size) {\ - return GRN_TRUE;\ - }\ - for (i = 0; i < lhs.size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - return GRN_FALSE; -/* grn_ts_op_not_equal_bool_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_bool_vector(grn_ts_bool_vector lhs, - grn_ts_bool_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(bool) -} - -/* grn_ts_op_not_equal_int_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(int) -} - -/* grn_ts_op_not_equal_float_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(float) -} - -/* grn_ts_op_not_equal_time_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(time) -} - -/* grn_ts_op_not_equal_text_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(text) -} - -/* grn_ts_op_not_equal_geo_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(geo) -} - -/* grn_ts_op_not_equal_ref_vector() returns lhs != rhs. */ -inline static grn_ts_bool -grn_ts_op_not_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) { - GRN_TS_OP_NOT_EQUAL_VECTOR(ref) -} -#undef GRN_TS_OP_NOT_EQUAL_VECTOR - -/* grn_ts_op_less_int() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_float() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_time() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs < rhs; -} - -/* grn_ts_op_less_text() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp < 0) : (lhs.size < rhs.size); -} - -#define GRN_TS_OP_LESS_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size < rhs.size; -/* grn_ts_op_less_int_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_LESS_VECTOR(int) -} - -/* grn_ts_op_less_float_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_float_vector(grn_ts_float_vector lhs, grn_ts_float_vector rhs) { - GRN_TS_OP_LESS_VECTOR(float) -} - -/* grn_ts_op_less_time_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_LESS_VECTOR(time) -} - -/* grn_ts_op_less_text_vector() returns lhs < rhs. */ -inline static grn_ts_bool -grn_ts_op_less_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_LESS_VECTOR(text) -} -#undef GRN_TS_OP_LESS_VECTOR - -/* grn_ts_op_less_equal_int() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_float() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_time() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs <= rhs; -} - -/* grn_ts_op_less_equal_text() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp < 0) : (lhs.size <= rhs.size); -} - -#define GRN_TS_OP_LESS_EQUAL_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size <= rhs.size; -/* grn_ts_op_less_equal_int_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(int) -} - -/* grn_ts_op_less_equal_float_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(float) -} +/*------------------------------------------------------------- + * Groonga objects. + */ -/* grn_ts_op_less_equal_time_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(time) +/* grn_ts_obj_increment_ref_count() increments an object reference count. */ +static grn_rc +grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) { + grn_id id = grn_obj_id(ctx, obj); + grn_obj *obj_clone = grn_ctx_at(ctx, id); + if (!obj_clone) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id); + } + if (obj_clone != obj) { + grn_obj_unlink(ctx, obj_clone); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p", + obj, obj_clone); + } + return GRN_SUCCESS; } -/* grn_ts_op_less_equal_text_vector() returns lhs <= rhs. */ -inline static grn_ts_bool -grn_ts_op_less_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_LESS_EQUAL_VECTOR(text) -} -#undef GRN_TS_OP_LESS_EQUAL_VECTOR - -/* grn_ts_op_greater_int() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_float() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_time() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs > rhs; -} - -/* grn_ts_op_greater_text() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp > 0) : (lhs.size > rhs.size); -} - -#define GRN_TS_OP_GREATER_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size > rhs.size; -/* grn_ts_op_greater_int_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(int) -} - -/* grn_ts_op_greater_float_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(float) -} - -/* grn_ts_op_greater_time_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(time) -} - -/* grn_ts_op_greater_text_vector() returns lhs > rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) { - GRN_TS_OP_GREATER_VECTOR(text) -} -#undef GRN_TS_OP_GREATER_VECTOR - -/* grn_ts_op_greater_equal_int() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_int(grn_ts_int lhs, grn_ts_int rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_float() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_float(grn_ts_float lhs, grn_ts_float rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_time() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_time(grn_ts_time lhs, grn_ts_time rhs) { - return lhs >= rhs; -} - -/* grn_ts_op_greater_equal_text() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_text(grn_ts_text lhs, grn_ts_text rhs) { - size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; - int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); - return cmp ? (cmp > 0) : (lhs.size >= rhs.size); -} - -#define GRN_TS_OP_GREATER_EQUAL_VECTOR(kind)\ - size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ - for (i = 0; i < min_size; i++) {\ - if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ - return GRN_TRUE;\ - }\ - }\ - }\ - return lhs.size >= rhs.size; -/* grn_ts_op_greater_equal_int_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_int_vector(grn_ts_int_vector lhs, - grn_ts_int_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(int) -} - -/* grn_ts_op_greater_equal_float_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_float_vector(grn_ts_float_vector lhs, - grn_ts_float_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(float) -} - -/* grn_ts_op_greater_equal_time_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_time_vector(grn_ts_time_vector lhs, - grn_ts_time_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(time) -} - -/* grn_ts_op_greater_equal_text_vector() returns lhs >= rhs. */ -inline static grn_ts_bool -grn_ts_op_greater_equal_text_vector(grn_ts_text_vector lhs, - grn_ts_text_vector rhs) { - GRN_TS_OP_GREATER_EQUAL_VECTOR(text) -} -#undef GRN_TS_OP_GREATER_EQUAL_VECTOR - -/* grn_ts_op_shift_arithmetic_left() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_arithmetic_left(grn_ts_int lhs, grn_ts_int rhs) { - return lhs << rhs; -} - -/* grn_ts_op_shift_arithmetic_right() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_arithmetic_right(grn_ts_int lhs, grn_ts_int rhs) { - return lhs >> rhs; -} - -/* grn_ts_op_shift_logical_left() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_logical_left(grn_ts_int lhs, grn_ts_int rhs) { - return lhs << rhs; -} - -/* grn_ts_op_shift_logical_right() returns lhs << rhs. */ -inline static grn_ts_int -grn_ts_op_shift_logical_right(grn_ts_int lhs, grn_ts_int rhs) { - return (uint64_t)lhs >> rhs; -} - -inline static grn_rc -grn_ts_op_plus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, - grn_ts_int *out) { - *out = lhs + rhs; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_plus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, - grn_ts_float *out) { - *out = lhs + rhs; - if (!grn_ts_float_is_valid(*out)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g + %g = %g", lhs, rhs, *out); - } - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_plus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs, - grn_ts_time *out) { - *out = lhs + (rhs * 1000000); - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_plus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs, - grn_ts_time *out) { - *out = (grn_ts_time)(lhs + (rhs * 1000000.0)); - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_minus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, - grn_ts_int *out) { - *out = lhs - rhs; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_minus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, - grn_ts_float *out) { - *out = lhs - rhs; - if (!grn_ts_float_is_valid(*out)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g - %g = %g", lhs, rhs, *out); - } - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_minus_time_time(grn_ctx *ctx, grn_ts_time lhs, grn_ts_time rhs, - grn_ts_float *out) { - *out = (lhs - rhs) * 0.000001; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_minus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs, - grn_ts_time *out) { - *out = lhs - (rhs * 1000000); - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_minus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs, - grn_ts_time *out) { - *out = lhs - (grn_ts_int)(rhs * 1000000.0); - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_multiplication_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, - grn_ts_int *out) { - *out = lhs * rhs; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_multiplication_float_float(grn_ctx *ctx, grn_ts_float lhs, - grn_ts_float rhs, grn_ts_float *out) { - *out = lhs * rhs; - if (!grn_ts_float_is_valid(*out)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g * %g = %g", lhs, rhs, *out); - } - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_division_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, - grn_ts_int *out) { - if (!rhs) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "%ld / %ld causes division by zero", - lhs, rhs); - } - *out = (rhs != -1) ? (lhs / rhs) : -lhs; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_division_float_float(grn_ctx *ctx, grn_ts_float lhs, - grn_ts_float rhs, grn_ts_float *out) { - *out = lhs / rhs; - if (!grn_ts_float_is_valid(*out)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g / %g = %g", lhs, rhs, *out); - } - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_modulus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, - grn_ts_int *out) { - if (!rhs) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "%ld %% %ld causes division by zero", - lhs, rhs); - } - *out = (rhs != -1) ? (lhs % rhs) : -lhs; - return GRN_SUCCESS; -} - -inline static grn_rc -grn_ts_op_modulus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, - grn_ts_float *out) { - *out = fmod(lhs, rhs); - if (!grn_ts_float_is_valid(*out)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g %% %g = %g", lhs, rhs, *out); - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * Groonga objects. - */ - -/* grn_ts_obj_increment_ref_count() increments an object reference count. */ -static grn_rc -grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) { - grn_id id = grn_obj_id(ctx, obj); - grn_obj *obj_clone = grn_ctx_at(ctx, id); - if (!obj_clone) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id); - } - if (obj_clone != obj) { - grn_obj_unlink(ctx, obj_clone); - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p", - obj, obj_clone); - } - return GRN_SUCCESS; -} - -/* grn_ts_obj_is_table() returns whether or not an object is a table. */ -static grn_ts_bool -grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) { - return grn_obj_is_table(ctx, obj); +/* grn_ts_obj_is_table() returns whether or not an object is a table. */ +static grn_ts_bool +grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) { + return grn_obj_is_table(ctx, obj); } /* grn_ts_obj_is_column() returns whether or not an object is a column. */ @@ -1138,3621 +276,6 @@ grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) { } } -/* - * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note the a - * value is appended to the end of buf. - */ -static grn_rc -grn_ts_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_ts_id id, - grn_ts_buf *buf, size_t *value_size) { - grn_rc rc; - uint32_t size; - grn_io_win iw; - char *ptr = (char *)grn_ja_ref(ctx, ja, id, &iw, &size); - if (!ptr) { - if (value_size) { - *value_size = 0; - } - return GRN_SUCCESS; - } - rc = grn_ts_buf_write(ctx, buf, ptr, size); - grn_ja_unref(ctx, &iw); - if (rc != GRN_SUCCESS) { - return rc; - } - if (value_size) { - *value_size = size; - } - return GRN_SUCCESS; -} - -#define GRN_TS_TABLE_GET_KEY(type)\ - uint32_t key_size;\ - const void *key_ptr = _grn_ ## type ## _key(ctx, type, id, &key_size);\ - if (!key_ptr) {\ - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "_grn_" #type "_key failed: %u", id);\ - }\ -/* grn_ts_hash_get_bool_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_bool_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_bool *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_bool *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int16_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int32_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_int64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_int64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const int64_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint16_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const uint32_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_uint64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_uint64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = (grn_ts_int)*(const uint64_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_float_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_float_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_float *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_float *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_time_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_time_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_time *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_time *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_geo_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_geo_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_geo *key) { - GRN_TS_TABLE_GET_KEY(hash) - *key = *(const grn_ts_geo *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_text_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(hash) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} - -/* grn_ts_hash_get_ref_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_hash_get_ref_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, - grn_ts_ref *key) { - GRN_TS_TABLE_GET_KEY(hash) - key->id = *(const grn_ts_id *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_bool_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_bool_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_bool *key) { - GRN_TS_TABLE_GET_KEY(pat) - *key = *(const grn_ts_bool *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int8_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int16_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - int32_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_int64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_int64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(key, key_ptr, sizeof(grn_ts_int)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint8_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - *key = *(const uint8_t *)key_ptr; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint16_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - uint16_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint32_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - uint32_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - *key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_uint64_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_uint64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_int *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(key, key_ptr, sizeof(grn_ts_int)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_float_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_float_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_float *key) { - int64_t tmp; - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&tmp, key_ptr, sizeof(tmp)); - tmp ^= (((tmp ^ ((int64_t)1 << 63)) >> 63) | ((int64_t)1 << 63)); - *(int64_t *)key = tmp; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_time_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_time_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_time *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntohi(key, key_ptr, sizeof(grn_ts_time)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_geo_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_geo_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_geo *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntog(key, key_ptr, sizeof(grn_ts_geo)); - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_text_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(pat) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} - -/* grn_ts_pat_get_ref_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_pat_get_ref_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, - grn_ts_ref *key) { - GRN_TS_TABLE_GET_KEY(pat) - grn_ntoh(&key->id, key_ptr, sizeof(key->id)); - return GRN_SUCCESS; -} - -/* grn_ts_dat_get_text_key() gets a reference to a key (_key). */ -static grn_rc -grn_ts_dat_get_text_key(grn_ctx *ctx, grn_dat *dat, grn_ts_id id, - grn_ts_text *key) { - GRN_TS_TABLE_GET_KEY(dat) - key->ptr = key_ptr; - key->size = key_size; - return GRN_SUCCESS; -} -#undef GRN_TS_TABLE_GET_KEY - -/* grn_ts_table_has_key() returns whether or not a table has _key. */ -static grn_ts_bool -grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table) { - switch (table->header.type) { - case GRN_TABLE_HASH_KEY: - case GRN_TABLE_PAT_KEY: - case GRN_TABLE_DAT_KEY: { - return GRN_TRUE; - } - default: { - return GRN_FALSE; - } - } -} - -/* grn_ts_table_has_value() returns whether or not a table has _value. */ -static grn_ts_bool -grn_ts_table_has_value(grn_ctx *ctx, grn_obj *table) { - return DB_OBJ(table)->range != GRN_DB_VOID; -} - -/* - * grn_ts_table_get_value() gets a reference to a value (_value). On failure, - * this function returns NULL. - */ -static const void * -grn_ts_table_get_value(grn_ctx *ctx, grn_obj *table, grn_ts_id id) { - switch (table->header.type) { - case GRN_TABLE_HASH_KEY: { - uint32_t size; - return grn_hash_get_value_(ctx, (grn_hash *)table, id, &size); - } - case GRN_TABLE_PAT_KEY: { - uint32_t size; - return grn_pat_get_value_(ctx, (grn_pat *)table, id, &size); - } - /* GRN_TABLE_DAT_KEY does not support _value. */ - case GRN_TABLE_NO_KEY: { - return _grn_array_get_value(ctx, (grn_array *)table, id); - } - default: { - return NULL; - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_id_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_id_node; - -/* grn_ts_expr_id_node_init() initializes a node. */ -static void -grn_ts_expr_id_node_init(grn_ctx *ctx, grn_ts_expr_id_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_ID_NODE; - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_UINT32; -} - -/* grn_ts_expr_id_node_fin() finalizes a node. */ -static void -grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) { - /* Nothing to do. */ -} - -/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */ -static grn_rc -grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { - grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_id_node)); - } - grn_ts_expr_id_node_init(ctx, new_node); - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_id_node_close() destroys a node. */ -static void -grn_ts_expr_id_node_close(grn_ctx *ctx, grn_ts_expr_id_node *node) { - grn_ts_expr_id_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_id_node_evaluate() outputs IDs. */ -static grn_rc -grn_ts_expr_id_node_evaluate(grn_ctx *ctx, grn_ts_expr_id_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - size_t i; - grn_ts_int *out_ptr = (grn_ts_int *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = (grn_ts_int)in[i].id; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_score_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_score_node; - -/* grn_ts_expr_score_node_init() initializes a node. */ -static void -grn_ts_expr_score_node_init(grn_ctx *ctx, grn_ts_expr_score_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_SCORE_NODE; - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; -} - -/* grn_ts_expr_score_node_fin() finalizes a node. */ -static void -grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) { - /* Nothing to do. */ -} - -/* - * grn_ts_expr_score_node_open() creates a node associated with scores - * (_score). - */ -static grn_rc -grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { - grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_score_node)); - } - grn_ts_expr_score_node_init(ctx, new_node); - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_score_node_close() destroys a node. */ -static void -grn_ts_expr_score_node_close(grn_ctx *ctx, grn_ts_expr_score_node *node) { - grn_ts_expr_score_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_score_node_evaluate() outputs scores. */ -static grn_rc -grn_ts_expr_score_node_evaluate(grn_ctx *ctx, grn_ts_expr_score_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_ts_float *out_ptr = (grn_ts_float *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = (grn_ts_float)in[i].score; - } - return GRN_SUCCESS; -} - -/* grn_ts_expr_score_node_adjust() does nothing. */ -static grn_rc -grn_ts_expr_score_node_adjust(grn_ctx *ctx, grn_ts_expr_score_node *node, - grn_ts_record *io, size_t n_io) { - /* Nothing to do. */ - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_key_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *table; - grn_ts_buf buf; -} grn_ts_expr_key_node; - -/* grn_ts_expr_key_node_init() initializes a node. */ -static void -grn_ts_expr_key_node_init(grn_ctx *ctx, grn_ts_expr_key_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_KEY_NODE; - node->table = NULL; - grn_ts_buf_init(ctx, &node->buf); -} - -/* grn_ts_expr_key_node_fin() finalizes a node. */ -static void -grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) { - grn_ts_buf_fin(ctx, &node->buf); - if (node->table) { - grn_obj_unlink(ctx, node->table); - } -} - -/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */ -static grn_rc -grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_key_node *new_node; - if (!grn_ts_table_has_key(ctx, table)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "the table has no _key"); - } - new_node = GRN_MALLOCN(grn_ts_expr_key_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_key_node)); - } - grn_ts_expr_key_node_init(ctx, new_node); - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - grn_ts_expr_key_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - new_node->data_kind = grn_ts_data_type_to_kind(table->header.domain); - new_node->data_type = table->header.domain; - new_node->table = table; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_key_node_close() destroys a node. */ -static void -grn_ts_expr_key_node_close(grn_ctx *ctx, grn_ts_expr_key_node *node) { - grn_ts_expr_key_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(table, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ ## kind ## _key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_ ## kind ## _zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(table, TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ ## type ## _key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_int_zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(table)\ - case GRN_TS_TEXT: {\ - char *buf_ptr;\ - grn_ts_text *out_ptr = (grn_ts_text *)out;\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - grn_ts_text key;\ - rc = grn_ts_ ## table ## _get_text_key(ctx, table, in[i].id, &key);\ - if (rc != GRN_SUCCESS) {\ - key = grn_ts_text_zero();\ - }\ - rc = grn_ts_buf_write(ctx, &node->buf, key.ptr, key.size);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - out_ptr[i].size = key.size;\ - }\ - buf_ptr = (char *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(table)\ - case GRN_TS_REF: {\ - grn_ts_ref *out_ptr = (grn_ts_ref *)out;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_ ## table ## _get_ref_key(ctx, table, in[i].id,\ - &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - out_ptr[i] = grn_ts_ref_zero();\ - }\ - out_ptr[i].score = in[i].score;\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_key_node_evaluate() outputs keys. */ -static grn_rc -grn_ts_expr_key_node_evaluate(grn_ctx *ctx, grn_ts_expr_key_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_rc rc; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT8, int8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT16, int16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT32, int32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT64, int64) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT8, uint8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT16, uint16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT32, uint32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT64, uint64) - } - } - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, FLOAT, float) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, TIME, time) - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(hash) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, GEO, geo) - GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(hash) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT8, int8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT16, int16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT32, int32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT64, int64) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT8, uint8) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT16, uint16) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT32, uint32) - GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT64, uint64) - } - } - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, FLOAT, float) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, TIME, time) - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(pat) - GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, GEO, geo) - GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(pat) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - case GRN_TABLE_DAT_KEY: { - grn_dat *dat = (grn_dat *)node->table; - switch (node->data_kind) { - GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(dat) - /* GRN_TABLE_DAT_KEY supports only Text. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } - } - /* GRN_TABLE_NO_KEY doesn't support _key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE -#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE - -/* grn_ts_expr_key_node_filter() filters records. */ -static grn_rc -grn_ts_expr_key_node_filter(grn_ctx *ctx, grn_ts_expr_key_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_ts_bool key; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - for (i = 0, count = 0; i < n_in; i++) { - grn_rc rc = grn_ts_hash_get_bool_key(ctx, hash, in[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_bool_zero(); - } - if (key) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - for (i = 0, count = 0; i < n_in; i++) { - grn_rc rc = grn_ts_pat_get_bool_key(ctx, pat, in[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_bool_zero(); - } - if (key) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; - } - /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Bool key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} - -/* grn_ts_expr_key_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_key_node_adjust(grn_ctx *ctx, grn_ts_expr_key_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_float key; - switch (node->table->header.type) { - case GRN_TABLE_HASH_KEY: { - grn_hash *hash = (grn_hash *)node->table; - for (i = 0; i < n_io; i++) { - grn_rc rc = grn_ts_hash_get_float_key(ctx, hash, io[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_float_zero(); - } - io[i].score = (grn_ts_score)key; - } - return GRN_SUCCESS; - } - case GRN_TABLE_PAT_KEY: { - grn_pat *pat = (grn_pat *)node->table; - for (i = 0; i < n_io; i++) { - grn_rc rc = grn_ts_pat_get_float_key(ctx, pat, io[i].id, &key); - if (rc != GRN_SUCCESS) { - key = grn_ts_float_zero(); - } - io[i].score = (grn_ts_score)key; - } - return GRN_SUCCESS; - } - /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Float key. */ - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", - node->table->header.type); - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_value_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *table; -} grn_ts_expr_value_node; - -/* grn_ts_expr_value_node_init() initializes a node. */ -static void -grn_ts_expr_value_node_init(grn_ctx *ctx, grn_ts_expr_value_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_VALUE_NODE; - node->table = NULL; -} - -/* grn_ts_expr_value_node_fin() finalizes a node. */ -static void -grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) { - if (node->table) { - grn_obj_unlink(ctx, node->table); - } -} - -/* - * grn_ts_expr_value_node_open() creates a node associated with values - * (_value). - */ -static grn_rc -grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_value_node *new_node; - if (!grn_ts_table_has_value(ctx, table)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table has no _value"); - } - new_node = GRN_MALLOCN(grn_ts_expr_value_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_value_node)); - } - grn_ts_expr_value_node_init(ctx, new_node); - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - GRN_FREE(new_node); - return rc; - } - new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(table)->range); - new_node->data_type = DB_OBJ(table)->range; - new_node->table = table; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_value_node_close() destroys a node. */ -static void -grn_ts_expr_value_node_close(grn_ctx *ctx, grn_ts_expr_value_node *node) { - grn_ts_expr_value_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ - if (ptr) {\ - out_ptr[i] = *(const grn_ts_ ## kind *)ptr;\ - } else {\ - out_ptr[i] = grn_ts_ ## kind ## _zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - for (i = 0; i < n_in; i++) {\ - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ - if (ptr) {\ - out_ptr[i] = (grn_ts_int)*(const type ## _t *)ptr;\ - } else {\ - out_ptr[i] = grn_ts_int_zero();\ - }\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_value_node_evaluate() outputs values. */ -static grn_rc -grn_ts_expr_value_node_evaluate(grn_ctx *ctx, grn_ts_expr_value_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT8, int8) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT16, int16) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT32, int32) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT64, int64) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT32, uint32) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(FLOAT, float) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(TIME, time) - GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(GEO, geo) - case GRN_TS_REF: { - size_t i; - grn_ts_ref *out_ptr = (grn_ts_ref *)out; - for (i = 0; i < n_in; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); - if (ptr) { - out_ptr[i].id = *(const grn_ts_id *)ptr; - out_ptr[i].score = in[i].score; - } else { - out_ptr[i] = grn_ts_ref_zero(); - } - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE -#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE - -/* grn_ts_expr_value_node_filter() filters records. */ -static grn_rc -grn_ts_expr_value_node_filter(grn_ctx *ctx, grn_ts_expr_value_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count = 0; - for (i = 0; i < n_in; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); - if (ptr && *(const grn_ts_bool *)ptr) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_value_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_value_node_adjust(grn_ctx *ctx, grn_ts_expr_value_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - for (i = 0; i < n_io; i++) { - const void *ptr = grn_ts_table_get_value(ctx, node->table, io[i].id); - if (ptr) { - io[i].score = (grn_ts_score)*(const grn_ts_float *)ptr; - } - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_const_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_any content; - grn_ts_buf text_buf; - grn_ts_buf vector_buf; -} grn_ts_expr_const_node; - -/* grn_ts_expr_const_node_init() initializes a node. */ -static void -grn_ts_expr_const_node_init(grn_ctx *ctx, grn_ts_expr_const_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_CONST_NODE; - grn_ts_buf_init(ctx, &node->text_buf); - grn_ts_buf_init(ctx, &node->vector_buf); -} - -/* grn_ts_expr_const_node_fin() finalizes a node. */ -static void -grn_ts_expr_const_node_fin(grn_ctx *ctx, grn_ts_expr_const_node *node) { - grn_ts_buf_fin(ctx, &node->vector_buf); - grn_ts_buf_fin(ctx, &node->text_buf); -} - -#define GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - node->content.as_ ## kind = *(const grn_ts_ ## kind *)value;\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_const_node_set_scalar() sets a scalar value. */ -static grn_rc -grn_ts_expr_const_node_set_scalar(grn_ctx *ctx, grn_ts_expr_const_node *node, - const void *value) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(TIME, time) - case GRN_TS_TEXT: { - grn_ts_text text_value = *(const grn_ts_text *)value; - grn_rc rc = grn_ts_buf_write(ctx, &node->text_buf, - text_value.ptr, text_value.size); - if (rc != GRN_SUCCESS) { - return rc; - } - node->content.as_text.ptr = (const char *)node->text_buf.ptr; - node->content.as_text.size = text_value.size; - return GRN_SUCCESS; - } - GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(GEO, geo) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE - -#define GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND ## _VECTOR: {\ - grn_rc rc;\ - size_t n_bytes;\ - const grn_ts_ ## kind *buf_ptr;\ - grn_ts_ ## kind ## _vector vector;\ - vector = *(const grn_ts_ ## kind ## _vector *)value;\ - n_bytes = sizeof(grn_ts_ ## kind) * vector.size;\ - rc = grn_ts_buf_write(ctx, &node->vector_buf, vector.ptr, n_bytes);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptr = (const grn_ts_ ## kind *)node->vector_buf.ptr;\ - node->content.as_ ## kind ## _vector.ptr = buf_ptr;\ - node->content.as_ ## kind ## _vector.size = vector.size;\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_const_node_set_vector() sets a vector value. */ -static grn_rc -grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node, - const void *value) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(TIME, time) - case GRN_TS_TEXT_VECTOR: { - grn_rc rc; - size_t i, n_bytes, offset, total_size; - grn_ts_text_vector vector = *(const grn_ts_text_vector *)value; - grn_ts_text *vector_buf; - char *text_buf; - n_bytes = sizeof(grn_ts_text) * vector.size; - rc = grn_ts_buf_resize(ctx, &node->vector_buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - vector_buf = (grn_ts_text *)node->vector_buf.ptr; - total_size = 0; - for (i = 0; i < vector.size; i++) { - total_size += vector.ptr[i].size; - } - rc = grn_ts_buf_resize(ctx, &node->text_buf, total_size); - if (rc != GRN_SUCCESS) { - return rc; - } - text_buf = (char *)node->text_buf.ptr; - offset = 0; - for (i = 0; i < vector.size; i++) { - grn_memcpy(text_buf + offset, vector.ptr[i].ptr, vector.ptr[i].size); - vector_buf[i].ptr = text_buf + offset; - vector_buf[i].size = vector.ptr[i].size; - offset += vector.ptr[i].size; - } - node->content.as_text_vector.ptr = vector_buf; - node->content.as_text_vector.size = vector.size; - return GRN_SUCCESS; - } - GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(GEO, geo) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE - -/* grn_ts_expr_const_node_open() creates a node associated with a const. */ -static grn_rc -grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, - const void *value, grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_const_node *new_node = GRN_MALLOCN(grn_ts_expr_const_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_const_node)); - } - grn_ts_expr_const_node_init(ctx, new_node); - new_node->data_kind = kind; - new_node->data_type = grn_ts_data_kind_to_type(kind); - if (kind & GRN_TS_VECTOR_FLAG) { - rc = grn_ts_expr_const_node_set_vector(ctx, new_node, value); - } else { - rc = grn_ts_expr_const_node_set_scalar(ctx, new_node, value); - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_const_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_node_close() destroys a node. */ -static void -grn_ts_expr_const_node_close(grn_ctx *ctx, grn_ts_expr_const_node *node) { - grn_ts_expr_const_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = node->content.as_ ## kind;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND ## _VECTOR, kind ## _vector) -/* grn_ts_expr_const_node_evaluate() outputs the stored const. */ -static grn_rc -grn_ts_expr_const_node_evaluate(grn_ctx *ctx, grn_ts_expr_const_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TIME, time) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TEXT, text) - GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(GEO, geo) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(INT, int) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TIME, time) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TEXT, text) - GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(GEO, geo) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE -#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE - -/* grn_ts_expr_const_node_filter() filters records. */ -static grn_rc -grn_ts_expr_const_node_filter(grn_ctx *ctx, grn_ts_expr_const_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (node->content.as_bool) { - /* All the records pass through the filter. */ - if (in != out) { - size_t i; - for (i = 0; i < n_in; i++) { - out[i] = in[i]; - } - } - *n_out = n_in; - } else { - /* All the records are discarded. */ - *n_out = 0; - } - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_const_node_adjust(grn_ctx *ctx, grn_ts_expr_const_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_score score = (grn_ts_score)node->content.as_float; - for (i = 0; i < n_io; i++) { - io[i].score = score; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_column_node. - */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_obj *column; - grn_ts_buf buf; - grn_ts_buf body_buf; -} grn_ts_expr_column_node; - -/* grn_ts_expr_column_node_init() initializes a node. */ -static void -grn_ts_expr_column_node_init(grn_ctx *ctx, grn_ts_expr_column_node *node) { - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_COLUMN_NODE; - node->column = NULL; - grn_ts_buf_init(ctx, &node->buf); - grn_ts_buf_init(ctx, &node->body_buf); -} - -/* grn_ts_expr_column_node_fin() finalizes a node. */ -static void -grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) { - grn_ts_buf_fin(ctx, &node->body_buf); - grn_ts_buf_fin(ctx, &node->buf); - if (node->column) { - grn_obj_unlink(ctx, node->column); - } -} - -#define GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE(TYPE)\ - case GRN_DB_ ## TYPE: {\ - GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\ - break;\ - } -/* grn_ts_expr_column_node_open() creates a node associated with a column. */ -static grn_rc -grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, - grn_ts_expr_node **node) { - grn_rc rc; - grn_ts_expr_column_node *new_node = GRN_MALLOCN(grn_ts_expr_column_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_column_node)); - } - grn_ts_expr_column_node_init(ctx, new_node); - new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(column)->range); - if (column->header.type == GRN_COLUMN_VAR_SIZE) { - grn_obj_flags type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; - if (type == GRN_OBJ_COLUMN_VECTOR) { - new_node->data_kind |= GRN_TS_VECTOR_FLAG; - } - } - new_node->data_type = DB_OBJ(column)->range; - rc = grn_ts_obj_increment_ref_count(ctx, column); - if (rc != GRN_SUCCESS) { - grn_ts_expr_column_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - new_node->column = column; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} -#undef GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE - -/* grn_ts_expr_column_node_close() destroys a node. */ -static void -grn_ts_expr_column_node_close(grn_ctx *ctx, grn_ts_expr_column_node *node) { - grn_ts_expr_column_node_fin(ctx, node); - GRN_FREE(node); -} - -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - size_t i;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - grn_ra *ra = (grn_ra *)node->column;\ - grn_ra_cache cache;\ - GRN_RA_CACHE_INIT(ra, &cache);\ - for (i = 0; i < n_in; i++) {\ - grn_ts_ ## kind *ptr = NULL;\ - if (in[i].id) {\ - ptr = (grn_ts_ ## kind *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ - }\ - out_ptr[i] = ptr ? *ptr : grn_ts_ ## kind ## _zero();\ - }\ - GRN_RA_CACHE_FIN(ra, &cache);\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - grn_ra *ra = (grn_ra *)node->column;\ - grn_ra_cache cache;\ - GRN_RA_CACHE_INIT(ra, &cache);\ - for (i = 0; i < n_in; i++) {\ - type ## _t *ptr = NULL;\ - if (in[i].id) {\ - ptr = (type ## _t *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ - }\ - out_ptr[i] = ptr ? (grn_ts_int)*ptr : grn_ts_int_zero();\ - }\ - GRN_RA_CACHE_FIN(ra, &cache);\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_column_node_evaluate_scalar() outputs scalar column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate_scalar(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(BOOL, bool) - case GRN_TS_INT: { - switch (node->data_type) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT8, int8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT16, int16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT32, int32) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT64, int64) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT32, uint32) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(FLOAT, float) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(TIME, time) - case GRN_TS_TEXT: { - size_t i, size; - char *buf_ptr; - grn_ja *ja = (grn_ja *)node->column; - grn_ts_text *out_ptr = (grn_ts_text *)out; - /* Read column values into node->buf and save the size of each value. */ - node->buf.pos = 0; - for (i = 0; i < n_in; i++) { - grn_rc rc = grn_ts_ja_get_value(ctx, ja, in[i].id, &node->buf, &size); - out_ptr[i].size = (rc == GRN_SUCCESS) ? size : 0; - } - buf_ptr = (char *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - out_ptr[i].ptr = buf_ptr; - buf_ptr += out_ptr[i].size; - } - return GRN_SUCCESS; - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(GEO, geo) - case GRN_TS_REF: { - size_t i; - grn_ts_ref *out_ptr = (grn_ts_ref *)out; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_in; i++) { - grn_ts_id *ptr = NULL; - if (in[i].id) { - ptr = (grn_ts_id *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache); - } - out_ptr[i].id = ptr ? *ptr : GRN_ID_NIL; - out_ptr[i].score = in[i].score; - } - GRN_RA_CACHE_FIN(ra, &cache); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE - -/* - * grn_ts_expr_column_node_evaluate_text_vector() outputs text vector column - * values. - */ -static grn_rc -grn_ts_expr_column_node_evaluate_text_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, - size_t n_in, void *out) { - grn_rc rc; - char *buf_ptr; - size_t i, j, n_bytes, n_values, total_n_bytes = 0, total_n_values = 0; - grn_ts_text *text_ptr; - grn_ts_text_vector *out_ptr = (grn_ts_text_vector *)out; - /* Read encoded values into node->body_buf and get the size of each value. */ - node->body_buf.pos = 0; - for (i = 0; i < n_in; i++) { - char *ptr; - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id, - &node->body_buf, &n_bytes); - if (rc == GRN_SUCCESS) { - ptr = (char *)node->body_buf.ptr + total_n_bytes; - GRN_B_DEC(n_values, ptr); - } else { - n_bytes = 0; - n_values = 0; - } - grn_memcpy(&out_ptr[i].ptr, &n_bytes, sizeof(n_bytes)); - out_ptr[i].size = n_values; - total_n_bytes += n_bytes; - total_n_values += n_values; - } - /* Resize node->buf. */ - n_bytes = sizeof(grn_ts_text) * total_n_values; - rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Decode values and compose the result. */ - buf_ptr = (char *)node->body_buf.ptr; - text_ptr = (grn_ts_text *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - char *ptr = buf_ptr; - grn_memcpy(&n_bytes, &out_ptr[i].ptr, sizeof(n_bytes)); - buf_ptr += n_bytes; - GRN_B_DEC(n_values, ptr); - out_ptr[i].ptr = text_ptr; - for (j = 0; j < out_ptr[i].size; j++) { - GRN_B_DEC(text_ptr[j].size, ptr); - } - for (j = 0; j < out_ptr[i].size; j++) { - text_ptr[j].ptr = ptr; - ptr += text_ptr[j].size; - } - text_ptr += out_ptr[i].size; - } - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_column_node_evaluate_ref_vector() outputs ref vector column - * values. - */ -static grn_rc -grn_ts_expr_column_node_evaluate_ref_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, - size_t n_in, void *out) { - grn_rc rc; - size_t i, j, n_bytes, offset = 0; - grn_ts_id *buf_ptr; - grn_ts_ref *ref_ptr; - grn_ts_ref_vector *out_ptr = (grn_ts_ref_vector *)out; - /* Read column values into node->body_buf and get the size of each value. */ - node->body_buf.pos = 0; - for (i = 0; i < n_in; i++) { - size_t size; - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id, - &node->body_buf, &size); - if (rc == GRN_SUCCESS) { - out_ptr[i].size = size / sizeof(grn_ts_id); - offset += out_ptr[i].size; - } else { - out_ptr[i].size = 0; - } - } - /* Resize node->buf. */ - n_bytes = sizeof(grn_ts_ref) * offset; - rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Compose the result. */ - buf_ptr = (grn_ts_id *)node->body_buf.ptr; - ref_ptr = (grn_ts_ref *)node->buf.ptr; - for (i = 0; i < n_in; i++) { - out_ptr[i].ptr = ref_ptr; - for (j = 0; j < out_ptr[i].size; j++, buf_ptr++, ref_ptr++) { - ref_ptr->id = *buf_ptr; - ref_ptr->score = in[i].score; - } - } - return GRN_SUCCESS; -} - -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ - case GRN_TS_ ## KIND ## _VECTOR: {\ - size_t i;\ - grn_ts_ ## kind *buf_ptr;\ - grn_ts_ ## kind ## _vector *out_ptr = (grn_ts_ ## kind ## _vector *)out;\ - /* Read column values into node->buf and save the size of each value. */\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - size_t n_bytes;\ - grn_rc rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\ - &node->buf, &n_bytes);\ - if (rc == GRN_SUCCESS) {\ - out_ptr[i].size = n_bytes / sizeof(grn_ts_ ## kind);\ - } else {\ - out_ptr[i].size = 0;\ - }\ - }\ - buf_ptr = (grn_ts_ ## kind *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(TYPE, type)\ - case GRN_DB_ ## TYPE: {\ - size_t i, j;\ - grn_ts_int *buf_ptr;\ - grn_ts_int_vector *out_ptr = (grn_ts_int_vector *)out;\ - /* - * Read column values into body_buf and typecast the values to grn_ts_int. - * Then, store the grn_ts_int values into node->buf and save the size of - * each value. - */\ - node->buf.pos = 0;\ - for (i = 0; i < n_in; i++) {\ - grn_rc rc;\ - size_t n_bytes, new_n_bytes;\ - node->body_buf.pos = 0;\ - rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\ - &node->body_buf, &n_bytes);\ - if (rc == GRN_SUCCESS) {\ - out_ptr[i].size = n_bytes / sizeof(type ## _t);\ - } else {\ - out_ptr[i].size = 0;\ - }\ - new_n_bytes = node->buf.pos + (sizeof(grn_ts_int) * out_ptr[i].size);\ - rc = grn_ts_buf_reserve(ctx, &node->buf, new_n_bytes);\ - if (rc == GRN_SUCCESS) {\ - type ## _t *src_ptr = (type ## _t *)node->body_buf.ptr;\ - grn_ts_int *dest_ptr;\ - dest_ptr = (grn_ts_int *)((char *)node->buf.ptr + node->buf.pos);\ - for (j = 0; j < out_ptr[i].size; j++) {\ - dest_ptr[j] = (grn_ts_int)src_ptr[j];\ - }\ - node->buf.pos = new_n_bytes;\ - } else {\ - out_ptr[i].size = 0;\ - }\ - }\ - buf_ptr = (grn_ts_int *)node->buf.ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i].ptr = buf_ptr;\ - buf_ptr += out_ptr[i].size;\ - }\ - return GRN_SUCCESS;\ - } -/* grn_ts_expr_column_node_evaluate_vector() outputs vector column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate_vector(grn_ctx *ctx, - grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) - case GRN_TS_INT_VECTOR: { - switch (node->data_type) { - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT8, int8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT16, int16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT32, int32) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT64, int64) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT8, uint8) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT16, uint16) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT32, uint32) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT64, uint64) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", - node->data_type); - } - } - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(TIME, time) - case GRN_TS_TEXT_VECTOR: { - return grn_ts_expr_column_node_evaluate_text_vector(ctx, node, in, n_in, - out); - } - GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(GEO, geo) - case GRN_TS_REF_VECTOR: { - return grn_ts_expr_column_node_evaluate_ref_vector(ctx, node, in, n_in, - out); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE -#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE - -/* grn_ts_expr_column_node_evaluate() outputs column values. */ -static grn_rc -grn_ts_expr_column_node_evaluate(grn_ctx *ctx, grn_ts_expr_column_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - if (node->data_kind & GRN_TS_VECTOR_FLAG) { - return grn_ts_expr_column_node_evaluate_vector(ctx, node, in, n_in, out); - } else { - return grn_ts_expr_column_node_evaluate_scalar(ctx, node, in, n_in, out); - } -} - -/* grn_ts_expr_column_node_filter() filters records. */ -static grn_rc -grn_ts_expr_column_node_filter(grn_ctx *ctx, grn_ts_expr_column_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count = 0; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_in; i++) { - grn_ts_bool *ptr = NULL; - if (in[i].id) { - ptr = grn_ra_ref_cache(ctx, ra, in[i].id, &cache); - } - if (ptr && *ptr) { - out[count++] = in[i]; - } - } - GRN_RA_CACHE_FIN(ra, &cache); - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_column_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_column_node_adjust(grn_ctx *ctx, grn_ts_expr_column_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ra *ra = (grn_ra *)node->column; - grn_ra_cache cache; - GRN_RA_CACHE_INIT(ra, &cache); - for (i = 0; i < n_io; i++) { - grn_ts_float *ptr = NULL; - if (io[i].id) { - ptr = grn_ra_ref_cache(ctx, ra, io[i].id, &cache); - } - if (ptr) { - io[i].score = (grn_ts_score)*ptr; - } - } - GRN_RA_CACHE_FIN(ra, &cache); - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_op_node. - */ - -enum { - GRN_TS_EXPR_OP_NODE_MAX_N_ARGS = 3, - GRN_TS_EXPR_OP_NODE_N_BUFS = 3 -}; - -/* Forward declarations. */ -static void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node); -static grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, - void *out); -static grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, - grn_ts_expr_node *node, - const grn_ts_record *in, - size_t n_in, - grn_ts_buf *out); -static grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out); -static grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *io, size_t n_io); - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_op_type op_type; - grn_ts_expr_node *args[GRN_TS_EXPR_OP_NODE_MAX_N_ARGS]; - size_t n_args; - grn_ts_buf bufs[GRN_TS_EXPR_OP_NODE_N_BUFS]; -} grn_ts_expr_op_node; - -/* grn_ts_expr_op_node_init() initializes a node. */ -static void -grn_ts_expr_op_node_init(grn_ctx *ctx, grn_ts_expr_op_node *node) { - size_t i; - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_OP_NODE; - for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) { - node->args[i] = NULL; - } - for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { - grn_ts_buf_init(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_op_node_fin() finalizes a node. */ -static void -grn_ts_expr_op_node_fin(grn_ctx *ctx, grn_ts_expr_op_node *node) { - size_t i; - for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { - grn_ts_buf_fin(ctx, &node->bufs[i]); - } - for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) { - if (node->args[i]) { - grn_ts_expr_node_close(ctx, node->args[i]); - } - } -} - -/* - * grn_ts_op_plus_check_args() checks arguments. Note that arguments are - * rearranged in some cases. - */ -static grn_rc -grn_ts_op_plus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: { - /* Int + Int = Int. */ - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Int + Time = Time + Int = Time. */ - grn_ts_expr_node *tmp = node->args[0]; - node->args[0] = node->args[1]; - node->args[1] = tmp; - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - case GRN_TS_FLOAT: { - switch (node->args[1]->data_kind) { - case GRN_TS_FLOAT: { - /* Float + Float = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Float + Time = Time + Float = Time. */ - grn_ts_expr_node *tmp = node->args[0]; - node->args[0] = node->args[1]; - node->args[1] = tmp; - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - /* Time + Int or Float = Time. */ - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_minus_check_args() checks arguments. */ -static grn_rc -grn_ts_op_minus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - if (node->args[1]->data_kind != GRN_TS_INT) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - /* Int - Int = Int. */ - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_FLOAT: { - if (node->args[1]->data_kind != GRN_TS_FLOAT) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - /* Float - Float = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - /* Time - Int or Float = Time. */ - node->data_kind = GRN_TS_TIME; - node->data_type = GRN_DB_TIME; - return GRN_SUCCESS; - } - case GRN_TS_TIME: { - /* Time - Time = Float. */ - node->data_kind = GRN_TS_FLOAT; - node->data_type = GRN_DB_FLOAT; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* - * grn_ts_expr_op_node_check_args() checks the combination of an operator and - * its arguments. - */ -static grn_rc -grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - if (node->args[0]->data_kind != GRN_TS_BOOL) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_BITWISE_NOT: { - switch (node->args[0]->data_kind) { - case GRN_TS_BOOL: - case GRN_TS_INT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - } - case GRN_TS_OP_POSITIVE: - case GRN_TS_OP_NEGATIVE: { - if ((node->args[0]->data_kind != GRN_TS_INT) && - (node->args[0]->data_kind != GRN_TS_FLOAT)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - case GRN_TS_OP_LOGICAL_AND: - case GRN_TS_OP_LOGICAL_OR: - case GRN_TS_OP_LOGICAL_SUB: { - if ((node->args[0]->data_kind != GRN_TS_BOOL) || - (node->args[1]->data_kind != GRN_TS_BOOL)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_BITWISE_AND: - case GRN_TS_OP_BITWISE_OR: - case GRN_TS_OP_BITWISE_XOR: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_BOOL: - case GRN_TS_INT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_EQUAL: - case GRN_TS_OP_NOT_EQUAL: { - grn_ts_data_kind scalar_data_kind; - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - scalar_data_kind = node->args[0]->data_kind & ~GRN_TS_VECTOR_FLAG; - if (((scalar_data_kind == GRN_TS_REF) || - (scalar_data_kind == GRN_TS_GEO)) && - (node->args[0]->data_type != node->args[1]->data_type)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data type conflict: %d != %d", - node->args[0]->data_type, node->args[1]->data_type); - } - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - case GRN_TS_OP_LESS: - case GRN_TS_OP_LESS_EQUAL: - case GRN_TS_OP_GREATER: - case GRN_TS_OP_GREATER_EQUAL: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", - node->args[0]->data_kind, node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: - case GRN_TS_TIME: - case GRN_TS_TEXT: - case GRN_TS_INT_VECTOR: - case GRN_TS_FLOAT_VECTOR: - case GRN_TS_TIME_VECTOR: - case GRN_TS_TEXT_VECTOR: { - node->data_kind = GRN_TS_BOOL; - node->data_type = GRN_DB_BOOL; - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - if ((node->args[0]->data_kind != GRN_TS_INT) || - (node->args[1]->data_kind != GRN_TS_INT)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - node->data_kind = GRN_TS_INT; - node->data_type = GRN_DB_INT64; - return GRN_SUCCESS; - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_check_args(ctx, node); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_check_args(ctx, node); - } - case GRN_TS_OP_MULTIPLICATION: - case GRN_TS_OP_DIVISION: - case GRN_TS_OP_MODULUS: { - if (node->args[0]->data_kind != node->args[1]->data_kind) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, - "data kind conflict: %d != %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - switch (node->args[0]->data_kind) { - case GRN_TS_INT: - case GRN_TS_FLOAT: { - node->data_kind = node->args[0]->data_kind; - node->data_type = grn_ts_data_kind_to_type(node->data_kind); - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid operator: %d", - node->op_type); - } - } -} - -/* grn_ts_expr_op_node_open() creates a node associated with an operator. */ -static grn_rc -grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, - grn_ts_expr_node **args, size_t n_args, - grn_ts_expr_node **node) { - size_t i; - grn_rc rc; - grn_ts_expr_op_node *new_node = GRN_MALLOCN(grn_ts_expr_op_node, 1); - if (!new_node) { - for (i = 0; i < n_args; i++) { - grn_ts_expr_node_close(ctx, args[i]); - } - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_op_node)); - } - grn_ts_expr_op_node_init(ctx, new_node); - new_node->op_type = op_type; - for (i = 0; i < n_args; i++) { - new_node->args[i] = args[i]; - } - new_node->n_args = n_args; - - /* Check arguments. */ - rc = grn_ts_expr_op_node_check_args(ctx, new_node); - if (rc == GRN_SUCCESS) { - if (new_node->data_kind == GRN_TS_VOID) { - GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data kind: %d", GRN_TS_VOID); - rc = ctx->rc; - } else if (new_node->data_type == GRN_DB_VOID) { - GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data type: %d", GRN_DB_VOID); - rc = ctx->rc; - } - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_op_node_fin(ctx, new_node); - GRN_FREE(new_node); - return rc; - } - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_op_node_close() destroys a node. */ -static void -grn_ts_expr_op_node_close(grn_ctx *ctx, grn_ts_expr_op_node *node) { - grn_ts_expr_op_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_op_logical_not_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_ts_bool *out_ptr = (grn_ts_bool *)out; - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_logical_not_bool(out_ptr[i]); - } - return GRN_SUCCESS; -} - -/* grn_ts_op_bitwise_not_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i; - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); - if (rc != GRN_SUCCESS) { - return rc; - } - switch (node->data_kind) { - case GRN_TS_BOOL: { - grn_ts_bool *out_ptr = (grn_ts_bool *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_bitwise_not_bool(out_ptr[i]); - } - return GRN_SUCCESS; - } - case GRN_TS_INT: { - grn_ts_int *out_ptr = (grn_ts_int *)out; - for (i = 0; i < n_in; i++) { - out_ptr[i] = grn_ts_op_bitwise_not_int(out_ptr[i]); - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -#define GRN_TS_OP_SIGN_EVALUATE_CASE(type, KIND, kind) \ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_SIGN_EVALUATE(type) \ - size_t i;\ - grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - switch (node->data_kind) {\ - GRN_TS_OP_SIGN_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_SIGN_EVALUATE_CASE(type, FLOAT, float)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->data_kind);\ - }\ - } -/* grn_ts_op_positive_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_positive_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_SIGN_EVALUATE(positive) -} - -/* grn_ts_op_negative_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_negative_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_SIGN_EVALUATE(negative) -} -#undef GRN_TS_OP_SIGN_EVALUATE -#undef GRN_TS_OP_SIGN_EVALUATE_CASE - -/* grn_ts_op_logical_and_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of true records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] && buf_ptrs[1][j++]; - } - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_or_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of false records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (!buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] || buf_ptrs[1][j++]; - } - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_sub_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_logical_sub_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of true records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - out_ptr[count++] = buf_ptrs[0][i] && - grn_ts_op_logical_not_bool(buf_ptrs[1][j++]); - } - return GRN_SUCCESS; -} - -#define GRN_TS_OP_BITWISE_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_bitwise_ ## type ## _ ## kind(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -/* grn_ts_op_bitwise_and_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(and, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(and, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_bitwise_or_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(or, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(or, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_bitwise_xor_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_bitwise_xor_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->args[0]->data_kind) { - GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, BOOL, bool) - GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, INT, int) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} -#undef GRN_TS_OP_BITWISE_EVALUATE_CASE - -#define GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ - buf_ptrs[1][i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CHK_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ - if (node->args[0]->data_kind == GRN_TS_BOOL) {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_buf *buf = &node->bufs[0];\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, buf);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_bool *buf_ptr = (grn_ts_bool *)buf->ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _bool(out_ptr[i], buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - }\ - for (i = 0; i < 2; i++) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, GEO, geo)\ - GRN_TS_OP_CHK_EVALUATE_CASE(type, REF, ref)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, GEO, geo)\ - GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, REF, ref)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CHK_EVALUATE(equal) -} - -/* grn_ts_op_not_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_not_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CHK_EVALUATE(not_equal) -} -#undef GRN_TS_OP_CHK_EVALUATE -#undef GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE -#undef GRN_TS_OP_CHK_EVALUATE_CASE - -#define GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ - buf_ptrs[1][i]);\ - }\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CMP_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ - for (i = 0; i < 2; i++) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, INT, int)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_EVALUATE_CASE(type, TEXT, text)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TEXT, text)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_less_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_less_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CMP_EVALUATE(less) -} - -/* grn_ts_op_less_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_less_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_CMP_EVALUATE(less_equal) -} - -/* grn_ts_op_greater_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_greater_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - GRN_TS_OP_CMP_EVALUATE(greater) -} - -/* grn_ts_op_greater_equal_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_greater_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_CMP_EVALUATE(greater_equal) -} -#undef GRN_TS_OP_CMP_EVALUATE -#undef GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE -#undef GRN_TS_OP_CMP_EVALUATE_CASE - -#define GRN_TS_OP_SHIFT_EVALUATE(type)\ - size_t i;\ - grn_rc rc;\ - grn_ts_int *out_ptr = (grn_ts_int *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_shift_ ## type(out_ptr[i], buf_ptr[i]);\ - }\ - }\ - }\ - return rc; -/* grn_ts_op_shift_arithmetic_left_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_arithmetic_left_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(arithmetic_left) -} - -/* grn_ts_op_shift_arithmetic_right_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_arithmetic_right_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(arithmetic_right) -} - -/* grn_ts_op_shift_logical_left_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_logical_left_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(logical_left) -} - -/* grn_ts_op_shift_logical_right_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_shift_logical_right_evaluate(grn_ctx *ctx, - grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - GRN_TS_OP_SHIFT_EVALUATE(logical_right) -} -#undef GRN_TS_OP_SHIFT_EVALUATE - -#define GRN_TS_OP_ARITH_EVALUATE(type, lhs_kind, rhs_kind)\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## lhs_kind *out_ptr = (grn_ts_ ## lhs_kind *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## rhs_kind *buf_ptr = (grn_ts_ ## rhs_kind *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - rc = grn_ts_op_ ## type ## _ ## lhs_kind ## _ ## rhs_kind(\ - ctx, out_ptr[i], buf_ptr[i], &out_ptr[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - }\ - }\ - return rc; - -#define GRN_TS_OP_ARITH_EVALUATE_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -#define GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(type, KIND, lhs, rhs)\ - case GRN_TS_ ## KIND: {\ - /* - * Use the output buffer to put evaluation results of the 1st argument, - * because the data kind is same. - */\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## lhs *out_ptr = (grn_ts_ ## lhs *)out;\ - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ - in, n_in, &node->bufs[0]);\ - if (rc == GRN_SUCCESS) {\ - grn_ts_ ## rhs *buf_ptr = (grn_ts_ ## rhs *)node->bufs[0].ptr;\ - for (i = 0; i < n_in; i++) {\ - out_ptr[i] = grn_ts_op_ ## type ## _ ## lhs ## _ ## rhs(out_ptr[i],\ - buf_ptr[i]);\ - }\ - }\ - }\ - return rc;\ - } -/* grn_ts_op_plus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_plus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(plus, int, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(plus, float, float) - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(plus, time, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(plus, time, float) - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} - -/* grn_ts_op_minus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_minus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->args[0]->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(minus, int, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(minus, float, float) - } - case GRN_TS_TIME: { - switch (node->args[1]->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(minus, time, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(minus, time, float) - } - case GRN_TS_TIME: { - size_t i; - grn_rc rc; - grn_ts_float *out_ptr = (grn_ts_float *)out; - grn_ts_time *buf_ptrs[2]; - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], in, n_in, - &node->bufs[1]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_time *)node->bufs[0].ptr; - buf_ptrs[1] = (grn_ts_time *)node->bufs[1].ptr; - for (i = 0; i < n_in; i++) { - rc = grn_ts_op_minus_time_time(ctx, buf_ptrs[0][i], buf_ptrs[1][i], - &out_ptr[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", - node->args[0]->data_kind, - node->args[1]->data_kind); - } - } - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->args[0]->data_kind); - } - } -} -#undef GRN_TS_OP_ARITH_EVALUATE_TIME_CASE - -/* grn_ts_op_multiplication_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_multiplication_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(multiplication, int, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(multiplication, float, float) - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -/* grn_ts_op_division_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_division_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(division, int, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(division, float, float) - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} - -/* grn_ts_op_modulus_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_op_modulus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->data_kind) { - case GRN_TS_INT: { - GRN_TS_OP_ARITH_EVALUATE(modulus, int, int) - } - case GRN_TS_FLOAT: { - GRN_TS_OP_ARITH_EVALUATE(modulus, float, float) - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - node->data_kind); - } - } -} -#undef GRN_TS_OP_ARITH_EVALUATE_CASE - -/* grn_ts_expr_op_node_evaluate() evaluates an operator. */ -static grn_rc -grn_ts_expr_op_node_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - return grn_ts_op_logical_not_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_NOT: { - return grn_ts_op_bitwise_not_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_POSITIVE: { - return grn_ts_op_positive_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_NEGATIVE: { - return grn_ts_op_negative_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_AND: { - return grn_ts_op_logical_and_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_OR: { - return grn_ts_op_logical_or_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LOGICAL_SUB: { - return grn_ts_op_logical_sub_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_AND: { - return grn_ts_op_bitwise_and_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_OR: { - return grn_ts_op_bitwise_or_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_BITWISE_XOR: { - return grn_ts_op_bitwise_xor_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_EQUAL: { - return grn_ts_op_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_NOT_EQUAL: { - return grn_ts_op_not_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LESS: { - return grn_ts_op_less_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_LESS_EQUAL: { - return grn_ts_op_less_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_GREATER: { - return grn_ts_op_greater_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_GREATER_EQUAL: { - return grn_ts_op_greater_equal_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: { - return grn_ts_op_shift_arithmetic_left_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: { - return grn_ts_op_shift_arithmetic_right_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: { - return grn_ts_op_shift_logical_left_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - return grn_ts_op_shift_logical_right_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MULTIPLICATION: { - return grn_ts_op_multiplication_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_DIVISION: { - return grn_ts_op_division_evaluate(ctx, node, in, n_in, out); - } - case GRN_TS_OP_MODULUS: { - return grn_ts_op_modulus_evaluate(ctx, node, in, n_in, out); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -/* grn_ts_op_logical_not_filter() filters records. */ -static grn_rc -grn_ts_op_logical_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_rc rc; - grn_ts_bool *buf_ptr; - rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0, count = 0; i < n_in; i++) { - if (grn_ts_op_logical_not_bool(buf_ptr[i])) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_bitwise_not_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_rc rc; - grn_ts_bool *buf_ptr; - rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0, count = 0; i < n_in; i++) { - if (grn_ts_op_bitwise_not_bool(buf_ptr[i])) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_and_filter() filters records. */ -static grn_rc -grn_ts_op_logical_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, - out, n_out); - if (rc != GRN_SUCCESS) { - return rc; - } - return grn_ts_expr_node_filter(ctx, node->args[1], out, *n_out, out, n_out); -} - -/* grn_ts_op_logical_or_filter() filters records. */ -static grn_rc -grn_ts_op_logical_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, j, count; - grn_rc rc; - grn_ts_bool *buf_ptrs[2]; - grn_ts_buf *tmp_in_buf = &node->bufs[2]; - grn_ts_record *tmp_in; - - /* Evaluate the 1st argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; - - /* Create a list of false records. */ - rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp_in = (grn_ts_record *)tmp_in_buf->ptr; - count = 0; - for (i = 0; i < n_in; i++) { - if (!buf_ptrs[0][i]) { - tmp_in[count++] = in[i]; - } - } - - /* Evaluate the 2nd argument. */ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, - &node->bufs[1]); - buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; - - /* Merge the results. */ - count = 0; - for (i = 0, j = 0; i < n_in; i++) { - if (buf_ptrs[0][i] || buf_ptrs[1][j++]) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_op_logical_sub_filter() filters records. */ -static grn_rc -grn_ts_op_logical_sub_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, n, count; - grn_ts_bool *buf_ptr; - grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, out, &n); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], out, n, - &node->bufs[0]); - buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; - for (i = 0, count = 0; i < n; i++) { - if (grn_ts_op_logical_not_bool(buf_ptr[i])) { - out[count++] = out[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -#define GRN_TS_OP_BITWISE_FILTER(type)\ - size_t i, count = 0;\ - grn_ts_bool *buf_ptrs[2];\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptrs[i] = (grn_ts_bool *)node->bufs[i].ptr;\ - }\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_bitwise_ ## type ## _bool(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ -/* grn_ts_op_bitwise_and_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(and); -} - -/* grn_ts_op_bitwise_or_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(or); -} - -/* grn_ts_op_bitwise_xor_filter() filters records. */ -static grn_rc -grn_ts_op_bitwise_xor_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_BITWISE_FILTER(xor); -} -#undef GRN_TS_OP_BITWISE_FILTER_CASE - -#define GRN_TS_OP_CHK_FILTER_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CHK_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CHK_FILTER(type)\ - size_t i, count = 0;\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CHK_FILTER_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_FILTER_CASE(type, INT, int)\ - GRN_TS_OP_CHK_FILTER_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_FILTER_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_FILTER_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_FILTER_CASE(type, GEO, geo)\ - GRN_TS_OP_CHK_FILTER_CASE(type, REF, ref)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, BOOL, bool)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TEXT, text)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, GEO, geo)\ - GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, REF, ref)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_equal_filter() filters records. */ -static grn_rc -grn_ts_op_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CHK_FILTER(equal) -} - -/* grn_ts_op_not_equal_filter() filters records. */ -static grn_rc -grn_ts_op_not_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CHK_FILTER(not_equal) -} -#undef GRN_TS_OP_CHK_FILTER -#undef GRN_TS_OP_CHK_FILTER_VECTOR_CASE -#undef GRN_TS_OP_CHK_FILTER_CASE - -#define GRN_TS_OP_CMP_FILTER_CASE(type, KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_ts_ ## kind *buf_ptrs[] = {\ - (grn_ts_ ## kind *)node->bufs[0].ptr,\ - (grn_ts_ ## kind *)node->bufs[1].ptr\ - };\ - for (i = 0; i < n_in; i++) {\ - if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ - out[count++] = in[i];\ - }\ - }\ - *n_out = count;\ - return GRN_SUCCESS;\ - } -#define GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, KIND, kind)\ - GRN_TS_OP_CMP_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) -#define GRN_TS_OP_CMP_FILTER(type)\ - size_t i, count = 0;\ - for (i = 0; i < 2; i++) {\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - switch (node->args[0]->data_kind) {\ - GRN_TS_OP_CMP_FILTER_CASE(type, INT, int)\ - GRN_TS_OP_CMP_FILTER_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_FILTER_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_FILTER_CASE(type, TEXT, text)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, INT, int)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, FLOAT, float)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TIME, time)\ - GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TEXT, text)\ - default: {\ - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ - node->args[0]->data_kind);\ - }\ - } -/* grn_ts_op_less_filter() filters records. */ -static grn_rc -grn_ts_op_less_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(less) -} - -/* grn_ts_op_less_equal_filter() filters records. */ -static grn_rc -grn_ts_op_less_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(less_equal) -} - -/* grn_ts_op_greater_filter() filters records. */ -static grn_rc -grn_ts_op_greater_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(greater) -} - -/* grn_ts_op_greater_equal_filter() filters records. */ -static grn_rc -grn_ts_op_greater_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - GRN_TS_OP_CMP_FILTER(greater_equal) -} -#undef GRN_TS_OP_CMP_FILTER -#undef GRN_TS_OP_CMP_FILTER_VECTOR_CASE -#undef GRN_TS_OP_CMP_FILTER_CASE - -/* grn_ts_expr_op_node_filter() filters records. */ -static grn_rc -grn_ts_expr_op_node_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - switch (node->op_type) { - case GRN_TS_OP_LOGICAL_NOT: { - return grn_ts_op_logical_not_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_NOT: { - return grn_ts_op_bitwise_not_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_AND: { - return grn_ts_op_logical_and_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_OR: { - return grn_ts_op_logical_or_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LOGICAL_SUB: { - return grn_ts_op_logical_sub_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_AND: { - return grn_ts_op_bitwise_and_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_OR: { - return grn_ts_op_bitwise_or_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_BITWISE_XOR: { - return grn_ts_op_bitwise_xor_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_EQUAL: { - return grn_ts_op_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_NOT_EQUAL: { - return grn_ts_op_not_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LESS: { - return grn_ts_op_less_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_LESS_EQUAL: { - return grn_ts_op_less_equal_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_GREATER: { - return grn_ts_op_greater_filter(ctx, node, in, n_in, out, n_out); - } - case GRN_TS_OP_GREATER_EQUAL: { - return grn_ts_op_greater_equal_filter(ctx, node, in, n_in, out, n_out); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -#define GRN_TS_OP_SIGN_ADJUST(type)\ - size_t i, count = 0;\ - grn_ts_float *buf_ptr;\ - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], io, n_io,\ - &node->bufs[0]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - buf_ptr = (grn_ts_float *)node->bufs[0].ptr;\ - for (i = 0; i < n_io; i++) {\ - grn_ts_float result = grn_ts_op_ ## type ## _float(buf_ptr[i]);\ - io[count++].score = (grn_ts_score)result;\ - }\ - return GRN_SUCCESS; -/* grn_ts_op_positive_adjust() updates scores. */ -static grn_rc -grn_ts_op_positive_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_SIGN_ADJUST(positive) -} - -/* grn_ts_op_negative_adjust() updates scores. */ -static grn_rc -grn_ts_op_negative_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_SIGN_ADJUST(negative) -} -#undef GRN_TS_OP_SIGN_ADJUST - -#define GRN_TS_OP_ARITH_ADJUST(type)\ - grn_rc rc;\ - size_t i, count = 0;\ - grn_ts_float *buf_ptrs[2];\ - for (i = 0; i < 2; i++) {\ - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], io, n_io,\ - &node->bufs[i]);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - }\ - buf_ptrs[0] = (grn_ts_float *)node->bufs[0].ptr;\ - buf_ptrs[1] = (grn_ts_float *)node->bufs[1].ptr;\ - for (i = 0; i < n_io; i++) {\ - grn_ts_float result;\ - rc = grn_ts_op_ ## type ## _float_float(ctx, buf_ptrs[0][i],\ - buf_ptrs[1][i], &result);\ - io[count].score = (grn_ts_score)result;\ - if (!isfinite(io[count].score)) {\ - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid score: %g", result);\ - }\ - count++;\ - }\ - return GRN_SUCCESS; -/* grn_ts_op_plus_adjust() updates scores. */ -static grn_rc -grn_ts_op_plus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(plus) -} - -/* grn_ts_op_minus_adjust() updates scores. */ -static grn_rc -grn_ts_op_minus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(minus) -} - -/* grn_ts_op_multiplication_adjust() updates scores. */ -static grn_rc -grn_ts_op_multiplication_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(multiplication) -} - -/* grn_ts_op_division_adjust() updates scores. */ -static grn_rc -grn_ts_op_division_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(division) -} - -/* grn_ts_op_modulus_adjust() updates scores. */ -static grn_rc -grn_ts_op_modulus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - GRN_TS_OP_ARITH_ADJUST(modulus) -} -#undef GRN_TS_OP_ARITH_ADJUST - -/* grn_ts_expr_op_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_op_node_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, - grn_ts_record *io, size_t n_io) { - switch (node->op_type) { - case GRN_TS_OP_POSITIVE: { - return grn_ts_op_positive_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_NEGATIVE: { - return grn_ts_op_negative_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_PLUS: { - return grn_ts_op_plus_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MINUS: { - return grn_ts_op_minus_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MULTIPLICATION: { - return grn_ts_op_multiplication_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_DIVISION: { - return grn_ts_op_division_adjust(ctx, node, io, n_io); - } - case GRN_TS_OP_MODULUS: { - return grn_ts_op_modulus_adjust(ctx, node, io, n_io); - } - // TODO: Add operators. - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "operator not supported: %d", node->op_type); - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_bridge_node. - */ - -enum { GRN_TS_EXPR_BRIDGE_NODE_N_BUFS = 2 }; - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS - grn_ts_expr_node *src; - grn_ts_expr_node *dest; - grn_ts_buf bufs[GRN_TS_EXPR_BRIDGE_NODE_N_BUFS]; -} grn_ts_expr_bridge_node; - -/* grn_ts_expr_bridge_node_init() initializes a node. */ -static void -grn_ts_expr_bridge_node_init(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - size_t i; - memset(node, 0, sizeof(*node)); - node->type = GRN_TS_EXPR_BRIDGE_NODE; - node->src = NULL; - node->dest = NULL; - for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { - grn_ts_buf_init(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_bridge_node_fin() finalizes a node. */ -static void -grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - size_t i; - for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { - grn_ts_buf_fin(ctx, &node->bufs[i]); - } -} - -/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */ -static grn_rc -grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, - grn_ts_expr_node *dest, grn_ts_expr_node **node) { - grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1); - if (!new_node) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_bridge_node)); - } - grn_ts_expr_bridge_node_init(ctx, new_node); - new_node->data_kind = dest->data_kind; - new_node->data_type = dest->data_type; - new_node->src = src; - new_node->dest = dest; - *node = (grn_ts_expr_node *)new_node; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_node_close() destroys a node. */ -static void -grn_ts_expr_bridge_node_close(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { - grn_ts_expr_bridge_node_fin(ctx, node); - GRN_FREE(node); -} - -/* grn_ts_expr_bridge_node_evaluate() evaluates a bridge. */ -static grn_rc -grn_ts_expr_bridge_node_evaluate(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - const grn_ts_record *in, size_t n_in, - void *out) { - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - return grn_ts_expr_node_evaluate(ctx, node->dest, tmp, n_in, out); -} - -/* grn_ts_expr_bridge_node_filter() filters records. */ -static grn_rc -grn_ts_expr_bridge_node_filter(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - size_t i, count; - grn_ts_bool *values; - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->dest, in, n_in, - &node->bufs[1]); - if (rc != GRN_SUCCESS) { - return rc; - } - values = (grn_ts_bool *)&node->bufs[1].ptr; - for (i = 0, count = 0; i < n_in; i++) { - if (values[i]) { - out[count++] = in[i]; - } - } - *n_out = count; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node, - grn_ts_record *io, size_t n_io) { - size_t i; - grn_ts_record *tmp; - grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, io, n_io, - &node->bufs[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - tmp = (grn_ts_record *)node->bufs[0].ptr; - rc = grn_ts_expr_node_adjust(ctx, node->dest, tmp, n_io); - if (rc != GRN_SUCCESS) { - return rc; - } - for (i = 0; i < n_io; i++) { - io[i].score = tmp[i].score; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_node. - */ - -#define GRN_TS_EXPR_NODE_CLOSE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\ - return;\ - } -/* grn_ts_expr_node_close() destroys a node. */ -static void -grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) { - switch (node->type) { - GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id) - GRN_TS_EXPR_NODE_CLOSE_CASE(SCORE, score) - GRN_TS_EXPR_NODE_CLOSE_CASE(KEY, key) - GRN_TS_EXPR_NODE_CLOSE_CASE(VALUE, value) - GRN_TS_EXPR_NODE_CLOSE_CASE(CONST, const) - GRN_TS_EXPR_NODE_CLOSE_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_CLOSE_CASE(OP, op) - GRN_TS_EXPR_NODE_CLOSE_CASE(BRIDGE, bridge) - } -} -#undef GRN_TS_EXPR_NODE_CLOSE_CASE - -#define GRN_TS_EXPR_NODE_EVALUATE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\ - in, n_in, out);\ - } -/* grn_ts_expr_node_evaluate() evaluates a subtree. */ -static grn_rc -grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, void *out) { - switch (node->type) { - GRN_TS_EXPR_NODE_EVALUATE_CASE(ID, id) - GRN_TS_EXPR_NODE_EVALUATE_CASE(SCORE, score) - GRN_TS_EXPR_NODE_EVALUATE_CASE(KEY, key) - GRN_TS_EXPR_NODE_EVALUATE_CASE(VALUE, value) - GRN_TS_EXPR_NODE_EVALUATE_CASE(CONST, const) - GRN_TS_EXPR_NODE_EVALUATE_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_EVALUATE_CASE(OP, op) - GRN_TS_EXPR_NODE_EVALUATE_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_EVALUATE_CASE - -#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - grn_rc rc = grn_ts_buf_reserve(ctx, out, sizeof(grn_ts_ ## kind) * n_in);\ - if (rc != GRN_SUCCESS) {\ - return rc;\ - }\ - return grn_ts_expr_node_evaluate(ctx, node, in, n_in, out->ptr);\ - } -#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\ - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector) -/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */ -static grn_rc -grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, - grn_ts_buf *out) { - switch (node->data_kind) { - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(BOOL, bool) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(INT, int) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(FLOAT, float) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TIME, time) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TEXT, text) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(GEO, geo) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(REF, ref) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(INT, int) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(FLOAT, float) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TIME, time) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TEXT, text) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(GEO, geo) - GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(REF, ref) - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, - "invalid data kind: %d", node->data_kind); - } - } -} -#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE -#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE - -#define GRN_TS_EXPR_NODE_FILTER_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\ - in, n_in, out, n_out);\ - } -/* grn_ts_expr_node_filter() filters records. */ -static grn_rc -grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (node->data_kind != GRN_TS_BOOL) { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid data kind: %d", node->data_kind); - } - switch (node->type) { - GRN_TS_EXPR_NODE_FILTER_CASE(KEY, key) - GRN_TS_EXPR_NODE_FILTER_CASE(VALUE, value) - GRN_TS_EXPR_NODE_FILTER_CASE(CONST, const) - GRN_TS_EXPR_NODE_FILTER_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_FILTER_CASE(OP, op) - GRN_TS_EXPR_NODE_FILTER_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_FILTER_CASE - -#define GRN_TS_EXPR_NODE_ADJUST_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ - grn_ts_expr_ ## type ## _node *type ## _node;\ - type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ - return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\ - } -/* grn_ts_expr_node_adjust() updates scores. */ -static grn_rc -grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *io, size_t n_io) { - if (node->data_kind != GRN_TS_FLOAT) { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid data kind: %d", node->data_kind); - } - switch (node->type) { - GRN_TS_EXPR_NODE_ADJUST_CASE(SCORE, score) - GRN_TS_EXPR_NODE_ADJUST_CASE(KEY, key) - GRN_TS_EXPR_NODE_ADJUST_CASE(VALUE, value) - GRN_TS_EXPR_NODE_ADJUST_CASE(CONST, const) - GRN_TS_EXPR_NODE_ADJUST_CASE(COLUMN, column) - GRN_TS_EXPR_NODE_ADJUST_CASE(OP, op) - GRN_TS_EXPR_NODE_ADJUST_CASE(BRIDGE, bridge) - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid node type: %d", node->type); - } - } -} -#undef GRN_TS_EXPR_NODE_ADJUST_CASE - /*------------------------------------------------------------- * grn_ts_expr_parser. */ Modified: lib/ts/ts_expr.h (+1 -54) =================================================================== --- lib/ts/ts_expr.h 2015-11-12 09:59:27 +0900 (67f7022) +++ lib/ts/ts_expr.h 2015-11-12 11:20:53 +0900 (9b6b130) @@ -20,6 +20,7 @@ #define GRN_TS_EXPR_H #include "ts_buf.h" +#include "ts_expr_node.h" #include "ts_types.h" #ifdef __cplusplus @@ -31,40 +32,6 @@ extern "C" { */ typedef enum { - /* Invalid operator. */ - GRN_TS_OP_NOP, - - /* Unary operators. */ - GRN_TS_OP_LOGICAL_NOT, /* !X */ - GRN_TS_OP_BITWISE_NOT, /* ~X */ - GRN_TS_OP_POSITIVE, /* +X */ - GRN_TS_OP_NEGATIVE, /* -X */ - - /* Binary operators. */ - GRN_TS_OP_LOGICAL_AND, /* X && Y */ - GRN_TS_OP_LOGICAL_OR, /* X || Y */ - GRN_TS_OP_LOGICAL_SUB, /* X &! Y */ - GRN_TS_OP_BITWISE_AND, /* X & Y */ - GRN_TS_OP_BITWISE_OR, /* X | Y */ - GRN_TS_OP_BITWISE_XOR, /* X ^ Y */ - GRN_TS_OP_EQUAL, /* X == Y */ - GRN_TS_OP_NOT_EQUAL, /* X != Y */ - GRN_TS_OP_LESS, /* X < Y */ - GRN_TS_OP_LESS_EQUAL, /* X <= Y */ - GRN_TS_OP_GREATER, /* X > Y */ - GRN_TS_OP_GREATER_EQUAL, /* X >= Y */ - GRN_TS_OP_SHIFT_ARITHMETIC_LEFT, /* X << Y */ - GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y */ - GRN_TS_OP_SHIFT_LOGICAL_LEFT, /* X <<< Y */ - GRN_TS_OP_SHIFT_LOGICAL_RIGHT, /* X >>> Y */ - GRN_TS_OP_PLUS, /* X + Y */ - GRN_TS_OP_MINUS, /* X - Y */ - GRN_TS_OP_MULTIPLICATION, /* X * Y */ - GRN_TS_OP_DIVISION, /* X / Y */ - GRN_TS_OP_MODULUS /* X % Y */ -} grn_ts_op_type; - -typedef enum { GRN_TS_EXPR_INCOMPLETE, /* An incomplete expression. */ GRN_TS_EXPR_BROKEN, /* A broken expression. */ /* Any operation fails for a broken expression. */ @@ -74,30 +41,10 @@ typedef enum { GRN_TS_EXPR_VARIABLE /* An expression that contains a variable. */ } grn_ts_expr_type; -typedef enum { - GRN_TS_EXPR_ID_NODE, /* Associated with the ID (_id). */ - GRN_TS_EXPR_SCORE_NODE, /* Asscoaited with the score (_score). */ - GRN_TS_EXPR_KEY_NODE, /* Asscoaited with the key (_key). */ - GRN_TS_EXPR_VALUE_NODE, /* Asscoaited with the embedded value (_value). */ - GRN_TS_EXPR_CONST_NODE, /* Associated with a const. */ - GRN_TS_EXPR_COLUMN_NODE, /* Associated with a column. */ - GRN_TS_EXPR_OP_NODE, /* Associated with an operator. */ - GRN_TS_EXPR_BRIDGE_NODE /* Associated with a bridge to a subexpression. */ -} grn_ts_expr_node_type; - /*------------------------------------------------------------- * Expression components. */ -#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\ - grn_ts_expr_node_type type; /* Node type. */\ - grn_ts_data_kind data_kind; /* Abstract data type. */\ - grn_ts_data_type data_type; /* Detailed data type. */ - -typedef struct { - GRN_TS_EXPR_NODE_COMMON_MEMBERS -} grn_ts_expr_node; - typedef struct { grn_obj *src_table; /* The source table of a bridge (no ref. count). */ grn_obj *dest_table; /* The destination table of a bridge. */ Copied: lib/ts/ts_expr_node.c (+14 -2343) 66% =================================================================== --- lib/ts/ts_expr.c 2015-11-12 09:59:27 +0900 (3c4a119) +++ lib/ts/ts_expr_node.c 2015-11-12 11:20:53 +0900 (fed0eb2) @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ts_expr.h" +#include "ts_expr_node.h" #include <math.h> #include <stdlib.h> @@ -37,23 +37,6 @@ * Built-in data kinds. */ -typedef union { - grn_ts_bool as_bool; - grn_ts_int as_int; - grn_ts_float as_float; - grn_ts_time as_time; - grn_ts_text as_text; - grn_ts_geo as_geo; - grn_ts_ref as_ref; - grn_ts_bool_vector as_bool_vector; - grn_ts_int_vector as_int_vector; - grn_ts_float_vector as_float_vector; - grn_ts_time_vector as_time_vector; - grn_ts_text_vector as_text_vector; - grn_ts_geo_vector as_geo_vector; - grn_ts_ref_vector as_ref_vector; -} grn_ts_any; - /* grn_ts_bool_is_valid() returns whether a value is valid or not. */ inline static grn_ts_bool grn_ts_bool_is_valid(grn_ts_bool value) { @@ -311,107 +294,6 @@ grn_ts_data_kind_to_type(grn_ts_data_kind kind) { /* Operator precedence. */ typedef int grn_ts_op_precedence; -/* grn_ts_op_get_n_args() returns the number of arguments. */ -static size_t -grn_ts_op_get_n_args(grn_ts_op_type op_type) { - switch (op_type) { - case GRN_TS_OP_LOGICAL_NOT: /* !X */ - case GRN_TS_OP_BITWISE_NOT: /* ~X */ - case GRN_TS_OP_POSITIVE: /* +X */ - case GRN_TS_OP_NEGATIVE: { /* -X */ - return 1; - } - case GRN_TS_OP_LOGICAL_AND: /* X && Y */ - case GRN_TS_OP_LOGICAL_OR: /* X || Y */ - case GRN_TS_OP_LOGICAL_SUB: /* X &! Y */ - case GRN_TS_OP_BITWISE_AND: /* X & Y */ - case GRN_TS_OP_BITWISE_OR: /* X | Y */ - case GRN_TS_OP_BITWISE_XOR: /* X ^ Y */ - case GRN_TS_OP_EQUAL: /* X == Y */ - case GRN_TS_OP_NOT_EQUAL: /* X != Y */ - case GRN_TS_OP_LESS: /* X < Y */ - case GRN_TS_OP_LESS_EQUAL: /* X <= Y */ - case GRN_TS_OP_GREATER: /* X > Y */ - case GRN_TS_OP_GREATER_EQUAL: /* X >= Y */ - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: /* X << Y */ - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: /* X >> Y */ - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: /* X <<< Y */ - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: /* X >>> Y */ - case GRN_TS_OP_PLUS: /* X + Y */ - case GRN_TS_OP_MINUS: /* X - Y */ - case GRN_TS_OP_MULTIPLICATION: /* X * Y */ - case GRN_TS_OP_DIVISION: /* X / Y */ - case GRN_TS_OP_MODULUS: { /* X % Y */ - return 2; - } - default: { - return 0; - } - } -} - -/* - * grn_ts_op_get_precedence() returns the precedence. - * A prior operator has a higher precedence. - */ -static grn_ts_op_precedence -grn_ts_op_get_precedence(grn_ts_op_type op_type) { - switch (op_type) { - case GRN_TS_OP_LOGICAL_NOT: - case GRN_TS_OP_BITWISE_NOT: - case GRN_TS_OP_POSITIVE: - case GRN_TS_OP_NEGATIVE: { - return 14; - } - case GRN_TS_OP_LOGICAL_AND: { - return 5; - } - case GRN_TS_OP_LOGICAL_OR: { - return 3; - } - case GRN_TS_OP_LOGICAL_SUB: { - return 4; - } - case GRN_TS_OP_BITWISE_AND: { - return 8; - } - case GRN_TS_OP_BITWISE_OR: { - return 6; - } - case GRN_TS_OP_BITWISE_XOR: { - return 7; - } - case GRN_TS_OP_EQUAL: - case GRN_TS_OP_NOT_EQUAL: { - return 9; - } - case GRN_TS_OP_LESS: - case GRN_TS_OP_LESS_EQUAL: - case GRN_TS_OP_GREATER: - case GRN_TS_OP_GREATER_EQUAL: { - return 10; - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - return 11; - } - case GRN_TS_OP_PLUS: - case GRN_TS_OP_MINUS: { - return 12; - } - case GRN_TS_OP_MULTIPLICATION: - case GRN_TS_OP_DIVISION: - case GRN_TS_OP_MODULUS: { - return 13; - } - default: { - return 0; - } - } -} - /* grn_ts_op_logical_not_bool() returns !arg. */ inline static grn_ts_bool grn_ts_op_logical_not_bool(grn_ts_bool arg) { @@ -1117,27 +999,6 @@ grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) { return GRN_SUCCESS; } -/* grn_ts_obj_is_table() returns whether or not an object is a table. */ -static grn_ts_bool -grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) { - return grn_obj_is_table(ctx, obj); -} - -/* grn_ts_obj_is_column() returns whether or not an object is a column. */ -static grn_ts_bool -grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) { - switch (obj->header.type) { - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: { - return GRN_TRUE; - } - /* GRN_COLUMN_INDEX is not supported. */ - default: { - return GRN_FALSE; - } - } -} - /* * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note the a * value is appended to the end of buf. @@ -1519,8 +1380,7 @@ grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) { /* Nothing to do. */ } -/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */ -static grn_rc +grn_rc grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1); if (!new_node) { @@ -1574,11 +1434,7 @@ grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) { /* Nothing to do. */ } -/* - * grn_ts_expr_score_node_open() creates a node associated with scores - * (_score). - */ -static grn_rc +grn_rc grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) { grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1); if (!new_node) { @@ -1646,8 +1502,7 @@ grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) { } } -/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */ -static grn_rc +grn_rc grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node **node) { grn_rc rc; @@ -1933,11 +1788,7 @@ grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) { } } -/* - * grn_ts_expr_value_node_open() creates a node associated with values - * (_value). - */ -static grn_rc +grn_rc grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node **node) { grn_rc rc; @@ -2205,8 +2056,7 @@ grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node, } #undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE -/* grn_ts_expr_const_node_open() creates a node associated with a const. */ -static grn_rc +grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, const void *value, grn_ts_expr_node **node) { grn_rc rc; @@ -2346,8 +2196,7 @@ grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) { GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\ break;\ } -/* grn_ts_expr_column_node_open() creates a node associated with a column. */ -static grn_rc +grn_rc grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, grn_ts_expr_node **node) { grn_rc rc; @@ -2772,22 +2621,6 @@ enum { GRN_TS_EXPR_OP_NODE_N_BUFS = 3 }; -/* Forward declarations. */ -static void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node); -static grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, - const grn_ts_record *in, size_t n_in, - void *out); -static grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, - grn_ts_expr_node *node, - const grn_ts_record *in, - size_t n_in, - grn_ts_buf *out); -static grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out); -static grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, - grn_ts_record *io, size_t n_io); - typedef struct { GRN_TS_EXPR_NODE_COMMON_MEMBERS grn_ts_op_type op_type; @@ -3121,8 +2954,7 @@ grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) { } } -/* grn_ts_expr_op_node_open() creates a node associated with an operator. */ -static grn_rc +grn_rc grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, grn_ts_expr_node **args, size_t n_args, grn_ts_expr_node **node) { @@ -4507,8 +4339,7 @@ grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) { } } -/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */ -static grn_rc +grn_rc grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, grn_ts_expr_node *dest, grn_ts_expr_node **node) { grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1); @@ -4609,8 +4440,7 @@ grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node, grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\ return;\ } -/* grn_ts_expr_node_close() destroys a node. */ -static void +void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) { switch (node->type) { GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id) @@ -4632,8 +4462,7 @@ grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) { return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\ in, n_in, out);\ } -/* grn_ts_expr_node_evaluate() evaluates a subtree. */ -static grn_rc +grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, const grn_ts_record *in, size_t n_in, void *out) { switch (node->type) { @@ -4663,8 +4492,7 @@ grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, } #define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\ GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector) -/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */ -static grn_rc +grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, const grn_ts_record *in, size_t n_in, grn_ts_buf *out) { @@ -4699,8 +4527,7 @@ grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\ in, n_in, out, n_out);\ } -/* grn_ts_expr_node_filter() filters records. */ -static grn_rc +grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, grn_ts_record *in, size_t n_in, grn_ts_record *out, size_t *n_out) { @@ -4729,8 +4556,7 @@ grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\ } -/* grn_ts_expr_node_adjust() updates scores. */ -static grn_rc +grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, grn_ts_record *io, size_t n_io) { if (node->data_kind != GRN_TS_FLOAT) { @@ -4752,2158 +4578,3 @@ grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, } } #undef GRN_TS_EXPR_NODE_ADJUST_CASE - -/*------------------------------------------------------------- - * grn_ts_expr_parser. - */ - -/* - * FIXME: A grn_ts_expr_parser object is designed to parse one expression - * string. grn_ts_expr_parser_parse() should not be called more than - * once. - */ - -typedef enum { - GRN_TS_EXPR_DUMMY_TOKEN, /* No extra data. */ - GRN_TS_EXPR_START_TOKEN, /* No extra data. */ - GRN_TS_EXPR_END_TOKEN, /* No extra data. */ - GRN_TS_EXPR_CONST_TOKEN, /* +data_kind, content and buf. */ - GRN_TS_EXPR_NAME_TOKEN, /* +name. */ - GRN_TS_EXPR_OP_TOKEN, /* +op_type. */ - GRN_TS_EXPR_BRIDGE_TOKEN, /* No extra data. */ - GRN_TS_EXPR_BRACKET_TOKEN /* No extra data. */ -} grn_ts_expr_token_type; - -#define GRN_TS_EXPR_TOKEN_COMMON_MEMBERS\ - grn_ts_str src; /* Source string. */\ - grn_ts_expr_token_type type; /* Token type. */ - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS -} grn_ts_expr_token; - -typedef grn_ts_expr_token grn_ts_expr_dummy_token; -typedef grn_ts_expr_token grn_ts_expr_start_token; -typedef grn_ts_expr_token grn_ts_expr_end_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_data_kind data_kind; /* The data kind of the const. */ - grn_ts_any content; /* The const. */ - grn_ts_buf buf; /* Buffer for content.as_text. */ -} grn_ts_expr_const_token; - -typedef grn_ts_expr_token grn_ts_expr_name_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_op_type op_type; /* Operator type. */ -} grn_ts_expr_op_token; - -typedef grn_ts_expr_token grn_ts_expr_bridge_token; -typedef grn_ts_expr_token grn_ts_expr_bracket_token; - -typedef struct { - grn_ts_expr *expr; /* Associated expression. */ - grn_ts_buf str_buf; /* Buffer for a source string. */ - grn_ts_expr_token **tokens; /* Tokens. */ - size_t n_tokens; /* Number of tokens. */ - size_t max_n_tokens; /* Max. number of tokens. */ - grn_ts_expr_dummy_token *dummy_tokens; /* Dummy tokens. */ - size_t n_dummy_tokens; /* Number of dummy tokens. */ - grn_ts_expr_token **stack; /* Token stack. */ - size_t stack_depth; /* Token stack's current depth. */ -} grn_ts_expr_parser; - -#define GRN_TS_EXPR_TOKEN_INIT(TYPE)\ - memset(token, 0, sizeof(*token));\ - token->type = GRN_TS_EXPR_ ## TYPE ## _TOKEN;\ - token->src = src; -/* grn_ts_expr_dummy_token_init() initializes a token. */ -static void -grn_ts_expr_dummy_token_init(grn_ctx *ctx, grn_ts_expr_dummy_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(DUMMY) -} - -/* grn_ts_expr_start_token_init() initializes a token. */ -static void -grn_ts_expr_start_token_init(grn_ctx *ctx, grn_ts_expr_start_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(START) -} - -/* grn_ts_expr_end_token_init() initializes a token. */ -static void -grn_ts_expr_end_token_init(grn_ctx *ctx, grn_ts_expr_end_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(END) -} - -/* grn_ts_expr_const_token_init() initializes a token. */ -static void -grn_ts_expr_const_token_init(grn_ctx *ctx, grn_ts_expr_const_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(CONST); - grn_ts_buf_init(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_init() initializes a token. */ -static void -grn_ts_expr_name_token_init(grn_ctx *ctx, grn_ts_expr_name_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(NAME); -} - -/* grn_ts_expr_op_token_init() initializes a token. */ -static void -grn_ts_expr_op_token_init(grn_ctx *ctx, grn_ts_expr_op_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(OP); -} - -/* grn_ts_expr_bridge_token_init() initializes a token. */ -static void -grn_ts_expr_bridge_token_init(grn_ctx *ctx, grn_ts_expr_bridge_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRIDGE) -} - -/* grn_ts_expr_bracket_token_init() initializes a token. */ -static void -grn_ts_expr_bracket_token_init(grn_ctx *ctx, grn_ts_expr_bracket_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRACKET) -} -#undef GRN_TS_EXPR_TOKEN_INIT - -/* grn_ts_expr_dummy_token_fin() finalizes a token. */ -static void -grn_ts_expr_dummy_token_fin(grn_ctx *ctx, grn_ts_expr_dummy_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_start_token_fin() finalizes a token. */ -static void -grn_ts_expr_start_token_fin(grn_ctx *ctx, grn_ts_expr_start_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_end_token_fin() finalizes a token. */ -static void -grn_ts_expr_end_token_fin(grn_ctx *ctx, grn_ts_expr_end_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_const_token_fin() finalizes a token. */ -static void -grn_ts_expr_const_token_fin(grn_ctx *ctx, grn_ts_expr_const_token *token) { - grn_ts_buf_fin(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_fin() finalizes a token. */ -static void -grn_ts_expr_name_token_fin(grn_ctx *ctx, grn_ts_expr_name_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_op_token_fin() finalizes a token. */ -static void -grn_ts_expr_op_token_fin(grn_ctx *ctx, grn_ts_expr_op_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bridge_token_fin() finalizes a token. */ -static void -grn_ts_expr_bridge_token_fin(grn_ctx *ctx, grn_ts_expr_bridge_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bracket_token_fin() finalizes a token. */ -static void -grn_ts_expr_bracket_token_fin(grn_ctx *ctx, grn_ts_expr_bracket_token *token) { - /* Nothing to do. */ -} - -#define GRN_TS_EXPR_TOKEN_OPEN(TYPE, type)\ - grn_ts_expr_ ## type ## _token *new_token;\ - new_token = GRN_MALLOCN(grn_ts_expr_ ## type ## _token, 1);\ - if (!new_token) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",\ - sizeof(grn_ts_expr_ ## type ## _token));\ - }\ - grn_ts_expr_ ## type ## _token_init(ctx, new_token, src);\ - *token = new_token; -/* grn_ts_expr_dummy_token_open() creates a token. */ -/* -static grn_rc -grn_ts_expr_dummy_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_dummy_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(DUMMY, dummy) - return GRN_SUCCESS; -} -*/ - -/* grn_ts_expr_start_token_open() creates a token. */ -static grn_rc -grn_ts_expr_start_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_start_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(START, start) - return GRN_SUCCESS; -} - -/* grn_ts_expr_end_token_open() creates a token. */ -static grn_rc -grn_ts_expr_end_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_end_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(END, end) - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_token_open() creates a token. */ -static grn_rc -grn_ts_expr_const_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_const_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(CONST, const) - return GRN_SUCCESS; -} - -/* grn_ts_expr_name_token_open() creates a token. */ -static grn_rc -grn_ts_expr_name_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_name_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(NAME, name) - return GRN_SUCCESS; -} - -/* grn_ts_expr_op_token_open() creates a token. */ -static grn_rc -grn_ts_expr_op_token_open(grn_ctx *ctx, grn_ts_str src, grn_ts_op_type op_type, - grn_ts_expr_op_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(OP, op) - new_token->op_type = op_type; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bridge_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bridge_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRIDGE, bridge) - return GRN_SUCCESS; -} - -/* grn_ts_expr_bracket_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bracket_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bracket_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRACKET, bracket) - return GRN_SUCCESS; -} -#undef GRN_TS_EXPR_TOKEN_OPEN - -#define GRN_TS_EXPR_TOKEN_CLOSE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _TOKEN: {\ - grn_ts_expr_ ## type ## _token *type ## _token;\ - type ## _token = (grn_ts_expr_ ## type ## _token *)token;\ - grn_ts_expr_ ## type ## _token_fin(ctx, type ## _token);\ - break;\ - } -/* grn_ts_expr_token_close() destroys a token. */ -static void -grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) { - switch (token->type) { - GRN_TS_EXPR_TOKEN_CLOSE_CASE(DUMMY, dummy) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(START, start) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(END, end) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(CONST, const) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(NAME, name) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(OP, op) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRACKET, bracket) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRIDGE, bridge) - } - GRN_FREE(token); -} -#undef GRN_TS_EXPR_TOKEN_CLOSE_CASE - -/* grn_ts_expr_parser_init() initializes a parser. */ -static void -grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser *parser) { - memset(parser, 0, sizeof(*parser)); - parser->expr = expr; - grn_ts_buf_init(ctx, &parser->str_buf); - parser->tokens = NULL; - parser->dummy_tokens = NULL; - parser->stack = NULL; -} - -/* grn_ts_expr_parser_fin() finalizes a parser. */ -static void -grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) { - if (parser->stack) { - GRN_FREE(parser->stack); - } - if (parser->dummy_tokens) { - size_t i; - for (i = 0; i < parser->n_dummy_tokens; i++) { - grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]); - } - GRN_FREE(parser->dummy_tokens); - } - if (parser->tokens) { - size_t i; - for (i = 0; i < parser->n_tokens; i++) { - grn_ts_expr_token_close(ctx, parser->tokens[i]); - } - GRN_FREE(parser->tokens); - } - grn_ts_buf_fin(ctx, &parser->str_buf); -} - -/* grn_ts_expr_parser_open() creates a parser. */ -static grn_rc -grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser **parser) { - grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); - if (!new_parser) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_parser)); - } - grn_ts_expr_parser_init(ctx, expr, new_parser); - *parser = new_parser; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_close() destroys a parser. */ -static void -grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) { - grn_ts_expr_parser_fin(ctx, parser); - GRN_FREE(parser); -} - -/* grn_ts_expr_parser_tokenize_start() creates the start token. */ -static grn_rc -grn_ts_expr_parser_tokenize_start(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_start_token *new_token; - grn_rc rc = grn_ts_expr_start_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_end() creates the end token. */ -static grn_rc -grn_ts_expr_parser_tokenize_end(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_end_token *new_token; - grn_rc rc = grn_ts_expr_end_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_number() tokenizes an Int or Float literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_number(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - char *end; - grn_rc rc; - grn_ts_int int_value; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - - int_value = strtol(str.ptr, &end, 0); - if ((end != str.ptr) && (*end != '.') && (*end != 'e')) { - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Int literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_INT; - new_token->content.as_int = int_value; - } else { - grn_ts_float float_value = strtod(str.ptr, &end); - if (end == str.ptr) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid number literal: \"%.*s\"", - (int)str.size, str.ptr); - } - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Float literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_FLOAT; - new_token->content.as_float = float_value; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_text() tokenizes a Text literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_text(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i, n_escapes = 0; - grn_rc rc; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - for (i = 1; i < str.size; i++) { - if (str.ptr[i] == '\\') { - i++; - n_escapes++; - } else if (str.ptr[i] == '"') { - break; - } - } - if (i >= str.size) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "no closing double quote: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = i + 1; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_TEXT; - if (n_escapes) { - char *buf_ptr; - const char *str_ptr = str.ptr + 1; - size_t size = token_str.size - 2 - n_escapes; - rc = grn_ts_buf_resize(ctx, &new_token->buf, size); - if (rc != GRN_SUCCESS) { - grn_ts_expr_token_close(ctx, (grn_ts_expr_token *)new_token); - return rc; - } - buf_ptr = (char *)new_token->buf.ptr; - for (i = 0; i < size; i++) { - if (str_ptr[i] == '\\') { - str_ptr++; - } - buf_ptr[i] = str_ptr[i]; - } - new_token->content.as_text.ptr = buf_ptr; - new_token->content.as_text.size = size; - } else { - new_token->content.as_text.ptr = token_str.ptr + 1; - new_token->content.as_text.size = token_str.size - 2; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_name() tokenizes a Bool literal or a name. */ -static grn_rc -grn_ts_expr_parser_tokenize_name(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i; - grn_ts_str token_str; - for (i = 1; i < str.size; i++) { - if (!grn_ts_byte_is_name_char(str.ptr[i])) { - break; - } - } - token_str.ptr = str.ptr; - token_str.size = i; - - if (grn_ts_str_is_bool(token_str)) { - grn_ts_expr_const_token *new_token; - grn_rc rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_BOOL; - if (token_str.ptr[0] == 't') { - new_token->content.as_bool = GRN_TRUE; - } else { - new_token->content.as_bool = GRN_FALSE; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; - } - return grn_ts_expr_name_token_open(ctx, token_str, token); -} - -/* grn_ts_expr_parser_tokenize_bridge() tokenizes a bridge. */ -static grn_rc -grn_ts_expr_parser_tokenize_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bridge_token *new_token; - grn_rc rc = grn_ts_expr_bridge_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_bracket() tokenizes a bracket. */ -static grn_rc -grn_ts_expr_parser_tokenize_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, - grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bracket_token *new_token; - grn_rc rc = grn_ts_expr_bracket_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parsre_tokenize_sign() tokenizes an operator '+' or '-'. - * Note that '+' and '-' have two roles each. - * '+' is GRN_TS_OP_POSITIVE or GRN_TS_OP_PLUS. - * '-' is GRN_TS_OP_NEGATIVE or GRN_TS_OP_MINUS. - */ -static grn_rc -grn_ts_expr_parser_tokenize_sign(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t n_args; - grn_rc rc; - grn_ts_op_type op_type; - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_token *prev_token = parser->tokens[parser->n_tokens - 1]; - grn_ts_expr_op_token *new_token; - switch (prev_token->type) { - case GRN_TS_EXPR_START_TOKEN: - case GRN_TS_EXPR_OP_TOKEN: { - n_args = 1; - break; - } - case GRN_TS_EXPR_CONST_TOKEN: - case GRN_TS_EXPR_NAME_TOKEN: { - n_args = 2; - break; - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_str bracket; - const grn_ts_expr_bracket_token *bracket_token; - bracket_token = (const grn_ts_expr_bracket_token *)prev_token; - bracket = bracket_token->src; - switch (bracket.ptr[0]) { - case '(': case '[': { - n_args = 1; - break; - } - case ')': case ']': { - n_args = 2; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "undefined bracket: \"%.*s\"", - (int)bracket.size, bracket.ptr); - } - } - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence: %d", - prev_token->type); - } - } - if (token_str.ptr[0] == '+') { - op_type = (n_args == 1) ? GRN_TS_OP_POSITIVE : GRN_TS_OP_PLUS; - } else { - op_type = (n_args == 1) ? GRN_TS_OP_NEGATIVE : GRN_TS_OP_MINUS; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_op() tokenizes an operator. */ -static grn_rc -grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_rc rc = GRN_SUCCESS; - grn_ts_str token_str = str; - grn_ts_op_type op_type; - grn_ts_expr_op_token *new_token; - switch (str.ptr[0]) { - case '+': case '-': { - return grn_ts_expr_parser_tokenize_sign(ctx, parser, str, token); - } - case '!': { - if ((str.size >= 2) && (str.ptr[1] == '=')) { - token_str.size = 2; - op_type = GRN_TS_OP_NOT_EQUAL; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_LOGICAL_NOT; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE_1, TYPE_2, TYPE_3,\ - TYPE_EQUAL)\ - case label: {\ - if ((str.size >= 2) && (str.ptr[1] == '=')) {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_EQUAL;\ - } else if ((str.size >= 2) && (str.ptr[1] == label)) {\ - if ((str.size >= 3) && (str.ptr[2] == label)) {\ - token_str.size = 3;\ - op_type = GRN_TS_OP_ ## TYPE_3;\ - } else {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_2;\ - }\ - } else {\ - token_str.size = 1;\ - op_type = GRN_TS_OP_ ## TYPE_1;\ - }\ - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('<', LESS, SHIFT_ARITHMETIC_LEFT, - SHIFT_LOGICAL_LEFT, LESS_EQUAL) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('>', GREATER, SHIFT_ARITHMETIC_RIGHT, - SHIFT_LOGICAL_RIGHT, GREATER_EQUAL) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - case '&': { - if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_AND; - } else if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_SUB; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_AND; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '|': { - if ((str.size >= 2) && (str.ptr[1] == '|')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_OR; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_OR; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '=': { - if ((str.size < 2) || (str.ptr[1] != '=')) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "single equal not available: =\"%.*s\"", - (int)str.size, str.ptr); - } - token_str.size = 2; - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_EQUAL, - &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE)\ - case label: {\ - token_str.size = 1;\ - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_ ## TYPE,\ - &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('~', BITWISE_NOT) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('^', BITWISE_XOR) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('*', MULTIPLICATION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('/', DIVISION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('%', MODULUS) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid character: \"%.*s\"", - (int)str.size, str.ptr); - } - } - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_next() extracts the next token. */ -static grn_rc -grn_ts_expr_parser_tokenize_next(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str rest; - if (!parser->n_tokens) { - return grn_ts_expr_parser_tokenize_start(ctx, parser, str, token); - } - rest = grn_ts_str_trim_left(str); - if (!rest.size) { - return grn_ts_expr_parser_tokenize_end(ctx, parser, rest, token); - } - if (grn_ts_str_has_number_prefix(rest)) { - grn_ts_expr_token *prev_token; - if ((rest.ptr[0] != '+') && (rest.ptr[0] != '-')) { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - prev_token = parser->tokens[parser->n_tokens - 1]; - switch (prev_token->type) { - case GRN_TS_EXPR_START_TOKEN: - case GRN_TS_EXPR_OP_TOKEN: { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - if ((prev_token->src.ptr[0] == '(') || - (prev_token->src.ptr[0] == '[')) { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - break; - } - default: { - break; - } - } - } - if (rest.ptr[0] == '"') { - return grn_ts_expr_parser_tokenize_text(ctx, parser, rest, token); - } - if (grn_ts_byte_is_name_char(rest.ptr[0])) { - return grn_ts_expr_parser_tokenize_name(ctx, parser, rest, token); - } - switch (rest.ptr[0]) { - case '(': case ')': case '[': case ']': { - return grn_ts_expr_parser_tokenize_bracket(ctx, parser, rest, token); - } - case '.': { - return grn_ts_expr_parser_tokenize_bridge(ctx, parser, rest, token); - } - default: { - return grn_ts_expr_parser_tokenize_op(ctx, parser, rest, token); - } - } -} - -/* - * grn_ts_expr_parser_reserve_tokens() extends a token buffer for a new token. - */ -static grn_rc -grn_ts_expr_parser_reserve_tokens(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i, n_bytes, new_max_n_tokens; - grn_ts_expr_token **new_tokens; - if (parser->n_tokens < parser->max_n_tokens) { - return GRN_SUCCESS; - } - new_max_n_tokens = parser->n_tokens * 2; - if (!new_max_n_tokens) { - new_max_n_tokens = 1; - } - n_bytes = sizeof(grn_ts_expr_token *) * new_max_n_tokens; - new_tokens = (grn_ts_expr_token **)GRN_REALLOC(parser->tokens, n_bytes); - if (!new_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = parser->n_tokens; i < new_max_n_tokens; i++) { - new_tokens[i] = NULL; - } - parser->tokens = new_tokens; - parser->max_n_tokens = new_max_n_tokens; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize() tokenizes a string. */ -static grn_rc -grn_ts_expr_parser_tokenize(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str) { - grn_ts_str rest = str; - const char *end = str.ptr + str.size; - grn_ts_expr_token *token = NULL; - GRN_TS_DEBUG("str = \"%.*s\"", (int)str.size, str.ptr); - do { - grn_rc rc = grn_ts_expr_parser_reserve_tokens(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_tokenize_next(ctx, parser, rest, &token); - if (rc != GRN_SUCCESS) { - return rc; - } - if ((token->type != GRN_TS_EXPR_START_TOKEN) && - (token->type != GRN_TS_EXPR_END_TOKEN)) { - GRN_TS_DEBUG("token = \"%.*s\"", (int)token->src.size, token->src.ptr); - } - parser->tokens[parser->n_tokens++] = token; - rest.ptr = token->src.ptr + token->src.size; - rest.size = end - rest.ptr; - } while (token->type != GRN_TS_EXPR_END_TOKEN); - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_push_const() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_const_token *token) { - switch (token->data_kind) { - case GRN_TS_BOOL: { - return grn_ts_expr_push_bool(ctx, parser->expr, token->content.as_bool); - } - case GRN_TS_INT: { - return grn_ts_expr_push_int(ctx, parser->expr, token->content.as_int); - } - case GRN_TS_FLOAT: { - return grn_ts_expr_push_float(ctx, parser->expr, - token->content.as_float); - } - case GRN_TS_TEXT: { - return grn_ts_expr_push_text(ctx, parser->expr, token->content.as_text); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - token->data_kind); - } - } -} - -/* grn_ts_expr_parser_push_name() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_name(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_name_token *token) { - return grn_ts_expr_push_name(ctx, parser->expr, - token->src.ptr, token->src.size); -} - -/* grn_ts_expr_parser_push_op() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_op_token *token) { - return grn_ts_expr_push_op(ctx, parser->expr, token->op_type); -} - -/* - * grn_ts_expr_parser_apply_one() applies a bridge or prior operator. - * If there is no target, this function returns GRN_END_OF_DATA. - */ -// FIXME: Support a ternary operator. -static grn_rc -grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_op_precedence precedence_threshold) { - grn_rc rc; - grn_ts_str src; - grn_ts_expr_token **stack = parser->stack; - grn_ts_expr_dummy_token *dummy_token; - size_t n_args, depth = parser->stack_depth; - if (depth < 2) { - return GRN_END_OF_DATA; - } - if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "argument must be dummy token"); - } - - /* Check the number of arguments. */ - switch (stack[depth - 2]->type) { - case GRN_TS_EXPR_BRIDGE_TOKEN: { - rc = grn_ts_expr_end_subexpr(ctx, parser->expr); - if (rc != GRN_SUCCESS) { - return rc; - } - n_args = 2; - break; - } - case GRN_TS_EXPR_OP_TOKEN: { - grn_ts_expr_op_token *op_token; - grn_ts_op_precedence precedence; - op_token = (grn_ts_expr_op_token *)stack[depth - 2]; - precedence = grn_ts_op_get_precedence(op_token->op_type); - if (precedence < precedence_threshold) { - return GRN_END_OF_DATA; - } - rc = grn_ts_expr_parser_push_op(ctx, parser, op_token); - if (rc != GRN_SUCCESS) { - return rc; - } - n_args = grn_ts_op_get_n_args(op_token->op_type); - break; - } - default: { - return GRN_END_OF_DATA; - } - } - - /* Concatenate the source strings. */ - switch (n_args) { - case 1: { - grn_ts_expr_token *arg = stack[depth - 1]; - src.ptr = stack[depth - 2]->src.ptr; - src.size = (arg->src.ptr + arg->src.size) - src.ptr; - break; - } - case 2: { - grn_ts_expr_token *args[2] = { stack[depth - 3], stack[depth - 1] }; - src.ptr = args[0]->src.ptr; - src.size = (args[1]->src.ptr + args[1]->src.size) - src.ptr; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid #arguments: %zu", n_args); - } - } - - /* Replace the operator and argument tokens with a dummy token. */ - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); - grn_ts_expr_dummy_token_init(ctx, dummy_token, src); - depth -= n_args + 1; - stack[depth++] = dummy_token; - parser->stack_depth = depth; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_apply() applies bridges and prior operators. */ -static grn_rc -grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_op_precedence precedence_threshold) { - for ( ; ; ) { - grn_rc rc = grn_ts_expr_parser_apply_one(ctx, parser, - precedence_threshold); - if (rc == GRN_END_OF_DATA) { - return GRN_SUCCESS; - } else if (rc != GRN_SUCCESS) { - return rc; - } - } -} - -/* grn_ts_expr_parser_analyze_op() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_op_token *token) { - size_t n_args = grn_ts_op_get_n_args(token->op_type); - grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; - if (n_args == 1) { - if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - } else if (n_args == 2) { - grn_ts_op_precedence precedence = grn_ts_op_get_precedence(token->op_type); - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, precedence); - if (rc != GRN_SUCCESS) { - return rc; - } - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bridge() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_bridge_token *token) { - grn_rc rc = grn_ts_expr_begin_subexpr(ctx, parser->expr); - if (rc != GRN_SUCCESS) { - return rc; - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bracket() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_bracket_token *token) { - grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; - switch (token->src.ptr[0]) { - case '(': { - if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; - } - case '[': { - if (ex_token->type != GRN_TS_EXPR_DUMMY_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; - } - case ')': case ']': { - grn_ts_expr_token *ex_ex_token; - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, 0); - if (rc != GRN_SUCCESS) { - return rc; - } - if (parser->stack_depth < 2) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - ex_ex_token = parser->stack[parser->stack_depth - 2]; - if (ex_ex_token->type != GRN_TS_EXPR_BRACKET_TOKEN) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - if (token->src.ptr[0] == ')') { - size_t depth = parser->stack_depth; - grn_ts_str src; - grn_ts_expr_dummy_token *dummy_token; - if (ex_ex_token->src.ptr[0] != '(') { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - src.ptr = ex_ex_token->src.ptr; - src.size = (token->src.ptr + token->src.size) - src.ptr; - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); - grn_ts_expr_dummy_token_init(ctx, dummy_token, src); - parser->stack[depth - 2] = dummy_token; - parser->stack_depth--; - // TODO: Apply a function. - } else if (token->src.ptr[0] == ']') { - size_t depth = parser->stack_depth; - if (ex_ex_token->src.ptr[0] != '[') { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[depth - 2] = parser->stack[depth - 1]; - parser->stack_depth--; - // TODO: Push a subscript operator. - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"", - (int)token->src.size, token->src.ptr); - } - } -} - -/* grn_ts_expr_parser_analyze_token() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_token *token) { - switch (token->type) { - case GRN_TS_EXPR_START_TOKEN: { - parser->stack[parser->stack_depth++] = token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_END_TOKEN: { - return grn_ts_expr_parser_apply(ctx, parser, 0); - } - case GRN_TS_EXPR_CONST_TOKEN: { - grn_ts_expr_const_token *const_token = (grn_ts_expr_const_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_const(ctx, parser, const_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_NAME_TOKEN: { - grn_ts_expr_name_token *name_token = (grn_ts_expr_name_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_name(ctx, parser, name_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_OP_TOKEN: { - grn_ts_expr_op_token *op_token = (grn_ts_expr_op_token *)token; - return grn_ts_expr_parser_analyze_op(ctx, parser, op_token); - } - case GRN_TS_EXPR_BRIDGE_TOKEN: { - grn_ts_expr_bridge_token *bridge_token; - bridge_token = (grn_ts_expr_bridge_token *)token; - return grn_ts_expr_parser_analyze_bridge(ctx, parser, bridge_token); - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_expr_bracket_token *bracket_token; - bracket_token = (grn_ts_expr_bracket_token *)token; - return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d", - token->type); - } - } -} - -/* grn_ts_expr_parser_analyze() analyzes tokens. */ -static grn_rc -grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i; - - /* Reserve temporary work spaces. */ - parser->dummy_tokens = GRN_MALLOCN(grn_ts_expr_dummy_token, - parser->n_tokens); - if (!parser->dummy_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_dummy_token), parser->n_tokens); - } - parser->stack = GRN_MALLOCN(grn_ts_expr_token *, parser->n_tokens); - if (!parser->stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_token *), parser->n_tokens); - } - - /* Analyze tokens. */ - for (i = 0; i < parser->n_tokens; i++) { - grn_rc rc; - rc = grn_ts_expr_parser_analyze_token(ctx, parser, parser->tokens[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - if (parser->stack_depth != 2) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "tokens left in stack: %zu", - parser->stack_depth); - } - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parser_parse() parses a string and pushes nodes into an - * expression. - */ -static grn_rc -grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, - const char *str_ptr, size_t str_size) { - grn_rc rc; - grn_ts_str str; - rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str_size + 1); - if (rc != GRN_SUCCESS) { - return rc; - } - grn_memcpy(parser->str_buf.ptr, str_ptr, str_size); - ((char *)parser->str_buf.ptr)[str_size] = '\0'; - str.ptr = (const char *)parser->str_buf.ptr; - str.size = str_size; - rc = grn_ts_expr_parser_tokenize(ctx, parser, str); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_analyze(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - return GRN_SUCCESS; -} - -/*------------------------------------------------------------- - * grn_ts_expr_bridge. - */ - -/* grn_ts_expr_bridge_init() initializes a bridge. */ -static void -grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) { - memset(bridge, 0, sizeof(*bridge)); - bridge->src_table = NULL; - bridge->dest_table = NULL; -} - -/* grn_ts_expr_bridge_fin() finalizes a bridge. */ -static void -grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) { - if (bridge->dest_table) { - grn_obj_unlink(ctx, bridge->dest_table); - } - /* Note: bridge->src_table does not increment a reference count. */ -} - -/*------------------------------------------------------------- - * grn_ts_expr. - */ - -/* grn_ts_expr_init() initializes an expression. */ -static void -grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) { - memset(expr, 0, sizeof(*expr)); - expr->table = NULL; - expr->curr_table = NULL; - expr->root = NULL; - expr->stack = NULL; - expr->bridges = NULL; -} - -/* grn_ts_expr_fin() finalizes an expression. */ -static void -grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i; - if (expr->bridges) { - for (i = 0; i < expr->n_bridges; i++) { - grn_ts_expr_bridge_fin(ctx, &expr->bridges[i]); - } - GRN_FREE(expr->bridges); - } - if (expr->stack) { - for (i = 0; i < expr->stack_depth; i++) { - if (expr->stack[i]) { - grn_ts_expr_node_close(ctx, expr->stack[i]); - } - } - GRN_FREE(expr->stack); - } - /* Note: expr->curr_table does not increment a reference count. */ - if (expr->table) { - grn_obj_unlink(ctx, expr->table); - } -} - -grn_rc -grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr) { - grn_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || !expr) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - new_expr = GRN_MALLOCN(grn_ts_expr, 1); - if (!new_expr) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr)); - } - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - GRN_FREE(new_expr); - return rc; - } - grn_ts_expr_init(ctx, new_expr); - new_expr->table = table; - new_expr->curr_table = table; - *expr = new_expr; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, - const char *str_ptr, size_t str_size, grn_ts_expr **expr) { - grn_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || - (!str_ptr && str_size) || !expr) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_open(ctx, table, &new_expr); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_push(ctx, new_expr, str_ptr, str_size); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_complete(ctx, new_expr); - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_close(ctx, new_expr); - return rc; - } - *expr = new_expr; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) { - if (!ctx || !expr) { - return GRN_INVALID_ARGUMENT; - } - grn_ts_expr_fin(ctx, expr); - GRN_FREE(expr); - return GRN_SUCCESS; -} - -grn_obj * -grn_ts_expr_get_table(grn_ctx *ctx, grn_ts_expr *expr) { - if (!ctx || !expr) { - return NULL; - } - /* The reference counting will never fail in practice. */ - if (grn_ts_obj_increment_ref_count(ctx, expr->table) != GRN_SUCCESS) { - return NULL; - } - return expr->table; -} - -grn_ts_expr_type -grn_ts_expr_get_type(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_TS_EXPR_BROKEN : expr->type; -} - -grn_ts_data_kind -grn_ts_expr_get_data_kind(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_TS_VOID : expr->data_kind; -} - -grn_ts_data_type -grn_ts_expr_get_data_type(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_DB_VOID : expr->data_type; -} - -grn_ts_expr_node * -grn_ts_expr_get_root(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? NULL : expr->root; -} - -/* grn_ts_expr_reserve_stack() extends a stack. */ -static grn_rc -grn_ts_expr_reserve_stack(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i, n_bytes, new_size; - grn_ts_expr_node **new_stack; - if (expr->stack_depth < expr->stack_size) { - return GRN_SUCCESS; - } - new_size = expr->stack_size ? (expr->stack_size * 2) : 1; - n_bytes = sizeof(grn_ts_expr_node *) * new_size; - new_stack = GRN_REALLOC(expr->stack, n_bytes); - if (!new_stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = expr->stack_size; i < new_size; i++) { - new_stack[i] = NULL; - } - expr->stack = new_stack; - expr->stack_size = new_size; - return GRN_SUCCESS; -} - -/* grn_ts_expr_deref() dereferences a node. */ -static grn_rc -grn_ts_expr_deref(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node_ptr) { - grn_ts_expr_node *node = *node_ptr; - while (node->data_kind == GRN_TS_REF) { - grn_rc rc; - grn_ts_expr_node *key_node, *bridge_node; - grn_id table_id = node->data_type; - grn_obj *table = grn_ctx_at(ctx, table_id); - if (!table) { - return GRN_OBJECT_CORRUPT; - } - if (!grn_ts_obj_is_table(ctx, table)) { - grn_obj_unlink(ctx, table); - return GRN_OBJECT_CORRUPT; - } - rc = grn_ts_expr_key_node_open(ctx, table, &key_node); - grn_obj_unlink(ctx, table); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_bridge_node_open(ctx, node, key_node, &bridge_node); - if (rc != GRN_SUCCESS) { - return rc; - } - node = bridge_node; - } - *node_ptr = node; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push(grn_ctx *ctx, grn_ts_expr *expr, - const char *str_ptr, size_t str_size) { - grn_rc rc; - grn_ts_expr_parser *parser; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (!str_ptr && str_size)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_parser_open(ctx, expr, &parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_parse(ctx, parser, str_ptr, str_size); - grn_ts_expr_parser_close(ctx, parser); - return rc; -} - -grn_rc -grn_ts_expr_push_name(grn_ctx *ctx, grn_ts_expr *expr, - const char *name_ptr, size_t name_size) { - grn_obj *column; - grn_ts_str name = { name_ptr, name_size }; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !grn_ts_str_is_name(name)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - if (grn_ts_str_is_id_name(name)) { - return grn_ts_expr_push_id(ctx, expr); - } - if (grn_ts_str_is_score_name(name)) { - return grn_ts_expr_push_score(ctx, expr); - } - if (grn_ts_str_is_key_name(name)) { - return grn_ts_expr_push_key(ctx, expr); - } - if (grn_ts_str_is_value_name(name)) { - return grn_ts_expr_push_value(ctx, expr); - } - /* grn_obj_column() returns a column or accessor. */ - column = grn_obj_column(ctx, expr->curr_table, name.ptr, name.size); - if (!column) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"", - (int)name.size, name.ptr); - } - return grn_ts_expr_push_obj(ctx, expr, column); -} - -#define GRN_TS_EXPR_PUSH_BULK_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - return grn_ts_expr_push_ ## kind(ctx, expr, GRN_ ## TYPE ## _VALUE(obj));\ - } -/* grn_ts_expr_push_bulk() pushes a scalar. */ -static grn_rc -grn_ts_expr_push_bulk(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_BULK_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_BULK_CASE(INT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT32, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT32, int) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_PUSH_BULK_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_BULK_CASE(TIME, time) - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - grn_ts_text value = { GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj) }; - return grn_ts_expr_push_text(ctx, expr, value); - } - case GRN_DB_TOKYO_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_tokyo_geo(ctx, expr, value); - } - case GRN_DB_WGS84_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_wgs84_geo(ctx, expr, value); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk"); - } - } -} -#undef GRN_TS_EXPR_PUSH_BULK_CASE - -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - grn_ts_ ## kind ##_vector value = { (grn_ts_ ## kind *)GRN_BULK_HEAD(obj),\ - grn_uvector_size(ctx, obj) };\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - } -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *buf;\ - grn_ts_ ## kind ## _vector value = { NULL, grn_uvector_size(ctx, obj) };\ - if (!value.size) {\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - }\ - buf = GRN_MALLOCN(grn_ts_ ## kind, value.size);\ - if (!buf) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ - "GRN_MALLOCN failed: %zu x 1",\ - sizeof(grn_ts_ ## kind));\ - }\ - for (i = 0; i < value.size; i++) {\ - buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\ - }\ - value.ptr = buf;\ - rc = grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - GRN_FREE(buf);\ - return rc;\ - } -/* grn_ts_expr_push_uvector() pushes an array of fixed-size values. */ -static grn_rc -grn_ts_expr_push_uvector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_UVECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(INT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TIME, time) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, tokyo_geo) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, wgs84_geo) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE - -/* grn_ts_expr_push_vector() pushes an array of texts. */ -static grn_rc -grn_ts_expr_push_vector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - size_t i; - grn_rc rc; - grn_ts_text *buf; - grn_ts_text_vector value = { NULL, grn_vector_size(ctx, obj) }; - if (!value.size) { - return grn_ts_expr_push_text_vector(ctx, expr, value); - } - buf = GRN_MALLOCN(grn_ts_text, value.size); - if (!buf) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, - "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_text), value.size); - } - for (i = 0; i < value.size; i++) { - buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr, - NULL, NULL); - } - value.ptr = buf; - rc = grn_ts_expr_push_text_vector(ctx, expr, value); - GRN_FREE(buf); - return rc; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} - -static grn_rc -grn_ts_expr_push_single_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) { - switch (accessor->action) { - case GRN_ACCESSOR_GET_ID: { - return grn_ts_expr_push_id(ctx, expr); - } - case GRN_ACCESSOR_GET_SCORE: { - return grn_ts_expr_push_score(ctx, expr); - } - case GRN_ACCESSOR_GET_KEY: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_key(ctx, expr); - } - case GRN_ACCESSOR_GET_VALUE: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_value(ctx, expr); - } - case GRN_ACCESSOR_GET_COLUMN_VALUE: { - return grn_ts_expr_push_column(ctx, expr, accessor->obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d", - accessor->action); - } - } -} - -static grn_rc -grn_ts_expr_push_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) { - grn_rc rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - for (accessor = accessor->next; accessor; accessor = accessor->next) { - rc = grn_ts_expr_begin_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_end_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - } - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_obj(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !obj) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (obj->header.type) { - case GRN_BULK: { - return grn_ts_expr_push_bulk(ctx, expr, obj); - } - case GRN_UVECTOR: { - return grn_ts_expr_push_uvector(ctx, expr, obj); - } - case GRN_VECTOR: { - return grn_ts_expr_push_vector(ctx, expr, obj); - } - case GRN_ACCESSOR: { - return grn_ts_expr_push_accessor(ctx, expr, (grn_accessor *)obj); - } - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: { - return grn_ts_expr_push_column(ctx, expr, obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d", - obj->header.type); - } - } -} - -grn_rc -grn_ts_expr_push_id(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_id_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_score(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_score_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_key(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_key_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_value(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_value_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - return grn_ts_expr_push_ ## kind(ctx, expr,\ - *(const grn_ts_ ## kind *)value);\ - } -grn_rc -grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value) { - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !value) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (kind) { - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_CONST_CASE(INT, int) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME, time) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT, text) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO, geo) - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL_VECTOR, bool_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(INT_VECTOR, int_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT_VECTOR, float_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME_VECTOR, time_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT_VECTOR, text_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO_VECTOR, geo_vector) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", kind); - } - } -} -#undef GRN_TS_EXPR_PUSH_CONST_CASE - -grn_rc -grn_ts_expr_push_column(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *column) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !column || !grn_ts_obj_is_column(ctx, column) || - (DB_OBJ(expr->curr_table)->id != column->header.domain)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_column_node_open(ctx, column, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_op(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_op_type op_type) { - grn_rc rc; - grn_ts_expr_node **args, *node; - size_t i, n_args; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - n_args = grn_ts_op_get_n_args(op_type); - if (!n_args) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu", n_args); - } - if (n_args > expr->stack_depth) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu, %zu", - n_args, expr->stack_depth); - } - /* Arguments are the top n_args nodes in the stack. */ - args = &expr->stack[expr->stack_depth - n_args]; - for (i = 0; i < n_args; i++) { - /* - * FIXME: Operators "==" and "!=" should compare arguments as references - * if possible. - */ - rc = grn_ts_expr_deref(ctx, expr, &args[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - expr->stack_depth -= n_args; - rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST(KIND, kind)\ - grn_rc rc;\ - grn_ts_expr_node *node;\ - if (!ctx) {\ - return GRN_INVALID_ARGUMENT;\ - }\ - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||\ - !grn_ts_ ## kind ## _is_valid(value)) {\ - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");\ - }\ - rc = grn_ts_expr_reserve_stack(ctx, expr);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_const_node_open(ctx, GRN_TS_ ## KIND, &value, &node);\ - if (rc == GRN_SUCCESS) {\ - expr->stack[expr->stack_depth++] = node;\ - }\ - } -grn_rc -grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool value) { - GRN_TS_EXPR_PUSH_CONST(BOOL, bool) - return rc; -} - -grn_rc -grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_int value) { - GRN_TS_EXPR_PUSH_CONST(INT, int) - return rc; -} - -grn_rc -grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_float value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT, float) - return rc; -} - -grn_rc -grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_time value) { - GRN_TS_EXPR_PUSH_CONST(TIME, time) - return rc; -} - -grn_rc -grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_text value) { - GRN_TS_EXPR_PUSH_CONST(TEXT, text) - return rc; -} - -grn_rc -grn_ts_expr_push_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - node->data_type = GRN_DB_WGS84_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool_vector value) { - GRN_TS_EXPR_PUSH_CONST(BOOL_VECTOR, bool_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int_vector value) { - GRN_TS_EXPR_PUSH_CONST(INT_VECTOR, int_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float_vector value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT_VECTOR, float_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time_vector value) { - GRN_TS_EXPR_PUSH_CONST(TIME_VECTOR, time_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text_vector value) { - GRN_TS_EXPR_PUSH_CONST(TEXT_VECTOR, text_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} -#undef GRN_TS_EXPR_PUSH_CONST - -/* grn_ts_expr_reserve_bridges() extends a bridge buffer for a new bridge. */ -static grn_rc -grn_ts_expr_reserve_bridges(grn_ctx *ctx, grn_ts_expr *expr) { - size_t n_bytes, new_max_n_bridges; - grn_ts_expr_bridge *new_bridges; - if (expr->n_bridges < expr->max_n_bridges) { - return GRN_SUCCESS; - } - new_max_n_bridges = expr->n_bridges * 2; - if (!new_max_n_bridges) { - new_max_n_bridges = 1; - } - n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges; - new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(expr->bridges, n_bytes); - if (!new_bridges) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - expr->bridges = new_bridges; - expr->max_n_bridges = new_max_n_bridges; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_begin_subexpr(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_obj *obj; - grn_ts_expr_node *node; - grn_ts_expr_bridge *bridge; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !expr->stack_depth) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - - /* Check whehter or not the latest node refers to a table. */ - node = expr->stack[expr->stack_depth - 1]; - if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->data_kind); - } - obj = grn_ctx_at(ctx, node->data_type); - if (!obj) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", - node->data_type); - } - if (!grn_ts_obj_is_table(ctx, obj)) { - grn_obj_unlink(ctx, obj); - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type); - } - - /* Creates a bridge to a subexpression. */ - rc = grn_ts_expr_reserve_bridges(ctx, expr); - if (rc != GRN_SUCCESS) { - grn_obj_unlink(ctx, obj); - return rc; - } - bridge = &expr->bridges[expr->n_bridges++]; - grn_ts_expr_bridge_init(ctx, bridge); - bridge->src_table = expr->curr_table; - bridge->dest_table = obj; - bridge->stack_depth = expr->stack_depth; - expr->curr_table = bridge->dest_table; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_end_subexpr(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node **args, *node; - grn_ts_expr_bridge *bridge; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (expr->stack_depth < 2) || !expr->n_bridges) { - return GRN_INVALID_ARGUMENT; - } - /* Check whehter or not the subexpression is complete.*/ - bridge = &expr->bridges[expr->n_bridges - 1]; - if (expr->stack_depth != (bridge->stack_depth + 1)) { - return GRN_INVALID_ARGUMENT; - } - /* Creates a bridge node. */ - args = &expr->stack[expr->stack_depth - 2]; - rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Note: grn_ts_expr_reserve_stack() is not required. */ - expr->stack_depth -= 2; - expr->stack[expr->stack_depth++] = node; - expr->curr_table = bridge->src_table; - grn_ts_expr_bridge_fin(ctx, bridge); - expr->n_bridges--; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *root; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - return GRN_INVALID_ARGUMENT; - } - if (expr->stack_depth != 1) { - return GRN_INVALID_ARGUMENT; - } - rc = grn_ts_expr_deref(ctx, expr, &expr->stack[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - root = expr->stack[0]; - switch (root->data_kind) { - case GRN_TS_REF: - case GRN_TS_REF_VECTOR: { - return GRN_INVALID_ARGUMENT; - } - default: { - break; - } - } - switch (root->type) { - case GRN_TS_EXPR_ID_NODE: { - expr->type = GRN_TS_EXPR_ID; - break; - } - case GRN_TS_EXPR_SCORE_NODE: { - expr->type = GRN_TS_EXPR_SCORE; - break; - } - case GRN_TS_EXPR_KEY_NODE: - case GRN_TS_EXPR_VALUE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - case GRN_TS_EXPR_CONST_NODE: { - expr->type = GRN_TS_EXPR_CONST; - break; - } - case GRN_TS_EXPR_COLUMN_NODE: - case GRN_TS_EXPR_OP_NODE: - case GRN_TS_EXPR_BRIDGE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - default: { - return GRN_INVALID_ARGUMENT; - } - } - expr->data_type = root->data_type; - expr->data_kind = root->data_kind; - expr->root = root; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, - const grn_ts_record *in, size_t n_in, - grn_ts_buf *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || !out) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out); -} - -grn_rc -grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, - const grn_ts_record *in, size_t n_in, void *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || (n_in && !out)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out); -} - -grn_rc -grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || - !out || !n_out) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - *n_out = 0; - return GRN_SUCCESS; - } - return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out); -} - -grn_rc -grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_record *io, size_t n_io) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!io && n_io)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_io) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); -} Added: lib/ts/ts_expr_node.h (+113 -0) 100644 =================================================================== --- /dev/null +++ lib/ts/ts_expr_node.h 2015-11-12 11:20:53 +0900 (6cbb03e) @@ -0,0 +1,113 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_TS_EXPR_NODE_H +#define GRN_TS_EXPR_NODE_H + +#include "ts_buf.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GRN_TS_EXPR_ID_NODE, /* ID (_id). */ + GRN_TS_EXPR_SCORE_NODE, /* Score (_score). */ + GRN_TS_EXPR_KEY_NODE, /* Key (_key). */ + GRN_TS_EXPR_VALUE_NODE, /* Embedded value (_value). */ + GRN_TS_EXPR_CONST_NODE, /* Const. */ + GRN_TS_EXPR_COLUMN_NODE, /* Column. */ + GRN_TS_EXPR_OP_NODE, /* Operator. */ + GRN_TS_EXPR_BRIDGE_NODE /* Bridge to a subexpression. */ +} grn_ts_expr_node_type; + +#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\ + grn_ts_expr_node_type type; /* Node type. */\ + grn_ts_data_kind data_kind; /* Abstract data type. */\ + grn_ts_data_type data_type; /* Detailed data type. */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS +} grn_ts_expr_node; + +/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */ +grn_rc grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node); + +/* + * grn_ts_expr_score_node_open() creates a node associated with scores + * (_score). + */ +grn_rc grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node); + +/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */ +grn_rc grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node); + +/* + * grn_ts_expr_value_node_open() creates a node associated with values + * (_value). + */ +grn_rc grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node); + +/* grn_ts_expr_const_node_open() creates a node associated with a const. */ +grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind, + const void *value, grn_ts_expr_node **node); + +/* grn_ts_expr_column_node_open() creates a node associated with a column. */ +grn_rc grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, + grn_ts_expr_node **node); + +/* grn_ts_expr_op_node_open() creates a node associated with an operator. */ +grn_rc grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, + grn_ts_expr_node **args, size_t n_args, + grn_ts_expr_node **node); + +/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */ +grn_rc grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, + grn_ts_expr_node *dest, + grn_ts_expr_node **node); + +/* grn_ts_expr_node_close() destroys a node. */ +void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node); + +/* grn_ts_expr_node_evaluate() evaluates a subtree. */ +grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, + void *out); + +/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */ +grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_buf *out); + +/* grn_ts_expr_node_filter() filters records. */ +grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out); + +/* grn_ts_expr_node_adjust() updates scores. */ +grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *io, size_t n_io); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_TS_EXPR_NODE_H */ Modified: lib/ts/ts_types.h (+79 -24) =================================================================== --- lib/ts/ts_types.h 2015-11-12 09:59:27 +0900 (13088b7) +++ lib/ts/ts_types.h 2015-11-12 11:20:53 +0900 (970afec) @@ -26,6 +26,44 @@ extern "C" { #endif /*------------------------------------------------------------- + * Enumeration types. + */ + +typedef enum { + /* Invalid operator. */ + GRN_TS_OP_NOP, + + /* Unary operators. */ + GRN_TS_OP_LOGICAL_NOT, /* !X */ + GRN_TS_OP_BITWISE_NOT, /* ~X */ + GRN_TS_OP_POSITIVE, /* +X */ + GRN_TS_OP_NEGATIVE, /* -X */ + + /* Binary operators. */ + GRN_TS_OP_LOGICAL_AND, /* X && Y */ + GRN_TS_OP_LOGICAL_OR, /* X || Y */ + GRN_TS_OP_LOGICAL_SUB, /* X &! Y */ + GRN_TS_OP_BITWISE_AND, /* X & Y */ + GRN_TS_OP_BITWISE_OR, /* X | Y */ + GRN_TS_OP_BITWISE_XOR, /* X ^ Y */ + GRN_TS_OP_EQUAL, /* X == Y */ + GRN_TS_OP_NOT_EQUAL, /* X != Y */ + GRN_TS_OP_LESS, /* X < Y */ + GRN_TS_OP_LESS_EQUAL, /* X <= Y */ + GRN_TS_OP_GREATER, /* X > Y */ + GRN_TS_OP_GREATER_EQUAL, /* X >= Y */ + GRN_TS_OP_SHIFT_ARITHMETIC_LEFT, /* X << Y */ + GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y */ + GRN_TS_OP_SHIFT_LOGICAL_LEFT, /* X <<< Y */ + GRN_TS_OP_SHIFT_LOGICAL_RIGHT, /* X >>> Y */ + GRN_TS_OP_PLUS, /* X + Y */ + GRN_TS_OP_MINUS, /* X - Y */ + GRN_TS_OP_MULTIPLICATION, /* X * Y */ + GRN_TS_OP_DIVISION, /* X / Y */ + GRN_TS_OP_MODULUS /* X % Y */ +} grn_ts_op_type; + +/*------------------------------------------------------------- * Built-in data types. */ @@ -45,30 +83,6 @@ typedef struct { } grn_ts_record; /*------------------------------------------------------------- - * Built-in data kinds. - */ - -enum { GRN_TS_VECTOR_FLAG = 1 << 7 }; - -typedef enum { - GRN_TS_VOID = 0, /* GRN_DB_VOID */ - GRN_TS_BOOL = 1, /* GRN_DB_BOOL */ - GRN_TS_INT = 2, /* GRN_DB_[U]INT(8/16/32/64) */ - GRN_TS_FLOAT = 3, /* GRN_DB_FLOAT */ - GRN_TS_TIME = 4, /* GRN_DB_TIME */ - GRN_TS_TEXT = 5, /* GRN_DB_[SHORT_/LONG_]TEST */ - GRN_TS_GEO = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */ - GRN_TS_REF = 7, /* Table reference. */ - GRN_TS_BOOL_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL, - GRN_TS_INT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_INT, - GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT, - GRN_TS_TIME_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TIME, - GRN_TS_TEXT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT, - GRN_TS_GEO_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_GEO, - GRN_TS_REF_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_REF -} grn_ts_data_kind; - -/*------------------------------------------------------------- * Built-in scalar data kinds. */ @@ -146,6 +160,47 @@ typedef struct { size_t size; } grn_ts_ref_vector; +/*------------------------------------------------------------- + * Built-in data kinds. + */ + +enum { GRN_TS_VECTOR_FLAG = 1 << 7 }; + +typedef enum { + GRN_TS_VOID = 0, /* GRN_DB_VOID */ + GRN_TS_BOOL = 1, /* GRN_DB_BOOL */ + GRN_TS_INT = 2, /* GRN_DB_[U]INT(8/16/32/64) */ + GRN_TS_FLOAT = 3, /* GRN_DB_FLOAT */ + GRN_TS_TIME = 4, /* GRN_DB_TIME */ + GRN_TS_TEXT = 5, /* GRN_DB_[SHORT_/LONG_]TEST */ + GRN_TS_GEO = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */ + GRN_TS_REF = 7, /* Table reference. */ + GRN_TS_BOOL_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL, + GRN_TS_INT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_INT, + GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT, + GRN_TS_TIME_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TIME, + GRN_TS_TEXT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT, + GRN_TS_GEO_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_GEO, + GRN_TS_REF_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_REF +} grn_ts_data_kind; + +typedef union { + grn_ts_bool as_bool; + grn_ts_int as_int; + grn_ts_float as_float; + grn_ts_time as_time; + grn_ts_text as_text; + grn_ts_geo as_geo; + grn_ts_ref as_ref; + grn_ts_bool_vector as_bool_vector; + grn_ts_int_vector as_int_vector; + grn_ts_float_vector as_float_vector; + grn_ts_time_vector as_time_vector; + grn_ts_text_vector as_text_vector; + grn_ts_geo_vector as_geo_vector; + grn_ts_ref_vector as_ref_vector; +} grn_ts_any; + #ifdef __cplusplus } #endif