Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BlockParseState.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
4
6{
7 internal class BlockParseState
8 {
9 private readonly List<Block> blocks;
10 private string[] rows;
11 private int[] positions;
12 private string currentRow;
13 private int current;
14 private int blockIndex;
15 private readonly int endBlock;
16 private int start;
17 private int end;
18 private int pos;
19 private int len;
20 private bool lineBreakAfter;
21 private readonly bool preserveCrLf;
22 private char lastChar = (char)0;
23
24 public BlockParseState(string[] Rows, int[] Positions, int Start, int End, bool PreserveCrLf, List<Block> Blocks, int BlockIndex,
25 int EndBlock)
26 {
27 this.blocks = Blocks;
28 this.blockIndex = BlockIndex;
29 this.endBlock = EndBlock;
30 this.rows = Rows;
31 this.positions = Positions;
32 this.current = this.start = Start;
33 this.end = End;
34 this.currentRow = this.rows[this.current];
35 this.lineBreakAfter = this.currentRow.EndsWith(" ");
36 this.pos = 0;
37 this.len = this.currentRow.Length; // >= 1
38 this.preserveCrLf = PreserveCrLf;
39
40 if (this.lineBreakAfter)
41 {
42 this.currentRow = this.currentRow.Substring(0, this.len - 2);
43 this.len -= 2;
44 }
45 }
46
47 public List<Block> Blocks => this.blocks;
48 public string[] Rows => this.rows;
49 public int[] Positions => this.positions;
50 public int Start => this.start;
51 public int End => this.end;
52 public int Current => this.current;
53 public int BlockIndex => this.blockIndex;
54 public int EndBlock => this.endBlock;
55 public bool PreserveCrLf => this.preserveCrLf;
56
57 public char NextNonWhitespaceChar()
58 {
59 char ch = this.NextChar();
60
61 while (ch > (char)0 && (ch <= ' ' || ch == 160))
62 ch = this.NextChar();
63
64 return ch;
65 }
66
67 public char NextNonWhitespaceCharSameRow()
68 {
69 char ch = this.NextCharSameRow();
70
71 while (ch > (char)0 && (ch <= ' ' || ch == 160))
72 ch = this.NextCharSameRow();
73
74 return ch;
75 }
76
77 public char NextCharSameRow()
78 {
79 if (this.pos >= this.len)
80 return this.lastChar = (char)0;
81 else
82 return this.lastChar = this.currentRow[this.pos++];
83 }
84
85 public char PeekNextNonWhitespaceCharSameRow(bool SkipWhitespace)
86 {
87 char ch = this.PeekNextCharSameRow();
88
89 if (ch > 0 && (ch <= ' ' || ch == 160))
90 {
91 if (SkipWhitespace)
92 {
93 do
94 {
95 this.NextCharSameRow();
96 ch = this.PeekNextCharSameRow();
97 }
98 while (ch > 0 && (ch <= ' ' || ch == 160));
99 }
100 else
101 {
102 int PosBak = this.pos;
103 int LenBak = this.len;
104 int CurrentBak = this.current;
105 string CurrentRowBak = this.currentRow;
106 bool LineBreakAfterBak = this.lineBreakAfter;
107
108 do
109 {
110 this.NextCharSameRow();
111 ch = this.PeekNextCharSameRow();
112 }
113 while (ch > 0 && (ch <= ' ' || ch == 160));
114
115 this.pos = PosBak;
116 this.len = LenBak;
117 this.current = CurrentBak;
118 this.currentRow = CurrentRowBak;
119 this.lineBreakAfter = LineBreakAfterBak;
120 }
121 }
122
123 return ch;
124 }
125
126 public char PeekNextNonWhitespaceChar(bool SkipWhitespace)
127 {
128 char ch = this.PeekNextChar();
129
130 if (ch > 0 && (ch <= ' ' || ch == 160))
131 {
132 if (SkipWhitespace)
133 {
134 do
135 {
136 this.NextChar();
137 ch = this.PeekNextChar();
138 }
139 while (ch > 0 && (ch <= ' ' || ch == 160));
140 }
141 else
142 {
143 int PosBak = this.pos;
144 int LenBak = this.len;
145 int CurrentBak = this.current;
146 string CurrentRowBak = this.currentRow;
147 bool LineBreakAfterBak = this.lineBreakAfter;
148
149 do
150 {
151 this.NextChar();
152 ch = this.PeekNextChar();
153 }
154 while (ch > 0 && (ch <= ' ' || ch == 160));
155
156 this.pos = PosBak;
157 this.len = LenBak;
158 this.current = CurrentBak;
159 this.currentRow = CurrentRowBak;
160 this.lineBreakAfter = LineBreakAfterBak;
161 }
162 }
163
164 return ch;
165 }
166
167 public char PeekNextCharSameRow()
168 {
169 if (this.pos >= this.len)
170 return (char)0;
171 else
172 return this.currentRow[this.pos];
173 }
174
175 public char PeekNextChar()
176 {
177 int PosBak = this.pos;
178 int LenBak = this.len;
179 int CurrentBak = this.current;
180 string CurrentRowBak = this.currentRow;
181 bool LineBreakAfterBak = this.lineBreakAfter;
182
183 char ch = this.NextChar();
184
185 this.pos = PosBak;
186 this.len = LenBak;
187 this.current = CurrentBak;
188 this.currentRow = CurrentRowBak;
189 this.lineBreakAfter = LineBreakAfterBak;
190
191 return ch;
192 }
193
194 public char[] PeekNextChars(int Len)
195 {
196 int PosBak = this.pos;
197 int LenBak = this.len;
198 int CurrentBak = this.current;
199 string CurrentRowBak = this.currentRow;
200 bool LineBreakAfterBak = this.lineBreakAfter;
201 char[] Result = new char[Len];
202 int i;
203
204 for (i = 0; i < Len; i++)
205 Result[i] = this.NextChar();
206
207 this.pos = PosBak;
208 this.len = LenBak;
209 this.current = CurrentBak;
210 this.currentRow = CurrentRowBak;
211 this.lineBreakAfter = LineBreakAfterBak;
212
213 return Result;
214 }
215
216 private class StateBackup
217 {
218 public int Pos;
219 public int Len;
220 public int Current;
221 public char LastChar;
222 public string CurrentRow;
223 public bool LineBreakAfter;
224 }
225
226 private LinkedList<StateBackup> backup = null;
227
228 public void BackupState()
229 {
230 StateBackup Backup = new StateBackup()
231 {
232 Pos = this.pos,
233 Len = this.len,
234 Current = this.current,
235 CurrentRow = this.currentRow,
236 LineBreakAfter = this.lineBreakAfter,
237 LastChar = this.lastChar
238 };
239
240 if (this.backup is null)
241 this.backup = new LinkedList<StateBackup>();
242
243 this.backup.AddFirst(Backup);
244 }
245
246 public void RestoreState()
247 {
248 if (this.backup is null || this.backup.First is null)
249 throw new Exception("No state backup to restore.");
250
251 StateBackup Backup = this.backup.First.Value;
252 this.backup.RemoveFirst();
253
254 this.pos = Backup.Pos;
255 this.len = Backup.Len;
256 this.current = Backup.Current;
257 this.currentRow = Backup.CurrentRow;
258 this.lineBreakAfter = Backup.LineBreakAfter;
259 this.lastChar = Backup.LastChar;
260 }
261
262 public void DiscardBackup()
263 {
264 if (this.backup is null || this.backup.First is null)
265 throw new Exception("No state backup to discard.");
266
267 this.backup.RemoveFirst();
268 }
269
270 public void SkipWhitespaceSameRow(int MaxSpaces)
271 {
272 char ch;
273
274 while ((((ch = this.PeekNextCharSameRow()) <= ' ' && ch > 0) || ch == 160) && MaxSpaces > 0)
275 {
276 this.NextCharSameRow();
277
278 if (ch == ' ' || ch == 160)
279 MaxSpaces--;
280 else if (ch == '\t')
281 MaxSpaces -= 4;
282 }
283 }
284
285 public char NextChar()
286 {
287 char ch;
288
289 if (this.pos >= this.len)
290 {
291 this.current++;
292 if (this.current > this.end)
293 {
294 this.pos = 0;
295 this.len = 0;
296
297 ch = (char)0;
298 }
299 else
300 {
301 if (this.lineBreakAfter)
302 ch = '\n';
303 else if (this.preserveCrLf)
304 ch = '\r';
305 else
306 ch = ' ';
307
308 this.currentRow = this.rows[this.current];
309 this.pos = 0;
310 this.len = this.currentRow.Length;
311 this.lineBreakAfter = this.currentRow.EndsWith(" ");
312
313 if (this.lineBreakAfter)
314 {
315 this.currentRow = this.currentRow.Substring(0, this.len - 2);
316 this.len -= 2;
317 }
318 }
319 }
320 else
321 ch = this.currentRow[this.pos++];
322
323 return this.lastChar = ch;
324 }
325
326 public char NextCharRaw()
327 {
328 char ch;
329
330 if (this.pos >= this.len)
331 {
332 this.current++;
333 if (this.current > this.end)
334 {
335 this.pos = 0;
336 this.len = 0;
337
338 ch = (char)0;
339 }
340 else
341 {
342 this.currentRow = this.rows[this.current];
343 this.pos = 0;
344 this.len = this.currentRow.Length;
345 this.lineBreakAfter = this.currentRow.EndsWith(" ");
346
347 if (this.lineBreakAfter)
348 {
349 this.currentRow = this.currentRow.Substring(0, this.len - 2);
350 this.len -= 2;
351 ch = '\r';
352 }
353 else
354 ch = '\n';
355 }
356 }
357 else
358 ch = this.currentRow[this.pos++];
359
360 return this.lastChar = ch;
361 }
362
363 public bool CheckRestOfTermination(char ch, int Count)
364 {
365 if (this.pos + Count > this.len)
366 return false;
367
368 int i;
369
370 for (i = 0; i < Count; i++)
371 {
372 if (this.currentRow[this.pos + i] != ch)
373 return false;
374 }
375
376 this.pos += Count;
377
378 return true;
379 }
380
381 public int CurrentPosition
382 {
383 get
384 {
385 if (this.current <= this.end)
386 return this.positions[this.current] + this.pos;
387 else
388 return this.positions[this.end] + this.rows[this.end].Length;
389 }
390 }
391
392 public string RestOfRow()
393 {
394 string Result;
395
396 if (this.pos >= this.len)
397 Result = string.Empty;
398 else
399 Result = this.currentRow.Substring(this.pos);
400
401 this.current++;
402 if (this.current > this.end)
403 {
404 this.pos = 0;
405 this.len = 0;
406 }
407 else
408 {
409 this.currentRow = this.rows[this.current];
410 this.pos = 0;
411 this.len = this.currentRow.Length;
412 this.lineBreakAfter = this.currentRow.EndsWith(" ");
413
414 if (this.lineBreakAfter)
415 {
416 this.currentRow = this.currentRow.Substring(0, this.len - 2);
417 this.len -= 2;
418 }
419 }
420
421 return Result;
422 }
423
424 public bool IsFirstCharOnLine
425 {
426 get
427 {
428 int i = this.pos - 2;
429 char ch;
430
431 if (i == -1)
432 return true;
433
434 if (i < 0 || i >= this.len)
435 return false;
436
437 while (i >= 0 && ((ch = this.currentRow[i]) <= ' ' || ch == 160))
438 i--;
439
440 return i < 0;
441 }
442 }
443
444 public bool EOF
445 {
446 get
447 {
448 return (this.pos >= this.len && this.current > this.end);
449 }
450 }
451
452 public string CurrentRow => this.currentRow;
453
454 public char LastCharacter => this.lastChar;
455
456 public string UntilToken(string Token)
457 {
458 StringBuilder sb = new StringBuilder();
459 int i = 0;
460 int c = Token.Length;
461 char ch;
462
463 while (true)
464 {
465 ch = this.NextCharRaw();
466
467 if (ch == 0)
468 {
469 if (!(this.blocks is null) && this.blockIndex < this.endBlock)
470 {
471 Block Next = this.blocks[++this.blockIndex];
472
473 this.rows = Next.Rows;
474 this.positions = Next.Positions;
475 this.current = this.start = Next.Start;
476 this.end = Next.End;
477 this.currentRow = this.rows[this.current];
478 this.lineBreakAfter = this.currentRow.EndsWith(" ");
479 this.pos = 0;
480 this.len = this.currentRow.Length; // >= 1
481
482 if (this.lineBreakAfter)
483 {
484 this.currentRow = this.currentRow.Substring(0, this.len - 2);
485 this.len -= 2;
486 }
487
488 sb.AppendLine();
489 sb.AppendLine();
490 }
491 else
492 {
493 if (i > 0)
494 sb.Append(Token.Substring(0, i));
495
496 return sb.ToString();
497 }
498 }
499 else if (ch == '\n') // Next line, no trailing double-space
500 {
501 if (i > 0)
502 {
503 sb.Append(Token.Substring(0, i));
504 i = 0;
505 }
506
507 sb.AppendLine();
508 }
509 else if (ch == '\r') // Next line, with trailing double-space
510 {
511 if (i > 0)
512 {
513 sb.Append(Token.Substring(0, i));
514 i = 0;
515 }
516
517 sb.AppendLine(" ");
518 }
519 else if (char.ToUpper(ch) == Token[i])
520 {
521 i++;
522 if (i >= c)
523 return sb.ToString();
524 }
525 else
526 {
527 if (i > 0)
528 {
529 sb.Append(Token.Substring(0, i));
530 i = 0;
531 }
532
533 sb.Append(ch);
534 }
535 }
536 }
537
538 }
539}