Skip to content

Instantly share code, notes, and snippets.

@yne
Last active October 10, 2016 23:43
Show Gist options
  • Save yne/bc816f2549313e65e122da62b2b5671b to your computer and use it in GitHub Desktop.
Save yne/bc816f2549313e65e122da62b2b5671b to your computer and use it in GitHub Desktop.
Smart json import/update into internal structure
#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