Skip to content

Instantly share code, notes, and snippets.

@yne
Created February 13, 2017 23:45
Show Gist options
  • Save yne/ee5dbf6a233754d8bd51ef7bb3d0a64c to your computer and use it in GitHub Desktop.
Save yne/ee5dbf6a233754d8bd51ef7bb3d0a64c to your computer and use it in GitHub Desktop.
khash diff example
#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