diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-05-31 20:18:12 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-05-31 20:18:12 -0700 |
commit | 59beb217e76f3518ad35ea1d51b36452cf5723fd (patch) | |
tree | 3c3131edd6e6a0d3e363bd69f2564df90ccfcb1f /lib.c | |
parent | fdb8f90b22f8d4993b5937d55f5cbffc45ae940c (diff) | |
download | txr-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.c | 55 |
1 files changed, 34 insertions, 21 deletions
@@ -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) { |