private IEnumerable<Chunk> ParseChunkData(Stream stream, string listName)
{
var redirects = new List<string>();
byte[] buffer = new byte[1048576]; //1MB
//safe method to read the data
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
buffer = ms.ToArray();
break;
}
ms.Write(buffer, 0, read);
}
}
var dict = new List<Chunk>();
int mode = 0xA;
int position = 0;
bool error = false;
int chunkLen = 0;
int count = 0;
int startPos = 0;
bool isBlackList = false;
int chunkId = 0;
while (position < buffer.Length)
{
switch (buffer[position])
{
case 0x61: //'a'
if (mode != 0xA)
{
error = true;
break;
}
isBlackList = false;
mode = 0xB;
++position;
break;
case 0x73: //'s'
if (mode != 0xA)
{
error = true;
break;
}
isBlackList = true;
mode = 0xB;
++position;
break;
case 0x3A: //':'
if (mode == 0xB)
{
chunkId = ReadNumber(buffer, ++position, out position);
mode = 0xC;
}
else if (mode == 0xC)
{
ReadNumber(buffer, ++position, out position);
//hashlength igonored, assumed 4
mode = 0xD;
}
else if (mode == 0xD)
{
chunkLen = ReadNumber(buffer, ++position, out position);
mode = 0xE;
}
else
{
error = true;
}
break;
case 0xA: //'\n'
if (mode != 0xE)
{
error = true;
break;
}
startPos = ++position;
while ((position - startPos) < chunkLen)
{
dict.Add(new Chunk()
{
ChunkId = chunkId,
IsBlackList = isBlackList,
Key = DecodeNumber(buffer, position, out position),
List = listName,
IsHost = true
});
count = (int)buffer[position++];
if (!isBlackList)
{
for (int i = 0; i < count; i++)
dict.Add(new Chunk()
{
ChunkId = chunkId,
IsBlackList = isBlackList,
Key = DecodeNumber(buffer, position, out position),
List = listName,
IsHost = false
});
}
else //'s'
{
for (int i = 0; i < count; i++)
{
position += 4; //skip chunknum
dict.Add(new Chunk()
{
ChunkId = chunkId,
IsBlackList = isBlackList,
Key = DecodeNumber(buffer, position, out position),
List = listName,
IsHost = false
});
}
if (count < 1)
position += 4; //skip chunknum
}
}
mode = 0xA;
break;
case 0:
if (mode != 0xA)
error = true;
position = buffer.Length; //exit the FSM
break;
default:
error = true;
break;
}
if (error)
break;
}
return dict;
}