Harden history parsing and single-point chart rendering
This commit is contained in:
@@ -252,6 +252,40 @@ static String history_date_from_epoch(uint32_t ts_utc) {
|
|||||||
return String(buf);
|
return String(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool history_parse_u32_field(const char *start, size_t len, uint32_t &out) {
|
||||||
|
if (!start || len == 0 || len >= 16) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char buf[16];
|
||||||
|
memcpy(buf, start, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
char *end = nullptr;
|
||||||
|
unsigned long value = strtoul(buf, &end, 10);
|
||||||
|
if (end == buf || *end != '\0' || value > static_cast<unsigned long>(UINT32_MAX)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out = static_cast<uint32_t>(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool history_parse_float_field(const char *start, size_t len, float &out) {
|
||||||
|
if (!start || len == 0 || len >= 24) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char buf[24];
|
||||||
|
memcpy(buf, start, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
char *end = nullptr;
|
||||||
|
float value = strtof(buf, &end);
|
||||||
|
if (end == buf || *end != '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool history_open_next_file() {
|
static bool history_open_next_file() {
|
||||||
if (!g_history.active || g_history.done || g_history.error) {
|
if (!g_history.active || g_history.done || g_history.error) {
|
||||||
return false;
|
return false;
|
||||||
@@ -274,40 +308,32 @@ static bool history_parse_line(const char *line, uint32_t &ts_out, float &p_out)
|
|||||||
if (!line || line[0] < '0' || line[0] > '9') {
|
if (!line || line[0] < '0' || line[0] > '9') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *comma1 = strchr(line, ',');
|
const char *comma1 = strchr(line, ',');
|
||||||
if (!comma1) {
|
if (!comma1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char ts_buf[16];
|
|
||||||
size_t ts_len = static_cast<size_t>(comma1 - line);
|
uint32_t ts = 0;
|
||||||
if (ts_len >= sizeof(ts_buf)) {
|
if (!history_parse_u32_field(line, static_cast<size_t>(comma1 - line), ts)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(ts_buf, line, ts_len);
|
|
||||||
ts_buf[ts_len] = '\0';
|
|
||||||
char *end = nullptr;
|
|
||||||
uint32_t ts = static_cast<uint32_t>(strtoul(ts_buf, &end, 10));
|
|
||||||
if (end == ts_buf) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *comma2 = strchr(comma1 + 1, ',');
|
const char *comma2 = strchr(comma1 + 1, ',');
|
||||||
if (!comma2) {
|
if (!comma2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float p = 0.0f;
|
||||||
|
if (!history_parse_float_field(comma1 + 1, static_cast<size_t>(comma2 - (comma1 + 1)), p)) {
|
||||||
const char *p_start = comma2 + 1;
|
const char *p_start = comma2 + 1;
|
||||||
const char *p_end = strchr(p_start, ',');
|
const char *p_end = strchr(p_start, ',');
|
||||||
char p_buf[16];
|
|
||||||
size_t p_len = p_end ? static_cast<size_t>(p_end - p_start) : strlen(p_start);
|
size_t p_len = p_end ? static_cast<size_t>(p_end - p_start) : strlen(p_start);
|
||||||
if (p_len == 0 || p_len >= sizeof(p_buf)) {
|
if (!history_parse_float_field(p_start, p_len, p)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(p_buf, p_start, p_len);
|
|
||||||
p_buf[p_len] = '\0';
|
|
||||||
char *endp = nullptr;
|
|
||||||
float p = strtof(p_buf, &endp);
|
|
||||||
if (endp == p_buf) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_out = ts;
|
ts_out = ts;
|
||||||
p_out = p;
|
p_out = p;
|
||||||
return true;
|
return true;
|
||||||
@@ -649,10 +675,11 @@ static void handle_sender() {
|
|||||||
html += "if(min===max){min=0;}";
|
html += "if(min===max){min=0;}";
|
||||||
html += "ctx.strokeStyle='#333';ctx.lineWidth=1;ctx.beginPath();";
|
html += "ctx.strokeStyle='#333';ctx.lineWidth=1;ctx.beginPath();";
|
||||||
html += "let first=true;";
|
html += "let first=true;";
|
||||||
|
html += "const xDen=series.length>1?(series.length-1):1;";
|
||||||
html += "for(let i=0;i<series.length;i++){";
|
html += "for(let i=0;i<series.length;i++){";
|
||||||
html += "const v=series[i][1];";
|
html += "const v=series[i][1];";
|
||||||
html += "if(v===null)continue;";
|
html += "if(v===null)continue;";
|
||||||
html += "const x=(i/(series.length-1))* (w-2) + 1;";
|
html += "const x=series.length>1?((i/xDen)*(w-2)+1):(w/2);";
|
||||||
html += "const y=h-2-((v-min)/(max-min))*(h-4);";
|
html += "const y=h-2-((v-min)/(max-min))*(h-4);";
|
||||||
html += "if(first){ctx.moveTo(x,y);first=false;} else {ctx.lineTo(x,y);} }";
|
html += "if(first){ctx.moveTo(x,y);first=false;} else {ctx.lineTo(x,y);} }";
|
||||||
html += "ctx.stroke();";
|
html += "ctx.stroke();";
|
||||||
|
|||||||
Reference in New Issue
Block a user