X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=retrace%2Fjson.hpp;h=2c555dbb1e906bd361b73732a50e9dae6c23796a;hb=7a9fb5103e052150232b64cb5d99374cda3f1234;hp=2f50a8c55aedc28fccad91c1493031289113cc2b;hpb=c748fbcb434374ec13e14cc837ade7c581789e0c;p=apitrace diff --git a/retrace/json.hpp b/retrace/json.hpp index 2f50a8c..2c555db 100644 --- a/retrace/json.hpp +++ b/retrace/json.hpp @@ -24,21 +24,21 @@ **************************************************************************/ /* - * Trace writing functions. + * JSON writing functions. */ #ifndef _JSON_HPP_ #define _JSON_HPP_ -#include #include #include #ifdef _MSC_VER # include # define isfinite _finite +# define isnan _isnan #else -# include // isfinite +# include // isfinite, isnan #endif #include @@ -47,6 +47,11 @@ #include +namespace image { + class Image; +} + + class JSONWriter { private: @@ -56,277 +61,71 @@ private: bool value; char space; - void newline(void) { - os << "\n"; - for (int i = 0; i < level; ++i) - os << " "; - } - - void separator(void) { - if (value) { - os << ","; - switch (space) { - case '\0': - break; - case '\n': - newline(); - break; - default: - os << space; - break; - } - } else { - if (space == '\n') { - newline(); - } - } - } - - void escapeAsciiString(const char *str) { - os << "\""; - - const unsigned char *src = (const unsigned char *)str; - unsigned char c; - while ((c = *src++)) { - if ((c == '\"') || - (c == '\\')) { - // escape character - os << '\\' << (unsigned char)c; - } else if ((c >= 0x20 && c <= 0x7e) || - c == '\t' || - c == '\r' || - c == '\n') { - // pass-through character - os << (unsigned char)c; - } else { - assert(0); - os << "?"; - } - } - - os << "\""; - } - - void escapeUnicodeString(const char *str) { - os << "\""; - - const char *locale = setlocale(LC_CTYPE, ""); - const char *src = str; - mbstate_t state; - - memset(&state, 0, sizeof state); - - do { - // Convert characters one at a time in order to recover from - // conversion errors - wchar_t c; - size_t written = mbsrtowcs(&c, &src, 1, &state); - if (written == 0) { - // completed - break; - } if (written == (size_t)-1) { - // conversion error -- skip - os << "?"; - do { - ++src; - } while (*src & 0x80); - } else if ((c == '\"') || - (c == '\\')) { - // escape character - os << '\\' << (unsigned char)c; - } else if ((c >= 0x20 && c <= 0x7e) || - c == '\t' || - c == '\r' || - c == '\n') { - // pass-through character - os << (unsigned char)c; - } else { - // unicode - os << "\\u" << std::setfill('0') << std::hex << std::setw(4) << (unsigned)c; - os << std::dec; - } - } while (src); - - setlocale(LC_CTYPE, locale); - - 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; + void + newline(void); - 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 << "\""; - } + void + separator(void); public: - JSONWriter(std::ostream &_os) : - os(_os), - level(0), - value(false), - space(0) - { - beginObject(); - } + JSONWriter(std::ostream &_os); - ~JSONWriter() { - endObject(); - newline(); - } + ~JSONWriter(); - inline void beginObject() { - separator(); - os << "{"; - ++level; - value = false; - } + void + beginObject(); - inline void endObject() { - --level; - if (value) - newline(); - os << "}"; - value = true; - space = '\n'; - } + void + endObject(); - inline void beginMember(const char * name) { - space = 0; - separator(); - newline(); - escapeAsciiString(name); - os << ": "; - value = false; - } + void + beginMember(const char * name); - inline void beginMember(const std::string &name) { + 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; - } + void + endMember(void); - inline void endArray(void) { - --level; - if (space == '\n') { - newline(); - } - os << "]"; - value = true; - space = '\n'; - } + void + beginArray(); - inline void writeString(const char *s) { - if (!s) { - writeNull(); - return; - } + void + endArray(void); - separator(); - escapeUnicodeString(s); - value = true; - space = ' '; - } + void + writeString(const char *s); - inline void writeString(const std::string &s) { + 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 = ' '; - } + void + writeBase64(const void *bytes, size_t size); - inline void writeNull(void) { - separator(); - os << "null"; - value = true; - space = ' '; - } - - inline void writeBool(bool b) { - separator(); - os << (b ? "true" : "false"); - value = true; - space = ' '; - } + void + writeNull(void); + void + writeBool(bool b); /** * Special case for char to prevent it to be written as a literal * character. */ - inline void writeNumber(char n) { + inline void + writeInt(signed char n) { separator(); os << std::dec << static_cast(n); value = true; space = ' '; } - inline void writeNumber(unsigned char n) { + inline void + writeInt(unsigned char n) { separator(); os << std::dec << static_cast(n); value = true; @@ -334,36 +133,58 @@ public: } template - inline void writeNumber(T n) { - if (!isfinite(n)) { - // NaN/Inf - writeNull(); + inline void + writeInt(T n) { + separator(); + os << std::dec << n; + value = true; + space = ' '; + } + + template + void + writeFloat(T n) { + separator(); + if (isnan(n)) { + // NaN is non-standard but widely supported + os << "NaN"; + } else if (!isfinite(n)) { + // Infinite is non-standard but widely supported + if (n < 0) { + os << '-'; + } + os << "Infinity"; } else { - separator(); os << std::dec << std::setprecision(std::numeric_limits::digits10 + 1) << n; - value = true; - space = ' '; } + value = true; + space = ' '; } - inline void writeStringMember(const char *name, const char *s) { + inline void + writeStringMember(const char *name, const char *s) { beginMember(name); writeString(s); endMember(); } - inline void writeBoolMember(const char *name, bool b) { + inline void + writeBoolMember(const char *name, bool b) { beginMember(name); writeBool(b); endMember(); } template - inline void writeNumberMember(const char *name, T n) { + inline void + writeIntMember(const char *name, T n) { beginMember(name); - writeNumber(n); + writeInt(n); endMember(); } + + void + writeImage(image::Image *image, const char *format, unsigned depth = 1); }; #endif /* _JSON_HPP_ */