summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-05-31 20:18:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-05-31 20:18:12 -0700
commit59beb217e76f3518ad35ea1d51b36452cf5723fd (patch)
tree3c3131edd6e6a0d3e363bd69f2564df90ccfcb1f /lib.c
parentfdb8f90b22f8d4993b5937d55f5cbffc45ae940c (diff)
downloadtxr-59beb217e76f3518ad35ea1d51b36452cf5723fd.tar.gz
txr-59beb217e76f3518ad35ea1d51b36452cf5723fd.tar.bz2
txr-59beb217e76f3518ad35ea1d51b36452cf5723fd.zip
json: fix circular printing.
The recursive JSON printer must check for the circularity circularity-related conditions and emit #n= and #n# notations. * lib.c (circle_print_eligible): Function moved before out_json_rec to avoid a forward declaration. (check_emit_circle): New static function. This is a block of code for doing the circular logic, taken out of obj_print_impl, because we would like to use it in out_json_rec. (out_json_rec): Call check_emit_circle to emit any #n= or #n# notation. The function returns 1 if it has emitted #n#, in which a se we are done. (obj_print_impl): Replace moved block of code with call to check_emit_circle.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/lib.c b/lib.c
index 26966cbb..1989bf0c 100644
--- a/lib.c
+++ b/lib.c
@@ -12625,8 +12625,40 @@ static void out_json_str(val str, val out)
put_char(chr('"'), out);
}
+INLINE int circle_print_eligible(val obj)
+{
+ return is_ptr(obj) && (!symbolp(obj) || !symbol_package(obj));
+}
+
+static int check_emit_circle(val obj, val out, struct strm_ctx *ctx, val self)
+{
+ if (ctx->obj_hash && circle_print_eligible(obj)) {
+ loc pcdr = gethash_l(self, ctx->obj_hash, obj, nulloc);
+ val label = deref(pcdr);
+
+ if (label == t) {
+ val counter = succ(ctx->counter);
+ ctx->counter = counter;
+ set(pcdr, counter);
+ format(out, lit("#~s="), counter, nao);
+ } else if (integerp(label)) {
+ format(out, lit("#~s#"), label, nao);
+ return 1;
+ } else if (!label) {
+ set(pcdr, colon_k);
+ }
+ }
+
+ return 0;
+}
+
static void out_json_rec(val obj, val out, struct strm_ctx *ctx)
{
+ val self = lit("print");
+
+ if (ctx && check_emit_circle(obj, out, ctx, self))
+ return;
+
switch (type(obj)) {
case NIL:
put_string(lit("false"), out);
@@ -12786,11 +12818,6 @@ static void out_json(val op, val obj, val out, struct strm_ctx *ctx)
set_indent_mode(out, save_mode);
}
-INLINE int circle_print_eligible(val obj)
-{
- return is_ptr(obj) && (!symbolp(obj) || !symbol_package(obj));
-}
-
static int unquote_star_check(val obj, val pretty)
{
if (!obj || !symbolp(obj))
@@ -12806,22 +12833,8 @@ val obj_print_impl(val obj, val out, val pretty, struct strm_ctx *ctx)
val ret = obj;
cnum save_depth = ctx->depth;
- if (ctx->obj_hash && circle_print_eligible(obj)) {
- loc pcdr = gethash_l(self, ctx->obj_hash, obj, nulloc);
- val label = deref(pcdr);
-
- if (label == t) {
- val counter = succ(ctx->counter);
- ctx->counter = counter;
- set(pcdr, counter);
- format(out, lit("#~s="), counter, nao);
- } else if (integerp(label)) {
- format(out, lit("#~s#"), label, nao);
- return ret;
- } else if (!label) {
- set(pcdr, colon_k);
- }
- }
+ if (check_emit_circle(obj, out, ctx, self))
+ return ret;
if (ctx->strm->max_depth) {
if (ctx->depth > ctx->strm->max_depth) {