Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 36 additions & 57 deletions Countdown/Models/WordDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,19 @@ private void LoadResourceFile()
using DeflateStream stream = new DeflateStream(resourceStream, CompressionMode.Decompress);

StreamManager sm = new StreamManager(stream);
byte[] line;
ReadOnlySpan<byte> line;

while ((line = sm.ReadLine()) != null)
while ((line = sm.ReadLine()) != Span<byte>.Empty)
{
int keyLength = line.Length;

// check for a word break within the line
if (keyLength > (cMinLetters * 2))
{
for (keyLength = cMinLetters; keyLength < line.Length; ++keyLength)
{
if (line[keyLength] == cWord_seperator)
break;
}
int pos = line.Slice(cMinLetters).IndexOf(cWord_seperator);

if (pos >= 0)
keyLength = pos + cMinLetters;
}

// make key
Expand All @@ -174,20 +173,17 @@ private void LoadResourceFile()

// add to dictionary
if ((keyLength == cMaxLetters) && (keyLength == line.Length))
conundrumWords[key] = line;
conundrumWords[key] = line.ToArray();
else
otherWords[key] = line;
otherWords[key] = line.ToArray();
}
}
}


// a simple encoder, the source is known quantity
private static char[] GetChars(byte[] bytes, int count, bool toUpper = false)
private static char[] GetChars(ReadOnlySpan<byte> bytes, int count, bool toUpper = false)
{
if (bytes is null)
throw new ArgumentNullException(nameof(bytes));

if ((count < 0) || (count > bytes.Length))
throw new ArgumentOutOfRangeException(nameof(count));

Expand Down Expand Up @@ -235,7 +231,7 @@ private sealed class StreamManager
private readonly DeflateStream stream;
private readonly byte[] buffer = new byte[cBufferSize];

private int bufferEnd = 0;
private int dataSize = 0;
private int position = 0;
private bool endOfStream = false;

Expand All @@ -244,71 +240,54 @@ public StreamManager(DeflateStream s)
stream = s ?? throw new ArgumentNullException(nameof(s));
}


public byte[] ReadLine()
public ReadOnlySpan<byte> ReadLine()
{
int length = SeekNextLine();

if (length > 0) // simple case
if (length > 0) // simple case, the line is within the buffer
{
// copy line
byte[] line = new byte[length];
Buffer.BlockCopy(buffer, position, line, 0, length);

// update position
ReadOnlySpan<byte> line = buffer.AsSpan(position, length);
position += length + 1;
return line;
}
else if (!endOfStream) // part or all of the line is still in the stream
else if (!endOfStream) // some of the line remains in the stream
{
byte[] temp = null;
int sizeLeft = bufferEnd - position;
int sizeLeft = dataSize - position;

if (sizeLeft > 0) // copy remaining if any
{
temp = new byte[sizeLeft];
Buffer.BlockCopy(buffer, position, temp, 0, sizeLeft);
}

// always refill the whole buffer
bufferEnd = stream.Read(buffer, 0, buffer.Length);
endOfStream = bufferEnd < buffer.Length;
position = 0;
if (sizeLeft > 0) // move partial line to the start of the buffer
Buffer.BlockCopy(buffer, position, buffer, 0, sizeLeft);

length = SeekNextLine();
// refill buffer
dataSize = sizeLeft;
Span<byte> span = buffer.AsSpan();

if (length >= 0) // its not the end of the stream, it shouldn't be
while (dataSize < buffer.Length)
{
byte[] line = new byte[sizeLeft + length];
int bytesRead = stream.Read(span.Slice(dataSize));

if (sizeLeft > 0) // copy remaining and new part of the buffer
if (bytesRead == 0)
{
Buffer.BlockCopy(temp, 0, line, 0, temp.Length);
Buffer.BlockCopy(buffer, 0, line, temp.Length, length);
endOfStream = true;
break;
}
else
Buffer.BlockCopy(buffer, 0, line, 0, length);

// update position
position += length + 1;
return line;
dataSize += bytesRead;
}
}

return null;
}

position = 0;
length = SeekNextLine();

private int SeekNextLine()
{
for (int index = position; index < bufferEnd; ++index)
{
if (buffer[index] == cLine_seperator)
return index - position;
if (length > 0) // its not the end of the stream, it shouldn't be
{
position += length + 1;
return span.Slice(0, length);
}
}

return -1; // the buffer doesn't contain a full line
return Span<byte>.Empty;
}

private int SeekNextLine() => buffer.AsSpan(position).IndexOf(cLine_seperator);
}
}
}
Expand Down