-// 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);