2 Star 1 Fork 0

张浩 / dbcc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
2json.c 5.52 KB
一键复制 编辑 原始数据 按行查看 历史
/* @brief Convert the Abstract Syntax Tree generated by mpc for the DBC file
* into an equivalent JSON file.
* @copyright Richard James Howe (2018)
* @license MIT *
*/
#include "2json.h"
#include "util.h"
#include <assert.h>
#include <time.h>
static int print_escaped(FILE *o, const char *string)
{
assert(o);
assert(string);
char c;
int r = 0;
while ((c = *(string)++)) {
switch(c) {
case '"': r = fputs("&quot;", o); break;
case '\'': r = fputs("&apos;", o); break;
case '<': r = fputs("&lt;", o); break;
case '>': r = fputs("&gt;", o); break;
case '&': r = fputs("&amp;", o); break;
default:
r = fputc(c, o);
}
if (r < 0)
return -1;
}
return 0;
}
static int indent(FILE *o, unsigned depth)
{
assert(o);
while (depth--)
if (fputc('\t', o) != '\t')
return -1;
return 0;
}
enum { INT, STRING, BOOL, FLOAT };
static int pfield(FILE *o, unsigned depth, bool last, int type, const char *node, const char *fmt, ...)
{
assert(o);
assert(node);
assert(fmt);
va_list args;
assert(o && node && fmt);
errno = 0;
if (indent(o, depth) < 0)
goto warn;
if (fprintf(o, "\"%s\" : %s", node, type == STRING ? "\"" : "") < 0)
goto warn;
assert(fmt);
va_start(args, fmt);
int r = vfprintf(o, fmt, args);
va_end(args);
if (r < 0)
goto warn;
if (fprintf(o, "%s%s\n", type == STRING ? "\"" : "", !last ? "," : "") < 0)
goto warn;
return 0;
warn:
warning("XML node generation, problem writing to FILE* <%p>: %s", o, emsg());
return -1;
}
static int signal2json(signal_t *sig, FILE *o, unsigned depth, int multiplexed, int selector, int is_value)
{
assert(sig);
assert(o);
if (!is_value)
indent(o, depth);
fprintf(o, "{\n");
pfield(o, depth+1, false, STRING, "name", "%s", sig->name);
pfield(o, depth+1, false, INT, "startbit", "%u", sig->start_bit);
pfield(o, depth+1, false, INT, "bitlength", "%u", sig->bit_length);
pfield(o, depth+1, false, STRING, "endianess", "%s", sig->endianess == endianess_motorola_e ? "motorola" : "intel");
pfield(o, depth+1, false, FLOAT, "scaling", "%g", sig->scaling);
pfield(o, depth+1, false, FLOAT, "offset", "%g", sig->offset);
pfield(o, depth+1, false, FLOAT, "minimum", "%g", sig->minimum);
pfield(o, depth+1, false, FLOAT, "maximum", "%g", sig->maximum);
pfield(o, depth+1, false, BOOL, "signed", "%s", sig->is_signed ? "true" : "false");
pfield(o, depth+1, false, INT, "floating", "%u", sig->is_floating ? sig->sigval : 0);
if (multiplexed)
pfield(o, depth+1, false, STRING, "selector", "%u", selector);
indent(o, depth+1);
fprintf(o, "\"units\" : \"");
print_escaped(o, sig->units);
fprintf(o, "\"\n");
indent(o, depth);
if (fprintf(o, "}") < 0)
return -1;
return 0;
}
static int msg2json(can_msg_t *msg, FILE *o, unsigned depth)
{
assert(msg);
assert(o);
indent(o, depth);
fprintf(o, "{\n");
pfield(o, depth+1, false, STRING, "name", "%s", msg->name);
pfield(o, depth+1, false, INT, "id", "%u", msg->id);
pfield(o, depth+1, false, BOOL, "extended", "%s", msg->is_extended ? "true" : "false");
pfield(o, depth+1, false, INT, "dlc", "%u", msg->dlc);
signal_t *multiplexor = NULL;
indent(o, depth+1);
fprintf(o, "\"signals\": [\n");
for (size_t i = 0; i < msg->signal_count; i++) {
signal_t *sig = msg->sigs[i];
if (sig->is_multiplexor) {
if (multiplexor) {
error("multiple multiplexor values detected (only one per CAN msg is allowed) for %s", msg->name);
return -1;
}
multiplexor = sig;
continue;
}
if (sig->is_multiplexed)
continue;
if (signal2json(sig, o, depth+2, 0, 0, 0) < 0)
return -1;
if ((msg->signal_count && i < (msg->signal_count - 1)))// || multiplexor)
fprintf(o, ",");
fprintf(o, "\n");
}
indent(o, depth+1);
fprintf(o, "]%s\n", multiplexor ? "," : "");
if (multiplexor) {
indent(o, depth+1);
fprintf(o, "\"multiplexor-group\" : {\n");
indent(o, depth+2);
fprintf(o, "\"multiplexor\" : ");
if (signal2json(multiplexor, o, depth+3, 0, 0, 1) < 0)
return -1;
fprintf(o, "%s\n", msg->signal_count ? "," : "");
size_t multiplexed_count = 0;
for (size_t i = 0; i < msg->signal_count; i++) {
signal_t *sig = msg->sigs[i];
if (sig->is_multiplexed)
multiplexed_count++;
}
indent(o, depth+2);
fprintf(o, "\"multiplexed\" : [\n");
for (size_t i = 0, j = 0; i < msg->signal_count; i++) {
signal_t *sig = msg->sigs[i];
if (!(sig->is_multiplexed))
continue;
j++;
if (signal2json(sig, o, depth+3, 1, sig->switchval, 0) < 0)
return -1;
if (multiplexed_count && j < multiplexed_count)
fprintf(o, ",");
fprintf(o, "\n");
}
indent(o, depth+2);
fprintf(o, "]\n");
indent(o, depth+1);
fprintf(o, "}\n");
}
indent(o, depth);
if (fprintf(o, "}") < 0)
return -1;
return 0;
}
int dbc2json(dbc_t *dbc, FILE *output, bool use_time_stamps)
{
assert(dbc);
assert(output);
time_t rawtime = time(NULL);
struct tm *timeinfo = localtime(&rawtime);
fprintf(output, "{\n");
fprintf(output, "\t\"description\" : \"JSON generated from a CAN DBC file\",\n");
fprintf(output, "\t\"compiler\" : \"dbcc\",\n");
fprintf(output, "\t\"site\" : \"https://github.com/howerj/dbcc\",\n");
if (use_time_stamps)
fprintf(output, "\t\"generated-on\": %s,", asctime(timeinfo));
fprintf(output, "\t\"messages\" : [\n");
for (size_t i = 0; i < dbc->message_count; i++) {
if (msg2json(dbc->messages[i], output, 2) < 0)
return -1;
if (dbc->message_count && i < (dbc->message_count - 1))
fprintf(output, ",");
fprintf(output, "\n");
}
fprintf(output, "\t]\n");
if (fprintf(output, "}\n") < 0)
return -1;
return 0;
}
C/C++
1
https://gitee.com/hao878/dbcc.git
git@gitee.com:hao878/dbcc.git
hao878
dbcc
dbcc
master

搜索帮助