summaryrefslogtreecommitdiff
path: root/encoding/json/dump.ha
blob: 7e7dd8dc57a1de349208acfa0fe5bb46a3933b72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// License: MPL-2.0
// (c) 2022 Sebastian <sebastian@sebsite.pw>
use fmt;
use io;
use strings;
use memio;

// Dumps a [[value]] into an [[io::handle]] as a string without any additional
// formatting.
export fn dump(out: io::handle, val: value) (size | io::error) = {
	let z = 0z;
	match (val) {
	case let v: (f64 | bool) =>
		z += fmt::fprint(out, v)?;
	case let s: str =>
		z += fmt::fprint(out, `"`)?;
		let it = strings::iter(s);
		for (const r => strings::next(&it)) {
			switch (r) {
			case '\b' =>
				z += fmt::fprint(out, `\b`)?;
			case '\f' =>
				z += fmt::fprint(out, `\f`)?;
			case '\n' =>
				z += fmt::fprint(out, `\n`)?;
			case '\r' =>
				z += fmt::fprint(out, `\r`)?;
			case '\t' =>
				z += fmt::fprint(out, `\t`)?;
			case '\"' =>
				z += fmt::fprint(out, `\"`)?;
			case '\\' =>
				z += fmt::fprint(out, `\\`)?;
			case =>
				if (iscntrl(r)) {
					z += fmt::fprintf(out, `\u{:.4x}`,
						r: u32)?;
				} else {
					z += fmt::fprint(out, r)?;
				};
			};
		};
		z += fmt::fprint(out, `"`)?;
	case _null =>
		z += fmt::fprint(out, "null")?;
	case let a: []value =>
		z += fmt::fprint(out, "[")?;
		for (let i = 0z; i < len(a); i += 1) {
			z += dump(out, a[i])?;
			if (i < len(a) - 1) {
				z += fmt::fprint(out, ",")?;
			};
		};
		z += fmt::fprint(out, "]")?;
	case let o: object =>
		z += fmt::fprint(out, "{")?;
		let comma = false;
		let it = iter(&o);
		for (true) match (next(&it)) {
		case void => break;
		case let pair: (const str, const *value) =>
			if (comma) {
				z += fmt::fprint(out, ",")?;
			};
			comma = true;
			z += dump(out, pair.0)?;
			z += fmt::fprint(out, ":")?;
			z += dump(out, *pair.1)?;
		};
		z += fmt::fprint(out, "}")?;
	};
	return z;
};

// Dumps a [[value]] into a string without any additional formatting. The caller
// must free the return value.
export fn dumpstr(val: value) str = {
	let s = memio::dynamic();
	dump(&s, val)!;
	return memio::string(&s)!;
};