diff --git a/c/containers/lrec.c b/c/containers/lrec.c index 111cfcbad..548284556 100644 --- a/c/containers/lrec.c +++ b/c/containers/lrec.c @@ -154,6 +154,17 @@ char* lrec_get_pff(lrec_t* prec, char* key, char** ppfree_flags) { } } +char* lrec_get_ext(lrec_t* prec, char* key, lrece_t** ppentry) { + lrece_t* pe = lrec_find_entry(prec, key); + if (pe != NULL) { + *ppentry = pe; + return pe->value; + } else { + *ppentry = NULL;; + return NULL; + } +} + // ---------------------------------------------------------------- void lrec_remove(lrec_t* prec, char* key) { lrece_t* pe = lrec_find_entry(prec, key); diff --git a/c/containers/lrec.h b/c/containers/lrec.h index 8215a2288..f4a23b647 100644 --- a/c/containers/lrec.h +++ b/c/containers/lrec.h @@ -118,10 +118,16 @@ void lrec_put(lrec_t* prec, char* key, char* value, char free_flags); void lrec_prepend(lrec_t* prec, char* key, char* value, char free_flags); char* lrec_get(lrec_t* prec, char* key); + // This returns a pointer to the lrec's free-flags so that the caller can do ownership-transfer // of about-to-be-removed key-value pairs. char* lrec_get_pff(lrec_t* prec, char* key, char** ppfree_flags); +// This returns a pointer to the entry so the caller can update it directly without needing +// to do another field-scan on subsequent lrec_put etc. This is a performance optimization; +// it also allows mlr nest --explode to do explode-in-place rather than explode-at-end. +char* lrec_get_ext(lrec_t* prec, char* key, lrece_t** ppentry); + void lrec_remove(lrec_t* prec, char* key); void lrec_rename(lrec_t* prec, char* old_key, char* new_key, int new_needs_freeing); void lrec_move_to_head(lrec_t* prec, char* key); diff --git a/c/mapping/mapper_nest.c b/c/mapping/mapper_nest.c index e59398a78..3b1930d5f 100644 --- a/c/mapping/mapper_nest.c +++ b/c/mapping/mapper_nest.c @@ -237,10 +237,8 @@ static sllv_t* mapper_nest_explode_values_across_fields(lrec_t* pinrec, context_ return sllv_single(NULL); mapper_nest_state_t* pstate = (mapper_nest_state_t*)pvstate; - // xxx get_ext w/ lrece_t* - // xxx insert after - // xxx unlink - char* field_value = lrec_get(pinrec, pstate->field_name); + lrece_t* pentry = NULL; + char* field_value = lrec_get_ext(pinrec, pstate->field_name, &pentry); if (field_value == NULL) { return sllv_single(pinrec); } @@ -254,8 +252,9 @@ static sllv_t* mapper_nest_explode_values_across_fields(lrec_t* pinrec, context_ if (istring_free_flags & FREE_ENTRY_KEY) free(istring); lrec_put(pinrec, new_key, mlr_strdup_or_die(piece), FREE_ENTRY_KEY|FREE_ENTRY_VALUE); + // xxx insert after if it doesn't already exit } - lrec_remove(pinrec, pstate->field_name); + lrec_unlink_and_free(pinrec, pentry); return sllv_single(pinrec);; } diff --git a/c/todo.txt b/c/todo.txt index af5ba6606..397cb454f 100644 --- a/c/todo.txt +++ b/c/todo.txt @@ -26,6 +26,7 @@ TOP-OF-LIST SUMMARY * valgrinds * xxxes * lrec get followed by put/remove: getext variant returning node for unlink, valpoke, or null == append to avoid double-searching. +* dsls deps still not quite right? ================================================================ * relcut material since 3.4.0: