Skip to content

Instantly share code, notes, and snippets.

@yne yne/kh_diff.c
Created Feb 13, 2017

Embed
What would you like to do?
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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.