@@ -2,6 +2,7 | |||
|
2 | 2 | using System.Collections.Generic; |
|
3 | 3 | using System.IO; |
|
4 | 4 | using System.Globalization; |
|
5 | using System.Diagnostics; | |
|
5 | 6 | |
|
6 | 7 | namespace Implab.JSON { |
|
7 | 8 | public class JSONWriter { |
@@ -12,10 +13,15 namespace Implab.JSON { | |||
|
12 | 13 | Stack<Context> m_contextStack = new Stack<Context>(); |
|
13 | 14 | Context m_context; |
|
14 | 15 | |
|
16 | const int BUFFER_SIZE = 64; | |
|
17 | ||
|
15 | 18 | TextWriter m_writer; |
|
16 | 19 | readonly bool m_indent = true; |
|
17 | 20 | readonly int m_indentSize = 4; |
|
21 | readonly char[] m_buffer = new char[BUFFER_SIZE]; | |
|
22 | int m_bufferPos; | |
|
18 | 23 | |
|
24 | static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; | |
|
19 | 25 | static readonly char [] _escapeBKS, |
|
20 | 26 | _escapeFWD, |
|
21 | 27 | _escapeCR, |
@@ -211,7 +217,13 namespace Implab.JSON { | |||
|
211 | 217 | void Write(bool value) { |
|
212 | 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 | 228 | void Write(string value) { |
|
217 | 229 | if (value == null) { |
@@ -219,46 +231,73 namespace Implab.JSON { | |||
|
219 | 231 | return; |
|
220 | 232 | } |
|
221 | 233 | |
|
234 | Debug.Assert(m_bufferPos == 0); | |
|
235 | ||
|
222 | 236 | var chars = value.ToCharArray(); |
|
223 | m_writer.Write('"'); | |
|
224 | ||
|
237 | m_buffer[m_bufferPos++] = '"'; | |
|
238 | ||
|
225 | 239 | // Analysis disable once ForCanBeConvertedToForeach |
|
226 | 240 | for (int i = 0; i < chars.Length; i++) { |
|
227 | 241 | var ch = chars[i]; |
|
228 | 242 | |
|
243 | char[] escapeSeq; | |
|
244 | ||
|
229 | 245 | switch (ch) { |
|
230 | 246 | case '\b': |
|
231 |
|
|
|
247 | escapeSeq = _escapeBKS; | |
|
232 | 248 | break; |
|
233 | 249 | case '\f': |
|
234 |
|
|
|
250 | escapeSeq = _escapeFWD; | |
|
235 | 251 | break; |
|
236 | 252 | case '\r': |
|
237 |
|
|
|
253 | escapeSeq = _escapeCR; | |
|
238 | 254 | break; |
|
239 | 255 | case '\n': |
|
240 |
|
|
|
256 | escapeSeq = _escapeNL; | |
|
241 | 257 | break; |
|
242 | 258 | case '\t': |
|
243 |
|
|
|
259 | escapeSeq = _escapeTAB; | |
|
244 | 260 | break; |
|
245 | 261 | case '\\': |
|
246 |
|
|
|
262 | escapeSeq = _escapeBSLASH; | |
|
247 | 263 | break; |
|
248 | 264 | case '"': |
|
249 |
|
|
|
265 | escapeSeq = _escapeQ; | |
|
250 | 266 | break; |
|
251 | 267 | default: |
|
252 | 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 | 279 | } else { |
|
255 |
|
|
|
280 | if (m_bufferPos >= BUFFER_SIZE) | |
|
281 | FlushBuffer(); | |
|
282 | m_buffer[m_bufferPos++] = ch; | |
|
256 | 283 | } |
|
257 |
|
|
|
284 | continue; | |
|
258 | 285 | } |
|
286 | ||
|
287 | if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) | |
|
288 | FlushBuffer(); | |
|
289 | ||
|
290 | Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); | |
|
291 | m_bufferPos += escapeSeq.Length; | |
|
292 | ||
|
259 | 293 | } |
|
260 | 294 | |
|
261 | m_writer.Write('"'); | |
|
295 | if (m_bufferPos >= BUFFER_SIZE) | |
|
296 | FlushBuffer(); | |
|
297 | ||
|
298 | m_buffer[m_bufferPos++] = '"'; | |
|
299 | ||
|
300 | FlushBuffer(); | |
|
262 | 301 | } |
|
263 | 302 | |
|
264 | 303 | void Write(double value) { |
@@ -5,6 +5,8 using Implab; | |||
|
5 | 5 | using System.Collections.Generic; |
|
6 | 6 | using System.Collections.Concurrent; |
|
7 | 7 | using System.Threading; |
|
8 | using Implab.JSON; | |
|
9 | using System.IO; | |
|
8 | 10 | |
|
9 | 11 | namespace MonoPlay { |
|
10 | 12 | class MainClass { |
@@ -16,25 +18,27 namespace MonoPlay { | |||
|
16 | 18 | |
|
17 | 19 | var t1 = Environment.TickCount; |
|
18 | 20 | |
|
19 |
for |
|
|
20 | ||
|
21 |
var |
|
|
22 | p.On(HandleResult); | |
|
23 | p.Resolve(i); | |
|
21 | for(int i =0; i < 1000000; i++) | |
|
22 | using (var tw = new StringWriter()) { | |
|
23 | var jw = new JSONWriter(tw); | |
|
24 | ||
|
25 | jw.WriteValue("\r\nhere\tvalue\u0002\u0003"); | |
|
26 | ||
|
27 | //Console.WriteLine(tw); | |
|
24 | 28 | } |
|
25 | 29 | |
|
30 | ||
|
31 | ||
|
26 | 32 | var t2 = Environment.TickCount; |
|
27 | 33 | Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); |
|
28 | 34 | |
|
29 | 35 | } |
|
30 | 36 | |
|
31 |
static void |
|
|
32 | { | |
|
33 | ||
|
37 | static void DoTest() { | |
|
38 | ||
|
39 | ||
|
40 | ||
|
34 | 41 | } |
|
35 | 42 | |
|
36 | static void HandleResult(int x) { | |
|
37 | ||
|
38 | } | |
|
39 | 43 | } |
|
40 | 44 | } |
General Comments 0
You need to be logged in to leave comments.
Login now