Skip to content

Commit 9b86d72

Browse files
committed
Put common token reader methods in one class
1 parent ff1dfaa commit 9b86d72

File tree

5 files changed

+97
-167
lines changed

5 files changed

+97
-167
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace ValveKeyValue.Deserialization
5+
{
6+
abstract class KVTokenReader : IDisposable
7+
{
8+
public KVTokenReader(TextReader textReader)
9+
{
10+
Require.NotNull(textReader, nameof(textReader));
11+
12+
this.textReader = textReader;
13+
}
14+
15+
protected TextReader textReader;
16+
protected int? peekedNext;
17+
protected bool disposed;
18+
19+
public void Dispose()
20+
{
21+
if (!disposed)
22+
{
23+
textReader.Dispose();
24+
textReader = null;
25+
26+
disposed = true;
27+
}
28+
}
29+
30+
protected char Next()
31+
{
32+
int next;
33+
34+
if (peekedNext.HasValue)
35+
{
36+
next = peekedNext.Value;
37+
peekedNext = null;
38+
}
39+
else
40+
{
41+
next = textReader.Read();
42+
}
43+
44+
if (IsEndOfFile(next))
45+
{
46+
throw new EndOfStreamException();
47+
}
48+
49+
return (char)next;
50+
}
51+
52+
protected int Peek()
53+
{
54+
if (peekedNext.HasValue)
55+
{
56+
return peekedNext.Value;
57+
}
58+
59+
var next = textReader.Read();
60+
peekedNext = next;
61+
62+
return next;
63+
}
64+
65+
protected void ReadChar(char expectedChar)
66+
{
67+
var next = Next();
68+
if (next != expectedChar)
69+
{
70+
throw new InvalidDataException($"The syntax is incorrect, expected '{expectedChar}' but got '{next}'.");
71+
}
72+
}
73+
74+
protected void SwallowWhitespace()
75+
{
76+
while (PeekWhitespace())
77+
{
78+
Next();
79+
}
80+
}
81+
82+
protected bool PeekWhitespace()
83+
{
84+
var next = Peek();
85+
return !IsEndOfFile(next) && char.IsWhiteSpace((char)next);
86+
}
87+
88+
protected bool IsEndOfFile(int value) => value == -1;
89+
}
90+
}

ValveKeyValue/ValveKeyValue/Deserialization/KeyValues1/KV1TokenReader.cs

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace ValveKeyValue.Deserialization.KeyValues1
88
{
9-
class KV1TokenReader : IDisposable
9+
class KV1TokenReader : KVTokenReader
1010
{
1111
const char QuotationMark = '"';
1212
const char ObjectStart = '{';
@@ -16,19 +16,14 @@ class KV1TokenReader : IDisposable
1616
const char ConditionEnd = ']';
1717
const char InclusionMark = '#';
1818

19-
public KV1TokenReader(TextReader textReader, KVSerializerOptions options)
19+
public KV1TokenReader(TextReader textReader, KVSerializerOptions options) : base(textReader)
2020
{
21-
Require.NotNull(textReader, nameof(textReader));
2221
Require.NotNull(options, nameof(options));
2322

24-
this.textReader = textReader;
2523
this.options = options;
2624
}
2725

2826
readonly KVSerializerOptions options;
29-
TextReader textReader;
30-
bool disposed;
31-
int? peekedNext;
3227

3328
public KVToken ReadNextToken()
3429
{
@@ -52,17 +47,6 @@ public KVToken ReadNextToken()
5247
};
5348
}
5449

55-
public void Dispose()
56-
{
57-
if (!disposed)
58-
{
59-
textReader.Dispose();
60-
textReader = null;
61-
62-
disposed = true;
63-
}
64-
}
65-
6650
KVToken ReadString()
6751
{
6852
var text = ReadStringRaw();
@@ -143,50 +127,6 @@ KVToken ReadInclusion()
143127
throw new InvalidDataException("Unrecognized term after '#' symbol.");
144128
}
145129

146-
char Next()
147-
{
148-
int next;
149-
150-
if (peekedNext.HasValue)
151-
{
152-
next = peekedNext.Value;
153-
peekedNext = null;
154-
}
155-
else
156-
{
157-
next = textReader.Read();
158-
}
159-
160-
if (next == -1)
161-
{
162-
throw new EndOfStreamException();
163-
}
164-
165-
return (char)next;
166-
}
167-
168-
int Peek()
169-
{
170-
if (peekedNext.HasValue)
171-
{
172-
return peekedNext.Value;
173-
}
174-
175-
var next = textReader.Read();
176-
peekedNext = next;
177-
178-
return next;
179-
}
180-
181-
void ReadChar(char expectedChar)
182-
{
183-
var next = Next();
184-
if (next != expectedChar)
185-
{
186-
throw new InvalidDataException($"The syntax is incorrect, expected '{expectedChar}' but got '{next}'.");
187-
}
188-
}
189-
190130
string ReadUntil(params char[] terminators)
191131
{
192132
var sb = new StringBuilder();
@@ -254,20 +194,6 @@ string ReadUntilWhitespaceOrQuote()
254194
return sb.ToString();
255195
}
256196

257-
void SwallowWhitespace()
258-
{
259-
while (PeekWhitespace())
260-
{
261-
Next();
262-
}
263-
}
264-
265-
bool PeekWhitespace()
266-
{
267-
var next = Peek();
268-
return !IsEndOfFile(next) && char.IsWhiteSpace((char)next);
269-
}
270-
271197
string ReadStringRaw()
272198
{
273199
SwallowWhitespace();
@@ -288,7 +214,5 @@ string ReadQuotedStringRaw()
288214
ReadChar(QuotationMark);
289215
return text;
290216
}
291-
292-
bool IsEndOfFile(int value) => value == -1;
293217
}
294218
}

ValveKeyValue/ValveKeyValue/Deserialization/KeyValues3/KV3TextReader.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,18 @@ namespace ValveKeyValue.Deserialization.KeyValues3
77
{
88
sealed class KV3TextReader : IVisitingReader
99
{
10-
public KV3TextReader(TextReader textReader, IParsingVisitationListener listener, KVSerializerOptions options)
10+
public KV3TextReader(TextReader textReader, IParsingVisitationListener listener)
1111
{
1212
Require.NotNull(textReader, nameof(textReader));
1313
Require.NotNull(listener, nameof(listener));
14-
Require.NotNull(options, nameof(options));
1514

1615
this.listener = listener;
17-
this.options = options;
1816

19-
tokenReader = new KV3TokenReader(textReader, options);
17+
tokenReader = new KV3TokenReader(textReader);
2018
stateMachine = new KV3TextReaderStateMachine();
2119
}
2220

2321
readonly IParsingVisitationListener listener;
24-
readonly KVSerializerOptions options;
2522

2623
readonly KV3TokenReader tokenReader;
2724
readonly KV3TextReaderStateMachine stateMachine;

ValveKeyValue/ValveKeyValue/Deserialization/KeyValues3/KV3TokenReader.cs

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace ValveKeyValue.Deserialization.KeyValues3
1010
{
11-
class KV3TokenReader : IDisposable
11+
class KV3TokenReader : KVTokenReader
1212
{
1313
const char ObjectStart = '{';
1414
const char ObjectEnd = '}';
@@ -19,24 +19,14 @@ class KV3TokenReader : IDisposable
1919
const char Assignment = '=';
2020
const char Comma = ',';
2121

22-
public KV3TokenReader(TextReader textReader, KVSerializerOptions options)
22+
public KV3TokenReader(TextReader textReader) : base(textReader)
2323
{
24-
Require.NotNull(textReader, nameof(textReader));
25-
Require.NotNull(options, nameof(options));
26-
27-
this.textReader = textReader;
28-
this.options = options;
29-
3024
// Dota 2 binary from 2017 used "+" as a terminate (for flagged values), but then they changed it to "|"
3125
var terminators = "{}[]=, \t\n\r'\":|;".ToCharArray();
3226
integerTerminators = new HashSet<int>(terminators.Select(t => (int)t));
3327
}
3428

35-
readonly KVSerializerOptions options;
3629
readonly HashSet<int> integerTerminators;
37-
TextReader textReader;
38-
bool disposed;
39-
int? peekedNext;
4030

4131
public KVToken ReadNextToken()
4232
{
@@ -63,17 +53,6 @@ public KVToken ReadNextToken()
6353
};
6454
}
6555

66-
public void Dispose()
67-
{
68-
if (!disposed)
69-
{
70-
textReader.Dispose();
71-
textReader = null;
72-
73-
disposed = true;
74-
}
75-
}
76-
7756
KVToken ReadAssignment()
7857
{
7958
ReadChar(Assignment);
@@ -309,50 +288,6 @@ KVToken ReadComment()
309288
return new KVToken(KVTokenType.Comment, text);
310289
}
311290

312-
char Next()
313-
{
314-
int next;
315-
316-
if (peekedNext.HasValue)
317-
{
318-
next = peekedNext.Value;
319-
peekedNext = null;
320-
}
321-
else
322-
{
323-
next = textReader.Read();
324-
}
325-
326-
if (IsEndOfFile(next))
327-
{
328-
throw new EndOfStreamException();
329-
}
330-
331-
return (char)next;
332-
}
333-
334-
int Peek()
335-
{
336-
if (peekedNext.HasValue)
337-
{
338-
return peekedNext.Value;
339-
}
340-
341-
var next = textReader.Read();
342-
peekedNext = next;
343-
344-
return next;
345-
}
346-
347-
void ReadChar(char expectedChar)
348-
{
349-
var next = Next();
350-
if (next != expectedChar)
351-
{
352-
throw new InvalidDataException($"The syntax is incorrect, expected '{expectedChar}' but got '{next}'.");
353-
}
354-
}
355-
356291
bool IsIdentifier(string text)
357292
{
358293
for (var i = 0; i < text.Length; i++)
@@ -406,20 +341,6 @@ string ReadToken()
406341
return sb.ToString();
407342
}
408343

409-
void SwallowWhitespace()
410-
{
411-
while (PeekWhitespace())
412-
{
413-
Next();
414-
}
415-
}
416-
417-
bool PeekWhitespace()
418-
{
419-
var next = Peek();
420-
return !IsEndOfFile(next) && char.IsWhiteSpace((char)next);
421-
}
422-
423344
string ReadQuotedStringRaw(char quotationMark)
424345
{
425346
ReadChar(quotationMark);
@@ -512,7 +433,5 @@ string ReadQuotedStringRaw(char quotationMark)
512433

513434
return sb.ToString();
514435
}
515-
516-
bool IsEndOfFile(int value) => value == -1;
517436
}
518437
}

ValveKeyValue/ValveKeyValue/KVSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ IVisitingReader MakeReader(Stream stream, IParsingVisitationListener listener, K
111111
{
112112
KVSerializationFormat.KeyValues1Text => new KV1TextReader(new StreamReader(stream), listener, options),
113113
KVSerializationFormat.KeyValues1Binary => new KV1BinaryReader(stream, listener),
114-
KVSerializationFormat.KeyValues3Text => new KV3TextReader(new StreamReader(stream), listener, options),
114+
KVSerializationFormat.KeyValues3Text => new KV3TextReader(new StreamReader(stream), listener),
115115
_ => throw new ArgumentOutOfRangeException(nameof(format), format, "Invalid serialization format."),
116116
};
117117
}

0 commit comments

Comments
 (0)