diff --git a/c/containers/mlhmmv.c b/c/containers/mlhmmv.c index b66036625..4539a29b5 100644 --- a/c/containers/mlhmmv.c +++ b/c/containers/mlhmmv.c @@ -37,6 +37,8 @@ static void mlhmmv_level_print_stacked(mlhmmv_level_t* plevel, int depth, static void mlhmmv_level_print_single_line(mlhmmv_level_t* plevel, int depth, int do_final_comma, int quote_values_always); +static void json_decimal_print(char* s); + static int mlhmmv_hash_func(mv_t* plevel_key); // ---------------------------------------------------------------- @@ -355,7 +357,7 @@ static void mlhmmv_level_enlarge(mlhmmv_level_t* plevel) { // xxx rename to have 'json' in the method name -void mlhmmv_print_stacked(mlhmmv_t* pmap, int quote_values_always) { +void mlhmmv_print_json_stacked(mlhmmv_t* pmap, int quote_values_always) { mlhmmv_level_print_stacked(pmap->proot_level, 0, FALSE, quote_values_always); } @@ -380,9 +382,8 @@ static void mlhmmv_level_print_stacked(mlhmmv_level_t* plevel, int depth, printf("\"%s\"", level_value_string); } else if (pentry->level_value.u.mlrval.type == MT_STRING) { double unused; - // xxx insert leading '0' if starts with '.'; insert leading '-0' if starts with '-.'. if (mlr_try_float_from_string(level_value_string, &unused)) - printf("%s", level_value_string); + json_decimal_print(level_value_string); else if (streq(level_value_string, "true") || streq(level_value_string, "false")) printf("%s", level_value_string); else @@ -411,7 +412,7 @@ static void mlhmmv_level_print_stacked(mlhmmv_level_t* plevel, int depth, } // ---------------------------------------------------------------- -void mlhmmv_print_single_line(mlhmmv_t* pmap, int quote_values_always) { +void mlhmmv_print_json_single_line(mlhmmv_t* pmap, int quote_values_always) { mlhmmv_level_print_single_line(pmap->proot_level, 0, FALSE, quote_values_always); printf("\n"); } @@ -435,7 +436,7 @@ static void mlhmmv_level_print_single_line(mlhmmv_level_t* plevel, int depth, } else if (pentry->level_value.u.mlrval.type == MT_STRING) { double unused; if (mlr_try_float_from_string(level_value_string, &unused)) - printf("%s", level_value_string); + json_decimal_print(level_value_string); else if (streq(level_value_string, "true") || streq(level_value_string, "false")) printf("%s", level_value_string); else @@ -459,6 +460,21 @@ static void mlhmmv_level_print_single_line(mlhmmv_level_t* plevel, int depth, printf(" }"); } +// ---------------------------------------------------------------- +// 0.123 is valid JSON; .123 is not. Meanwhile is a format-converter tool so if there is +// perfectly legitimate CSV/DKVP/etc. data to be JSON-formatted, we make it JSON-compliant. +// +// Precondition: the caller has already checked that the string represents a number. +static void json_decimal_print(char* s) { + if (s[0] == '.') { + printf("0%s", s); + } else if (s[0] == '-' && s[1] == '.') { + printf("-0.%s", &s[2]); + } else { + printf("%s", s); + } +} + // ---------------------------------------------------------------- typedef int mlhmmv_typed_hash_func(mv_t* pa); diff --git a/c/containers/mlhmmv.h b/c/containers/mlhmmv.h index b14c5f5d1..853d79354 100644 --- a/c/containers/mlhmmv.h +++ b/c/containers/mlhmmv.h @@ -76,7 +76,7 @@ void mlhmmv_put(mlhmmv_t* pmap, sllmv_t* pmvkeys, mv_t* pterminal_value); // The caller shouldn't free it, or modify it. mv_t* mlhmmv_get(mlhmmv_t* pmap, sllmv_t* pmvkeys, int* perror); -void mlhmmv_print_stacked(mlhmmv_t* pmap, int quote_values_always); -void mlhmmv_print_single_line(mlhmmv_t* pmap, int quote_values_always); +void mlhmmv_print_json_stacked(mlhmmv_t* pmap, int quote_values_always); +void mlhmmv_print_json_single_line(mlhmmv_t* pmap, int quote_values_always); #endif // MLHMMV_H diff --git a/c/mapping/mapper_put.c b/c/mapping/mapper_put.c index 35edf3da5..5a6f20f93 100644 --- a/c/mapping/mapper_put.c +++ b/c/mapping/mapper_put.c @@ -347,7 +347,7 @@ static void evaluate_statements( sllv_append(poutrecs, prec_to_emit); } else if (node_type == MD_AST_NODE_TYPE_DUMP) { - mlhmmv_print_stacked(pstate->poosvars, FALSE); + mlhmmv_print_json_stacked(pstate->poosvars, FALSE); } else if (node_type == MD_AST_NODE_TYPE_FILTER) { mlr_dsl_cst_statement_item_t* pitem = pstatement->pitems->phead->pvvalue; diff --git a/c/output/lrec_writer_json.c b/c/output/lrec_writer_json.c index ed0dfea27..d0d11660c 100644 --- a/c/output/lrec_writer_json.c +++ b/c/output/lrec_writer_json.c @@ -77,9 +77,9 @@ static void lrec_writer_json_process(FILE* output_stream, lrec_t* prec, void* pv } if (pstate->stack_vertically) - mlhmmv_print_stacked(pmap, pstate->quote_json_values_always); + mlhmmv_print_json_stacked(pmap, pstate->quote_json_values_always); else - mlhmmv_print_single_line(pmap, pstate->quote_json_values_always); + mlhmmv_print_json_single_line(pmap, pstate->quote_json_values_always); mlhmmv_free(pmap); diff --git a/c/todo.txt b/c/todo.txt index 0bca103f0..4d7023491 100644 --- a/c/todo.txt +++ b/c/todo.txt @@ -10,6 +10,7 @@ TOP-OF-LIST SUMMARY ! rh/fedora/centos mlr-3.3.2: after patch-file for manpage * parameterized emit: needs spec & impl * pattern-action: note that breaks the simple LHS/RHS partition I've enjoyed up until now +* valgrinds * explode & any other komosas from feature-request task diff --git a/c/unit_test/test_mlhmmv.c b/c/unit_test/test_mlhmmv.c index 07377a300..f3a656b36 100644 --- a/c/unit_test/test_mlhmmv.c +++ b/c/unit_test/test_mlhmmv.c @@ -27,7 +27,7 @@ static char* test_no_overlap() { printf("----------------------------------------------------------------\n"); printf("empty map:\n"); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); sllmv_t* pmvkeys1 = sllmv_single(imv(3)); mv_t value1 = mv_from_int(4LL); @@ -37,7 +37,7 @@ static char* test_no_overlap() { printf("value1: %s\n", mv_alloc_format_val(&value1)); mlhmmv_put(pmap, pmvkeys1, &value1); printf("map:\n"); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys1, &error), &value1)); sllmv_t* pmvkeys2 = sllmv_double(smv("abcde"), imv(-6)); @@ -48,7 +48,7 @@ static char* test_no_overlap() { printf("value2: %s\n", mv_alloc_format_val(&value2)); mlhmmv_put(pmap, pmvkeys2, &value2); printf("map:\n"); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys2, &error), &value2)); sllmv_t* pmvkeys3 = sllmv_triple(imv(0), smv("fghij"), imv(0)); @@ -59,7 +59,7 @@ static char* test_no_overlap() { printf("value3: %s\n", mv_alloc_format_val(&value3)); mlhmmv_put(pmap, pmvkeys3, &value3); printf("map:\n"); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys3, &error), &value3)); sllmv_free(pmvkeys1); @@ -76,35 +76,35 @@ static char* test_overlap() { sllmv_t* pmvkeys = sllmv_single(imv(3)); mv_t* ptermval = imv(4); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); ptermval = imv(5); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); pmvkeys = sllmv_double(imv(3), smv("x")); ptermval = imv(6); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); ptermval = imv(7); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); pmvkeys = sllmv_triple(imv(3), imv(9), smv("y")); ptermval = smv("z"); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); pmvkeys = sllmv_triple(imv(3), imv(9), smv("z")); ptermval = smv("y"); mlhmmv_put(pmap, pmvkeys, ptermval); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys, &error), ptermval)); mlhmmv_free(pmap); @@ -119,17 +119,17 @@ static char* test_resize() { printf("----------------------------------------------------------------\n"); for (int i = 0; i < 2*MLHMMV_INITIAL_ARRAY_LENGTH; i++) mlhmmv_put(pmap, sllmv_single(imv(i)), imv(-i)); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); printf("\n"); for (int i = 0; i < 2*MLHMMV_INITIAL_ARRAY_LENGTH; i++) mlhmmv_put(pmap, sllmv_double(smv("a"), imv(i)), imv(-i)); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); printf("\n"); for (int i = 0; i < 2*MLHMMV_INITIAL_ARRAY_LENGTH; i++) mlhmmv_put(pmap, sllmv_triple(imv(i*100), imv(i % 4), smv("b")), smv("term")); - mlhmmv_print_stacked(pmap, FALSE); + mlhmmv_print_json_stacked(pmap, FALSE); sllmv_t* pmvkeys = sllmv_single(imv(2)); mv_t* ptermval = imv(-2);