src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
126 / 126
100.0%
Branches:
47 / 51
92.2%
Functions:
30 / 30
100.0%

JsonFormatter.cpp
Line Branch Exec Source
1 #include "JsonFormatter.h"
2 #include "esp_log.h"
3
4 static const char *TAG = "JSON";
5
6 91 void BufferedJsonFormatter::setBuffer(char *b, size_t sz) {
7 91 this->buff = b;
8 91 this->buffSize = sz;
9 91 this->buff[0] = 0;
10 91 this->_len = 0;
11 91 this->_nocomma = true;
12 91 this->_overflow = false;
13 91 this->_objects = 0;
14 91 this->_arrays = 0;
15 91 }
16 509 size_t BufferedJsonFormatter::length() const {
17 509 return this->_len;
18 }
19 2 void JsonFormatter::discard() {
20 // With no room every _safecat() takes the overflow path, and as it has
21 // already overflowed that doesn't log either.
22 2 this->buff = nullptr;
23 2 this->buffSize = 0;
24 2 this->_len = 0;
25 2 this->_nocomma = true;
26 2 this->_overflow = true;
27 2 this->_objects = 0;
28 2 this->_arrays = 0;
29 2 }
30 248 void JsonFormatter::rollback(const json_mark_t &m) {
31 248 this->_len = m.len;
32
1/2
✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
248 if(this->buff) this->buff[this->_len] = 0;
33 248 this->_objects = m.objects;
34 248 this->_arrays = m.arrays;
35 248 this->_nocomma = m.nocomma;
36 248 this->_overflow = false;
37 248 }
38 1248 void JsonFormatter::beginObject(const char *name) {
39
3/4
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1187 times.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
1248 if(name && strlen(name) > 0) this->appendElem(name);
40
2/2
✓ Branch 0 taken 942 times.
✓ Branch 1 taken 245 times.
1187 else if(!this->_nocomma) this->_safecat(",");
41 1248 this->_safecat("{");
42 1248 this->_objects++;
43 1248 this->_nocomma = true;
44 1248 }
45 1244 void JsonFormatter::endObject() {
46 //if(strlen(this->buff) + 1 > this->buffSize - 1) this->send();
47 1244 this->_safecat("}");
48 1244 this->_objects--;
49 1244 this->_nocomma = false;
50 1244 }
51 579 void JsonFormatter::beginArray(const char *name) {
52
3/4
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 226 times.
✓ Branch 2 taken 353 times.
✗ Branch 3 not taken.
579 if(name && strlen(name) > 0) this->appendElem(name);
53
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 7 times.
226 else if(!this->_nocomma) this->_safecat(",");
54 579 this->_safecat("[");
55 579 this->_arrays++;
56 579 this->_nocomma = true;
57 579 }
58 464 void JsonFormatter::endArray() {
59 //if(strlen(this->buff) + 1 > this->buffSize - 1) this->send();
60 464 this->_safecat("]");
61 464 this->_arrays--;
62 464 this->_nocomma = false;
63 464 }
64
65 10029 void JsonFormatter::appendElem(const char *name) {
66
2/2
✓ Branch 0 taken 8487 times.
✓ Branch 1 taken 1542 times.
10029 if(!this->_nocomma) this->_safecat(",");
67
3/4
✓ Branch 0 taken 7475 times.
✓ Branch 1 taken 2554 times.
✓ Branch 2 taken 7475 times.
✗ Branch 3 not taken.
10029 if(name && strlen(name) > 0) {
68 7475 this->_safecat(name, true);
69 7475 this->_safecat(":");
70 }
71 10029 this->_nocomma = false;
72 10029 }
73
74 780 void JsonFormatter::addElem(const char *name, const char *val) {
75
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 779 times.
780 if(!val) return;
76 779 this->appendElem(name);
77 779 this->_safecat(val, true);
78 }
79 534 void JsonFormatter::addElem(const char *val) { this->addElem(nullptr, val); }
80 1 void JsonFormatter::addElem(float fval) { sprintf(this->_numbuff, "%.4f", fval); this->_appendNumber(nullptr); }
81 1 void JsonFormatter::addElem(int8_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(nullptr); }
82 79 void JsonFormatter::addElem(uint8_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(nullptr); }
83 1914 void JsonFormatter::addElem(int32_t nval) { sprintf(this->_numbuff, "%ld", (long)nval); this->_appendNumber(nullptr); }
84 23 void JsonFormatter::addElem(uint32_t nval) { sprintf(this->_numbuff, "%lu", (unsigned long)nval); this->_appendNumber(nullptr); }
85
86 /*
87 void JsonFormatter::addElem(int16_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(nullptr); }
88 void JsonFormatter::addElem(uint16_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(nullptr); }
89 void JsonFormatter::addElem(int64_t lval) { sprintf(this->_numbuff, "%lld", (long long)lval); this->_appendNumber(nullptr); }
90 void JsonFormatter::addElem(uint64_t lval) { sprintf(this->_numbuff, "%llu", (unsigned long long)lval); this->_appendNumber(nullptr); }
91 */
92
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 void JsonFormatter::addElem(bool bval) { strcpy(this->_numbuff, bval ? "true" : "false"); this->_appendNumber(nullptr); }
93
94 1 void JsonFormatter::addElem(const char *name, float fval) { sprintf(this->_numbuff, "%.4f", fval); this->_appendNumber(name); }
95 1 void JsonFormatter::addElem(const char *name, int8_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(name); }
96 1132 void JsonFormatter::addElem(const char *name, uint8_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(name); }
97 4216 void JsonFormatter::addElem(const char *name, int32_t nval) { sprintf(this->_numbuff, "%ld", (long)nval); this->_appendNumber(name); }
98 1448 void JsonFormatter::addElem(const char *name, uint32_t nval) { sprintf(this->_numbuff, "%lu", (unsigned long)nval); this->_appendNumber(name); }
99
100 /*
101 void JsonFormatter::addElem(const char *name, int16_t nval) { sprintf(this->_numbuff, "%d", nval); this->_appendNumber(name); }
102 void JsonFormatter::addElem(const char *name, uint16_t nval) { sprintf(this->_numbuff, "%u", nval); this->_appendNumber(name); }
103 void JsonFormatter::addElem(const char *name, int64_t lval) { sprintf(this->_numbuff, "%lld", (long long)lval); this->_appendNumber(name); }
104 */
105 2 void JsonFormatter::addElem(const char *name, uint64_t lval) { sprintf(this->_numbuff, "%llu", (unsigned long long)lval); this->_appendNumber(name); }
106
107
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10 times.
16 void JsonFormatter::addElem(const char *name, bool bval) { strcpy(this->_numbuff, bval ? "true" : "false"); this->_appendNumber(name); }
108
109 37748 void JsonFormatter::_safecat(const char *val, bool escape) {
110
2/2
✓ Branch 0 taken 8254 times.
✓ Branch 1 taken 29494 times.
37748 const size_t vlen = escape ? this->calcEscapedLength(val) + 2 : strlen(val);
111
2/2
✓ Branch 0 taken 5021 times.
✓ Branch 1 taken 32727 times.
37748 if(this->_len + vlen >= this->buffSize) {
112
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 4978 times.
5021 if(!this->_overflow && this->_logOverflow) ESP_LOGE(TAG, "JSON exceeded buffer size %u", (unsigned)this->buffSize);
113 5021 this->_overflow = true;
114 5021 return;
115 }
116 32727 this->_appendAt(val, escape, vlen);
117 }
118 32727 void JsonFormatter::_appendAt(const char *val, bool escape, size_t vlen) {
119 32727 char *p = this->buff + this->_len;
120
2/2
✓ Branch 0 taken 7182 times.
✓ Branch 1 taken 25545 times.
32727 if(escape) {
121 7182 *p++ = '"';
122 7182 *p = 0;
123 7182 this->escapeString(val, p);
124 7182 p += vlen - 2;
125 7182 *p++ = '"';
126 }
127 else {
128 25545 memcpy(p, val, vlen);
129 25545 p += vlen;
130 }
131 32727 *p = 0;
132 32727 this->_len += vlen;
133 32727 }
134 8836 void JsonFormatter::_appendNumber(const char *name) { this->appendElem(name); this->_safecat(this->_numbuff); }
135 32217 size_t JsonFormatter::escapeChar(char c, char *out) {
136 32217 const char *esc = nullptr;
137
9/9
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 32181 times.
32217 switch(c) {
138 18 case '"': esc = "\\\""; break;
139 4 case '/': esc = "\\/"; break;
140 2 case '\b': esc = "\\b"; break;
141 2 case '\f': esc = "\\f"; break;
142 4 case '\n': esc = "\\n"; break;
143 2 case '\r': esc = "\\r"; break;
144 2 case '\t': esc = "\\t"; break;
145 2 case '\\': esc = "\\\\"; break;
146 32181 default: break;
147 }
148
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 32181 times.
32217 if(esc) {
149 36 strcpy(out, esc);
150 36 return 2;
151 }
152 // Any other control character is not allowed raw in a JSON string.
153
2/2
✓ Branch 0 taken 8784 times.
✓ Branch 1 taken 23397 times.
32181 if((unsigned char)c < 0x20) return snprintf(out, 7, "\\u%04x", (unsigned char)c);
154 23397 out[0] = c;
155 23397 out[1] = 0x00;
156 23397 return 1;
157 }
158 8259 uint32_t JsonFormatter::calcEscapedLength(const char *raw) {
159 char tmp[7];
160 8259 uint32_t len = 0;
161
2/2
✓ Branch 1 taken 17174 times.
✓ Branch 2 taken 8259 times.
25433 for(size_t i = 0; raw[i]; i++) len += escapeChar(raw[i], tmp);
162 8259 return len;
163 }
164 7182 void JsonFormatter::escapeString(const char *raw, char *escaped) {
165 7182 char *out = escaped + strlen(escaped);
166
2/2
✓ Branch 1 taken 15043 times.
✓ Branch 2 taken 7182 times.
22225 for(size_t i = 0; raw[i]; i++) out += escapeChar(raw[i], out);
167 7182 }
168