1 /**
2  * Interface for writing `rpdl.tree.RpdlTree` to the external files
3  *
4  * Copyright: © 2017 Andrey Kabylin
5  * License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6  */
7 module rpdl.writer;
8 
9 import std.file;
10 import std.stdio;
11 import std.conv;
12 
13 import rpdl.node;
14 import rpdl.value;
15 import rpdl.exception;
16 
17 /// Declare interface for writers and tell them - how to write each type of node to file.
18 interface IWriter {
19     void writeObject(ObjectNode object);
20     void writeParameter(Parameter parameter);
21     void writeValue(Value value);
22     void writeNumberValue(NumberValue value);
23     void writeBooleanValue(BooleanValue value);
24     void writeStringValue(StringValue value);
25     void writeIdentifierValue(IdentifierValue value);
26     void writeArrayValue(ArrayValue array);
27 }
28 
29 /**
30  * Default IWriter implementation
31  */
32 abstract class Writer : IWriter {
33     /**
34      * Write `root` node and it children to file
35      */
36     this(Node root) {
37         this.root = root;
38     }
39 
40     void save(in string fileName) {
41         this.file = File(fileName, "w");
42 
43         foreach (Node node; root.children) {
44             writeObject(cast(ObjectNode) node);
45         }
46     }
47 
48 protected:
49     Node root;
50     File file;
51 
52     void rawWrite(in ubyte ch) {
53         file.rawWrite([ch]);
54     }
55 
56     void rawWrite(in bool value) {
57         file.rawWrite([value]);
58     }
59 
60     void rawWrite(in int value) {
61         file.rawWrite([value]);
62     }
63 
64     void rawWrite(in float value) {
65         file.rawWrite([value]);
66     }
67 
68     void rawWrite(in string str) {
69         file.rawWrite(str);
70     }
71 
72     override void writeObject(ObjectNode object) {
73         foreach (Node child; object.children) {
74             if (cast(Parameter) child) {
75                 writeParameter(cast(Parameter) child);
76             } else if (cast(ObjectNode) child) {
77                 writeObject(cast(ObjectNode) child);
78             } else {
79                 throw new WrongNodeType("Should be Value or Parameter");
80             }
81         }
82     }
83 
84     override void writeParameter(Parameter parameter) {
85         foreach (Node child; parameter.children) {
86             if (cast(Value) child) {
87                 writeValue(cast(Value) child);
88             } else {
89                 throw new WrongNodeType("Should be Value");
90             }
91         }
92     }
93 
94     override void writeValue(Value value) {
95         switch (value.type) {
96             case Value.Type.Number:
97                 writeNumberValue(cast(NumberValue) value);
98                 break;
99 
100             case Value.Type.Boolean:
101                 writeBooleanValue(cast(BooleanValue) value);
102                 break;
103 
104             case Value.Type.Identifier:
105                 writeIdentifierValue(cast(IdentifierValue) value);
106                 break;
107 
108             case Value.Type.String:
109                 writeStringValue(cast(StringValue) value);
110                 break;
111 
112             case Value.Type.Array:
113                 writeArrayValue(cast(ArrayValue) value);
114                 break;
115 
116             default:
117                 throw new WrongNodeType();
118         }
119     }
120 
121     override void writeNumberValue(NumberValue value) {}
122 
123     override void writeBooleanValue(BooleanValue value) {}
124 
125     override void writeStringValue(StringValue value) {}
126 
127     override void writeIdentifierValue(IdentifierValue value) {}
128 
129     override void writeArrayValue(ArrayValue array) {
130         foreach (Node node; array.children)
131             writeValue(cast(Value) node);
132     }
133 }