#include "Json_Utilities.hpp" extern "C" { #include "stdio.h" #include "stdlib.h" #include "string.h" } #include "functional" /** * @brief Json文件 格式检查 * @param path_to_file 文件路径串 * @return std::string 错误值 */ std::string JsonFile_FormatCheck(const char *path_to_file) { // 尝试打开文件 FILE *pFile = fopen(path_to_file, "rb"); if (pFile == nullptr) return "file \"" + std::string(path_to_file) + "\" open failed."; // 行列计数 size_t rol_count = 1; size_t column_count = 0; std::string err_str; // 跳过空白部分 return -> skip count auto Lambda_skip_blank = [&](void) -> size_t { size_t read_count = 0; while (true) { switch (fgetc(pFile)) { case EOF: return read_count; case ' ': column_count++; read_count++; break; case '\r': if (fgetc(pFile) == '\n') { read_count += 2; rol_count++; column_count = 0; } else { fseek(pFile, -2, SEEK_CUR); return read_count; } break; case '\n': read_count++; rol_count++; column_count = 0; break; default: fseek(pFile, -1, SEEK_CUR); return read_count; } } }; // 函数封装 std::function Check_Object; std::function Check_Value; std::function Check_Arry; std::function Check_Pair; // 函数定义 Check_Object = [&](void) -> std::string { Lambda_skip_blank(); char ch_get = fgetc(pFile); if (ch_get != '{') { if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected '" + ch_get + "'."; } column_count++; while (true) { Lambda_skip_blank(); ch_get = fgetc(pFile); column_count++; switch (ch_get) { case '}': return std::string(); case '\"': fseek(pFile, -1, SEEK_CUR); column_count--; { std::string err_str = Check_Pair(); if (!err_str.empty()) return err_str; // 结束后读取段 size_t now_rol_count = rol_count; size_t now_column_count = column_count; Lambda_skip_blank(); char ch_get = fgetc(pFile); if ((ch_get != '}') && (ch_get != ',')) { if (ch_get == ']') return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Missing '}'."; else if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Missing comma."; } fseek(pFile, -1, SEEK_CUR); } break; case ',': { size_t now_rol_count = rol_count; size_t now_column_count = column_count; Lambda_skip_blank(); if (fgetc(pFile) != '\"') return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Unexpected ','."; fseek(pFile, -1, SEEK_CUR); break; } case EOF: return std::string(path_to_file) + ':' + std::to_string(rol_count - 1) + ':' + std::to_string(column_count) + ": Unexpected EOF."; default: return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected '" + ch_get + "'."; } } }; Check_Value = [&](void) -> std::string { Lambda_skip_blank(); size_t begin_rol = rol_count; size_t begin_column = column_count; bool is_string = false; char ch_get = fgetc(pFile); // 判定第一个字符 switch (ch_get) { case EOF: return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; case '\"': is_string = true; break; case '{': fseek(pFile, -1, SEEK_CUR); return Check_Object(); case '[': fseek(pFile, -1, SEEK_CUR); return Check_Arry(); default: break; } // 判定为字符串 if (is_string) { column_count++; while (true) { ch_get = fgetc(pFile); column_count++; switch (ch_get) { case '\"': return std::string(); case '\\': // 转义符 ch_get = fgetc(pFile); if (ch_get != EOF) { column_count++; continue; } case EOF: return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; case '\n': return std::string(path_to_file) + ':' + std::to_string(begin_rol) + ':' + std::to_string(begin_column) + ": Unfinished string."; default: continue; } } } else fseek(pFile, -1, SEEK_CUR); // 识别有效数值 std::string segment_read; while (true) { bool segment_finish = false; ch_get = fgetc(pFile); column_count++; switch (ch_get) { case '\r': case ',': case '}': case ']': column_count--; fseek(pFile, -1, SEEK_CUR); case EOF: case ' ': case '\n': segment_finish = true; break; default: segment_read += ch_get; } if (segment_finish) break; } if ((segment_read == "true") || (segment_read == "false") || (segment_read == "null")) return std::string(); // 数值识别 { char *end_ptr; strtod(segment_read.c_str(), &end_ptr); // 未被完全转化、出现先导0、先导+、尾缀小数点时非法 if ((size_t(end_ptr - segment_read.c_str()) < segment_read.size()) || ((segment_read.c_str()[0] == '0') && (segment_read.size() > 1)) || (segment_read.c_str()[0] == '+') || end_ptr[-1] == '.') return std::string(path_to_file) + ':' + std::to_string(begin_rol) + ':' + std::to_string(begin_column) + ": Invalid value \"" + segment_read + "\"."; } return std::string(); }; Check_Arry = [&](void) -> std::string { Lambda_skip_blank(); char ch_get = fgetc(pFile); if (ch_get != '[') { if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected '" + ch_get + "'."; } column_count++; while (true) { Lambda_skip_blank(); ch_get = fgetc(pFile); column_count++; switch (ch_get) { case ']': return std::string(); case ',': { size_t now_rol_count = rol_count; size_t now_column_count = column_count; Lambda_skip_blank(); if (fgetc(pFile) == ']') return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Unexpected ','."; fseek(pFile, -1, SEEK_CUR); break; } case EOF: return std::string(path_to_file) + ':' + std::to_string(rol_count - 1) + ':' + std::to_string(column_count) + ": Unexpected EOF."; default: { column_count--; fseek(pFile, -1, SEEK_CUR); std::string err_str = Check_Value(); if (!err_str.empty()) return err_str; // 结束后读取段 size_t now_rol_count = rol_count; size_t now_column_count = column_count; Lambda_skip_blank(); char ch_get = fgetc(pFile); if ((ch_get != ',') && (ch_get != ']')) { if (ch_get == '}') return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Missing ']'."; else if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(now_rol_count) + ':' + std::to_string(now_column_count) + ": Missing comma."; } fseek(pFile, -1, SEEK_CUR); } } } }; Check_Pair = [&](void) -> std::string { Lambda_skip_blank(); char ch_get = fgetc(pFile); if (ch_get != '\"') { if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected '" + ch_get + "'."; } column_count++; // 遍历下一个引号 bool key_end = false; while (true) { ch_get = fgetc(pFile); column_count++; switch (ch_get) { case '\"': key_end = true; break; case '\n': rol_count++; column_count = 0; break; case EOF: return std::string(path_to_file) + ':' + std::to_string(rol_count - 1) + ':' + std::to_string(column_count) + ": Unexpected EOF."; } if (key_end) break; } // 寻找键值对标记 Lambda_skip_blank(); ch_get = fgetc(pFile); if (ch_get != ':') { if (ch_get == EOF) return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; else return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected '" + ch_get + "'. ':' is needed."; } column_count++; return Check_Value(); }; // 跳过空白检查第一个字符 Lambda_skip_blank(); switch (fgetc(pFile)) { case '[': fseek(pFile, -1, SEEK_CUR); err_str = Check_Arry(); break; case '{': fseek(pFile, -1, SEEK_CUR); err_str = Check_Object(); break; case EOF: err_str = std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF."; break; default: fseek(pFile, -1, SEEK_CUR); err_str = Check_Value(); } // 关闭文件 fclose(pFile); return err_str; } /** * @brief 解析Json文件 * @param path_to_file 文件路径串 * @param pJson_Value Value 指针 * @return std::string 错误值 */ std::string JsonFile_Parse(const char *path_to_file, Json_Value *pJson_Value) { // 存在格式错误时返回NULL值,通过格式检查时信任后续的输入 std::string err_str = JsonFile_FormatCheck(path_to_file); if (!err_str.empty()) return err_str; // 尝试打开文件 FILE *pFile = fopen(path_to_file, "rb"); if (pFile == nullptr) return "file \"" + std::string(path_to_file) + "\" open failed."; // 跳过空白部分 return -> skip count auto Lambda_skip_blank = [&](void) -> size_t { size_t read_count = 0; while (true) { switch (fgetc(pFile)) { case EOF: return read_count; case ' ': read_count++; break; case '\r': if (fgetc(pFile) == '\n') { read_count += 2; } else { fseek(pFile, -2, SEEK_CUR); return read_count; } break; case '\n': read_count++; break; default: fseek(pFile, -1, SEEK_CUR); return read_count; } } }; // 函数封装 std::function Parse_Object; std::function Parse_Value; std::function Parse_Arry; std::function Parse_Pair; // 函数定义 Parse_Object = [&](void) -> Json_Object { Json_Object temp_obj; Lambda_skip_blank(); // 拿掉第一个 '{' char ch_get = fgetc(pFile); while (true) { Lambda_skip_blank(); ch_get = fgetc(pFile); switch (ch_get) { case '}': return temp_obj; case '\"': fseek(pFile, -1, SEEK_CUR); { std::vector pair_list = temp_obj.element_list; pair_list.push_back(Parse_Pair()); temp_obj = Json_Object(pair_list); } break; default: break; } } }; Parse_Value = [&](void) -> Json_Value { Lambda_skip_blank(); bool is_string = false; char ch_get = fgetc(pFile); // 判定第一个字符 switch (ch_get) { case '\"': is_string = true; break; case '{': fseek(pFile, -1, SEEK_CUR); return Parse_Object(); case '[': fseek(pFile, -1, SEEK_CUR); return Parse_Arry(); default: break; } // 判定为字符串 if (is_string) { std::string value_str; while (true) { ch_get = fgetc(pFile); switch (ch_get) { case '\"': return value_str; case '\\': // 转义符 ch_get = fgetc(pFile); value_str.push_back('\\'); value_str.push_back(ch_get); break; default: value_str.push_back(ch_get); continue; } } } else fseek(pFile, -1, SEEK_CUR); // 识别非字符串类型Json值 std::string segment_read; while (true) { bool segment_finish = false; ch_get = fgetc(pFile); switch (ch_get) { case '\r': case ',': case '}': case ']': fseek(pFile, -1, SEEK_CUR); case EOF: case ' ': case '\n': segment_finish = true; break; default: segment_read += ch_get; } if (segment_finish) break; } // 逻辑值识别 if (segment_read == "true") return true; if (segment_read == "false") return false; if (segment_read == "null") return Json_Value(); // 数值识别 if (strstr(segment_read.c_str(), "e") || strstr(segment_read.c_str(), ".")) return strtod(segment_read.c_str(), nullptr); else return strtoll(segment_read.c_str(), nullptr, 0); }; Parse_Arry = [&](void) -> Json_Arry { Lambda_skip_blank(); // 拿掉第一个 '[' char ch_get = fgetc(pFile); std::vector value_list; while (true) { Lambda_skip_blank(); ch_get = fgetc(pFile); switch (ch_get) { case ']': return value_list; case ',': break; default: fseek(pFile, -1, SEEK_CUR); value_list.push_back(Parse_Value()); } } }; Parse_Pair = [&](void) -> Json_Pair { std::string key_str; Lambda_skip_blank(); // 拿掉第一个 '\"' char ch_get = fgetc(pFile); // 遍历下一个引号 bool key_end = false; while (true) { ch_get = fgetc(pFile); switch (ch_get) { case '\"': key_end = true; break; default: key_str.push_back(ch_get); break; } if (key_end) break; } // 拿掉键值对标记 Lambda_skip_blank(); ch_get = fgetc(pFile); // 返回键值对 return Json_Pair(key_str, Parse_Value()); }; // 跳过空白检查第一个字符 Lambda_skip_blank(); switch (fgetc(pFile)) { case '[': fseek(pFile, -1, SEEK_CUR); *pJson_Value = Parse_Arry(); break; case '{': fseek(pFile, -1, SEEK_CUR); *pJson_Value = Parse_Object(); break; default: fseek(pFile, -1, SEEK_CUR); *pJson_Value = Parse_Value(); break; } fclose(pFile); return std::string(); } /** * @brief Json对象保存 * @param path_to_file 文件路径串 * @param value Json Value * @param enable_pretty_print 启用美观打印 * @return std::string 错误值 */ std::string Json_Export(const char *path_to_file, Json_Value value, bool enable_pretty_print) { // 打开文件 FILE *pFile = fopen(path_to_file, "wb"); if (pFile == nullptr) { fclose(pFile); return "file \"" + std::string(path_to_file) + "\" open failed."; } // 函数封装 std::function Export_Object; std::function Export_Value; std::function Export_Arry; std::function Export_Pair; // 函数定义 Export_Object = [&](const Json_Object &obj, size_t depth, bool first_line_indent) { // 首行缩进 if (enable_pretty_print && first_line_indent) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); // 对象起始 fprintf(pFile, "{"); if (enable_pretty_print && (!obj.isNull())) fprintf(pFile, "\r\n"); // 输出键值对 for (auto pair : obj.element_list) { Export_Pair(pair, depth + 1); fprintf(pFile, enable_pretty_print ? ",\r\n" : ","); } if (!obj.isNull()) { fseek(pFile, enable_pretty_print ? -3 : -1, SEEK_CUR); if (enable_pretty_print) fprintf(pFile, "\r\n"); } // 尾部缩进 if (enable_pretty_print && (!obj.isNull())) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); // 对象结束 fprintf(pFile, "}"); }; Export_Value = [&](const Json_Value &value, size_t depth, bool indent) { if (enable_pretty_print && indent) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); switch (value.type) { case Json_Value::TYPE_NULL: // 空值 fprintf(pFile, "null"); break; case Json_Value::TYPE_STR: // 字符串 fprintf(pFile, "\"%s\"", value.asString().c_str()); break; case Json_Value::TYPE_ARRY: // 数组 Export_Arry(value.asArry(), depth, false); break; case Json_Value::TYPE_OBJ: // 对象 Export_Object(value.asObject(), depth, false); break; case Json_Value::TYPE_NUM_INTEGER: // 整数常数 fprintf(pFile, "%lld", value.asInteger()); break; case Json_Value::TYPE_NUM_FLOAT: // 浮点常数 fprintf(pFile, "%e", value.asFloat()); break; case Json_Value::TYPE_BOOLEAN: // 布尔逻辑值 if (value.asBoolean() == true) fprintf(pFile, "true"); else fprintf(pFile, "false"); } }; Export_Pair = [&](const Json_Pair &pair, size_t depth) { if (enable_pretty_print) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); fprintf(pFile, "\"%s\":", pair.key.c_str()); if (enable_pretty_print) fprintf(pFile, " "); Export_Value(pair.value, depth, false); }; Export_Arry = [&](const Json_Arry &arry, size_t depth, bool first_line_indent) { // 首行缩进 if (enable_pretty_print && first_line_indent) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); // 数组起始 fprintf(pFile, "["); if (enable_pretty_print && (!arry.isNull())) fprintf(pFile, "\r\n"); // 输出数组数值 for (auto value : arry.element_list) { Export_Value(value, depth + 1, true); fprintf(pFile, enable_pretty_print ? ",\r\n" : ","); } if (!arry.isNull()) { fseek(pFile, enable_pretty_print ? -3 : -1, SEEK_CUR); if (enable_pretty_print) fprintf(pFile, "\r\n"); } // 尾部缩进 if (enable_pretty_print && (!value.isNull())) for (size_t count = 0; count < depth; count++) fprintf(pFile, " "); // 对象结束 fprintf(pFile, "]"); }; if (value.type == Json_Value::TYPE_OBJ) Export_Object(value.asObject(), 0, false); else if (value.type == Json_Value::TYPE_ARRY) Export_Arry(value.asArry(), 0, false); else Export_Value(value, 0, false); fclose(pFile); return std::string(); } // std::string 构造 Json_Value::Json_Value(std::string str) : private_type(TYPE_STR), p_mem(malloc(sizeof(str))) { if (p_mem != nullptr) new (p_mem) std::string(str); else this->private_type = TYPE_NULL; } // Json_Arry 构造 Json_Value::Json_Value(Json_Arry arry) : private_type(TYPE_ARRY), p_mem(malloc(sizeof(arry))) { if (p_mem != nullptr) new (p_mem) Json_Arry(arry); else this->private_type = TYPE_NULL; } // Json_Object 构造 Json_Value::Json_Value(Json_Object object) : private_type(TYPE_OBJ), p_mem(malloc(sizeof(object))) { if (p_mem != nullptr) new (p_mem) Json_Object(object); else this->private_type = TYPE_NULL; } // 整数值 构造 Json_Value::Json_Value(int64_t num_integer) : private_type(TYPE_NUM_INTEGER), p_mem(malloc(sizeof(num_integer))) { if (p_mem != nullptr) *(decltype(num_integer) *)p_mem = num_integer; else this->private_type = TYPE_NULL; } // 浮点值 构造 Json_Value::Json_Value(double num_float) : private_type(TYPE_NUM_FLOAT), p_mem(malloc(sizeof(num_float))) { if (p_mem != nullptr) *(decltype(num_float) *)p_mem = num_float; else this->private_type = TYPE_NULL; } // Boolean 逻辑值构造 Json_Value::Json_Value(bool boolean) : private_type(TYPE_BOOLEAN), p_mem(malloc(sizeof(boolean))) { if (p_mem != nullptr) *(decltype(boolean) *)p_mem = boolean; else this->private_type = TYPE_NULL; } // 浅拷贝构造 Json_Value::Json_Value(const Json_Value &temp) : private_type(TYPE_NULL), p_mem(nullptr) { // 执行深拷贝 *this = temp; } // 深拷贝 Json_Value &Json_Value::operator=(const Json_Value &another) { if (this != &another) { // 先析构释放内存 this->~Json_Value(); // 重新赋值 this->private_type = another.type; switch (another.type) { case TYPE_STR: this->p_mem = malloc(sizeof(std::string)); if (this->p_mem != nullptr) { new (this->p_mem) std::string(); *((std::string *)this->p_mem) = *((std::string *)another.p_mem); } break; case TYPE_ARRY: this->p_mem = malloc(sizeof(Json_Arry)); if (this->p_mem != nullptr) { new (this->p_mem) Json_Arry(); *((Json_Arry *)this->p_mem) = *((Json_Arry *)another.p_mem); } break; case TYPE_OBJ: this->p_mem = malloc(sizeof(Json_Object)); if (this->p_mem != nullptr) { new (this->p_mem) Json_Object(); *((Json_Object *)this->p_mem) = *((Json_Object *)another.p_mem); } break; case TYPE_NUM_INTEGER: this->p_mem = malloc(sizeof(int64_t)); if (this->p_mem != nullptr) *((int64_t *)this->p_mem) = *((int64_t *)another.p_mem); break; case TYPE_NUM_FLOAT: this->p_mem = malloc(sizeof(double)); if (this->p_mem != nullptr) *((double *)this->p_mem) = *((double *)another.p_mem); break; case TYPE_BOOLEAN: this->p_mem = malloc(sizeof(bool)); if (this->p_mem != nullptr) *((bool *)this->p_mem) = *((bool *)another.p_mem); break; default: this->p_mem = nullptr; } } return *this; } // 析构 Json_Value::~Json_Value() { if (this->p_mem != nullptr) { // 对象析构 switch (this->private_type) { case TYPE_STR: ((std::string *)p_mem)->~basic_string(); break; case TYPE_ARRY: ((Json_Arry *)p_mem)->~Json_Arry(); break; case TYPE_OBJ: ((Json_Object *)p_mem)->~Json_Object(); break; default: break; }; // 释放内存 free(p_mem); } this->private_type = TYPE_NULL; } // 作为直接值获取 std::string Json_Value::asString(void) const { if (this->type == TYPE_STR) return *(std::string *)this->p_mem; else return std::string(""); } // 作为 Json_Arry 获取 Json_Arry Json_Value::asArry(void) const { if (this->type == TYPE_ARRY) return *(Json_Arry *)this->p_mem; else return Json_Arry(); } // 作为 Json_Object 获取 Json_Object Json_Value::asObject(void) const { if (this->type == TYPE_OBJ) return *(Json_Object *)this->p_mem; else return Json_Object(); } // 作为 int64 获取 int64_t Json_Value::asInteger(void) const { if (this->type == TYPE_NUM_INTEGER) return *(int64_t *)this->p_mem; else return 0; } // 作为 double 获取 double Json_Value::asFloat(void) const { if (this->type == TYPE_NUM_FLOAT) return *(double *)this->p_mem; else return 0; } // 作为 Boolean 逻辑值获取 bool Json_Value::asBoolean(void) const { if (this->type == TYPE_BOOLEAN) return *(bool *)this->p_mem; else return 0; } // 是否为空 bool Json_Value::isNull(void) const { return (this->private_type == TYPE_NULL); } // ================================================================================================= // 浅拷贝构造 Json_Pair::Json_Pair(const Json_Pair &temp) { *this = temp; } // 深拷贝 Json_Pair &Json_Pair::operator=(const Json_Pair &another) { if (this != &another) { this->Null_Flag = another.Null_Flag; this->private_key_str = another.private_key_str; this->private_value = another.private_value; } return *this; } // 空判定 bool Json_Pair::isNull() const { return this->Null_Flag; } // ================================================================================================= // 深拷贝 Json_Arry &Json_Arry::operator=(const Json_Arry &another) { if (this != &another) { this->private_element_list = another.private_element_list; } return *this; } // 获取元素大小 size_t Json_Arry::size(void) const { return this->private_element_list.size(); } // 数组索引重载 Json_Value Json_Arry::operator[](size_t index) const { if (index < this->private_element_list.size()) return this->private_element_list[index]; else return Json_Value(); } // 是否为空 bool Json_Arry::isNull(void) const { return (this->private_element_list.size() == 0); } // ================================================================================================= // 深拷贝 Json_Object &Json_Object::operator=(const Json_Object &another) { if (this != &another) { this->private_element_list = another.private_element_list; } return *this; } // 获取元素大小 size_t Json_Object::size(void) const { return this->private_element_list.size(); } // 数组索引重载 Json_Pair Json_Object::operator[](size_t index) const { if (index < this->private_element_list.size()) return this->private_element_list[index]; else return Json_Pair(); } // 由Key 查找值 Json_Value Json_Object::get(std::string key) const { for (auto pair : this->private_element_list) if (pair.key == key) return pair.value; return Json_Value(); } // 是否为空 bool Json_Object::isNull(void) const { return (this->private_element_list.size() == 0); }