#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "jv_alloc.h"
#include "jv.h"
#include "jv_unicode.h"
/*
* Internal refcounting helpers
*/
typedef struct jv_refcnt {
size_t count;
} jv_refcnt;
static void jvp_refcnt_init(jv_nontrivial* c) {
c->ptr->count = 1;
}
static void jvp_refcnt_inc(jv_nontrivial* c) {
c->ptr->count++;
}
static int jvp_refcnt_dec(jv_nontrivial* c) {
c->ptr->count--;
return c->ptr->count == 0;
}
static int jvp_refcnt_unshared(jv_nontrivial* c) {
assert(c->ptr->count > 0);
return c->ptr->count == 1;
}
/*
* Simple values (true, false, null)
*/
jv_kind jv_get_kind(jv x) {
return x.kind;
}
const char* jv_kind_name(jv_kind k) {
switch (k) {
case JV_KIND_INVALID: return "<invalid>";
case JV_KIND_NULL: return "null";
case JV_KIND_FALSE: return "boolean";
case JV_KIND_TRUE: return "boolean";
case JV_KIND_NUMBER: return "number";
case JV_KIND_STRING: return "string";
case JV_KIND_ARRAY: return "array";
case JV_KIND_OBJECT: return "object";
}
assert(0 && "invalid kind");
return "<unknown>";
}
static const jv JV_NULL = {JV_KIND_NULL, {0}};
static const jv JV_FALSE = {JV_KIND_FALSE, {0}};
static const jv JV_TRUE = {JV_KIND_TRUE, {0}};
jv jv_true() {
return JV_TRUE;
}
jv jv_false() {
return JV_FALSE;
}
jv jv_null() {
return JV_NULL;
}
jv jv_bool(int x) {
return x ? JV_TRUE : JV_FALSE;
}
/*
* Invalid objects, with optional error messages
*/
typedef struct {
jv_refcnt refcnt;
jv errmsg;
} jvp_invalid;
jv jv_invalid_with_msg(jv err) {
jv x;
x.kind = JV_KIND_INVALID;
x.val.nontrivial.i[0] = x.val.nontrivial.i[1] = 0;
jvp_invalid*