1 /**
2     JSON Writer
3 
4     Copyright: 
5         Copyright © 2020-2026, Inochi2D Project
6     
7     License:
8         $(LINK2 https://github.com/Inochi2D/inochi2d/blob/main/LICENSE, BSD 2-clause License)
9     
10     Authors:
11         Luna Nielsen
12 */
13 module inp.format.json.writer;
14 import inp.format.node;
15 import nulib.io.stream;
16 import nulib.io.stream.rw;
17 import nulib.math;
18 import numem;
19 
20 @nogc:
21 
22 /**
23     Writes $(D DataNode) to stream as JSON.
24 
25     Params:
26         stream =    The stream to write to
27         node =      The node to write.
28 */
29 void writeJson(Stream stream, ref DataNode node) {
30     scope StreamWriter writer = new StreamWriter(stream);
31     writer.writeJsonImpl(node);
32 }
33 
34 
35 
36 
37 //
38 //              IMPLEMENTATION DETAILS
39 //
40 private:
41 
42 void writeJsonString(StreamWriter writer, string text) {
43     writer.writeLE('"');
44     foreach(char c; text) {
45         if (c == '"') {
46             writer.writeLE('\\');
47             writer.writeLE('"');
48             continue;
49         }
50 
51         writer.writeLE!ubyte(c);
52     }
53     writer.writeLE('"');
54 }
55 
56 void writeJsonImpl()(StreamWriter writer, auto ref DataNode node) {
57     import nulib.conv : to;
58     final switch(node.type) {
59         case DataNodeType.undefined:
60             return;
61         
62         case DataNodeType.blob_:
63             return;
64         
65         case DataNodeType.boolean_:
66             writer.writeUTF8(node.tryCoerce!bool ? "true" : "false");
67             return;
68         
69         case DataNodeType.int_:
70             auto v = to!string(node.tryCoerce!int);
71             writer.writeUTF8(v[]);
72             return;
73 
74         case DataNodeType.uint_:
75             auto v = to!string(node.tryCoerce!uint);
76             writer.writeUTF8(v[]);
77             return;
78 
79         case DataNodeType.float_:
80             auto v = to!string(node.tryCoerce!float);
81             writer.writeUTF8(v[]);
82             return;
83         
84         case DataNodeType.string_:
85             writer.writeJsonString(node.text);
86             return;
87         
88         case DataNodeType.array_:
89             writer.writeLE('[');
90             foreach(i, ref n; node.array) {
91                 writer.writeJsonImpl(n);
92                 if (i+1 < node.length)
93                     writer.writeLE(',');
94             }
95             writer.writeLE(']');
96             return;
97         
98         case DataNodeType.object_:
99             writer.writeLE('{');
100             foreach(i, key, ref value; node.object) {
101 
102                 writer.writeJsonString(key);
103                 writer.writeLE(':');
104                 writer.writeJsonImpl(value);
105 
106                 if (i+1 < node.length)
107                     writer.writeLE(',');
108             }
109             writer.writeLE('}');
110             return;
111     }
112 }