+LineWriter, +TokenReader
parent
e8b0c8c4af
commit
e3f5e42574
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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">
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue