Implemented a JSON file format checking function.
This commit is contained in:
parent
057438652a
commit
b11e74e815
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "stdio.h"
|
|
||||||
#include "stdlib.h"
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +14,13 @@ class Json_Arry; // Json 数组 元素必须是值
|
|||||||
class Json_Object; // Json 对象 对象内必须是键值对序列
|
class Json_Object; // Json 对象 对象内必须是键值对序列
|
||||||
class Json_Value; // Json 值(可以是数组、对象、字符串、浮点数值和整数值、逻辑值、NULL)
|
class Json_Value; // Json 值(可以是数组、对象、字符串、浮点数值和整数值、逻辑值、NULL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Json文件 格式检查
|
||||||
|
* @param path_to_file 文件路径串
|
||||||
|
* @return std::string 错误值
|
||||||
|
*/
|
||||||
|
std::string JsonFile_FormatCheck(const char *path_to_file);
|
||||||
|
|
||||||
// Json 数组
|
// Json 数组
|
||||||
class Json_Arry
|
class Json_Arry
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,398 @@
|
|||||||
#include "Json_Utilities.hpp"
|
#include "Json_Utilities.hpp"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "stdlib.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<std::string(void)> Check_Object;
|
||||||
|
std::function<std::string(void)> Check_Value;
|
||||||
|
std::function<std::string(void)> Check_Arry;
|
||||||
|
std::function<std::string(void)> 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 EOF:
|
||||||
|
return std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Unexpected EOF.";
|
||||||
|
case '\r':
|
||||||
|
case ',':
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
column_count--;
|
||||||
|
fseek(pFile, -1, SEEK_CUR);
|
||||||
|
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:
|
||||||
|
err_str = std::string(path_to_file) + ':' + std::to_string(rol_count) + ':' + std::to_string(column_count) + ": Syntax error. Must begin with '{' or '['.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭文件
|
||||||
|
fclose(pFile);
|
||||||
|
return err_str;
|
||||||
|
}
|
||||||
|
|
||||||
// std::string 构造
|
// std::string 构造
|
||||||
Json_Value::Json_Value(std::string str) : private_type(TYPE_STR), p_mem(malloc(sizeof(str)))
|
Json_Value::Json_Value(std::string str) : private_type(TYPE_STR), p_mem(malloc(sizeof(str)))
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user