comparison Implab/Formats/JSON/JsonScanner.cs @ 229:5f7a3e1d32b9 v2

JsonXmlReader performance tuning JsonScanner now operates strings and doesn't parses number and literals. Added SerializationHelpers to common serialize/deserialize operations
author cin
date Tue, 12 Sep 2017 19:07:42 +0300
parents 6fa235c5a760
children
comparison
equal deleted inserted replaced
228:6fa235c5a760 229:5f7a3e1d32b9
23 m_buffer = buffer; 23 m_buffer = buffer;
24 m_pos = pos; 24 m_pos = pos;
25 m_length = length; 25 m_length = length;
26 } 26 }
27 27
28 bool Read(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) { 28 bool ReadChunk(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) {
29 scanner.Reset(); 29 scanner.ResetState();
30 30
31 if (m_pos == m_length) { 31 while(scanner.Scan(m_buffer, m_pos, m_length)) {
32 // scanner requests new data
33
34 if (m_pos != m_length) // capture results for the future
35 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
36
37 // read next data
38 m_length = Read(m_buffer, 0, m_buffer.Length);
39
40 if (m_length == 0) {
41 // no data is read
42 if (scanner.Position == m_pos) {
43 // scanned hasn't moved, that's the end
44 m_pos = 0;
45 tokenType = JsonGrammar.TokenType.None;
46 return false;
47 }
48
49 if (scanner.IsFinal) {
50 m_pos = 0;
51 tokenType = scanner.Tag;
52 return true;
53 } else {
54 throw new ParserException("Unexpected EOF");
55 }
56 }
57
32 m_pos = 0; 58 m_pos = 0;
33 m_length = Read(m_buffer, 0, m_buffer.Length);
34 if (m_length == 0) {
35 tokenType = JsonGrammar.TokenType.None;
36 return false; // EOF
37 }
38 }
39
40 while(scanner.Scan(m_buffer, m_pos, m_length - m_pos)) {
41 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
42 m_pos = 0;
43 m_length = Read(m_buffer, 0, m_buffer.Length);
44 } 59 }
45 var scannerPos = scanner.Position; 60 var scannerPos = scanner.Position;
61
62 // scanner stops as scannerPos
63 if (!scanner.IsFinal)
64 throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'");
65
66 tokenType = scanner.Tag;
67 if (scannerPos != m_pos && tokenType == JsonGrammar.TokenType.Number || tokenType == JsonGrammar.TokenType.Literal)
68 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos);
69
70 m_pos = scannerPos;
71 return true;
72 }
73
74 bool ReadStringChunk(InputScanner<JsonGrammar.TokenType> scanner, out JsonGrammar.TokenType tokenType) {
75 scanner.ResetState();
76
77 while (scanner.Scan(m_buffer, m_pos, m_length)) {
78 // scanner requests new data
79
80 if (m_pos != m_length) // capture results for the future
81 m_tokenBuilder.Append(m_buffer, m_pos, m_length - m_pos);
82
83 // read next data
84 m_length = Read(m_buffer, 0, m_buffer.Length);
85
86 if (m_length == 0) {
87 // no data is read
88 if (scanner.Position == m_pos) {
89 // scanned hasn't moved, that's the end
90 m_pos = 0;
91 tokenType = JsonGrammar.TokenType.None;
92 return false;
93 }
94
95 if (scanner.IsFinal) {
96 m_pos = 0;
97 tokenType = scanner.Tag;
98 return true;
99 } else {
100 throw new ParserException("Unexpected EOF");
101 }
102 }
103
104 m_pos = 0;
105 }
106 var scannerPos = scanner.Position;
107
108 // scanner stops as scannerPos
109 if (!scanner.IsFinal)
110 throw new ParserException($"Unexpected character '{m_buffer[scannerPos + 1]}'");
111
46 if (scannerPos != m_pos) { 112 if (scannerPos != m_pos) {
47 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos); 113 m_tokenBuilder.Append(m_buffer, m_pos, scannerPos - m_pos);
48 m_pos = scannerPos; 114 m_pos = scannerPos;
49 }
50
51 if (!scanner.IsFinal) {
52 if (m_length == 0) {
53 // unexpected EOF
54 throw new ParserException("Unexpected EOF");
55 } else {
56 // unecpected character
57 throw new ParserException($"Unexpected character '{m_buffer[m_pos + 1]}'");
58 }
59 } 115 }
60 tokenType = scanner.Tag; 116 tokenType = scanner.Tag;
61 return true; 117 return true;
62 } 118 }
63 119
70 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param> 126 /// <param name="tokenValue">Возвращает значение прочитанного токена.</param>
71 /// <param name="tokenType">Возвращает тип прочитанного токена.</param> 127 /// <param name="tokenType">Возвращает тип прочитанного токена.</param>
72 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns> 128 /// <returns><c>true</c> - чтение произведено успешно. <c>false</c> - достигнут конец входных данных</returns>
73 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. 129 /// <remarks>В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е.
74 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks> 130 /// в строках обрабатываются экранированные символы, числа становтся типа double.</remarks>
75 public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { 131 public bool ReadToken(out string tokenValue, out JsonTokenType tokenType) {
76 JsonGrammar.TokenType tag; 132 JsonGrammar.TokenType tag;
77 m_tokenBuilder.Clear(); 133 m_tokenBuilder.Clear();
78 while (Read(m_jsonContext, out tag)) { 134 while (ReadChunk(m_jsonContext, out tag)) {
79 switch (tag) { 135 switch (tag) {
80 case JsonGrammar.TokenType.StringBound: 136 case JsonGrammar.TokenType.StringBound:
81 tokenValue = ReadString(); 137 tokenValue = ReadString();
82 tokenType = JsonTokenType.String; 138 tokenType = JsonTokenType.String;
83 break; 139 break;
84 case JsonGrammar.TokenType.Number: 140 case JsonGrammar.TokenType.Number:
85 tokenValue = Double.Parse(m_tokenBuilder.ToString(), CultureInfo.InvariantCulture); 141 tokenValue = m_tokenBuilder.ToString();
86 tokenType = JsonTokenType.Number; 142 tokenType = JsonTokenType.Number;
87 break; 143 break;
88 case JsonGrammar.TokenType.Literal: 144 case JsonGrammar.TokenType.Literal:
89 tokenType = JsonTokenType.Literal; 145 tokenType = JsonTokenType.Literal;
90 tokenValue = m_tokenBuilder.ToString(); 146 tokenValue = m_tokenBuilder.ToString();
106 162
107 string ReadString() { 163 string ReadString() {
108 JsonGrammar.TokenType tag; 164 JsonGrammar.TokenType tag;
109 m_tokenBuilder.Clear(); 165 m_tokenBuilder.Clear();
110 166
111 while (Read(m_stringContext, out tag)) { 167 while (ReadStringChunk(m_stringContext, out tag)) {
112 switch (tag) { 168 switch (tag) {
113 case JsonGrammar.TokenType.StringBound: 169 case JsonGrammar.TokenType.StringBound:
114 m_tokenBuilder.Length--; 170 m_tokenBuilder.Length--;
115 return m_tokenBuilder.ToString(); 171 return m_tokenBuilder.ToString();
116 case JsonGrammar.TokenType.UnescapedChar: 172 case JsonGrammar.TokenType.UnescapedChar: