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 | 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 | 1248 | if(name && strlen(name) > 0) this->appendElem(name); | |
| 40 | 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 | 579 | if(name && strlen(name) > 0) this->appendElem(name); | |
| 53 | 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 | 10029 | if(!this->_nocomma) this->_safecat(","); | |
| 67 | 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 | 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 | 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 | 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 | 37748 | const size_t vlen = escape ? this->calcEscapedLength(val) + 2 : strlen(val); | |
| 111 | 37748 | if(this->_len + vlen >= this->buffSize) { | |
| 112 | 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 | 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 | 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 | 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 | 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 | 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 | 22225 | for(size_t i = 0; raw[i]; i++) out += escapeChar(raw[i], out); | |
| 167 | 7182 | } | |
| 168 |