free-flags for lhmss

This commit is contained in:
John Kerl 2016-01-07 21:58:59 +00:00
parent 52460b7445
commit 16ccc58649
8 changed files with 69 additions and 63 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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++) {

View file

@ -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);

View file

@ -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);
}

View file

@ -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"));