// (C) 2017 <>< Joshua Allen, Under MIT/x11 License. #include #include #include "survive_config.h" #include #include #define MAX_CONFIG_ENTRIES 100 #define MAX_LIGHTHOUSES 2 config_group global_config_values; config_group lh_config[MAX_LIGHTHOUSES]; //lighthouse configs //static uint16_t used_entries = 0; //static FILE *config_file = NULL; const FLT* config_set_float_a(config_group *cg, const char *tag, const FLT* values, uint8_t count); void init_config_group(config_group *cg, uint16_t count) { uint16_t i = 0; cg->config_entries = malloc(count*sizeof(config_entry)); cg->used_entries = 0; cg->max_entries = count; for (i=0;iconfig_entries[i].data = NULL; cg->config_entries[i].tag = NULL; cg->config_entries[i].type = CONFIG_UNKNOWN; cg->config_entries[i].elements = 0; } } void config_init() { uint16_t i = 0; init_config_group(&global_config_values, MAX_CONFIG_ENTRIES); for(i=0;iBaseStationID); config_set_float_a(cg,"position", bsd->Position, 3); config_set_float_a(cg,"quaternion", bsd->Quaternion, 4); config_set_float_a(cg,"fcalphase", bsd->fcalphase, 2); config_set_float_a(cg,"fcaltilt", bsd->fcaltilt,2); config_set_float_a(cg,"fcalcurve", bsd->fcalcurve,2); config_set_float_a(cg,"fcalgibpha", bsd->fcalgibpha,2); config_set_float_a(cg,"fcalgibmag", bsd->fcalgibmag,2); } void sstrcpy(char** dest, const char *src) { uint32_t len = strlen(src)+1; assert(dest!=NULL); char* ptr = (char*)realloc(*dest, len); //acts like mallos if dest==NULL assert(ptr!=NULL); *dest = ptr; strcpy(*dest,src); } config_entry* find_config_entry(config_group *cg, const char *tag) { uint16_t i = 0; for (i=0;i < cg->used_entries;++i) { if ( strcmp(cg->config_entries[i].tag, tag) == 0 ) { return cg->config_entries+i; } } return NULL; } const char* config_read_str(config_group *cg, const char *tag, const char *def) { config_entry *cv = find_config_entry(cg, tag); if (cv != NULL) return cv->data; return config_set_str(cg,tag,def); } uint32_t config_read_uint32(config_group *cg, const char *tag, const uint32_t def) { config_entry *cv = find_config_entry(cg, tag); if (cv != NULL) return cv->numeric.i; return config_set_uint32(cg, tag, def); } FLT config_read_float(config_group *cg, const char *tag, const FLT def) { config_entry *cv = find_config_entry(cg, tag); if (cv != NULL) return cv->numeric.f; return config_set_float(cg, tag, def); } uint16_t config_read_float_array(config_group *cg, const char *tag, FLT** values, const FLT* def, uint16_t count) { config_entry *cv = find_config_entry(cg, tag); if (cv != NULL) { *values = (FLT*)cv->data; return cv->elements; } if (def == NULL) return 0; config_set_float_a(cg, tag, def, count); *values = def; return count; } config_entry* next_unused_entry(config_group *cg) { config_entry *cv = cg->config_entries + cg->used_entries; assert(cg->used_entries < cg->max_entries); /* if (cg->used_entries >= cg->max_entries) { cg->max_entries+=10; cg->config_entries = realloc(cg->config_entries, sizeof(config_entry)*cg->max_entries); } */ cg->used_entries++; return cv; } const char* config_set_str(config_group *cg, const char *tag, const char* value) { config_entry *cv = find_config_entry(cg, tag); if (cv == NULL) cv = next_unused_entry(cg); sstrcpy(&(cv->tag), tag); sstrcpy(&(cv->data), value); cv->type = CONFIG_STRING; return value; } const uint32_t config_set_uint32(config_group *cg, const char *tag, const uint32_t value) { config_entry *cv = find_config_entry(cg, tag); if (cv == NULL) cv = next_unused_entry(cg); sstrcpy(&(cv->tag), tag); cv->numeric.i = value; cv->type = CONFIG_UINT32; return value; } const FLT config_set_float(config_group *cg, const char *tag, const FLT value) { config_entry *cv = find_config_entry(cg, tag); if (cv == NULL) cv = next_unused_entry(cg); sstrcpy(&(cv->tag), tag); cv->numeric.f = value; cv->type = CONFIG_FLOAT; return value; } const FLT* config_set_float_a(config_group *cg, const char *tag, const FLT* values, uint8_t count) { config_entry *cv = find_config_entry(cg, tag); if (cv == NULL) cv = next_unused_entry(cg); sstrcpy(&(cv->tag), tag); char* ptr = (char*)realloc(cv->data, sizeof(FLT)*count); assert(ptr!=NULL); cv->data = ptr; printf("float array\n"); memcpy(cv->data,values,sizeof(FLT)*count); cv->type = CONFIG_FLOAT_ARRAY; cv->elements = count; return values; } void _json_write_float_array(FILE* f, const char* tag, FLT* v, uint8_t count) { #ifdef USE_DOUBLE json_write_double_array(f,tag,v,count); #else json_write_float_array(f,tag,v,count); #endif } void write_config_group(FILE* f, config_group *cg, char *tag) { uint16_t i = 0; if (tag != NULL) { fprintf(f, "\"%s\":{\n", tag); } for (i=0;i < cg->used_entries;++i) { if (cg->config_entries[i].type == CONFIG_FLOAT) { json_write_float(f, cg->config_entries[i].tag, cg->config_entries[i].numeric.f); } else if (cg->config_entries[i].type == CONFIG_UINT32) { json_write_uint32(f, cg->config_entries[i].tag, cg->config_entries[i].numeric.i); } else if (cg->config_entries[i].type == CONFIG_STRING) { json_write_str(f, cg->config_entries[i].tag, cg->config_entries[i].data); } else if (cg->config_entries[i].type == CONFIG_FLOAT_ARRAY) { _json_write_float_array(f, cg->config_entries[i].tag, (FLT*)cg->config_entries[i].data, cg->config_entries[i].elements); } if ((i+1) < cg->used_entries) fprintf(f,","); fprintf(f,"\n"); }; if (tag != NULL) { fprintf(f,"}\n"); } } void config_save(const char* path) { uint16_t i = 0; FILE* f = fopen(path, "w"); write_config_group(f,&global_config_values, NULL); write_config_group(f,lh_config, "lighthouse0"); write_config_group(f,lh_config+1, "lighthouse1"); fclose(f); } void print_json_value(char* tag, char** values, uint16_t count) { uint16_t i = 0; for (i=0;i1) { config_set_float_a(cg, tag, f, count); } else { config_set_float(cg, tag, f[0]); } return 1; } int parse_uint32(char* tag, char** values, uint16_t count) { uint16_t i = 0; uint32_t l[count]; char* end = NULL; config_group* cg = cg_stack[cg_stack_head]; /* //look for non numeric values for(end=values[0];*end!='\0';++end) { if ((*end<48) || (*end>57)) return 0; } end=NULL; */ for(i=0;i1) // config_set_uint32_array(cg, tag, f, count); // else config_set_uint32(cg, tag, l[0]); return 1; } void handle_tag_value(char* tag, char** values, uint16_t count) { print_json_value(tag,values,count); config_group* cg = cg_stack[cg_stack_head]; if (parse_uint32(tag,values,count) > 0) return; //parse integers first, stricter rules if (parse_floats(tag,values,count) > 0) return; //should probably also handle string arrays config_set_str(cg,tag,values[0]); // else if (count>1) config_set_str } void config_read(const char* path) { json_begin_object = handle_config_group; json_end_object = pop_config_group; json_tag_value = handle_tag_value; cg_stack[0] = &global_config_values; json_load_file(path); json_begin_object = NULL; json_end_object = NULL; json_tag_value = NULL; }