Mercurial > pub > ImplabNet
diff Implab/JSON/JSONWriter.cs @ 150:3258399cba83 v2
JSONWriter improvements
author | cin |
---|---|
date | Sat, 12 Dec 2015 22:12:44 +0300 |
parents | 2100965eb97f |
children |
line wrap: on
line diff
--- a/Implab/JSON/JSONWriter.cs Wed May 06 17:11:27 2015 +0300 +++ b/Implab/JSON/JSONWriter.cs Sat Dec 12 22:12:44 2015 +0300 @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Globalization; +using System.Diagnostics; namespace Implab.JSON { public class JSONWriter { @@ -12,10 +13,15 @@ Stack<Context> m_contextStack = new Stack<Context>(); Context m_context; + const int BUFFER_SIZE = 64; + TextWriter m_writer; readonly bool m_indent = true; readonly int m_indentSize = 4; + readonly char[] m_buffer = new char[BUFFER_SIZE]; + int m_bufferPos; + static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static readonly char [] _escapeBKS, _escapeFWD, _escapeCR, @@ -211,7 +217,13 @@ void Write(bool value) { m_writer.Write(value ? "true" : "false"); } - + + void FlushBuffer() { + if (m_bufferPos > 0) { + m_writer.Write(m_buffer, 0, m_bufferPos); + m_bufferPos = 0; + } + } void Write(string value) { if (value == null) { @@ -219,46 +231,73 @@ return; } + Debug.Assert(m_bufferPos == 0); + var chars = value.ToCharArray(); - m_writer.Write('"'); - + m_buffer[m_bufferPos++] = '"'; + // Analysis disable once ForCanBeConvertedToForeach for (int i = 0; i < chars.Length; i++) { var ch = chars[i]; + char[] escapeSeq; + switch (ch) { case '\b': - m_writer.Write(_escapeBKS); + escapeSeq = _escapeBKS; break; case '\f': - m_writer.Write(_escapeFWD); + escapeSeq = _escapeFWD; break; case '\r': - m_writer.Write(_escapeCR); + escapeSeq = _escapeCR; break; case '\n': - m_writer.Write(_escapeNL); + escapeSeq = _escapeNL; break; case '\t': - m_writer.Write(_escapeTAB); + escapeSeq = _escapeTAB; break; case '\\': - m_writer.Write(_escapeBSLASH); + escapeSeq = _escapeBSLASH; break; case '"': - m_writer.Write(_escapeQ); + escapeSeq = _escapeQ; break; default: if (ch < 0x20) { - m_writer.Write("\\u00{0:x2}",(int)ch); + if (m_bufferPos + 6 > BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '\\'; + m_buffer[m_bufferPos++] = 'u'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; + m_buffer[m_bufferPos++] = _hex[ch & 0xf]; + } else { - m_writer.Write(ch); + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + m_buffer[m_bufferPos++] = ch; } - break; + continue; } + + if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) + FlushBuffer(); + + Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); + m_bufferPos += escapeSeq.Length; + } - m_writer.Write('"'); + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '"'; + + FlushBuffer(); } void Write(double value) {