Add PRV_SKIPDUPNULL flag

This flag allows to only skip duplicates if the value is null, otherwise
the value is emitted. Invalid combinations of PRV_* flags are also
checked on prv_register().
This commit is contained in:
Rodrigo Arias 2023-10-16 12:25:00 +02:00
parent 989685b134
commit bdd5696641
2 changed files with 42 additions and 9 deletions

View File

@ -94,16 +94,22 @@ emit(struct prv *prv, struct prv_chan *rchan)
return -1; return -1;
} }
/* Only test for duplicates if not emitting them */ /* Only test for duplicates without PRV_EMITDUP */
if (~rchan->flags & PRV_EMITDUP) { if (~rchan->flags & PRV_EMITDUP) {
if (is_value_dup(rchan, &value)) { if (is_value_dup(rchan, &value)) {
if (rchan->flags & PRV_SKIPDUP) if (rchan->flags & PRV_SKIPDUP)
return 0; return 0;
else if (rchan->flags & PRV_SKIPDUPNULL) {
if (value_is_null(value)) {
return 0;
}
/* Otherwise emit ... */
} else {
err("error duplicated value %s for channel %s", err("error duplicated value %s for channel %s",
value_str(value), chan->name); value_str(value), chan->name);
return -1; return -1;
} }
}
/* Only set when caring about duplicates */ /* Only set when caring about duplicates */
rchan->last_value = value; rchan->last_value = value;
@ -145,6 +151,27 @@ cb_prv(struct chan *chan, void *ptr)
return emit(prv, rchan); return emit(prv, rchan);
} }
static int
check_flags(long flags)
{
if ((flags & PRV_EMITDUP) && (flags & PRV_SKIPDUPNULL)) {
err("flags PRV_EMITDUP and PRV_SKIPDUPNULL are mutually exclusive");
return -1;
}
if ((flags & PRV_EMITDUP) && (flags & PRV_SKIPDUP)) {
err("flags PRV_EMITDUP and PRV_SKIPDUP are mutually exclusive");
return -1;
}
if ((flags & PRV_SKIPDUP) && (flags & PRV_SKIPDUPNULL)) {
err("flags PRV_SKIPDUP and PRV_SKIPDUPNULL are mutually exclusive");
return -1;
}
return 0;
}
int int
prv_register(struct prv *prv, long row, long type, struct bay *bay, struct chan *chan, long flags) prv_register(struct prv *prv, long row, long type, struct bay *bay, struct chan *chan, long flags)
{ {
@ -162,6 +189,11 @@ prv_register(struct prv *prv, long row, long type, struct bay *bay, struct chan
return -1; return -1;
} }
if (check_flags(flags) != 0) {
err("check_flags failed");
return -1;
}
rchan->id = id; rchan->id = id;
rchan->chan = chan; rchan->chan = chan;
rchan->row_base1 = row + 1; rchan->row_base1 = row + 1;

View File

@ -17,6 +17,7 @@ enum prv_flags {
PRV_SKIPDUP = 1<<1, /* Skip duplicates (no error, no emit) */ PRV_SKIPDUP = 1<<1, /* Skip duplicates (no error, no emit) */
PRV_NEXT = 1<<2, /* Add one to the channel value */ PRV_NEXT = 1<<2, /* Add one to the channel value */
PRV_ZERO = 1<<3, /* Value 0 is allowed */ PRV_ZERO = 1<<3, /* Value 0 is allowed */
PRV_SKIPDUPNULL = 1<<4, /* Skip duplicates if the value is null (no error, no emit) */
}; };
struct prv_chan { struct prv_chan {