Store mark labels into a hash table
Multiple threads can define the same values as long as the labels match. They will be combined into a single hash table by value.
This commit is contained in:
parent
505245d54c
commit
1b2f72cc3a
@ -4,6 +4,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "emu_ev.h"
|
#include "emu_ev.h"
|
||||||
#include "emu_prv.h"
|
#include "emu_prv.h"
|
||||||
|
#include "inttypes.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "ovni_priv.h"
|
#include "ovni_priv.h"
|
||||||
#include "parson.h"
|
#include "parson.h"
|
||||||
@ -12,28 +13,119 @@
|
|||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
struct mark_value {
|
struct mark_label {
|
||||||
int32_t type;
|
int64_t value;
|
||||||
char title[MAX_PCF_LABEL];
|
char label[MAX_PCF_LABEL];
|
||||||
struct chan ch;
|
UT_hash_handle hh; /* Indexed by value */
|
||||||
struct pcf_type *pcftype;
|
|
||||||
UT_hash_handle hh; /* Indexed by type */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mark_chan {
|
struct mark_chan {
|
||||||
long type;
|
long type;
|
||||||
char title[MAX_PCF_LABEL];
|
struct mark_label *labels; /* Hash table of labels */
|
||||||
struct chan ch;
|
struct chan ch;
|
||||||
|
char title[MAX_PCF_LABEL];
|
||||||
UT_hash_handle hh; /* Indexed by type */
|
UT_hash_handle hh; /* Indexed by type */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_number(const char *str, int64_t *result)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
char *endptr = NULL;
|
||||||
|
int64_t n = strtoll(str, &endptr, 10);
|
||||||
|
|
||||||
|
if (errno != 0 || endptr == str || endptr[0] != '\0') {
|
||||||
|
err("failed to parse number: %s", str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mark_label *
|
||||||
|
find_label(struct mark_chan *c, int64_t value)
|
||||||
|
{
|
||||||
|
struct mark_label *l;
|
||||||
|
HASH_FIND(hh, c->labels, &value, sizeof(value), l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_label(struct mark_chan *c, int64_t value, const char *label)
|
||||||
|
{
|
||||||
|
struct mark_label *l = find_label(c, value);
|
||||||
|
|
||||||
|
if (l != NULL) {
|
||||||
|
if (strcmp(l->label, label) == 0) {
|
||||||
|
/* Already exists with the same label, all good */
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
err("mark value %" PRIi64 " already defined with label %s", value, l->label);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l = calloc(1, sizeof(*l));
|
||||||
|
if (l == NULL) {
|
||||||
|
err("calloc failed:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->value = value;
|
||||||
|
|
||||||
|
int len = snprintf(l->label, MAX_PCF_LABEL, "%s", label);
|
||||||
|
if (len >= MAX_PCF_LABEL) {
|
||||||
|
err("mark label too long: %s", label);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_ADD(hh, c->labels, value, sizeof(value), l);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_labels(struct mark_chan *c, JSON_Object *labels)
|
parse_labels(struct mark_chan *c, JSON_Object *labels)
|
||||||
{
|
{
|
||||||
UNUSED(c);
|
UNUSED(c);
|
||||||
UNUSED(labels);
|
UNUSED(labels);
|
||||||
|
|
||||||
/* TODO: Implement */
|
/* It may happen that we call this function several times with
|
||||||
|
* overlapping subsets of values. The only restriction is that we don't
|
||||||
|
* define two values with different label. */
|
||||||
|
|
||||||
|
size_t n = json_object_get_count(labels);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
const char *valuestr = json_object_get_name(labels, i);
|
||||||
|
if (valuestr == NULL) {
|
||||||
|
err("json_object_get_name failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t value;
|
||||||
|
if (parse_number(valuestr, &value) != 0) {
|
||||||
|
err("parse_number failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_Value *labelval = json_object_get_value_at(labels, i);
|
||||||
|
if (labelval == NULL) {
|
||||||
|
err("json_object_get_value_at failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *label = json_value_get_string(labelval);
|
||||||
|
if (label == NULL) {
|
||||||
|
err("json_value_get_string() for label failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_label(c, value, label) != 0) {
|
||||||
|
err("add_label() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user