##// END OF EJS Templates
fixed JSON writer
cin -
r141:0fa293bb1351 v2
parent child
Show More
@@ -1,11 +1,8
1 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 2
6 3 namespace Implab {
7 4 public interface ICancellable {
8 5 void Cancel();
9 6 void Cancel(Exception reason);
10 7 }
11 8 }
@@ -1,16 +1,17
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Threading.Tasks;
6 6
7 7 namespace Implab.JSON {
8 8 /// <summary>
9 9 /// internal
10 10 /// </summary>
11 11 public enum JSONElementContext {
12 12 None,
13 13 Object,
14 Array
14 Array,
15 Closed
15 16 }
16 17 }
@@ -1,251 +1,273
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.IO;
4 4
5 5 namespace Implab.JSON {
6 6 public class JSONWriter {
7 7 struct Context {
8 8 public bool needComma;
9 9 public JSONElementContext element;
10 10 }
11 11 Stack<Context> m_contextStack = new Stack<Context>();
12 12 Context m_context;
13 13
14 14 TextWriter m_writer;
15 15 readonly bool m_indent = true;
16 16 readonly int m_indentSize = 4;
17 17
18 18 static readonly char [] _escapeBKS,
19 19 _escapeFWD,
20 20 _escapeCR,
21 21 _escapeNL,
22 22 _escapeTAB,
23 23 _escapeBSLASH,
24 24 _escapeQ;
25 25
26 26 static JSONWriter() {
27 27 _escapeBKS = "\\b".ToCharArray();
28 28 _escapeFWD = "\\f".ToCharArray();
29 29 _escapeCR = "\\r".ToCharArray();
30 30 _escapeNL = "\\n".ToCharArray();
31 31 _escapeTAB = "\\t".ToCharArray();
32 32 _escapeBSLASH = "\\\\".ToCharArray();
33 33 _escapeQ = "\\\"".ToCharArray();
34 34 }
35 35
36 36 public JSONWriter(TextWriter writer) {
37 37 Safe.ArgumentNotNull(writer, "writer");
38 38
39 39 m_writer = writer;
40 40 }
41 41
42 42 public JSONWriter(TextWriter writer, bool indent) {
43 43 Safe.ArgumentNotNull(writer, "writer");
44 44
45 45 m_writer = writer;
46 46 m_indent = indent;
47 47 }
48 48
49 49 void WriteIndent() {
50 50 if (m_indent) {
51 51 var indent = new char[m_contextStack.Count * m_indentSize + 1];
52 52 indent[0] = '\n';
53 53 for (int i = 1; i < indent.Length; i++)
54 54 indent[i] = ' ';
55 55 m_writer.Write(new String(indent));
56 56 } else {
57 57 m_writer.Write(' ');
58 58 }
59 59 }
60 60
61 61 void WriteMemberName(string name) {
62 62 Safe.ArgumentNotEmpty(name, "name");
63 63 if (m_context.element != JSONElementContext.Object)
64 64 OperationNotApplicable("WriteMember");
65 65 if (m_context.needComma)
66 66 m_writer.Write(",");
67 67
68 68 WriteIndent();
69 69 m_context.needComma = true;
70 70 Write(name);
71 71 m_writer.Write(" : ");
72 72 }
73 73
74 74 public void WriteValue(string name, string value) {
75 75 WriteMemberName(name);
76 76 Write(value);
77 77 }
78 78
79 79 public void WriteValue(string name, bool value) {
80 80 WriteMemberName(name);
81 81 Write(value);
82 82 }
83 83
84 84 public void WriteValue(string name, double value) {
85 85 WriteMemberName(name);
86 86 Write(value);
87 87 }
88 88
89 89 public void WriteValue(string value) {
90 if (m_context.element != JSONElementContext.Array)
91 OperationNotApplicable("WriteValue");
90 if (m_context.element == JSONElementContext.Array) {
91
92 92 if (m_context.needComma)
93 93 m_writer.Write(",");
94 94 WriteIndent();
95 95 m_context.needComma = true;
96 96
97 97 Write(value);
98 } else if (m_context.element == JSONElementContext.None) {
99 Write(value);
100 m_context.element = JSONElementContext.Closed;
101 } else {
102 OperationNotApplicable("WriteValue");
103 }
98 104 }
99 105
100 106 public void WriteValue(bool value) {
101 if (m_context.element != JSONElementContext.Array)
102 OperationNotApplicable("WriteValue");
107 if (m_context.element == JSONElementContext.Array) {
108
103 109 if (m_context.needComma)
104 110 m_writer.Write(",");
111 WriteIndent();
105 112 m_context.needComma = true;
106 113
107 WriteIndent();
114 Write(value);
115 } else if (m_context.element == JSONElementContext.None) {
108 116 Write(value);
117 m_context.element = JSONElementContext.Closed;
118 } else {
119 OperationNotApplicable("WriteValue");
120 }
109 121 }
110 122
111 123 public void WriteValue(double value) {
112 if (m_context.element != JSONElementContext.Array)
113 OperationNotApplicable("WriteValue");
124 if (m_context.element == JSONElementContext.Array) {
125
114 126 if (m_context.needComma)
115 127 m_writer.Write(",");
128 WriteIndent();
116 129 m_context.needComma = true;
117 130
118 WriteIndent();
131 Write(value);
132 } else if (m_context.element == JSONElementContext.None) {
119 133 Write(value);
134 m_context.element = JSONElementContext.Closed;
135 } else {
136 OperationNotApplicable("WriteValue");
137 }
120 138 }
121 139
122 140 public void BeginObject() {
123 141 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
124 142 OperationNotApplicable("BeginObject");
125 143 if (m_context.needComma)
126 144 m_writer.Write(",");
127 145
128 146 WriteIndent();
129 147
130 148 m_context.needComma = true;
131 149
132 150 m_contextStack.Push(m_context);
133 151
134 152 m_context = new Context { element = JSONElementContext.Object, needComma = false };
135 153 m_writer.Write("{");
136 154 }
137 155
138 156 public void BeginObject(string name) {
139 157 WriteMemberName(name);
140 158
141 159 m_contextStack.Push(m_context);
142 160
143 161 m_context = new Context { element = JSONElementContext.Object, needComma = false };
144 162 m_writer.Write("{");
145 163 }
146 164
147 165 public void EndObject() {
148 166 if (m_context.element != JSONElementContext.Object)
149 OperationNotApplicable("EndArray");
167 OperationNotApplicable("EndObject");
150 168
151 169 m_context = m_contextStack.Pop();
170 if (m_contextStack.Count == 0)
171 m_context.element = JSONElementContext.Closed;
152 172 WriteIndent();
153 173 m_writer.Write("}");
154 174 }
155 175
156 176 public void BeginArray() {
157 177 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
158 178 throw new InvalidOperationException();
159 179 if (m_context.needComma) {
160 180 m_writer.Write(",");
161 181
162 182 }
163 183 m_context.needComma = true;
164 184
165 185 WriteIndent();
166 186 m_contextStack.Push(m_context);
167 187 m_context = new Context { element = JSONElementContext.Array, needComma = false };
168 188 m_writer.Write("[");
169 189 }
170 190
171 191 public void BeginArray(string name) {
172 192 WriteMemberName(name);
173 193
174 194 m_contextStack.Push(m_context);
175 195
176 196 m_context = new Context { element = JSONElementContext.Array, needComma = false };
177 197 m_writer.Write("[");
178 198 }
179 199
180 200 public void EndArray() {
181 201 if (m_context.element != JSONElementContext.Array)
182 202 OperationNotApplicable("EndArray");
183 203
184 204 m_context = m_contextStack.Pop();
205 if (m_contextStack.Count == 0)
206 m_context.element = JSONElementContext.Closed;
185 207 WriteIndent();
186 208 m_writer.Write("]");
187 209 }
188 210
189 211 void Write(bool value) {
190 212 m_writer.Write(value ? "true" : "false");
191 213 }
192 214
193 215
194 216 void Write(string value) {
195 217 if (value == null) {
196 218 m_writer.Write("null");
197 219 return;
198 220 }
199 221
200 222 var chars = value.ToCharArray();
201 223 m_writer.Write('"');
202 224
203 225 // Analysis disable once ForCanBeConvertedToForeach
204 226 for (int i = 0; i < chars.Length; i++) {
205 227 var ch = chars[i];
206 228
207 229 switch (ch) {
208 230 case '\b':
209 231 m_writer.Write(_escapeBKS);
210 232 break;
211 233 case '\f':
212 234 m_writer.Write(_escapeFWD);
213 235 break;
214 236 case '\r':
215 237 m_writer.Write(_escapeCR);
216 238 break;
217 239 case '\n':
218 240 m_writer.Write(_escapeNL);
219 241 break;
220 242 case '\t':
221 243 m_writer.Write(_escapeTAB);
222 244 break;
223 245 case '\\':
224 246 m_writer.Write(_escapeBSLASH);
225 247 break;
226 248 case '"':
227 249 m_writer.Write(_escapeQ);
228 250 break;
229 251 default:
230 252 if (ch < 0x20) {
231 253 m_writer.Write("\\u00{0:x2}",(int)ch);
232 254 } else {
233 255 m_writer.Write(ch);
234 256 }
235 257 break;
236 258 }
237 259 }
238 260
239 261 m_writer.Write('"');
240 262 }
241 263
242 264 void Write(double value) {
243 265 m_writer.Write(value);
244 266 }
245 267
246 268 void OperationNotApplicable(string opName) {
247 269 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
248 270 }
249 271
250 272 }
251 273 }
General Comments 0
You need to be logged in to leave comments. Login now