#include "json_writer.h" #include #include #include #include static bool append(TrainlogJsonWriter *w, const char *s, size_t n) { if (w == NULL || s == NULL || w->failed || n > w->capacity - (w->size < w->capacity ? w->size : w->capacity) - 1U) { if (w != NULL) w->failed = true; return false; } (void)memcpy(w->data + w->size, s, n); w->size += n; w->data[w->size] = '\0'; return true; } void trainlog_json_init(TrainlogJsonWriter *w, char *data, size_t capacity) { if (w == NULL) return; w->data=data; w->capacity=capacity; w->size=0U; w->failed=data==NULL||capacity==0U; if (!w->failed) data[0]='\0'; } bool trainlog_json_raw(TrainlogJsonWriter *w,const char *v){return v!=NULL&&append(w,v,strlen(v));} bool trainlog_json_string(TrainlogJsonWriter *w,const char *v){ const unsigned char *p=(const unsigned char *)v; char escape[7]; if(v==NULL||!append(w,"\"",1U))return false; while(*p!='\0'){ utf8proc_int32_t codepoint; utf8proc_ssize_t sequence=utf8proc_iterate(p,-1,&codepoint); /* CONTRACT: valid UTF-8 is preserved byte-for-byte; corrupt storage * must fail serialization instead of producing invalid JSON. */ (void)codepoint; if(sequence<=0){w->failed=true;return false;} if(*p=='\"'||*p=='\\'){escape[0]='\\';escape[1]=(char)*p;if(!append(w,escape,2U))return false;} else if(*p=='\b'||*p=='\f'||*p=='\n'||*p=='\r'||*p=='\t'){const char codes[]="bfnrt";const char chars[]="\b\f\n\r\t";size_t i;escape[0]='\\';for(i=0U;i<5U&&chars[i]!=(char)*p;++i){}escape[1]=codes[i];if(!append(w,escape,2U))return false;} else if(*p<0x20U){int n=snprintf(escape,sizeof(escape),"\\u%04x",(unsigned int)*p);if(n!=6||!append(w,escape,6U))return false;} else if(!append(w,(const char *)p,(size_t)sequence))return false; p+=(size_t)sequence; } return append(w,"\"",1U); } bool trainlog_json_size(TrainlogJsonWriter*w,size_t v){char b[32];int n=snprintf(b,sizeof(b),"%zu",v);return n>0&&(size_t)n0&&(size_t)nfailed=true;return false;}n=snprintf(b,sizeof(b),"%.17g",v);return n>0&&(size_t)n