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_ev.h" | ||||
| #include "emu_prv.h" | ||||
| #include "inttypes.h" | ||||
| #include "ovni.h" | ||||
| #include "ovni_priv.h" | ||||
| #include "parson.h" | ||||
| @ -12,28 +13,119 @@ | ||||
| #include "uthash.h" | ||||
| #include <errno.h> | ||||
| 
 | ||||
| struct mark_value { | ||||
| 	int32_t type; | ||||
| 	char title[MAX_PCF_LABEL]; | ||||
| 	struct chan ch; | ||||
| 	struct pcf_type *pcftype; | ||||
| 	UT_hash_handle hh; /* Indexed by type */ | ||||
| struct mark_label { | ||||
| 	int64_t value; | ||||
| 	char label[MAX_PCF_LABEL]; | ||||
| 	UT_hash_handle hh; /* Indexed by value */ | ||||
| }; | ||||
| 
 | ||||
| struct mark_chan { | ||||
| 	long type; | ||||
| 	char title[MAX_PCF_LABEL]; | ||||
| 	struct mark_label *labels; /* Hash table of labels */ | ||||
| 	struct chan ch; | ||||
| 	char title[MAX_PCF_LABEL]; | ||||
| 	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 | ||||
| parse_labels(struct mark_chan *c, JSON_Object *labels) | ||||
| { | ||||
| 	UNUSED(c); | ||||
| 	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; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user