Before/after options for reorder verb (#510)

* mlr reorder -b/-a
* go test data
* c impl
This commit is contained in:
John Kerl 2021-05-03 04:26:53 +00:00 committed by GitHub
parent d00e6cf1d2
commit 2e9a695eb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 411 additions and 86 deletions

View file

@ -2,21 +2,28 @@
#include "containers/lrec.h"
#include "containers/sllv.h"
#include "containers/hss.h"
#include "containers/mixutil.h"
#include "mapping/mappers.h"
#include "cli/argparse.h"
typedef struct _mapper_reorder_state_t {
ap_state_t* pargp;
slls_t* pfield_name_list;
int put_at_end;
hss_t* pfield_name_set;
char* before_field_name;
char* after_field_name;
} mapper_reorder_state_t;
static void mapper_reorder_usage(FILE* o, char* argv0, char* verb);
static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
cli_reader_opts_t* _, cli_writer_opts_t* __);
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list, int put_at_end);
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list,
int put_at_end, char* before_field_name, char* after_field_name);
static void mapper_reorder_free(mapper_t* pmapper, context_t* _);
static sllv_t* mapper_reorder_process(lrec_t* pinrec, context_t* pctx, void* pvstate);
static sllv_t* mapper_reorder_to_start(lrec_t* pinrec, context_t* pctx, void* pvstate);
static sllv_t* mapper_reorder_to_end(lrec_t* pinrec, context_t* pctx, void* pvstate);
static sllv_t* mapper_reorder_before(lrec_t* pinrec, context_t* pctx, void* pvstate);
static sllv_t* mapper_reorder_after(lrec_t* pinrec, context_t* pctx, void* pvstate);
// ----------------------------------------------------------------
mapper_setup_t mapper_reorder_setup = {
@ -29,28 +36,36 @@ mapper_setup_t mapper_reorder_setup = {
// ----------------------------------------------------------------
static void mapper_reorder_usage(FILE* o, char* argv0, char* verb) {
fprintf(o, "Usage: %s %s [options]\n", argv0, verb);
fprintf(o, "-f {a,b,c} Field names to reorder.\n");
fprintf(o, "-e Put specified field names at record end: default is to put\n");
fprintf(o, " them at record start.\n");
fprintf(o, "-f {a,b,c} Field names to reorder.\n");
fprintf(o, "-e Put specified field names at record end: default is to put\n");
fprintf(o, " them at record start.\n");
fprintf(o, "-b {x} Put field names specified with -f before field name specified by {x},\n");
fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n");
fprintf(o, " will not be moved.\n");
fprintf(o, "-a {x} Put field names specified with -f after field name specified by {x},\n");
fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n");
fprintf(o, " will not be moved.\n");
fprintf(o, "Examples:\n");
fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n",
argv0, verb);
fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n",
argv0, verb);
fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n", argv0, verb);
fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n", argv0, verb);
}
// ----------------------------------------------------------------
static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
cli_reader_opts_t* _, cli_writer_opts_t* __)
{
slls_t* pfield_name_list = NULL;
int put_at_end = FALSE;
slls_t* pfield_name_list = NULL;
int put_at_end = FALSE;
char* before_field_name = NULL;
char* after_field_name = NULL;
char* verb = argv[(*pargi)++];
ap_state_t* pstate = ap_alloc();
ap_define_string_list_flag(pstate, "-f", &pfield_name_list);
ap_define_true_flag(pstate, "-e", &put_at_end);
ap_define_string_flag(pstate, "-b", &before_field_name);
ap_define_string_flag(pstate, "-a", &after_field_name);
if (!ap_parse(pstate, verb, pargi, argc, argv)) {
mapper_reorder_usage(stderr, argv[0], verb);
@ -62,50 +77,169 @@ static mapper_t* mapper_reorder_parse_cli(int* pargi, int argc, char** argv,
return NULL;
}
return mapper_reorder_alloc(pstate, pfield_name_list, put_at_end);
return mapper_reorder_alloc(pstate, pfield_name_list, put_at_end, before_field_name, after_field_name);
}
// ----------------------------------------------------------------
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list, int put_at_end) {
static mapper_t* mapper_reorder_alloc(ap_state_t* pargp, slls_t* pfield_name_list,
int put_at_end, char* before_field_name, char* after_field_name)
{
mapper_t* pmapper = mlr_malloc_or_die(sizeof(mapper_t));
mapper_reorder_state_t* pstate = mlr_malloc_or_die(sizeof(mapper_reorder_state_t));
pstate->pargp = pargp;
pstate->pfield_name_list = pfield_name_list;
pstate->put_at_end = put_at_end;
if (!put_at_end)
slls_reverse(pstate->pfield_name_list);
pstate->pfield_name_list = pfield_name_list;
pstate->pfield_name_set = hss_from_slls(pfield_name_list);
pstate->before_field_name = before_field_name;
pstate->after_field_name = after_field_name;
pmapper->pvstate = (void*)pstate;
pmapper->pprocess_func = mapper_reorder_process;
pmapper->pfree_func = mapper_reorder_free;
pmapper->pvstate = (void*)pstate;
if (put_at_end) {
pmapper->pprocess_func = mapper_reorder_to_end;
} else if (before_field_name != NULL) {
pmapper->pprocess_func = mapper_reorder_before;
} else if (after_field_name != NULL) {
pmapper->pprocess_func = mapper_reorder_after;
} else {
pmapper->pprocess_func = mapper_reorder_to_start;
slls_reverse(pstate->pfield_name_list);
}
pmapper->pfree_func = mapper_reorder_free;
return pmapper;
}
static void mapper_reorder_free(mapper_t* pmapper, context_t* _) {
mapper_reorder_state_t* pstate = pmapper->pvstate;
if (pstate->pfield_name_list != NULL)
slls_free(pstate->pfield_name_list);
slls_free(pstate->pfield_name_list);
hss_free(pstate->pfield_name_set);
ap_free(pstate->pargp);
free(pstate);
free(pmapper);
}
// ----------------------------------------------------------------
static sllv_t* mapper_reorder_process(lrec_t* pinrec, context_t* pctx, void* pvstate) {
static sllv_t* mapper_reorder_to_start(lrec_t* pinrec, context_t* pctx, void* pvstate) {
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
if (pinrec != NULL) {
if (!pstate->put_at_end) {
// OK since the field-name list was reversed at construction time.
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext)
lrec_move_to_head(pinrec, pe->value);
} else {
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext)
lrec_move_to_tail(pinrec, pe->value);
// OK since the field-name list was reversed at construction time.
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext) {
lrec_move_to_head(pinrec, pe->value);
}
return sllv_single(pinrec);
} else {
return sllv_single(NULL);
}
}
// ----------------------------------------------------------------
static sllv_t* mapper_reorder_to_end(lrec_t* pinrec, context_t* pctx, void* pvstate) {
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
if (pinrec != NULL) {
for (sllse_t* pe = pstate->pfield_name_list->phead; pe != NULL; pe = pe->pnext) {
lrec_move_to_tail(pinrec, pe->value);
}
return sllv_single(pinrec);
} else {
return sllv_single(NULL);
}
}
// ----------------------------------------------------------------
static sllv_t* mapper_reorder_before(lrec_t* pinrec, context_t* pctx, void* pvstate) {
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
if (pinrec != NULL) {
char* bvalue = lrec_get(pinrec, pstate->before_field_name);
if (bvalue == NULL) {
return sllv_single(pinrec);
}
lrec_t* poutrec = lrec_unbacked_alloc();
lrece_t* pe = pinrec->phead;
for (; pe != NULL; pe = pe->pnext) {
if (streq(pe->key, pstate->before_field_name)) {
break;
}
if (!hss_has(pstate->pfield_name_set, pe->key)) {
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
}
}
for (sllse_t* pf = pstate->pfield_name_list->phead; pf != NULL; pf = pf->pnext) {
char* field_name = pf->value;
char* value = lrec_get(pinrec, field_name);
if (value != NULL) {
lrec_put(poutrec, field_name, mlr_strdup_or_die(value), FREE_ENTRY_VALUE);
}
}
lrec_put(poutrec, pstate->before_field_name, mlr_strdup_or_die(bvalue), FREE_ENTRY_VALUE);
for (; pe != NULL; pe = pe->pnext) {
if (streq(pe->key, pstate->before_field_name)) {
continue;
}
if (!hss_has(pstate->pfield_name_set, pe->key)) {
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
}
}
lrec_free(pinrec);
return sllv_single(poutrec);
} else {
return sllv_single(NULL);
}
}
// ----------------------------------------------------------------
static sllv_t* mapper_reorder_after(lrec_t* pinrec, context_t* pctx, void* pvstate) {
mapper_reorder_state_t* pstate = (mapper_reorder_state_t*)pvstate;
if (pinrec != NULL) {
char* avalue = lrec_get(pinrec, pstate->after_field_name);
if (avalue == NULL) {
return sllv_single(pinrec);
}
lrec_t* poutrec = lrec_unbacked_alloc();
lrece_t* pe = pinrec->phead;
for (; pe != NULL; pe = pe->pnext) {
if (streq(pe->key, pstate->after_field_name)) {
break;
}
if (!hss_has(pstate->pfield_name_set, pe->key)) {
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
}
}
lrec_put(poutrec, pstate->after_field_name, mlr_strdup_or_die(avalue), FREE_ENTRY_VALUE);
for (sllse_t* pf = pstate->pfield_name_list->phead; pf != NULL; pf = pf->pnext) {
char* field_name = pf->value;
char* value = lrec_get(pinrec, field_name);
if (value != NULL) {
lrec_put(poutrec, field_name, mlr_strdup_or_die(value), FREE_ENTRY_VALUE);
}
}
for (; pe != NULL; pe = pe->pnext) {
if (streq(pe->key, pstate->after_field_name)) {
continue;
}
if (!hss_has(pstate->pfield_name_set, pe->key)) {
lrec_put(poutrec, mlr_strdup_or_die(pe->key), mlr_strdup_or_die(pe->value),
FREE_ENTRY_KEY|FREE_ENTRY_VALUE);
}
}
lrec_free(pinrec);
return sllv_single(poutrec);
} else {
return sllv_single(NULL);
}
}

View file

@ -52706,6 +52706,36 @@ y/,x/,i/,b/,a/
0.803142013402256216,0.000047786161325772/,3/,pan/,zee/
0.573903236805416328,0.676537984365847889/,4/,hat/,zee/
mlr --from ./reg_test/input/reorder.dkvp reorder -f x,y -b u
s=1,t=2,x=6,y=7,u=3,v=4,w=5,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -b x
s=1,t=2,w=5,u=3,v=4,x=6,y=7,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f z,w,s -b v
t=2,u=3,z=8,w=5,s=1,v=4,x=6,y=7
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -b nonesuch
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,nonesuch -b x
s=1,t=2,v=4,w=5,u=3,x=6,y=7,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f x,y -a u
s=1,t=2,u=3,x=6,y=7,v=4,w=5,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -a x
s=1,t=2,w=5,x=6,u=3,v=4,y=7,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f z,w,s -a v
t=2,u=3,v=4,z=8,w=5,s=1,x=6,y=7
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,v -a nonesuch
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8
mlr --from ./reg_test/input/reorder.dkvp reorder -f u,nonesuch -a x
s=1,t=2,v=4,w=5,x=6,u=3,y=7,z=8
mlr --icsv --otsv -N cat
a b c
1 2 3

View file

@ -155,6 +155,7 @@ EXTRA_DIST= \
regex.dkvp \
regularize.dkvp \
remove-empty-columns.csv \
reorder.dkvp \
repeat-input.dat \
repeats.dkvp \
reshape-long-ragged.dkvp \

View file

@ -0,0 +1 @@
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8

View file

@ -6469,6 +6469,18 @@ run_mlr --implicit-csv-header --icsv --ifs /, --opprint cut -x -f 2 $indir/mult
run_mlr --csv -N reorder -f 1,3,2,5,4 $indir/multi-sep.csv-crlf
run_mlr --csv -N reorder -f 5,4,3,2,1 $indir/multi-sep.csv-crlf
run_mlr --from $indir/reorder.dkvp reorder -f x,y -b u
run_mlr --from $indir/reorder.dkvp reorder -f u,v -b x
run_mlr --from $indir/reorder.dkvp reorder -f z,w,s -b v
run_mlr --from $indir/reorder.dkvp reorder -f u,v -b nonesuch
run_mlr --from $indir/reorder.dkvp reorder -f u,nonesuch -b x
run_mlr --from $indir/reorder.dkvp reorder -f x,y -a u
run_mlr --from $indir/reorder.dkvp reorder -f u,v -a x
run_mlr --from $indir/reorder.dkvp reorder -f z,w,s -a v
run_mlr --from $indir/reorder.dkvp reorder -f u,v -a nonesuch
run_mlr --from $indir/reorder.dkvp reorder -f u,nonesuch -a x
run_mlr --icsv --otsv -N cat <<EOF
a,b,c
1,2,3

View file

@ -2042,9 +2042,15 @@ reorder
$ mlr reorder --help
Usage: mlr reorder [options]
-f {a,b,c} Field names to reorder.
-e Put specified field names at record end: default is to put
them at record start.
-f {a,b,c} Field names to reorder.
-e Put specified field names at record end: default is to put
them at record start.
-b {x} Put field names specified with -f before field name specified by {x},
if any. If {x} isn't present in a given record, the specified fields
will not be moved.
-a {x} Put field names specified with -f after field name specified by {x},
if any. If {x} isn't present in a given record, the specified fields
will not be moved.
Examples:
mlr reorder -f a,b sends input record "d=4,b=2,a=1,c=3" to "a=1,b=2,d=4,c=3".
mlr reorder -e -f a,b sends input record "d=4,b=2,a=1,c=3" to "d=4,c=3,a=1,b=2".

View file

@ -514,6 +514,12 @@ Moves specified names to start of record, or end of record.
Options:
-e Put specified field names at record end: default is to put them at record start.
-f {a,b,c} Field names to reorder.
-b {x} Put field names specified with -f before field name specified by {x},
if any. If {x} isn't present in a given record, the specified fields
will not be moved.
-a {x} Put field names specified with -f after field name specified by {x},
if any. If {x} isn't present in a given record, the specified fields
will not be moved.
-h|--help Show this message.
Examples:

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f x,y -a u

View file

@ -0,0 +1 @@
s=1,t=2,u=3,x=6,y=7,v=4,w=5,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,v -a x

View file

@ -0,0 +1 @@
s=1,t=2,w=5,x=6,u=3,v=4,y=7,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f z,w,s -a v

View file

@ -0,0 +1 @@
t=2,u=3,v=4,z=8,w=5,s=1,x=6,y=7

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,v -a nonesuch

View file

@ -0,0 +1 @@
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,nonesuch -a x

View file

@ -0,0 +1 @@
s=1,t=2,v=4,w=5,x=6,u=3,y=7,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f x,y -b u

View file

@ -0,0 +1 @@
s=1,t=2,x=6,y=7,u=3,v=4,w=5,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,v -b x

View file

@ -0,0 +1 @@
s=1,t=2,w=5,u=3,v=4,x=6,y=7,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f z,w,s -b v

View file

@ -0,0 +1 @@
t=2,u=3,z=8,w=5,s=1,v=4,x=6,y=7

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,v -b nonesuch

View file

@ -0,0 +1 @@
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8

View file

@ -0,0 +1 @@
mlr --from regtest/input/reorder.dkvp reorder -f u,nonesuch -b x

View file

@ -0,0 +1 @@
s=1,t=2,v=4,w=5,u=3,x=6,y=7,z=8

View file

@ -0,0 +1 @@
s=1,t=2,u=3,v=4,w=5,x=6,y=7,z=8

View file

@ -26,26 +26,26 @@ func transformerReorderUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameReorder)
argv0 := lib.MlrExeName()
verb := verbNameReorder
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprint(o,
`Moves specified names to start of record, or end of record.
`)
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-e Put specified field names at record end: default is to put them at record start.\n")
fmt.Fprintf(o, "-f {a,b,c} Field names to reorder.\n")
fmt.Fprintf(o, "-b {x} Put field names specified with -f before field name specified by {x},\n")
fmt.Fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n")
fmt.Fprintf(o, " will not be moved.\n")
fmt.Fprintf(o, "-a {x} Put field names specified with -f after field name specified by {x},\n")
fmt.Fprintf(o, " if any. If {x} isn't present in a given record, the specified fields\n")
fmt.Fprintf(o, " will not be moved.\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")
fmt.Fprintf(o, "\n")
fmt.Fprintf(o, "Examples:\n")
fmt.Fprintf(
o,
"%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n",
lib.MlrExeName(), verbNameReorder,
)
fmt.Fprintf(
o,
"%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n",
lib.MlrExeName(), verbNameReorder,
)
fmt.Fprintf(o, "%s %s -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"a=1,b=2,d=4,c=3\".\n", argv0, verb)
fmt.Fprintf(o, "%s %s -e -f a,b sends input record \"d=4,b=2,a=1,c=3\" to \"d=4,c=3,a=1,b=2\".\n", argv0, verb)
if doExit {
os.Exit(exitCode)
@ -67,6 +67,8 @@ func transformerReorderParseCLI(
var fieldNames []string = nil
putAtEnd := false
beforeFieldName := ""
afterFieldName := ""
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
@ -81,8 +83,20 @@ func transformerReorderParseCLI(
} else if opt == "-f" {
fieldNames = cliutil.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
} else if opt == "-b" {
beforeFieldName = cliutil.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
afterFieldName = ""
putAtEnd = false
} else if opt == "-a" {
afterFieldName = cliutil.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
beforeFieldName = ""
putAtEnd = false
} else if opt == "-e" {
putAtEnd = true
beforeFieldName = ""
afterFieldName = ""
} else {
transformerReorderUsage(os.Stderr, true, 1)
@ -96,6 +110,8 @@ func transformerReorderParseCLI(
transformer, _ := NewTransformerReorder(
fieldNames,
putAtEnd,
beforeFieldName,
afterFieldName,
)
*pargi = argi
@ -105,7 +121,10 @@ func transformerReorderParseCLI(
// ----------------------------------------------------------------
type TransformerReorder struct {
// input
fieldNames []string
fieldNames []string
fieldNamesSet map[string]bool
beforeFieldName string
afterFieldName string
// state
recordTransformerFunc transforming.RecordTransformerFunc
@ -114,20 +133,26 @@ type TransformerReorder struct {
func NewTransformerReorder(
fieldNames []string,
putAtEnd bool,
beforeFieldName string,
afterFieldName string,
) (*TransformerReorder, error) {
if !putAtEnd {
lib.ReverseStringList(fieldNames)
}
this := &TransformerReorder{
fieldNames: fieldNames,
fieldNames: fieldNames,
fieldNamesSet: lib.StringListToSet(fieldNames),
beforeFieldName: beforeFieldName,
afterFieldName: afterFieldName,
}
if !putAtEnd {
this.recordTransformerFunc = this.reorderToStart
} else {
if putAtEnd {
this.recordTransformerFunc = this.reorderToEnd
} else if beforeFieldName != "" {
this.recordTransformerFunc = this.reorderBefore
} else if afterFieldName != "" {
this.recordTransformerFunc = this.reorderAfter
} else {
this.recordTransformerFunc = this.reorderToStart
lib.ReverseStringList(this.fieldNames)
}
return this, nil
@ -173,3 +198,113 @@ func (this *TransformerReorder) reorderToEnd(
outputChannel <- inrecAndContext // end-of-stream marker
}
}
// ----------------------------------------------------------------
func (this *TransformerReorder) reorderBefore(
inrecAndContext *types.RecordAndContext,
outputChannel chan<- *types.RecordAndContext,
) {
if !inrecAndContext.EndOfStream {
inrec := inrecAndContext.Record
if inrec.Get(this.beforeFieldName) == nil {
outputChannel <- inrecAndContext
return
}
outrec := types.NewMlrmapAsRecord()
pe := inrec.Head
// * inrec will be GC'ed
// * We will use outrec.PutReference not output.PutCopy since inrec will be GC'ed
for ; pe != nil; pe = pe.Next {
if pe.Key == this.beforeFieldName {
break
}
if !this.fieldNamesSet[pe.Key] {
outrec.PutReference(pe.Key, pe.Value)
}
}
for _, fieldName := range this.fieldNames {
value := inrec.Get(fieldName)
if value != nil {
outrec.PutReference(fieldName, value)
}
}
value := inrec.Get(this.beforeFieldName)
if value != nil {
outrec.PutReference(this.beforeFieldName, value)
}
for ; pe != nil; pe = pe.Next {
if pe.Key != this.beforeFieldName && !this.fieldNamesSet[pe.Key] {
outrec.PutReference(pe.Key, pe.Value)
}
}
for _, fieldName := range this.fieldNames {
inrec.MoveToHead(fieldName)
}
outputChannel <- types.NewRecordAndContext(outrec, &inrecAndContext.Context)
} else {
outputChannel <- inrecAndContext // end-of-stream marker
}
}
// ----------------------------------------------------------------
func (this *TransformerReorder) reorderAfter(
inrecAndContext *types.RecordAndContext,
outputChannel chan<- *types.RecordAndContext,
) {
if !inrecAndContext.EndOfStream {
inrec := inrecAndContext.Record
if inrec.Get(this.afterFieldName) == nil {
outputChannel <- inrecAndContext
return
}
outrec := types.NewMlrmapAsRecord()
pe := inrec.Head
// * inrec will be GC'ed
// * We will use outrec.PutReference not output.PutCopy since inrec will be GC'ed
for ; pe != nil; pe = pe.Next {
if pe.Key == this.afterFieldName {
break
}
if !this.fieldNamesSet[pe.Key] {
outrec.PutReference(pe.Key, pe.Value)
}
}
value := inrec.Get(this.afterFieldName)
if value != nil {
outrec.PutReference(this.afterFieldName, value)
}
for _, fieldName := range this.fieldNames {
value := inrec.Get(fieldName)
if value != nil {
outrec.PutReference(fieldName, value)
}
}
for ; pe != nil; pe = pe.Next {
if pe.Key != this.afterFieldName && !this.fieldNamesSet[pe.Key] {
outrec.PutReference(pe.Key, pe.Value)
}
}
for _, fieldName := range this.fieldNames {
inrec.MoveToHead(fieldName)
}
outputChannel <- types.NewRecordAndContext(outrec, &inrecAndContext.Context)
} else {
outputChannel <- inrecAndContext // end-of-stream marker
}
}

43
go/u/gg
View file

@ -3,7 +3,7 @@
path_to_mlr="./mlr"
indir="./regtest/input"
go build mlr.go
#go build mlr.go
if [ $? -ne 0 ]; then
exit 1
fi
@ -53,37 +53,16 @@ mention() {
# ================================================================
echo 'x=a;b;c' | run_mlr nest -evF -f x
echo 'foo=bar,x=a;b;c' | run_mlr nest -evF -f x
echo 'x=a;b;c,foo=bar' | run_mlr nest -evF -f x
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f x,y -b u
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -b x
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f z,w,s -b v
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -b nonesuch
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,nonesuch -b x
echo 'x=a;b;c' | run_mlr nest -evR -f x
echo 'foo=bar,x=a;b;c' | run_mlr nest -evR -f x
echo 'x=a;b;c,foo=bar' | run_mlr nest -evR -f x
echo 'x=a|b|c' | run_mlr nest -evF -S pipe -f x
echo 'foo=bar,x=a|b|c' | run_mlr nest -evF -S pipe -f x
echo 'x=a|b|c,foo=bar' | run_mlr nest -evF -S pipe -f x
echo 'x=a|b|c' | run_mlr nest -evF -S '|' -f x
echo 'foo=bar,x=a|b|c' | run_mlr nest -evF -S '|' -f x
echo 'x=a|b|c,foo=bar' | run_mlr nest -evF -S '|' -f x
echo 'x=a;b;c' | run_mlr nest -evR -f x
echo 'foo=bar,x=a;b;c' | run_mlr nest -evR -f x
echo 'x=a;b;c,foo=bar' | run_mlr nest -evR -f x
echo 'x=a:1;b:2;c:3' | run_mlr nest -epF -f x
echo 'foo=bar,x=a:1;b:2;c:3' | run_mlr nest -epF -f x
echo 'x=a:1;b:2;c:3,foo=bar' | run_mlr nest -epF -f x
echo 'x=a:1;b:2;c:3' | run_mlr nest -epR -f x
echo 'foo=bar,x=a:1;b:2;c:3' | run_mlr nest -epR -f x
echo 'x=a:1;b:2;c:3,foo=bar' | run_mlr nest -epR -f x
echo 'x_1=a:1,x_2=b:2,x_3=c:3' | run_mlr nest -ivF -f x
echo 'foo=bar,x_1=a:1,x_2=b:2,x_3=c:3' | run_mlr nest -ivF -f x
echo 'x_1=a:1,x_2=b:2,x_3=c:3,foo=bar' | run_mlr nest -ivF -f x
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f x,y -a u
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -a x
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f z,w,s -a v
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,v -a nonesuch
run_mlr --from ../go/regtest/input/reorder.dkvp reorder -f u,nonesuch -a x
# ================================================================