diff --git a/c/mapping/lrec_evaluators.c b/c/mapping/lrec_evaluators.c index 2067912ac..41c5b0f80 100644 --- a/c/mapping/lrec_evaluators.c +++ b/c/mapping/lrec_evaluators.c @@ -398,6 +398,32 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_s_x_func(mv_unary_func_t* pfunc, lre return pevaluator; } +// ---------------------------------------------------------------- +typedef struct _lrec_evaluator_b_x_state_t { + mv_unary_func_t* pfunc; + lrec_evaluator_t* parg1; +} lrec_evaluator_b_x_state_t; + +mv_t lrec_evaluator_b_x_func(lrec_t* prec, context_t* pctx, void* pvstate) { + lrec_evaluator_b_x_state_t* pstate = pvstate; + mv_t val1 = pstate->parg1->pevaluator_func(prec, pctx, pstate->parg1->pvstate); + return pstate->pfunc(&val1); +} + +lrec_evaluator_t* lrec_evaluator_alloc_from_b_x_func(mv_unary_func_t* pfunc, + lrec_evaluator_t* parg1) +{ + lrec_evaluator_b_x_state_t* pstate = mlr_malloc_or_die(sizeof(lrec_evaluator_b_x_state_t)); + pstate->pfunc = pfunc; + pstate->parg1 = parg1; + + lrec_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(lrec_evaluator_t)); + pevaluator->pvstate = pstate; + pevaluator->pevaluator_func = lrec_evaluator_b_x_func; + + return pevaluator; +} + // ---------------------------------------------------------------- typedef struct _lrec_evaluator_b_xx_state_t { mv_binary_func_t* pfunc; @@ -751,6 +777,7 @@ static function_lookup_t FUNCTION_LOOKUP_TABLE[] = { { FUNC_CLASS_CONVERSION, "float", 1 , "Convert int/float/bool/string to float."}, { FUNC_CLASS_CONVERSION, "int", 1 , "Convert int/float/bool/string to int."}, { FUNC_CLASS_CONVERSION, "string", 1 , "Convert int/float/bool/string to string."}, + { FUNC_CLASS_CONVERSION, "boolean", 1 , "Convert int/float/bool/string to boolean."}, { FUNC_CLASS_TIME, "gmt2sec", 1 , "Parses GMT timestamp as integer seconds since epoch."}, { FUNC_CLASS_TIME, "sec2gmt", 1 , "Formats seconds since epoch (integer part only) as GMT timestamp."}, @@ -883,6 +910,7 @@ lrec_evaluator_t* lrec_evaluator_alloc_from_unary_func_name(char* fnnm, lrec_eva } else if (streq(fnnm, "asinh")) { return lrec_evaluator_alloc_from_f_f_func(f_f_asinh_func, parg1); } else if (streq(fnnm, "atan")) { return lrec_evaluator_alloc_from_f_f_func(f_f_atan_func, parg1); } else if (streq(fnnm, "atanh")) { return lrec_evaluator_alloc_from_f_f_func(f_f_atanh_func, parg1); + } else if (streq(fnnm, "boolean")) { return lrec_evaluator_alloc_from_b_x_func(b_x_boolean_func, parg1); } else if (streq(fnnm, "cbrt")) { return lrec_evaluator_alloc_from_f_f_func(f_f_cbrt_func, parg1); } else if (streq(fnnm, "ceil")) { return lrec_evaluator_alloc_from_f_f_func(f_f_ceil_func, parg1); } else if (streq(fnnm, "cos")) { return lrec_evaluator_alloc_from_f_f_func(f_f_cos_func, parg1); diff --git a/c/mapping/mlr_val.c b/c/mapping/mlr_val.c index 9254f75ea..812135743 100644 --- a/c/mapping/mlr_val.c +++ b/c/mapping/mlr_val.c @@ -312,6 +312,28 @@ static mv_unary_func_t* float_dispositions[MT_MAX] = { mv_t f_x_float_func(mv_t* pval1) { return (float_dispositions[pval1->type])(pval1); } +// ---------------------------------------------------------------- +static mv_t boolean_b_n(mv_t* pa) { return (mv_t) {.type = MT_NULL, .u.intv = 0}; } +static mv_t boolean_b_e(mv_t* pa) { return (mv_t) {.type = MT_ERROR, .u.intv = 0}; } +static mv_t boolean_b_b(mv_t* pa) { return (mv_t) {.type = MT_BOOL, .u.boolv = pa->u.boolv}; } +static mv_t boolean_b_d(mv_t* pa) { return (mv_t) {.type = MT_BOOL, .u.boolv = (pa->u.dblv == 0.0) ? FALSE : TRUE}; } +static mv_t boolean_b_i(mv_t* pa) { return (mv_t) {.type = MT_BOOL, .u.boolv = (pa->u.intv == 0LL) ? FALSE : TRUE}; } +static mv_t boolean_b_s(mv_t* pa) { return (mv_t) {.type = MT_BOOL, + .u.boolv = (streq(pa->u.strv, "true") || streq(pa->u.strv, "TRUE")) ? TRUE : FALSE + }; +} + +static mv_unary_func_t* boolean_dispositions[MT_MAX] = { + /*NULL*/ boolean_b_n, + /*ERROR*/ boolean_b_e, + /*BOOL*/ boolean_b_b, + /*DOUBLE*/ boolean_b_d, + /*INT*/ boolean_b_i, + /*STRING*/ boolean_b_s, +}; + +mv_t b_x_boolean_func(mv_t* pval1) { return (boolean_dispositions[pval1->type])(pval1); } + // ---------------------------------------------------------------- static mv_t string_s_n(mv_t* pa) { return (mv_t) {.type = MT_NULL, .u.intv = 0}; } static mv_t string_s_e(mv_t* pa) { return (mv_t) {.type = MT_ERROR, .u.intv = 0}; } diff --git a/c/mapping/mlr_val.h b/c/mapping/mlr_val.h index eb392e87a..3aaaa6a3c 100644 --- a/c/mapping/mlr_val.h +++ b/c/mapping/mlr_val.h @@ -127,6 +127,7 @@ static inline mv_t f_f_uneg_func(mv_t* pval1){mv_t rv={.type=MT_DOUBLE,.u.db mv_t i_x_int_func(mv_t* pval1); mv_t f_x_float_func(mv_t* pval1); +mv_t b_x_boolean_func(mv_t* pval1); mv_t s_x_string_func(mv_t* pval1); // ---------------------------------------------------------------- diff --git a/c/todo.txt b/c/todo.txt index 30234338a..9e58195ac 100644 --- a/c/todo.txt +++ b/c/todo.txt @@ -10,6 +10,7 @@ TOP OF LIST !! booleans into put-dsl: should be able to do: mlr put '$ok = $x < 10' -> boolean literal parsing? on by default? doc why not if not. (various words in text columns, some ('true','false') suddenly changing type -- ick.) + -> boolean() function then?? -> certainly, for output: want mlr put '$z=true' -> UTs