X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=json.hpp;h=9e6b96004dc71be9dc96e85a6d4279f508c12765;hb=851d0b0452234ace66a511327bd8e6f9d68fe9e9;hp=8619191e9a3518fde402926e1e65cb2125ea053a;hpb=702c1c685e4214e8172d2973ed365044b2398331;p=apitrace diff --git a/json.hpp b/json.hpp index 8619191..9e6b960 100644 --- a/json.hpp +++ b/json.hpp @@ -34,8 +34,9 @@ #include #include -#include #include +#include +#include class JSONWriter @@ -45,6 +46,7 @@ private: int level; bool value; + char space; void newline(void) { os << "\n"; @@ -55,6 +57,20 @@ private: void separator(void) { if (value) { os << ","; + switch (space) { + case '\0': + break; + case '\n': + newline(); + break; + default: + os << space; + break; + } + } else { + if (space == '\n') { + newline(); + } } } @@ -128,11 +144,69 @@ private: os << "\""; } + void encodeBase64String(const unsigned char *bytes, size_t size) { + const char *table64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned char c0, c1, c2, c3; + char buf[4]; + unsigned written; + + os << "\""; + + written = 0; + while (size >= 3) { + c0 = bytes[0] >> 2; + c1 = ((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xf0) >> 4); + c2 = ((bytes[1] & 0x0f) << 2) | ((bytes[2] & 0xc0) >> 6); + c3 = bytes[2] & 0x3f; + + buf[0] = table64[c0]; + buf[1] = table64[c1]; + buf[2] = table64[c2]; + buf[3] = table64[c3]; + + os.write(buf, 4); + + bytes += 3; + size -= 3; + ++written; + + if (written >= 76/4 && size) { + os << "\n"; + written = 0; + } + } + + if (size > 0) { + c0 = bytes[0] >> 2; + c1 = ((bytes[0] & 0x03) << 4); + buf[2] = '='; + buf[3] = '='; + + if (size > 1) { + c1 |= ((bytes[1] & 0xf0) >> 4); + c2 = ((bytes[1] & 0x0f) << 2); + if (size > 2) { + c2 |= ((bytes[2] & 0xc0) >> 6); + c3 = bytes[2] & 0x3f; + buf[3] = table64[c3]; + } + buf[2] = table64[c2]; + } + buf[1] = table64[c1]; + buf[0] = table64[c0]; + + os.write(buf, 4); + } + + os << "\""; + } + public: JSONWriter(std::ostream &_os) : os(_os), level(0), - value(false) + value(false), + space(0) { beginObject(); } @@ -155,9 +229,11 @@ public: newline(); os << "}"; value = true; + space = '\n'; } inline void beginMember(const char * name) { + space = 0; separator(); newline(); escapeAsciiString(name); @@ -165,45 +241,96 @@ public: value = false; } + inline void beginMember(const std::string &name) { + beginMember(name.c_str()); + } + inline void endMember(void) { assert(value); value = true; + space = 0; } inline void beginArray() { separator(); os << "["; + ++level; value = false; + space = 0; } inline void endArray(void) { + --level; + if (space == '\n') { + newline(); + } os << "]"; value = true; + space = '\n'; } inline void writeString(const char *s) { separator(); escapeUnicodeString(s); value = true; + space = ' '; + } + + inline void writeString(const std::string &s) { + writeString(s.c_str()); + } + + inline void writeBase64(const void *bytes, size_t size) { + separator(); + encodeBase64String((const unsigned char *)bytes, size); + value = true; + space = ' '; } inline void writeNull(void) { separator(); os << "null"; value = true; + space = ' '; } inline void writeBool(bool b) { separator(); os << (b ? "true" : "false"); value = true; + space = ' '; } template - void writeNumber(T n) { - separator(); - os << std::dec << n; - value = true; + inline void writeNumber(T n) { + if (n != n) { + // NaN + writeNull(); + } else { + separator(); + os << std::dec << std::setprecision(9) << n; + value = true; + space = ' '; + } + } + + inline void writeStringMember(const char *name, const char *s) { + beginMember(name); + writeString(s); + endMember(); + } + + inline void writeBoolMember(const char *name, bool b) { + beginMember(name); + writeBool(b); + endMember(); + } + + template + inline void writeNumberMember(const char *name, T n) { + beginMember(name); + writeNumber(n); + endMember(); } };