summaryrefslogtreecommitdiffstats
path: root/c/jv.c
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2012-09-10 15:04:19 +0100
committerStephen Dolan <mu@netsoc.tcd.ie>2012-09-10 15:04:19 +0100
commit649cac791a1c7046b4441fe63526af5ca20825ff (patch)
tree5cad9dd4c7b675daf9439750e02fda785e2ff666 /c/jv.c
parent5c25c906576692c1d08e02e4a5fc0c5dca3a5f96 (diff)
Make jv_invalid() first-class values capable of holding an error.
Diffstat (limited to 'c/jv.c')
-rw-r--r--c/jv.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/c/jv.c b/c/jv.c
index 35ade789..be50c6f6 100644
--- a/c/jv.c
+++ b/c/jv.c
@@ -37,15 +37,10 @@ jv_kind jv_get_kind(jv x) {
return x.kind;
}
-static const jv JV_INVALID = {JV_KIND_INVALID, {0}};
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_invalid() {
- return JV_INVALID;
-}
-
jv jv_true() {
return JV_TRUE;
}
@@ -63,6 +58,43 @@ jv jv_bool(int x) {
}
/*
+ * 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.complex.i[0] = x.val.complex.i[1] = 0;
+ jvp_invalid* i = malloc(sizeof(jvp_invalid));
+ x.val.complex.ptr = &i->refcnt;
+ i->refcnt.count = 1;
+ i->errmsg = err;
+ return x;
+}
+
+jv jv_invalid() {
+ return jv_invalid_with_msg(jv_null());
+}
+
+jv jv_invalid_get_message(jv inv) {
+ jv x = ((jvp_invalid*)inv.val.complex.ptr)->errmsg;
+ jv_free(inv);
+ return x;
+}
+
+static void jvp_invalid_free(jv_complex* x) {
+ if (jvp_refcnt_dec(x)) {
+ jv_free(((jvp_invalid*)x->ptr)->errmsg);
+ free(x->ptr);
+ }
+}
+
+/*
* Numbers
*/
@@ -789,7 +821,8 @@ jv jv_object_iter_value(jv object, int iter) {
jv jv_copy(jv j) {
if (jv_get_kind(j) == JV_KIND_ARRAY ||
jv_get_kind(j) == JV_KIND_STRING ||
- jv_get_kind(j) == JV_KIND_OBJECT) {
+ jv_get_kind(j) == JV_KIND_OBJECT ||
+ jv_get_kind(j) == JV_KIND_INVALID) {
jvp_refcnt_inc(&j.val.complex);
}
return j;
@@ -802,6 +835,8 @@ void jv_free(jv j) {
jvp_string_free(&j.val.complex);
} else if (jv_get_kind(j) == JV_KIND_OBJECT) {
jvp_object_free(&j.val.complex);
+ } else if (jv_get_kind(j) == JV_KIND_INVALID) {
+ jvp_invalid_free(&j.val.complex);
}
}