+LineWriter, +TokenReader

master
Harald Wolff 2020-02-04 21:44:36 +01:00
parent e8b0c8c4af
commit e3f5e42574
3 changed files with 150 additions and 0 deletions

55
io/LineWriter.cs 100644
View File

@ -0,0 +1,55 @@
using System;
using System.IO;
using System.Text;
namespace ln.types.io
{
public delegate void LineReceivedDelegate(object sender, string line);
public class LineWriter : TextWriter
{
public event LineReceivedDelegate LineReceived;
public override Encoding Encoding => Encoding.UTF8;
private void FireLineReceived(string line) => LineReceived?.Invoke(this, line);
char[] lineBuffer = new char[8192];
int cursor = 0;
String CurrentLineBuffer => new string(lineBuffer, 0, cursor);
public LineWriter()
{
}
public override void Write(char value)
{
lock (this)
{
if (value == '\n')
{
FireLineReceived(CurrentLineBuffer);
cursor = 0;
} else if (cursor < lineBuffer.Length)
{
lineBuffer[cursor++] = value;
}
}
}
public override void WriteLine() => Write('\n');
public override void WriteLine(string value)
{
lock (this)
{
if (cursor > 0)
{
value = CurrentLineBuffer + value;
cursor = 0;
}
FireLineReceived(value);
}
}
}
}

View File

@ -137,6 +137,8 @@
<Compile Include="io\FileStorage.cs" />
<Compile Include="threads\SchedulingPool.cs" />
<Compile Include="test\SchedulingPoolTests.cs" />
<Compile Include="text\TokenReader.cs" />
<Compile Include="io\LineWriter.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="odb\" />
@ -160,6 +162,7 @@
<Folder Include="collections\" />
<Folder Include="odb\ng\diff\" />
<Folder Include="io\" />
<Folder Include="text\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.logging\ln.logging.csproj">

View File

@ -0,0 +1,92 @@
using System;
using System.IO;
using System.Text;
using System.Linq;
namespace ln.types.text
{
public class TokenReader
{
public TextReader Reader { get; }
public TokenReader(Stream stream)
: this(new UnbufferedStreamReader(stream)) { }
public TokenReader(TextReader textReader)
{
Reader = textReader;
}
public String Read(Func<char, bool> criteria)
{
StringBuilder stringBuilder = new StringBuilder();
int ch;
while (((ch = Reader.Peek()) != -1) && criteria((char)ch))
stringBuilder.Append((char)Reader.Read());
return stringBuilder.ToString();
}
public bool EndOfStream => Reader.Peek() == -1;
public String Read(char validChar) => Read((ch) => ch == validChar);
public String Read(char[] validChars) => Read((ch) => validChars.Contains(ch));
public String ReadWhiteSpace() => Read((ch) => char.IsWhiteSpace(ch));
public String ReadToken() => Read((ch) => char.IsLetterOrDigit(ch) || (ch == '_'));
public String ReadValue() => Reader.Peek() == '"' ? ReadQuotedString() : ReadToken();
public String ReadQuotedString()
{
StringBuilder stringBuilder = new StringBuilder();
int nextCh = Reader.Peek();
if (nextCh != -1)
{
if (nextCh != '"')
throw new FormatException("expected double quotes");
Reader.Read();
while (((nextCh = Reader.Read()) != -1) && (nextCh != '"'))
{
if (nextCh == '\\')
nextCh = Reader.Read();
stringBuilder.Append((char)nextCh);
}
}
return stringBuilder.ToString();
}
public String ReadPath()
{
StringBuilder stringBuilder = new StringBuilder();
string token;
if (Reader.Peek() == '/')
stringBuilder.Append((char)Reader.Read());
while ((token = ReadToken()).Length > 0)
{
stringBuilder.Append(token);
if (Reader.Peek() == '/')
stringBuilder.Append((char)Reader.Read());
else
break;
}
return stringBuilder.ToString();
}
class UnbufferedStreamReader : TextReader
{
public Stream BaseStream { get; }
public UnbufferedStreamReader(Stream stream)
{
BaseStream = stream;
}
public override int Read() => BaseStream.ReadByte();
}
}
}