diff --git a/src/tkc/expr_eval.c b/src/tkc/expr_eval.c index d508af3ef..a0344182c 100644 --- a/src/tkc/expr_eval.c +++ b/src/tkc/expr_eval.c @@ -1196,6 +1196,46 @@ static EvalResult func_if(const ExprValue* input, void* user_data, ExprValue* ou return EVAL_RESULT_OK; } +static EvalResult func_fformat(const ExprValue* input, void* user_data, ExprValue* output) { + (void)user_data; + if (args_count(input) != 2) { + return EVAL_RESULT_BAD_PARAMS; + } + + if (input->type == EXPR_VALUE_TYPE_STRING) { + char buff[128]; + const char* format = input->v.str.str; + double value = expr_value_get_number(input + 1); + return_value_if_fail(format != NULL, EVAL_RESULT_BAD_PARAMS); + + tk_snprintf(buff, sizeof(buff), format, value); + expr_value_set_string(output, buff, strlen(buff)); + return EVAL_RESULT_OK; + } else { + return EVAL_RESULT_BAD_PARAMS; + } +} + +static EvalResult func_iformat(const ExprValue* input, void* user_data, ExprValue* output) { + (void)user_data; + if (args_count(input) != 2) { + return EVAL_RESULT_BAD_PARAMS; + } + + if (input->type == EXPR_VALUE_TYPE_STRING) { + char buff[128]; + const char* format = input->v.str.str; + int value = (int)expr_value_get_number(input + 1); + return_value_if_fail(format != NULL, EVAL_RESULT_BAD_PARAMS); + + tk_snprintf(buff, sizeof(buff), format, value); + expr_value_set_string(output, buff, strlen(buff)); + return EVAL_RESULT_OK; + } else { + return EVAL_RESULT_BAD_PARAMS; + } +} + static EvalResult func_ceil(const ExprValue* input, void* user_data, ExprValue* output) { (void)user_data; expr_value_set_number(output, ceil(expr_value_get_number(input))); @@ -1216,13 +1256,14 @@ static EvalResult func_round(const ExprValue* input, void* user_data, ExprValue* static EvalFunc default_get_func(const char* name, void* user_data) { static const EvalFunctionEntry FUNCTIONS[] = { - {"number", func_number}, {"strlen", func_strlen}, {"path", func_path}, - {"string", func_string}, {"toupper", func_toupper}, {"tolower", func_tolower}, - {"cos", func_cos}, {"sin", func_sin}, {"tan", func_tan}, - {"acos", func_acos}, {"asin", func_asin}, {"atan", func_atan}, - {"exp", func_exp}, {"log", func_log}, {"log10", func_log10}, - {"sqrt", func_sqrt}, {"ceil", func_ceil}, {"floor", func_floor}, - {"int", func_floor}, {"round", func_round}, {"if", func_if}}; + {"number", func_number}, {"strlen", func_strlen}, {"path", func_path}, + {"string", func_string}, {"toupper", func_toupper}, {"tolower", func_tolower}, + {"cos", func_cos}, {"sin", func_sin}, {"tan", func_tan}, + {"acos", func_acos}, {"asin", func_asin}, {"atan", func_atan}, + {"exp", func_exp}, {"log", func_log}, {"log10", func_log10}, + {"sqrt", func_sqrt}, {"ceil", func_ceil}, {"floor", func_floor}, + {"int", func_floor}, {"round", func_round}, {"if", func_if}, + {"fformat", func_fformat}, {"iformat", func_iformat}}; const EvalFunctionEntry* i = FUNCTIONS; const EvalFunctionEntry* e = i + (sizeof(FUNCTIONS) / sizeof(*FUNCTIONS)); @@ -1305,3 +1346,19 @@ double tk_expr_eval(const char* expr) { return ret; } + +const char* tk_expr_eval_str(const char* expr, char* result, uint32_t max_size) { + ExprValue v; + EvalResult res; + const char* ret = NULL; + return_value_if_fail(result != NULL, NULL); + + expr_value_init(&v); + res = eval_execute(expr, eval_default_hooks(), NULL, &v); + + ret = res == EVAL_RESULT_OK ? expr_value_get_string(&v) : ""; + strncpy(result, ret, max_size - 1); + expr_value_clear(&v); + + return result; +} diff --git a/src/tkc/expr_eval.h b/src/tkc/expr_eval.h index 4bbb71a64..643862f0f 100644 --- a/src/tkc/expr_eval.h +++ b/src/tkc/expr_eval.h @@ -82,6 +82,7 @@ typedef struct { EvalResult eval_execute(const char* expr, const EvalHooks* hooks, void* ctx, ExprValue* output); double tk_expr_eval(const char* expr); +const char* tk_expr_eval_str(const char* expr, char* result, uint32_t max_size); const EvalHooks* eval_default_hooks(void); diff --git a/tests/expr_test.cc b/tests/expr_test.cc index b710a6490..ea66ff5c4 100644 --- a/tests/expr_test.cc +++ b/tests/expr_test.cc @@ -67,3 +67,16 @@ TEST(ExprEval, hex) { ASSERT_EQ(0xfffffffa, tk_expr_eval("0xffffFFFa")); ASSERT_EQ(0xfffafffa, tk_expr_eval("0xfffaFFFa")); } + +TEST(ExprEval, fformat) { + char result[128]; + ASSERT_STREQ("1.23", tk_expr_eval_str("fformat(\"%2.2f\", 1.23)", result, sizeof(result))); + ASSERT_STREQ("temp:1.20", + tk_expr_eval_str("fformat(\"temp:%2.2f\", 1.2)", result, sizeof(result))); +} + +TEST(ExprEval, iformat) { + char result[128]; + ASSERT_STREQ("123", tk_expr_eval_str("iformat(\"%d\", 123)", result, sizeof(result))); + ASSERT_STREQ("temp:123", tk_expr_eval_str("iformat(\"temp:%d\", 123)", result, sizeof(result))); +}