Skip to content

Commit ea64b28

Browse files
committed
Set up a helper method for reading arguments with the text reader.
1 parent 63d47f8 commit ea64b28

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using NUnit.Framework;
2+
3+
4+
namespace schema.text.reader;
5+
6+
internal class TextReaderExtensionTests {
7+
[Test]
8+
// Empty cases
9+
[TestCase("", ExpectedResult = new string[] { })]
10+
[TestCase(" \n \t ", ExpectedResult = new string[] { })]
11+
[TestCase(" ) ", ExpectedResult = new string[] { })]
12+
// One argument cases
13+
[TestCase("foo", ExpectedResult = new[] { "foo" })]
14+
[TestCase(" \n foo \t ", ExpectedResult = new[] { "foo" })]
15+
[TestCase("foo )", ExpectedResult = new[] { "foo" })]
16+
// Multiple argument cases
17+
[TestCase("foo,bar,123,abc", ExpectedResult = new[] { "foo", "bar", "123", "abc" })]
18+
[TestCase("foo,bar,123,abc,", ExpectedResult = new[] { "foo", "bar", "123", "abc" })]
19+
[TestCase(" foo , bar , 123, abc ", ExpectedResult = new[] { "foo", "bar", "123", "abc" })]
20+
// Mid-space cases
21+
[TestCase(" foo bar ", ExpectedResult = new[] { "foo bar" })]
22+
[TestCase("foo \t\n bar", ExpectedResult = new[] { "foo \t\n bar" })]
23+
// Quote cases
24+
[TestCase(" 'foo' ", ExpectedResult = new[] { "'foo'" })]
25+
[TestCase("'foo bar'", ExpectedResult = new[] { "'foo bar'" })]
26+
[TestCase("'foo, bar'", ExpectedResult = new[] { "'foo, bar'" })]
27+
[TestCase("'foo\"'", ExpectedResult = new[] { "'foo\"'" })]
28+
[TestCase("\"foo bar\"", ExpectedResult = new[] { "\"foo bar\"" })]
29+
[TestCase("`foo bar`", ExpectedResult = new[] { "`foo bar`" })]
30+
public string[] TestReadArguments(string text) {
31+
using var tr = TextSchemaTestUtil.CreateTextReader(text);
32+
return tr.ReadArguments([','], [')']);
33+
}
34+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
using schema.util.symbols;
6+
7+
namespace schema.text.reader;
8+
9+
public static partial class TextReaderExtensions {
10+
public static string[] ReadArguments(
11+
this ITextReader tr,
12+
ReadOnlySpan<char> separators,
13+
ReadOnlySpan<char> terminators) {
14+
if (tr.Eof) {
15+
return [];
16+
}
17+
18+
var arguments = new List<string>();
19+
20+
var sb = new StringBuilder();
21+
var internalWhitespaceSb = new StringBuilder();
22+
23+
char? inQuoteType = null;
24+
25+
do {
26+
var c = tr.ReadChar();
27+
28+
if (inQuoteType == null) {
29+
foreach (var terminatorC in terminators) {
30+
if (c == terminatorC) {
31+
--tr.Position;
32+
goto End;
33+
}
34+
}
35+
36+
foreach (var separatorC in separators) {
37+
if (c == separatorC) {
38+
arguments.Add(sb.ToString());
39+
sb.Clear();
40+
internalWhitespaceSb.Clear();
41+
goto Next;
42+
}
43+
}
44+
45+
if (c is ' ' or '\t' or '\n') {
46+
if (sb.Length > 0) {
47+
internalWhitespaceSb.Append(c);
48+
}
49+
50+
continue;
51+
}
52+
}
53+
54+
if (c is '`' or '\'' or '"') {
55+
if (inQuoteType == null) {
56+
inQuoteType = c;
57+
} else if (inQuoteType == c) {
58+
inQuoteType = null;
59+
}
60+
}
61+
62+
if (internalWhitespaceSb.Length > 0) {
63+
sb.Append(internalWhitespaceSb);
64+
internalWhitespaceSb.Clear();
65+
}
66+
67+
sb.Append(c);
68+
69+
Next: ;
70+
} while (!tr.Eof);
71+
72+
End:
73+
if (sb.Length > 0) {
74+
arguments.Add(sb.ToString());
75+
}
76+
77+
return arguments.ToArray();
78+
}
79+
}

0 commit comments

Comments
 (0)