X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=json.hpp;h=9e6b96004dc71be9dc96e85a6d4279f508c12765;hb=fb5d8739b40292a30559ac8b2a6727e71519dcd8;hp=7326891fd1f6939d4044b259f61e1ffe314d4687;hpb=2e8febd137df6f4471c2f3a361ae21ee2fb0a6bc;p=apitrace diff --git a/json.hpp b/json.hpp index 7326891..9e6b960 100644 --- a/json.hpp +++ b/json.hpp @@ -34,8 +34,9 @@ #include #include -#include #include +#include +#include class JSONWriter @@ -143,6 +144,63 @@ 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), @@ -183,6 +241,10 @@ public: value = false; } + inline void beginMember(const std::string &name) { + beginMember(name.c_str()); + } + inline void endMember(void) { assert(value); value = true; @@ -214,6 +276,17 @@ public: 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"; @@ -229,11 +302,35 @@ public: } template - void writeNumber(T n) { - separator(); - os << std::dec << n; - value = true; - space = ' '; + 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(); } };