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) {