From 16ccc58649e2c25cd8fdbced82c765ed5aec9f0b Mon Sep 17 00:00:00 2001 From: John Kerl Date: Thu, 7 Jan 2016 21:58:59 +0000 Subject: [PATCH] free-flags for lhmss --- c/cli/mlrcli.c | 68 +++++++++++++------------- c/containers/lhmss.c | 38 ++++++++------ c/containers/lhmss.h | 3 +- c/containers/lrec.c | 3 +- c/mapping/mapper_histogram.c | 8 ++- c/mapping/mapper_rename.c | 2 +- c/mapping/stats1_accumulators.c | 2 +- c/unit_test/test_multiple_containers.c | 8 +-- 8 files changed, 69 insertions(+), 63 deletions(-) diff --git a/c/cli/mlrcli.c b/c/cli/mlrcli.c index 15edfa333..fe9465450 100644 --- a/c/cli/mlrcli.c +++ b/c/cli/mlrcli.c @@ -61,22 +61,22 @@ static lhmss_t* singleton_pdesc_to_chars_map = NULL; static lhmss_t* get_desc_to_chars_map() { if (singleton_pdesc_to_chars_map == NULL) { singleton_pdesc_to_chars_map = lhmss_alloc(); - lhmss_put(singleton_pdesc_to_chars_map, "cr", "\r"); - lhmss_put(singleton_pdesc_to_chars_map, "crcr", "\r\r"); - lhmss_put(singleton_pdesc_to_chars_map, "newline", "\n"); - lhmss_put(singleton_pdesc_to_chars_map, "lf", "\n"); - lhmss_put(singleton_pdesc_to_chars_map, "lflf", "\n\n"); - lhmss_put(singleton_pdesc_to_chars_map, "crlf", "\r\n"); - lhmss_put(singleton_pdesc_to_chars_map, "crlfcrlf", "\r\n\r\n"); - lhmss_put(singleton_pdesc_to_chars_map, "tab", "\t"); - lhmss_put(singleton_pdesc_to_chars_map, "space", " "); - lhmss_put(singleton_pdesc_to_chars_map, "comma", ","); - lhmss_put(singleton_pdesc_to_chars_map, "newline", "\n"); - lhmss_put(singleton_pdesc_to_chars_map, "pipe", "|"); - lhmss_put(singleton_pdesc_to_chars_map, "slash", "/"); - lhmss_put(singleton_pdesc_to_chars_map, "colon", ":"); - lhmss_put(singleton_pdesc_to_chars_map, "semicolon", ";"); - lhmss_put(singleton_pdesc_to_chars_map, "equals", "="); + lhmss_put(singleton_pdesc_to_chars_map, "cr", "\r", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "crcr", "\r\r", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "newline", "\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "lf", "\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "lflf", "\n\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "crlf", "\r\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "crlfcrlf", "\r\n\r\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "tab", "\t", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "space", " ", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "comma", ",", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "newline", "\n", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "pipe", "|", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "slash", "/", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "colon", ":", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "semicolon", ";", NO_FREE); + lhmss_put(singleton_pdesc_to_chars_map, "equals", "=", NO_FREE); } return singleton_pdesc_to_chars_map; } @@ -98,12 +98,12 @@ static lhmsi_t* singleton_default_repeat_ipses = NULL; static lhmss_t* get_default_rses() { if (singleton_default_rses == NULL) { singleton_default_rses = lhmss_alloc(); - lhmss_put(singleton_default_rses, "dkvp", "\n"); - lhmss_put(singleton_default_rses, "nidx", "\n"); - lhmss_put(singleton_default_rses, "csv", "\r\n"); - lhmss_put(singleton_default_rses, "csvlite", "\n"); - lhmss_put(singleton_default_rses, "pprint", "\n"); - lhmss_put(singleton_default_rses, "xtab", "(N/A)"); + lhmss_put(singleton_default_rses, "dkvp", "\n", NO_FREE); + lhmss_put(singleton_default_rses, "nidx", "\n", NO_FREE); + lhmss_put(singleton_default_rses, "csv", "\r\n", NO_FREE); + lhmss_put(singleton_default_rses, "csvlite", "\n", NO_FREE); + lhmss_put(singleton_default_rses, "pprint", "\n", NO_FREE); + lhmss_put(singleton_default_rses, "xtab", "(N/A)", NO_FREE); } return singleton_default_rses; } @@ -111,12 +111,12 @@ static lhmss_t* get_default_rses() { static lhmss_t* get_default_fses() { if (singleton_default_fses == NULL) { singleton_default_fses = lhmss_alloc(); - lhmss_put(singleton_default_fses, "dkvp", ","); - lhmss_put(singleton_default_fses, "nidx", " "); - lhmss_put(singleton_default_fses, "csv", ","); - lhmss_put(singleton_default_fses, "csvlite", ","); - lhmss_put(singleton_default_fses, "pprint", " "); - lhmss_put(singleton_default_fses, "xtab", "\n"); + lhmss_put(singleton_default_fses, "dkvp", ",", NO_FREE); + lhmss_put(singleton_default_fses, "nidx", " ", NO_FREE); + lhmss_put(singleton_default_fses, "csv", ",", NO_FREE); + lhmss_put(singleton_default_fses, "csvlite", ",", NO_FREE); + lhmss_put(singleton_default_fses, "pprint", " ", NO_FREE); + lhmss_put(singleton_default_fses, "xtab", "\n", NO_FREE); } return singleton_default_fses; } @@ -124,12 +124,12 @@ static lhmss_t* get_default_fses() { static lhmss_t* get_default_pses() { if (singleton_default_pses == NULL) { singleton_default_pses = lhmss_alloc(); - lhmss_put(singleton_default_pses, "dkvp", "="); - lhmss_put(singleton_default_pses, "nidx", "(N/A)"); - lhmss_put(singleton_default_pses, "csv", "(N/A)"); - lhmss_put(singleton_default_pses, "csvlite", "(N/A)"); - lhmss_put(singleton_default_pses, "pprint", "(N/A)"); - lhmss_put(singleton_default_pses, "xtab", " "); + lhmss_put(singleton_default_pses, "dkvp", "=", NO_FREE); + lhmss_put(singleton_default_pses, "nidx", "(N/A)", NO_FREE); + lhmss_put(singleton_default_pses, "csv", "(N/A)", NO_FREE); + lhmss_put(singleton_default_pses, "csvlite", "(N/A)", NO_FREE); + lhmss_put(singleton_default_pses, "pprint", "(N/A)", NO_FREE); + lhmss_put(singleton_default_pses, "xtab", " ", NO_FREE); } return singleton_default_pses; } diff --git a/c/containers/lhmss.c b/c/containers/lhmss.c index 253e8635e..9e483369d 100644 --- a/c/containers/lhmss.c +++ b/c/containers/lhmss.c @@ -2,7 +2,7 @@ // Array-only (open addressing) string-to-string linked hash map with linear // probing for collisions. // -// Keys and values are strduped. +// Keys and values are not strduped. // // John Kerl 2012-08-13 // @@ -22,6 +22,7 @@ #include "lib/mlr_globals.h" #include "lib/mlrutil.h" #include "containers/lhmss.h" +#include "containers/free_flags.h" // ---------------------------------------------------------------- // Allow compile-time override, e.g using gcc -D. @@ -43,7 +44,7 @@ #define EMPTY 0xce // ---------------------------------------------------------------- -static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value); +static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value, char free_flags); static void lhmss_enlarge(lhmss_t* pmap); static void lhmss_init(lhmss_t *pmap, int length) { @@ -76,7 +77,7 @@ lhmss_t* lhmss_alloc() { lhmss_t* lhmss_copy(lhmss_t* pmap) { lhmss_t* pnew = lhmss_alloc(); for (lhmsse_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) - lhmss_put(pnew, pe->key, pe->value); + lhmss_put(pnew, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); return pnew; } @@ -84,8 +85,10 @@ void lhmss_free(lhmss_t* pmap) { if (pmap == NULL) return; for (lhmsse_t* pe = pmap->phead; pe != NULL; pe = pe->pnext) { - free(pe->key); - free(pe->value); + if (pe->free_flags & FREE_ENTRY_KEY) + free(pe->key); + if (pe->free_flags & FREE_ENTRY_VALUE) + free(pe->value); } free(pmap->entries); free(pmap->states); @@ -135,27 +138,33 @@ static int lhmss_find_index_for_key(lhmss_t* pmap, char* key) { } // ---------------------------------------------------------------- -void lhmss_put(lhmss_t* pmap, char* key, char* value) { +void lhmss_put(lhmss_t* pmap, char* key, char* value, char free_flags) { if ((pmap->num_occupied + pmap->num_freed) >= (pmap->array_length*LOAD_FACTOR)) lhmss_enlarge(pmap); - lhmss_put_no_enlarge(pmap, key, value); + lhmss_put_no_enlarge(pmap, key, value, free_flags); } -static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value) { +static void lhmss_put_no_enlarge(lhmss_t* pmap, char* key, char* value, char free_flags) { int index = lhmss_find_index_for_key(pmap, key); lhmsse_t* pe = &pmap->entries[index]; if (pmap->states[index] == OCCUPIED) { // Existing key found in chain; put value. if (streq(pe->key, key)) { - free(pe->value); - pe->value = mlr_strdup_or_die(value); + if (pe->free_flags & FREE_ENTRY_VALUE) + free(pe->value); + pe->value = value; + if (free_flags & FREE_ENTRY_VALUE) + pe->free_flags |= FREE_ENTRY_VALUE; + else + pe->free_flags &= ~FREE_ENTRY_VALUE; } } else if (pmap->states[index] == EMPTY) { // End of chain. pe->ideal_index = mlr_canonical_mod(mlr_string_hash_func(key), pmap->array_length); - pe->key = mlr_strdup_or_die(key); - pe->value = mlr_strdup_or_die(value); + pe->key = key; + pe->value = value; + pe->free_flags = free_flags; pmap->states[index] = OCCUPIED; if (pmap->phead == NULL) { @@ -254,10 +263,7 @@ static void lhmss_enlarge(lhmss_t* pmap) { lhmss_init(pmap, pmap->array_length*ENLARGEMENT_FACTOR); for (lhmsse_t* pe = old_head; pe != NULL; pe = pe->pnext) { - // xxx implement free-flags here so we can do this without the redundant strdups - lhmss_put_no_enlarge(pmap, pe->key, pe->value); - free(pe->key); - free(pe->value); + lhmss_put_no_enlarge(pmap, pe->key, pe->value, pe->free_flags); } free(old_entries); free(old_states); diff --git a/c/containers/lhmss.h b/c/containers/lhmss.h index 131e02c5f..29cca4516 100644 --- a/c/containers/lhmss.h +++ b/c/containers/lhmss.h @@ -21,6 +21,7 @@ // ---------------------------------------------------------------- typedef struct _lhmsse_t { int ideal_index; + char free_flags; char* key; char* value; struct _lhmsse_t *pprev; @@ -43,7 +44,7 @@ typedef struct _lhmss_t { lhmss_t* lhmss_alloc(); lhmss_t* lhmss_copy(lhmss_t* pmap); void lhmss_free(lhmss_t* pmap); -void lhmss_put(lhmss_t* pmap, char* key, char* value); +void lhmss_put(lhmss_t* pmap, char* key, char* value, char free_flags); char* lhmss_get(lhmss_t* pmap, char* key); int lhmss_has_key(lhmss_t* pmap, char* key); void lhmss_remove(lhmss_t* pmap, char* key); diff --git a/c/containers/lrec.c b/c/containers/lrec.c index b6d457690..ef11a2a67 100644 --- a/c/containers/lrec.c +++ b/c/containers/lrec.c @@ -74,9 +74,10 @@ void lrec_put(lrec_t* prec, char* key, char* value, char free_flags) { free(pe->value); } pe->value = value; - pe->free_flags &= ~FREE_ENTRY_VALUE; if (free_flags & FREE_ENTRY_VALUE) pe->free_flags |= FREE_ENTRY_VALUE; + else + pe->free_flags &= ~FREE_ENTRY_VALUE; } else { pe = mlr_malloc_or_die(sizeof(lrece_t)); pe->key = key; diff --git a/c/mapping/mapper_histogram.c b/c/mapping/mapper_histogram.c index a025eed06..0d0bf0bb5 100644 --- a/c/mapping/mapper_histogram.c +++ b/c/mapping/mapper_histogram.c @@ -197,8 +197,8 @@ static sllv_t* mapper_histogram_emit(mapper_histogram_state_t* pstate) { for (sllse_t* pe = pstate->value_field_names->phead; pe != NULL; pe = pe->pnext) { char* value_field_name = pe->value; char* count_field_name = mlr_paste_3_strings(value_field_name, "_", "count"); - lhmss_put(pcount_field_names, value_field_name, count_field_name); - free(count_field_name); + lhmss_put(pcount_field_names, mlr_strdup_or_die(value_field_name), count_field_name, + FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } for (int i = 0; i < pstate->nbins; i++) { @@ -304,9 +304,7 @@ static sllv_t* mapper_histogram_emit_auto(mapper_histogram_state_t* pstate) { for (sllse_t* pe = pstate->value_field_names->phead; pe != NULL; pe = pe->pnext) { char* value_field_name = pe->value; char* count_field_name = mlr_paste_3_strings(value_field_name, "_", "count"); - // xxx make a transfer-ownership option for lhmss (which currently is strdup-only) - lhmss_put(pcount_field_names, value_field_name, count_field_name); - free(count_field_name); + lhmss_put(pcount_field_names, mlr_strdup_or_die(value_field_name), count_field_name, FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } for (int i = 0; i < nbins; i++) { diff --git a/c/mapping/mapper_rename.c b/c/mapping/mapper_rename.c index ee519a9d8..ceeb3df9e 100644 --- a/c/mapping/mapper_rename.c +++ b/c/mapping/mapper_rename.c @@ -86,7 +86,7 @@ static mapper_t* mapper_rename_parse_cli(int* pargi, int argc, char** argv) { } lhmss_t* pold_to_new = lhmss_alloc(); for (sllse_t* pe = pnames->phead; pe != NULL; pe = pe->pnext->pnext) { - lhmss_put(pold_to_new, pe->value, pe->pnext->value); + lhmss_put(pold_to_new, mlr_strdup_or_die(pe->value), mlr_strdup_or_die(pe->pnext->value), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } slls_free(pnames); diff --git a/c/mapping/stats1_accumulators.c b/c/mapping/stats1_accumulators.c index a8f319164..7f7ab5673 100644 --- a/c/mapping/stats1_accumulators.c +++ b/c/mapping/stats1_accumulators.c @@ -555,7 +555,7 @@ static void stats1_percentile_emit(void* pvstate, char* value_field_name, char* 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, stats1_acc_name, output_field_name); + lhmss_put(pstate->poutput_field_names, mlr_strdup_or_die(stats1_acc_name), mlr_strdup_or_die(output_field_name), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } lrec_put(poutrec, output_field_name, s, FREE_ENTRY_KEY|FREE_ENTRY_VALUE); } diff --git a/c/unit_test/test_multiple_containers.c b/c/unit_test/test_multiple_containers.c index df31ab79d..50839793a 100644 --- a/c/unit_test/test_multiple_containers.c +++ b/c/unit_test/test_multiple_containers.c @@ -331,7 +331,7 @@ static char* test_lhmss() { mu_assert_lf(!lhmss_has_key(pmap, "z")); mu_assert_lf(lhmss_get(pmap, "z") == NULL); mu_assert_lf(lhmss_check_counts(pmap)); - lhmss_put(pmap, "x", "3"); + lhmss_put(pmap, "x", "3", NO_FREE); mu_assert_lf(pmap->num_occupied == 1); mu_assert_lf(!lhmss_has_key(pmap, "w")); mu_assert_lf(lhmss_get(pmap, "w") == NULL); mu_assert_lf( lhmss_has_key(pmap, "x")); mu_assert_lf(streq(lhmss_get(pmap, "x"), "3")); @@ -339,7 +339,7 @@ static char* test_lhmss() { mu_assert_lf(!lhmss_has_key(pmap, "z")); mu_assert_lf(lhmss_get(pmap, "z") == NULL); mu_assert_lf(lhmss_check_counts(pmap)); - lhmss_put(pmap, "y", "5"); + lhmss_put(pmap, "y", "5", NO_FREE); mu_assert_lf(pmap->num_occupied == 2); mu_assert_lf(!lhmss_has_key(pmap, "w")); mu_assert_lf(lhmss_get(pmap, "w") == NULL); mu_assert_lf( lhmss_has_key(pmap, "x")); mu_assert_lf(streq(lhmss_get(pmap, "x"), "3")); @@ -347,7 +347,7 @@ static char* test_lhmss() { mu_assert_lf(!lhmss_has_key(pmap, "z")); mu_assert_lf(lhmss_get(pmap, "z") == NULL); mu_assert_lf(lhmss_check_counts(pmap)); - lhmss_put(pmap, "x", "4"); + lhmss_put(pmap, "x", "4", NO_FREE); mu_assert_lf(pmap->num_occupied == 2); mu_assert_lf(!lhmss_has_key(pmap, "w")); mu_assert_lf(lhmss_get(pmap, "w") == NULL); mu_assert_lf( lhmss_has_key(pmap, "x")); mu_assert_lf(streq(lhmss_get(pmap, "x"), "4")); @@ -355,7 +355,7 @@ static char* test_lhmss() { mu_assert_lf(!lhmss_has_key(pmap, "z")); mu_assert_lf(lhmss_get(pmap, "z") == NULL); mu_assert_lf(lhmss_check_counts(pmap)); - lhmss_put(pmap, "z", "7"); + lhmss_put(pmap, "z", "7", NO_FREE); mu_assert_lf(pmap->num_occupied == 3); mu_assert_lf(!lhmss_has_key(pmap, "w")); mu_assert_lf(lhmss_get(pmap, "w") == NULL); mu_assert_lf( lhmss_has_key(pmap, "x")); mu_assert_lf(streq(lhmss_get(pmap, "x"), "4"));