| @@ -2,6 +2,7 | |||||
| 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 { | |
| @@ -12,10 +13,15 namespace Implab.JSON { | |||||
| 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; | |
|
|
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 | static readonly char [] _escapeBKS, |
|
25 | static readonly char [] _escapeBKS, | |
| 20 | _escapeFWD, |
|
26 | _escapeFWD, | |
| 21 | _escapeCR, |
|
27 | _escapeCR, | |
| @@ -211,7 +217,13 namespace Implab.JSON { | |||||
| 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) { | |
| @@ -219,46 +231,73 namespace Implab.JSON { | |||||
| 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 |
|
|
247 | escapeSeq = _escapeBKS; | |
| 232 | break; |
|
248 | break; | |
| 233 | case '\f': |
|
249 | case '\f': | |
| 234 |
|
|
250 | escapeSeq = _escapeFWD; | |
| 235 | break; |
|
251 | break; | |
| 236 | case '\r': |
|
252 | case '\r': | |
| 237 |
|
|
253 | escapeSeq = _escapeCR; | |
| 238 | break; |
|
254 | break; | |
| 239 | case '\n': |
|
255 | case '\n': | |
| 240 |
|
|
256 | escapeSeq = _escapeNL; | |
| 241 | break; |
|
257 | break; | |
| 242 | case '\t': |
|
258 | case '\t': | |
| 243 |
|
|
259 | escapeSeq = _escapeTAB; | |
| 244 | break; |
|
260 | break; | |
| 245 | case '\\': |
|
261 | case '\\': | |
| 246 |
|
|
262 | escapeSeq = _escapeBSLASH; | |
| 247 | break; |
|
263 | break; | |
| 248 | case '"': |
|
264 | case '"': | |
| 249 |
|
|
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 |
|
|
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 | void Write(double value) { |
|
303 | void Write(double value) { | |
| @@ -5,6 +5,8 using Implab; | |||||
| 5 | using System.Collections.Generic; |
|
5 | using System.Collections.Generic; | |
| 6 | using System.Collections.Concurrent; |
|
6 | using System.Collections.Concurrent; | |
| 7 | using System.Threading; |
|
7 | using System.Threading; | |
|
|
8 | using Implab.JSON; | |||
|
|
9 | using System.IO; | |||
| 8 |
|
10 | |||
| 9 | namespace MonoPlay { |
|
11 | namespace MonoPlay { | |
| 10 | class MainClass { |
|
12 | class MainClass { | |
| @@ -16,25 +18,27 namespace MonoPlay { | |||||
| 16 |
|
18 | |||
| 17 | var t1 = Environment.TickCount; |
|
19 | var t1 = Environment.TickCount; | |
| 18 |
|
20 | |||
| 19 |
for |
|
21 | for(int i =0; i < 1000000; i++) | |
| 20 |
|
22 | using (var tw = new StringWriter()) { | ||
| 21 |
var |
|
23 | var jw = new JSONWriter(tw); | |
| 22 | p.On(HandleResult); |
|
24 | ||
| 23 | p.Resolve(i); |
|
25 | jw.WriteValue("\r\nhere\tvalue\u0002\u0003"); | |
|
|
26 | ||||
|
|
27 | //Console.WriteLine(tw); | |||
| 24 | } |
|
28 | } | |
| 25 |
|
29 | |||
|
|
30 | ||||
|
|
31 | ||||
| 26 | var t2 = Environment.TickCount; |
|
32 | var t2 = Environment.TickCount; | |
| 27 | Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); |
|
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 |
|
37 | static void DoTest() { | |
| 32 | { |
|
38 | ||
| 33 |
|
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
