a
jconf_t * read_jconf(const char *file) { static jconf_t conf; // 清空數據 memset(&conf, 0, sizeof(jconf_t)); // 用於存儲文件內容的字符串指針 char *buf; // 解析文件內容后的json結構化數據 json_value *obj; // 打開文件 FILE *f = fopen(file, "rb"); if (f == NULL) { FATAL("Invalid config path."); } // 確定文件大小, 並將讀取指針移回文件開始 fseek(f, 0, SEEK_END); long pos = ftell(f); fseek(f, 0, SEEK_SET); if (pos < 0) { FATAL("Invalid config path."); } if (pos >= MAX_CONF_SIZE) { FATAL("Too large config file."); } // 根據文件大小申請內存空間, 注意這邊要多申請1個字節用於存放'\0' buf = ss_malloc(pos + 1); if (buf == NULL) { FATAL("No enough memory."); } // 讀取文件內容至buff int nread = fread(buf, pos, 1, f); if (!nread) { FATAL("Failed to read the config file."); } // 關閉文件 fclose(f); // 關閉字符串結尾 buf[pos] = '\0'; // end of string json_settings settings = { 0UL, 0, NULL, NULL, NULL }; char error_buf[512]; // 解析內容至結構化json數據 obj = json_parse_ex(&settings, buf, pos, error_buf); if (obj == NULL) { FATAL(error_buf); } if (obj->type == json_object) { unsigned int i, j; // 遍歷json數據 for (i = 0; i < obj->u.object.length; i++) { // 每一步, 都先讀取鍵名, 然后根據value類型, 讀取value內容 char *name = obj->u.object.values[i].name; json_value *value = obj->u.object.values[i].value; if (strcmp(name, "server") == 0) { if (value->type == json_array) { for (j = 0; j < value->u.array.length; j++) { if (j >= MAX_REMOTE_NUM) { break; } json_value *v = value->u.array.values[j]; char *addr_str = to_string(v); parse_addr(addr_str, conf.remote_addr + j); ss_free(addr_str); conf.remote_num = j + 1; } } else if (value->type == json_string) { conf.remote_addr[0].host = to_string(value); conf.remote_addr[0].port = NULL; conf.remote_num = 1; } } else if (strcmp(name, "port_password") == 0) { if (value->type == json_object) { for (j = 0; j < value->u.object.length; j++) { if (j >= MAX_PORT_NUM) { break; } json_value *v = value->u.object.values[j].value; if (v->type == json_string) { conf.port_password[j].port = ss_strndup(value->u.object.values[j].name, value->u.object.values[j].name_length); conf.port_password[j].password = to_string(v); conf.port_password_num = j + 1; } } } } else if (strcmp(name, "server_port") == 0) { conf.remote_port = to_string(value); } // ... } } else { FATAL("Invalid config file"); } // 釋放文件內容內存空間 do { free(buf); buf = NULL; } while (0); // 釋放結構化json數據空間 json_value_free(obj); return &conf; } void * ss_malloc(size_t size) { void *tmp = malloc(size); if (tmp == NULL) exit(EXIT_FAILURE); return tmp; }
.
