--- /dev/null
+// https://github.com/vivkin/gason - pulled January 10, 2016
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+
+enum JsonTag {
+ JSON_NUMBER = 0,
+ JSON_STRING,
+ JSON_ARRAY,
+ JSON_OBJECT,
+ JSON_TRUE,
+ JSON_FALSE,
+ JSON_NULL = 0xF
+};
+
+struct JsonNode;
+
+#define JSON_VALUE_PAYLOAD_MASK 0x00007FFFFFFFFFFFULL
+#define JSON_VALUE_NAN_MASK 0x7FF8000000000000ULL
+#define JSON_VALUE_TAG_MASK 0xF
+#define JSON_VALUE_TAG_SHIFT 47
+
+union JsonValue {
+ uint64_t ival;
+ double fval;
+
+ JsonValue(double x)
+ : fval(x) {
+ }
+ JsonValue(JsonTag tag = JSON_NULL, void *payload = nullptr) {
+ assert((uintptr_t)payload <= JSON_VALUE_PAYLOAD_MASK);
+ ival = JSON_VALUE_NAN_MASK | ((uint64_t)tag << JSON_VALUE_TAG_SHIFT) | (uintptr_t)payload;
+ }
+ bool isDouble() const {
+ return (int64_t)ival <= (int64_t)JSON_VALUE_NAN_MASK;
+ }
+ JsonTag getTag() const {
+ return isDouble() ? JSON_NUMBER : JsonTag((ival >> JSON_VALUE_TAG_SHIFT) & JSON_VALUE_TAG_MASK);
+ }
+ uint64_t getPayload() const {
+ assert(!isDouble());
+ return ival & JSON_VALUE_PAYLOAD_MASK;
+ }
+ double toNumber() const {
+ assert(getTag() == JSON_NUMBER);
+ return fval;
+ }
+ char *toString() const {
+ assert(getTag() == JSON_STRING);
+ return (char *)getPayload();
+ }
+ JsonNode *toNode() const {
+ assert(getTag() == JSON_ARRAY || getTag() == JSON_OBJECT);
+ return (JsonNode *)getPayload();
+ }
+};
+
+struct JsonNode {
+ JsonValue value;
+ JsonNode *next;
+ char *key;
+};
+
+struct JsonIterator {
+ JsonNode *p;
+
+ void operator++() {
+ p = p->next;
+ }
+ bool operator!=(const JsonIterator &x) const {
+ return p != x.p;
+ }
+ JsonNode *operator*() const {
+ return p;
+ }
+ JsonNode *operator->() const {
+ return p;
+ }
+};
+
+inline JsonIterator begin(JsonValue o) {
+ return JsonIterator{o.toNode()};
+}
+inline JsonIterator end(JsonValue) {
+ return JsonIterator{nullptr};
+}
+
+#define JSON_ERRNO_MAP(XX) \
+ XX(OK, "ok") \
+ XX(BAD_NUMBER, "bad number") \
+ XX(BAD_STRING, "bad string") \
+ XX(BAD_IDENTIFIER, "bad identifier") \
+ XX(STACK_OVERFLOW, "stack overflow") \
+ XX(STACK_UNDERFLOW, "stack underflow") \
+ XX(MISMATCH_BRACKET, "mismatch bracket") \
+ XX(UNEXPECTED_CHARACTER, "unexpected character") \
+ XX(UNQUOTED_KEY, "unquoted key") \
+ XX(BREAKING_BAD, "breaking bad") \
+ XX(ALLOCATION_FAILURE, "allocation failure")
+
+enum JsonErrno {
+#define XX(no, str) JSON_##no,
+ JSON_ERRNO_MAP(XX)
+#undef XX
+};
+
+const char *jsonStrError(int err);
+
+class JsonAllocator {
+ struct Zone {
+ Zone *next;
+ size_t used;
+ } *head = nullptr;
+
+public:
+ JsonAllocator() = default;
+ JsonAllocator(const JsonAllocator &) = delete;
+ JsonAllocator &operator=(const JsonAllocator &) = delete;
+ JsonAllocator(JsonAllocator &&x) : head(x.head) {
+ x.head = nullptr;
+ }
+ JsonAllocator &operator=(JsonAllocator &&x) {
+ head = x.head;
+ x.head = nullptr;
+ return *this;
+ }
+ ~JsonAllocator() {
+ deallocate();
+ }
+ void *allocate(size_t size);
+ void deallocate();
+};
+
+int jsonParse(char *str, char **endptr, JsonValue *value, JsonAllocator &allocator);