oguzakif's picture
init repo
d4b77ac
// 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);