Files

557 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "myjson.h"
#include "board.h"
#include "debug.h"
#include "mystdlib.h"
#include "bytearray.h"
// json字符串转化为json,返回临时指针
cJSON *json_parse(const char *jstr)
{
cJSON *json=cJSON_Parse(jstr);
if(json){
return tappend(json,cJSON_Delete);
}
return json;
}
/*r{ json 转列表 }c*/
list_def *jarray_to_list(cJSON *jarray,obj_def *obj)
{
param_check(obj);
param_check(obj->to_obj_fun);
param_check(obj->obj_size);
param_check(jarray);
list_def *l=list_creat(obj->obj_size,obj->sub,obj->del,0);
void *o;
int array_size;
if(jarray->type!=cJSON_Array){
DBG_WARN("json:%s not a array obj.",jarray->string?jarray->string:"null");
goto err;
}
array_size=cJSON_GetArraySize(jarray);
for(int i=0;i<array_size;i++)
{
o=obj->to_obj_fun(cJSON_GetArrayItem(jarray,i));
if(o==0)
{
DBG_WARN("json:%s conversion failed.",jarray->string?jarray->string:"null");
goto err;
}
list_append(l,o);
if(obj->del_fun) obj->del_fun(o);
}
err:
return l;
}
/*r{ json转整形 }c*/
static void *json_to_int(cJSON *j)
{
if(j->type==cJSON_Number)
{
int *ret=malloc(sizeof(int));
param_check(ret);
*ret=j->valueint;
return ret;
}
return 0;
}
static obj_def g_obj_int={
.obj_size=sizeof(int),
.to_obj_fun=json_to_int,
.del_fun=free,
.sub=INT_SUB,
.del=INT_DEL
};
obj_def *obj_int(void)
{
return &g_obj_int;
}
/*r{ json转字符串 }c*/
static void *json_to_str(cJSON *j)
{
if(j->type==cJSON_String)
{
int len=strlen(j->valuestring)+1;
char *ret=malloc(len);
char **ret_ptr=malloc(sizeof(char *));
param_check(ret);
param_check(ret_ptr);
memcpy(ret,j->valuestring,len+1);
*ret_ptr=ret;
return ret_ptr;
}
return 0;
}
static obj_def g_obj_str={
.obj_size=sizeof(char *),
.to_obj_fun=json_to_str,
.del_fun=free,
.sub=STR_SUB,
.del=STR_DEL
};
obj_def *obj_str(void)
{
return &g_obj_str;
}
static void *json_to_range(cJSON *j)
{
sch_range *s=malloc(sizeof(sch_range));
param_check(s);
JSON_GET_INT(cJSON_GetObjectItem(j,"Max"),s->max);
JSON_GET_INT(cJSON_GetObjectItem(j,"Min"),s->min);
if(s->min>s->max){
DBG_WARN("range is empty.");
}
return s;
}
static obj_def g_obj_range={
.obj_size=sizeof(sch_range),
.to_obj_fun=json_to_range,
.del_fun=free,
.sub=0,
.del=0
};
obj_def *obj_range(void)
{
return &g_obj_range;
}
// 返回1在范围内
int range_in_range(sch_range *r,int num)
{
if(num>=r->min&&num<=r->max)
return 1;
else
return 0;
}
static void *json_to_task(cJSON *j)
{
sch_task *task=calloc(1,sizeof(sch_range));
JSON_GET_STR(cJSON_GetObjectItem(j,"TaskBrief"),task->brief);
JSON_GET_INT(cJSON_GetObjectItem(j,"TaskID"),task->task_id);
JSON_GET_INT(cJSON_GetObjectItem(j,"TaskIndex"),task->index);
JSON_GET_INT(cJSON_GetObjectItem(j,"ErrJumpTo"),task->err_jump);
JSON_GET_INT(cJSON_GetObjectItem(j,"RetryCount"),task->retry);
JSON_GET_INT(cJSON_GetObjectItem(j,"ParamCount"),task->param_num);
JSON_GET_INT(cJSON_GetObjectItem(j,"ReturnCount"),task->return_num);
task->params_info=jarray_to_list(cJSON_GetObjectItem(j,"ParamInfo"),obj_str());
task->returns_info=jarray_to_list(cJSON_GetObjectItem(j,"ReturnInfo"),obj_str());
task->params=jarray_to_list(cJSON_GetObjectItem(j,"ParamVal"),obj_int());
task->ranges=jarray_to_list(cJSON_GetObjectItem(j,"TestStandard"),obj_range());
JSON_GET_INT(cJSON_GetObjectItem(j,"ExecuteErrCode"),task->failed_code);
task->ret_failed_code=jarray_to_list(cJSON_GetObjectItem(j,"ResultErrCode"),obj_int());
return task;
}
static int _list_del_task(void *p)
{
sch_task *t=p;
CHECK_DO(t->brief,free);
CHECK_DO(t->params_info,list_delete);
CHECK_DO(t->returns_info,list_delete);
CHECK_DO(t->params,list_delete);
CHECK_DO(t->ranges,list_delete);
CHECK_DO(t->ret_failed_code,list_delete);
CHECK_DO(t->ch_errcode,list_delete);
return 0;
}
static obj_def g_obj_task={
.obj_size=sizeof(sch_task),
.to_obj_fun=json_to_task,
.del_fun=free,
.sub=0,
.del=_list_del_task
};
obj_def *obj_task(void)
{
return &g_obj_task;
}
// 任务转化为数组
array_def *task_to_array(sch_task *t)
{
array_def *a=arr_creat();
arr_append(a,(uint8_t)t->task_id);
arr_append(a,(uint8_t)t->index);
arr_append(a,(uint8_t)t->retry);
arr_append(a,(uint8_t)t->err_jump);
arr_append(a,(uint8_t)(t->param_num&0x0f)|(t->return_num<<4));
for(int i=0;i<list_length(t->params);i++)
{
arr_append(a,(uint8_t)(list_get_int(t->params,i)&0xff));
arr_append(a,(uint8_t)(list_get_int(t->params,i)>>8));
}
if(list_length(t->params)!=t->param_num)
{
DBG_WARN("name=%s param_num!=params.size().",t->brief);
}
if(t->return_num>list_length(t->returns_info))
{
DBG_WARN("name=%s return_num>returns_info.size().",t->brief);
}
if(list_length(t->ch_errcode)!=list_length(t->ranges))
{
DBG_WARN("name=%s ch_errcode.size()!=ranges.size().",t->brief);
}
return a;
}
// ack==0成功
task_returns *task_check_returns(sch_task *t,int ack,array_def *data)
{
int size=sizeof(task_returns)+sizeof(reurn_item)*t->return_num;
task_returns *res=malloc(size);
param_check(res);
res->size=size;
memset(res,0,size);
if(t->ch_errcode==0) t->ch_errcode=list_creat_int();
list_clear(t->ch_errcode);
res->index=t->index;
res->id=t->task_id;
res->ack=ack;
if(res->ack==0){
res->exe_err=0;
}else{
res->exe_err=t->failed_code;
list_append_int(t->ch_errcode,t->failed_code);
}
if(arr_length(data)/2<t->return_num){
DBG_WARN("task=%s, data size too less.",t->brief);
}else{
for(int i=0;i<t->return_num;i++)
{
reurn_item *item=&res->items[i];
int value=arr_get(data,i*2)|(arr_get(data,i*2+1)<<8);
item->value=value;
if(list_length(t->ranges)>i)
{
if(range_in_range(list_get(t->ranges,i),value))
item->err=0;
else{
if(list_length(t->ret_failed_code)>i)
{
item->err=list_get_int(t->ret_failed_code,i);
list_append_int(t->ch_errcode,item->err);
}
}
}
}
}
return res;
}
static void *json_to_errcode(cJSON *j)
{
sch_errcode *e=calloc(1,sizeof(sch_errcode));
param_check(e);
JSON_GET_INT(cJSON_GetObjectItem(j,"MajorErrCode"),e->err);
JSON_GET_STR(cJSON_GetObjectItem(j,"Info"),e->info);
e->suberr=jarray_to_list(cJSON_GetObjectItem(j,"SubErrCode"),obj_int());
return e;
}
static int _list_del_errcode(void *p)
{
sch_errcode *e=p;
CHECK_DO(e->info,free);
CHECK_DO(e->suberr,list_delete);
return 0;
}
static obj_def g_obj_errcode={
.obj_size=sizeof(sch_errcode),
.to_obj_fun=json_to_errcode,
.del_fun=free,
.sub=0,
.del=_list_del_errcode
};
obj_def *obj_errcode(void)
{
return &g_obj_errcode;
}
// 返回1在范围内
int errcode_in_range(sch_errcode *e,int subcode)
{
param_check(e);
for(int i=0;i<list_length(e->suberr);i++)
{
if(subcode==list_get_int(e->suberr,i))
return 1;
}
return 0;
}
static void *_json_to_scheme(cJSON *j)
{
scheme_def *s=calloc(1,sizeof(scheme_def));
param_check(s);
JSON_GET_INT(cJSON_GetObjectItem(j,"PlanID"),s->plan_id);
JSON_GET_STR(cJSON_GetObjectItem(j,"PlanBrief"),s->brief);
s->slave_soft_versions=jarray_to_list(cJSON_GetObjectItem(j,"CheckSoftVersion"),obj_int());
s->slave_hard_versions=jarray_to_list(cJSON_GetObjectItem(j,"CheckHardVersion"),obj_int());
JSON_GET_INT(cJSON_GetObjectItem(j,"TimeOutS"),s->timeout_s);
JSON_GET_INT(cJSON_GetObjectItem(j,"TimeOutM"),s->timeout_m);
JSON_GET_INT(cJSON_GetObjectItem(j,"TaskIDMax"),s->task_id_max);
s->errs=jarray_to_list(cJSON_GetObjectItem(j,"MajorErrInfo"),obj_errcode());
s->tasks=jarray_to_list(cJSON_GetObjectItem(j,"TaskArray"),obj_task());
return s;
}
static int _list_del_scheme(void *p)
{
scheme_def *t=p;
CHECK_DO(t->brief,free);
CHECK_DO(t->slave_soft_versions,list_delete);
CHECK_DO(t->slave_hard_versions,list_delete);
CHECK_DO(t->errs,list_delete);
CHECK_DO(t->tasks,list_delete);
CHECK_DO(t->ch_errcode,list_delete);
return 0;
}
static obj_def g_obj_scheme={
.obj_size=sizeof(scheme_def),
.to_obj_fun=_json_to_scheme,
.del_fun=free,
.sub=0,
.del=_list_del_scheme
};
obj_def *obj_scheme(void)
{
return &g_obj_scheme;
}
scheme_def *json_to_scheme(cJSON *j)
{
param_check(j);
obj_def *obj=obj_scheme();
scheme_def *s=obj->to_obj_fun(j);
return s;
}
void scheme_delete(scheme_def *s)
{
obj_def *obj=obj_scheme();
param_check(s);
obj->del(s);
obj->del_fun(s);
}
// 任务id转化为字节数据
#define TASKSID_MAX_SIZE 0x100
static array_def *scheme_taskid_to_array(scheme_def *s)
{
param_check(s);
array_def *res=arr_creat();
param_check(res);
arr_append(res,s->plan_id&0xff);
arr_append(res,(s->plan_id>>8)&0xff);
arr_append(res,(s->plan_id>>16)&0xff);
arr_append(res,(s->plan_id>>24)&0xff);
for(int i=0;i<list_length(s->tasks);i++)
{
sch_task *t=list_get(s->tasks,i);
arr_append(res,t->task_id);
}
int size=arr_length(res);
if(size<TASKSID_MAX_SIZE){
arr_append_num(res,TASKSID_MAX_SIZE-size,0xff);
}else{
DBG_WARN("taskid array size too larg.");
}
return res;
}
// 任务转化为字节数据
#define TASKS_MAX_SIZE (0x700-4)
static array_def *scheme_tasks_to_array(scheme_def *s)
{
param_check(s);
array_def *res=arr_creat();
param_check(res);
for(int i=0;i<list_length(s->tasks);i++)
{
sch_task *t=list_get(s->tasks,i);
array_def *a=task_to_array(t);
arr_appends_from(res,a);
arr_delete(a);
}
int size=arr_length(res);
if(size<TASKS_MAX_SIZE)
{
arr_append_num(res,TASKS_MAX_SIZE-size,0xff);
}else{
DBG_WARN("tasks array size too larg.");
}
return res;
}
// 方案转化为字节数据
array_def *scheme_to_byte_array(scheme_def *s)
{
param_check(s);
array_def *res=arr_creat();
param_check(res);
array_def *src;
src=scheme_taskid_to_array(s);
arr_appends_from(res,src);
arr_delete(src);
src=scheme_tasks_to_array(s);
arr_appends_from(res,src);
arr_delete(src);
return res;
}
// 统计返回数据长度
int scheme_get_returns_num(scheme_def *s)
{
int num=0;
for(int i=0;i<list_length(s->tasks);i++)
{
sch_task *t=list_get(s->tasks,i);
num+=t->return_num;
}
return num;
}
// 返回0成功1失败
int scheme_check_ack(array_def *data,int index)
{
param_check(index>=0);
param_check(index<arr_length(data)*8);
uint8_t temp=arr_get(data,index/8);
if((temp&(1<<(index%8)))!=0)
{return 1;}else{return 0;}
}
// 返回子错误所在的主错误失败返回0
int scheme_fine_majercode(scheme_def *s,int subcode)
{
for(int i=0;i<list_length(s->errs);i++)
{
sch_errcode *e=list_get(s->errs,i);
if(errcode_in_range(e,subcode))
return e->err;
}
return 0;
}
// 判定检测数据
scheme_returns *scheme_check_returns(scheme_def *s,array_def *data)
{
int size=0;
size+=sizeof(scheme_returns);
size+=sizeof(task_returns)*list_length(s->tasks);
size+=sizeof(reurn_item)*scheme_get_returns_num(s);
scheme_returns *res=malloc(size);
param_check(res);
memset(res,0,size);
res->size=size;
if(s->ch_errcode==0) s->ch_errcode= list_creat_int();
list_clear(s->ch_errcode);
int start=16;
int off=0;
for(int i=0;i<list_length(s->tasks);i++)
{
int ack=scheme_check_ack(data,i);
sch_task *t=list_get(s->tasks,i);
array_def *arr_temp=arr_mid(data,start,t->return_num*2);
task_returns *task_ret=task_check_returns(t,ack,arr_temp);
arr_delete(arr_temp);
memcpy(&res->data[off],task_ret,task_ret->size);
off+=task_ret->size;
start+=t->return_num*2;
list_append_from(s->ch_errcode,t->ch_errcode);
}
if(list_length(s->ch_errcode)>0)
{
res->errcode=scheme_fine_majercode(s,list_get_int(s->ch_errcode,0));
}else{
res->errcode=0;
}
return res;
}