Created
February 13, 2017 23:45
-
-
Save yne/ee5dbf6a233754d8bd51ef7bb3d0a64c to your computer and use it in GitHub Desktop.
khash diff example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <inttypes.h> | |
#include <stdio.h> | |
//#include "klist.h" | |
#include "khash.h" | |
#define kh_forall(h) for(khint_t __i=kh_begin(h);__i!=kh_end(h);++__i)if(kh_exist(h,__i)) | |
#define kh_diff(name, old, new, on_add, on_keep, on_del)\ | |
kh_forall(new){/*find added(exist in new, not in old) and kept(exist in both) entries */\ | |
khiter_t __j = kh_get(name, old, kh_key(new,__i));\ | |
if((__j==kh_end(old))||(!kh_exist(old,__j))){on_add;}else{on_keep;}\ | |
}\ | |
kh_forall(old){/*find deleted(exist in old, not in new) entries*/\ | |
khiter_t __j = kh_get(name, new, kh_key(old,__i));\ | |
if((__j==kh_end(new))||(!kh_exist(new,__j))){on_del;}\ | |
} | |
#define DST(X) (&(dest_t){X,X*10,0,NULL}) | |
#define LIST(X) X,(sizeof(X)/sizeof(*X)) | |
typedef struct { | |
uint32_t id; | |
uint64_t mac; | |
size_t size; | |
char*name; | |
} dest_t; | |
KHASH_MAP_INIT_INT(dest_by_id, dest_t*) | |
KHASH_MAP_INIT_INT64(dest_by_mac, dest_t*) | |
typedef struct{ | |
khash_t(dest_by_id)* dest_by_id; | |
khash_t(dest_by_mac)* dest_by_mac; | |
}conf_t; | |
int dest_add(conf_t*cnf, dest_t* __dest){ | |
dest_t* dest = malloc(sizeof(*dest)); | |
*dest=*__dest; | |
int ret_id=-1,ret_mac=-1; | |
khiter_t pos_id = kh_put(dest_by_id , cnf->dest_by_id , dest->id , &ret_id); | |
khiter_t pos_mac= kh_put(dest_by_mac, cnf->dest_by_mac, dest->mac, &ret_mac); | |
if(ret_id ==0){fprintf(stderr,"id=%i already exist\n",dest->id);return -1;} | |
if(ret_mac==0){fprintf(stderr,"mac=%012"PRIu64" already exist\n",dest->mac);return -1;} | |
kh_value(cnf->dest_by_id, pos_id ) = dest; | |
kh_value(cnf->dest_by_mac, pos_mac) = dest; | |
dest->name = malloc(43); | |
return 0; | |
} | |
dest_t*dest_get_by_id(conf_t*cnf, uint32_t dest_id){ | |
khiter_t pos_id = kh_get(dest_by_id, cnf->dest_by_id, dest_id); | |
if(pos_id==kh_end(cnf->dest_by_id)){return fprintf(stderr,"no such dest\n"),NULL;} | |
return kh_value(cnf->dest_by_id, pos_id); | |
} | |
dest_t*dest_get_by_mac(conf_t*cnf, uint64_t mac){ | |
khiter_t pos_mac = kh_get(dest_by_mac, cnf->dest_by_mac, mac); | |
if(pos_mac==kh_end(cnf->dest_by_mac)){return fprintf(stderr,"can't get %012"PRIu64"\n",mac),NULL;} | |
return kh_value(cnf->dest_by_mac, pos_mac); | |
} | |
int dest_del(conf_t*cnf, uint32_t dest_id){ | |
dest_t* dest = dest_get_by_id(cnf, dest_id); | |
if(dest==NULL){return fprintf(stderr,"can't del id=%u\n",dest_id),-1;} | |
khiter_t pos_id = kh_get(dest_by_id, cnf->dest_by_id, dest->id); | |
khiter_t pos_mac = kh_get(dest_by_mac, cnf->dest_by_mac, dest->mac); | |
kh_del(dest_by_id, cnf->dest_by_id, pos_id); | |
kh_del(dest_by_mac, cnf->dest_by_mac, pos_mac); | |
free(dest->name); | |
return 0; | |
} | |
int conf_init(conf_t*conf){ | |
conf->dest_by_id = kh_init(dest_by_id); | |
conf->dest_by_mac = kh_init(dest_by_mac); | |
return 0; | |
} | |
int conf_fini(conf_t*conf){ | |
kh_destroy(dest_by_id, conf->dest_by_id); | |
kh_destroy(dest_by_mac, conf->dest_by_mac); | |
return 0; | |
} | |
void dest_batch(conf_t*conf, int*list, size_t len){ | |
for(size_t i=0;i<len;i++){ | |
if(list[i]>0) | |
dest_add(conf, DST(list[i])); | |
else | |
dest_del(conf, -list[i]); | |
} | |
} | |
int main(){ | |
conf_t old,new; | |
conf_init(&old); | |
conf_init(&new); | |
dest_batch(&old, LIST(((int[]){+5,-5,+4,+8,-4,+44,+45,-8}))); | |
dest_batch(&new, LIST(((int[]){+6,+7,+1,-1,+5,+44,+45,+8}))); | |
kh_diff(dest_by_id, old.dest_by_id,new.dest_by_id, | |
printf("add %3i\n", kh_val(new.dest_by_id, __i)->id), | |
printf("keep%3i%3i\n", kh_val(new.dest_by_id, __i)->id, kh_val(old.dest_by_id, __j)->id), | |
printf("del %3i\n", kh_val(old.dest_by_id, __i)->id)); | |
conf_fini(&new); | |
conf_fini(&old); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment