static void stats1_count_emit(void* pvstate, char* value_field_name, char* stats1_acc_name, int copy_data, lrec_t* poutrec) { stats1_count_state_t* pstate = pvstate; if (copy_data) lrec_put(poutrec, mlr_strdup_or_die(pstate->output_field_name), mv_alloc_format_val(&pstate->counter), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); else lrec_put(poutrec, pstate->output_field_name, mv_alloc_format_val(&pstate->counter), FREE_ENTRY_VALUE); }
static void stats1_max_emit(void* pvstate, char* value_field_name, char* stats1_acc_name, int copy_data, lrec_t* poutrec) { stats1_max_state_t* pstate = pvstate; if (mv_is_null(&pstate->max)) { if (copy_data) lrec_put(poutrec, mlr_strdup_or_die(pstate->output_field_name), "", FREE_ENTRY_KEY); else lrec_put(poutrec, pstate->output_field_name, "", NO_FREE); } else { if (copy_data) lrec_put(poutrec, mlr_strdup_or_die(pstate->output_field_name), mv_alloc_format_val(&pstate->max), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); else lrec_put(poutrec, pstate->output_field_name, mv_alloc_format_val(&pstate->max), FREE_ENTRY_VALUE); } }
// ---------------------------------------------------------------- static char* test_no_overlap() { mlhmmv_t* pmap = mlhmmv_alloc(); int error = 0; printf("----------------------------------------------------------------\n"); printf("empty map:\n"); mlhmmv_print(pmap); sllmv_t* pmvkeys1 = sllmv_single(imv(3)); mv_t value1 = mv_from_int(4LL); printf("\n"); printf("keys1: "); sllmv_print(pmvkeys1); printf("value1: %s\n", mv_alloc_format_val(&value1)); mlhmmv_put(pmap, pmvkeys1, &value1); printf("map:\n"); mlhmmv_print(pmap); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys1, &error), &value1)); sllmv_t* pmvkeys2 = sllmv_double(smv("abcde"), imv(-6)); mv_t value2 = mv_from_int(7); printf("\n"); printf("keys2: "); sllmv_print(pmvkeys2); printf("value2: %s\n", mv_alloc_format_val(&value2)); mlhmmv_put(pmap, pmvkeys2, &value2); printf("map:\n"); mlhmmv_print(pmap); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys2, &error), &value2)); sllmv_t* pmvkeys3 = sllmv_triple(imv(0), smv("fghij"), imv(0)); mv_t value3 = mv_from_int(0LL); printf("\n"); printf("keys3: "); sllmv_print(pmvkeys3); printf("value3: %s\n", mv_alloc_format_val(&value3)); mlhmmv_put(pmap, pmvkeys3, &value3); printf("map:\n"); mlhmmv_print(pmap); mu_assert_lf(mv_equals_si(mlhmmv_get(pmap, pmvkeys3, &error), &value3)); sllmv_free(pmvkeys1); mlhmmv_free(pmap); return NULL; }
// ---------------------------------------------------------------- static void handle_full_srec_assignment( mlr_dsl_cst_statement_t* pstatement, variables_t* pvars, cst_outputs_t* pcst_outputs) { full_srec_assignment_state_t* pstate = pstatement->pvstate; lrec_t* poutrec = lrec_unbacked_alloc(); // pinrec might be part of the RHS. lhmsmv_t* pout_typed_overlay = lhmsmv_alloc(); rxval_evaluator_t* prhs_xevaluator = pstate->prhs_xevaluator; boxed_xval_t boxed_xval = prhs_xevaluator->pprocess_func(prhs_xevaluator->pvstate, pvars); if (!boxed_xval.xval.is_terminal) { for (mlhmmv_level_entry_t* pe = boxed_xval.xval.pnext_level->phead; pe != NULL; pe = pe->pnext) { mv_t* pkey = &pe->level_key; mlhmmv_xvalue_t* pval = &pe->level_xvalue; if (pval->is_terminal) { // xxx else collapse-down using json separator? char* skey = mv_alloc_format_val(pkey); // xxx if we're going to transfer here *and* free below, this needs a nullptr poke // at the copy-from site //mv_t val = boxed_xval.is_ephemeral ? pval->terminal_mlrval : mv_copy(&pval->terminal_mlrval); mv_t val = mv_copy(&pval->terminal_mlrval); // Write typed mlrval output to the typed overlay rather than into the lrec // (which holds only string values). // // The rval_evaluator reads the overlay in preference to the lrec. E.g. if the // input had "x"=>"abc","y"=>"def" but a previous statement had set "y"=>7.4 and // "z"=>"ghi", then an expression right-hand side referring to $y would get the // floating-point value 7.4. So we don't need to lrec_put the value here, and // moreover should not for two reasons: (1) there is a performance hit of doing // throwaway number-to-string formatting -- it's better to do it once at the // end; (2) having the string values doubly owned by the typed overlay and the // lrec would result in double frees, or awkward bookkeeping. However, the NR // variable evaluator reads prec->field_count, so we need to put something here. // And putting something statically allocated minimizes copying/freeing. lhmsmv_put(pout_typed_overlay, mlr_strdup_or_die(skey), &val, FREE_ENTRY_KEY | FREE_ENTRY_VALUE); lrec_put(poutrec, skey, "bug", FREE_ENTRY_KEY); } } if (boxed_xval.is_ephemeral) { mlhmmv_xvalue_free(&boxed_xval.xval); } } else { mlhmmv_xvalue_free(&boxed_xval.xval); } lrec_free(pvars->pinrec); lhmsmv_free(pvars->ptyped_overlay); pvars->pinrec = poutrec; pvars->ptyped_overlay = pout_typed_overlay; }
static void stats1_percentile_emit(void* pvstate, char* value_field_name, char* stats1_acc_name, int copy_data, lrec_t* poutrec) { stats1_percentile_state_t* pstate = pvstate; double p; (void)sscanf(stats1_acc_name, "p%lf", &p); // Assuming this was range-checked earlier on to be in [0,100]. mv_t v = percentile_keeper_emit(pstate->ppercentile_keeper, p); char* s = mv_alloc_format_val(&v); // For this type, one accumulator tracks many stats1_names, but a single value_field_name. char* output_field_name = lhmss_get(pstate->poutput_field_names, stats1_acc_name); if (output_field_name == NULL) { output_field_name = mlr_paste_3_strings(value_field_name, "_", stats1_acc_name); lhmss_put(pstate->poutput_field_names, mlr_strdup_or_die(stats1_acc_name), output_field_name, FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } lrec_put(poutrec, mlr_strdup_or_die(output_field_name), s, FREE_ENTRY_KEY|FREE_ENTRY_VALUE); }