Last active
October 10, 2016 23:43
-
-
Save yne/bc816f2549313e65e122da62b2b5671b to your computer and use it in GitHub Desktop.
Smart json import/update into internal structure
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 <json-c/json.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stddef.h> | |
typedef enum{ | |
diff_none, | |
diff_type, | |
diff_value, | |
diff_removed, | |
diff_added, | |
diff_length, | |
} diff_kind_t; | |
typedef struct Node{ | |
const char* name; | |
struct Node *attributes; | |
size_t size,count; | |
void* data_p; | |
/* primitives attributes */ | |
char* string_p; | |
double*number_p; | |
size_t at; | |
} Node; | |
#define ATTR(...) attributes:(Node[]){ __VA_ARGS__, {(char*)(~0)}} | |
#define countof(W) (sizeof(W)/sizeof(W[0])) | |
typedef struct{ | |
char name[32]; | |
double x,y,z,age[3]; | |
}satellite_t; | |
typedef struct{ | |
char name[32]; | |
char support[32]; | |
char manufacturer[32]; | |
double id; | |
}terminal_t; | |
void model_dump(Node*m,int depth){ | |
for(int i=0;i<depth;i++)fprintf(stderr," "); | |
if(m->name)fprintf(stderr,"'%s':",m->name); | |
if(m->attributes){/* tree */ | |
fprintf(stderr,"<obj/list>count:%zu,size:%zu,data:%p\n",m->count,m->size,m->data_p); | |
for(Node*i=m->attributes;i->name!=(char*)~0;i++) | |
model_dump(i,depth+1); | |
}else{/* primitive */ | |
if(m->string_p) | |
fprintf(stderr,"@%p\n",m->string_p); | |
if(m->number_p) | |
fprintf(stderr,"@%p\n",m->number_p); | |
else | |
fprintf(stderr,"@%zu\n",m->at); | |
} | |
} | |
void json_dump(json_object *node,int depth){ | |
json_object_iter it; | |
printf("\n"); | |
for(int i=0;i<depth;i++)printf(" "); | |
printf("%s:",json_type_to_name(json_object_get_type(node))); | |
switch(json_object_get_type(node)){ | |
case json_type_null :printf("null");break; | |
case json_type_boolean:printf("%s",json_object_get_boolean(node)?"true":"false");break; | |
case json_type_double :printf("%g",json_object_get_double(node));break; | |
case json_type_int :printf("%i",json_object_get_int(node));break; | |
case json_type_string :printf("'%s'",json_object_get_string(node));break; | |
case json_type_object :json_object_object_foreachC(node,it)printf("(%s)",(json_dump(it.val,depth+1),it.key));break; | |
case json_type_array :for(int i=0;i<json_object_array_length(node);i++)json_dump(json_object_array_get_idx(node,i),depth+1);break; | |
} | |
if(depth==0)printf("\n"); | |
} | |
int json_diff(json_object *node,json_object *node_b,char*path){ | |
json_object_iter it; | |
json_object*attr; | |
int ret; | |
if(json_object_get_type(node) != json_object_get_type(node))return diff_type; | |
switch(json_object_get_type(node)){ | |
case json_type_int : | |
if(json_object_get_int(node) != json_object_get_int(node_b)) | |
return diff_value; | |
break; | |
case json_type_double : | |
if(json_object_get_double(node) != json_object_get_double(node_b)) | |
return diff_value; | |
break; | |
case json_type_boolean: | |
if(json_object_get_boolean(node) != json_object_get_boolean(node_b)) | |
return diff_value; | |
break; | |
case json_type_string : | |
if(strcmp(json_object_get_string(node),json_object_get_string(node_b))) | |
return diff_value; | |
break; | |
case json_type_object : | |
json_object_object_foreachC(node_b,it){ | |
sprintf(path,".%s",it.key); | |
if(!json_object_object_get_ex(node,it.key,&attr)) | |
return diff_removed; | |
} | |
json_object_object_foreachC(node,it){ | |
sprintf(path,".%s",it.key); | |
if(!json_object_object_get_ex(node_b,it.key,&attr)) | |
return diff_added; | |
if((ret=json_diff(it.val,attr,path+strlen(path)))!=0) | |
return ret; | |
} | |
break; | |
case json_type_array : | |
if(json_object_array_length(node)!=json_object_array_length(node_b))return diff_length; | |
for(int i=0;i<json_object_array_length(node);i++){ | |
sprintf(path,"[%i]",i); | |
if((ret=json_diff(json_object_array_get_idx(node,i),json_object_array_get_idx(node_b,i),path+strlen(path))))return ret; | |
} | |
break; | |
} | |
return diff_none; | |
} | |
int model_load_json(Node*m, json_object*node, int depth){ | |
json_object_iter it; | |
printf("\n"); | |
for(int i=0;i<depth;i++)printf(" "); | |
printf("%s:",json_type_to_name(json_object_get_type(node))); | |
switch(json_object_get_type(node)){ | |
case json_type_null :printf("null");break; | |
case json_type_boolean:printf("%s",json_object_get_boolean(node)?"true":"false");break; | |
case json_type_double :printf("%g",json_object_get_double(node));break; | |
case json_type_int :printf("%i",json_object_get_int(node));break; | |
case json_type_string :printf("'%s'",json_object_get_string(node));break; | |
case json_type_object :json_object_object_foreachC(node,it)printf("(%s)",(model_load_json(m,it.val,depth+1),it.key));break; | |
case json_type_array :for(int i=0;i<json_object_array_length(node);i++)model_load_json(m,json_object_array_get_idx(node,i),depth+1);break; | |
} | |
if(depth==0)printf("\n"); | |
return 0; | |
} | |
satellite_t sat[32]; | |
terminal_t term[128]; | |
double version; | |
int main(int argc, char** argv){ | |
json_object*obj_a = json_object_from_file(argv[1]); | |
Node model = {ATTR( | |
{"version",number_p:&version}, | |
{"satellites",data_p:sat,size:sizeof(sat[0]),count:countof(sat),ATTR( | |
{"name",at:offsetof(satellite_t,name)}, | |
{"x",at:offsetof(satellite_t,x)}, | |
{"y",at:offsetof(satellite_t,y)}, | |
{"z",at:offsetof(satellite_t,z)} | |
)}, | |
{"terminals",ATTR( | |
{"name",at:offsetof(terminal_t,name)}, | |
{"info",ATTR( | |
{"support",at:offsetof(terminal_t,support)}, | |
{"manufacturer",at:offsetof(terminal_t,manufacturer)} | |
)}, | |
{"id",at:offsetof(terminal_t,name)} | |
)} | |
)}; | |
/* | |
json_object*obj_b = json_object_from_file(argv[2]); | |
char jpath[2048]; | |
diff_kind_t d = json_diff(obj_a,obj_b,jpath); | |
if(d != diff_none){ | |
printf("json_diff kind:%i at:%s\n", d, jpath); | |
} | |
json_dump(obj_a,0); | |
json_dump(obj_b,0); | |
*/ | |
model_dump(&model,0); | |
model_load_json(&model,obj_a,0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment