Mercurial > pub > ImplabNet
comparison Implab/JSON/JSONWriter.cs @ 150:3258399cba83 v2
JSONWriter improvements
author | cin |
---|---|
date | Sat, 12 Dec 2015 22:12:44 +0300 |
parents | 2100965eb97f |
children |
comparison
equal
deleted
inserted
replaced
149:eb793fbbe4ea | 150:3258399cba83 |
---|---|
1 using System; | 1 using System; |
2 using System.Collections.Generic; | 2 using System.Collections.Generic; |
3 using System.IO; | 3 using System.IO; |
4 using System.Globalization; | 4 using System.Globalization; |
5 using System.Diagnostics; | |
5 | 6 |
6 namespace Implab.JSON { | 7 namespace Implab.JSON { |
7 public class JSONWriter { | 8 public class JSONWriter { |
8 struct Context { | 9 struct Context { |
9 public bool needComma; | 10 public bool needComma; |
10 public JSONElementContext element; | 11 public JSONElementContext element; |
11 } | 12 } |
12 Stack<Context> m_contextStack = new Stack<Context>(); | 13 Stack<Context> m_contextStack = new Stack<Context>(); |
13 Context m_context; | 14 Context m_context; |
14 | 15 |
16 const int BUFFER_SIZE = 64; | |
17 | |
15 TextWriter m_writer; | 18 TextWriter m_writer; |
16 readonly bool m_indent = true; | 19 readonly bool m_indent = true; |
17 readonly int m_indentSize = 4; | 20 readonly int m_indentSize = 4; |
18 | 21 readonly char[] m_buffer = new char[BUFFER_SIZE]; |
22 int m_bufferPos; | |
23 | |
24 static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | |
19 static readonly char [] _escapeBKS, | 25 static readonly char [] _escapeBKS, |
20 _escapeFWD, | 26 _escapeFWD, |
21 _escapeCR, | 27 _escapeCR, |
22 _escapeNL, | 28 _escapeNL, |
23 _escapeTAB, | 29 _escapeTAB, |
209 } | 215 } |
210 | 216 |
211 void Write(bool value) { | 217 void Write(bool value) { |
212 m_writer.Write(value ? "true" : "false"); | 218 m_writer.Write(value ? "true" : "false"); |
213 } | 219 } |
214 | 220 |
221 void FlushBuffer() { | |
222 if (m_bufferPos > 0) { | |
223 m_writer.Write(m_buffer, 0, m_bufferPos); | |
224 m_bufferPos = 0; | |
225 } | |
226 } | |
215 | 227 |
216 void Write(string value) { | 228 void Write(string value) { |
217 if (value == null) { | 229 if (value == null) { |
218 m_writer.Write("null"); | 230 m_writer.Write("null"); |
219 return; | 231 return; |
220 } | 232 } |
221 | 233 |
234 Debug.Assert(m_bufferPos == 0); | |
235 | |
222 var chars = value.ToCharArray(); | 236 var chars = value.ToCharArray(); |
223 m_writer.Write('"'); | 237 m_buffer[m_bufferPos++] = '"'; |
224 | 238 |
225 // Analysis disable once ForCanBeConvertedToForeach | 239 // Analysis disable once ForCanBeConvertedToForeach |
226 for (int i = 0; i < chars.Length; i++) { | 240 for (int i = 0; i < chars.Length; i++) { |
227 var ch = chars[i]; | 241 var ch = chars[i]; |
228 | 242 |
243 char[] escapeSeq; | |
244 | |
229 switch (ch) { | 245 switch (ch) { |
230 case '\b': | 246 case '\b': |
231 m_writer.Write(_escapeBKS); | 247 escapeSeq = _escapeBKS; |
232 break; | 248 break; |
233 case '\f': | 249 case '\f': |
234 m_writer.Write(_escapeFWD); | 250 escapeSeq = _escapeFWD; |
235 break; | 251 break; |
236 case '\r': | 252 case '\r': |
237 m_writer.Write(_escapeCR); | 253 escapeSeq = _escapeCR; |
238 break; | 254 break; |
239 case '\n': | 255 case '\n': |
240 m_writer.Write(_escapeNL); | 256 escapeSeq = _escapeNL; |
241 break; | 257 break; |
242 case '\t': | 258 case '\t': |
243 m_writer.Write(_escapeTAB); | 259 escapeSeq = _escapeTAB; |
244 break; | 260 break; |
245 case '\\': | 261 case '\\': |
246 m_writer.Write(_escapeBSLASH); | 262 escapeSeq = _escapeBSLASH; |
247 break; | 263 break; |
248 case '"': | 264 case '"': |
249 m_writer.Write(_escapeQ); | 265 escapeSeq = _escapeQ; |
250 break; | 266 break; |
251 default: | 267 default: |
252 if (ch < 0x20) { | 268 if (ch < 0x20) { |
253 m_writer.Write("\\u00{0:x2}",(int)ch); | 269 if (m_bufferPos + 6 > BUFFER_SIZE) |
270 FlushBuffer(); | |
271 | |
272 m_buffer[m_bufferPos++] = '\\'; | |
273 m_buffer[m_bufferPos++] = 'u'; | |
274 m_buffer[m_bufferPos++] = '0'; | |
275 m_buffer[m_bufferPos++] = '0'; | |
276 m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; | |
277 m_buffer[m_bufferPos++] = _hex[ch & 0xf]; | |
278 | |
254 } else { | 279 } else { |
255 m_writer.Write(ch); | 280 if (m_bufferPos >= BUFFER_SIZE) |
281 FlushBuffer(); | |
282 m_buffer[m_bufferPos++] = ch; | |
256 } | 283 } |
257 break; | 284 continue; |
258 } | 285 } |
259 } | 286 |
260 | 287 if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) |
261 m_writer.Write('"'); | 288 FlushBuffer(); |
289 | |
290 Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); | |
291 m_bufferPos += escapeSeq.Length; | |
292 | |
293 } | |
294 | |
295 if (m_bufferPos >= BUFFER_SIZE) | |
296 FlushBuffer(); | |
297 | |
298 m_buffer[m_bufferPos++] = '"'; | |
299 | |
300 FlushBuffer(); | |
262 } | 301 } |
263 | 302 |
264 void Write(double value) { | 303 void Write(double value) { |
265 if (double.IsNaN(value)) | 304 if (double.IsNaN(value)) |
266 Write("NaN"); | 305 Write("NaN"); |