Skip to content

Commit

Permalink
0.0.6 beta3 (#19)
Browse files Browse the repository at this point in the history
* beta4

* value based array class

* incremental update

* beta4 fix edge cases

* correction this is beta3

* delete empty projs

* remove unneeded using statements
  • Loading branch information
clarkis117 authored May 21, 2018
1 parent b147d0c commit 71a799a
Show file tree
Hide file tree
Showing 14 changed files with 927 additions and 148 deletions.
169 changes: 75 additions & 94 deletions src/Mime-Detective/Analyzers/ArrayBasedTrie.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace MimeDetective.Analyzers
{
public sealed class ArrayBasedTrie : IFileAnalyzer
{
public const int NullStandInValue = 256;
public const int MaxNodeSize = 257;
private const int NullStandInValue = 256;
private const int MaxNodeSize = 257;

private List<OffsetNode> Nodes = new List<OffsetNode>(10);
private OffsetNode[] OffsetNodes = new OffsetNode[10];
private int offsetNodesLength = 1;

/// <summary>
/// Constructs an empty ArrayBasedTrie, <see cref="Insert(FileType)"/> to add definitions
/// </summary>
public ArrayBasedTrie()
{
OffsetNodes[0] = new OffsetNode(0);
}

/// <summary>
Expand All @@ -28,67 +28,55 @@ public ArrayBasedTrie(IEnumerable<FileType> types)
if (types is null)
throw new ArgumentNullException(nameof(types));

OffsetNodes[0] = new OffsetNode(0);

foreach (var type in types)
{
if ((object)type != null)
Insert(type);
}

Nodes = Nodes.OrderBy(x => x.Offset).ToList();
}

//TODO need tests for highestmatching count behavior
public FileType Search(in ReadResult readResult)
{
FileType match = null;
int highestMatchingCount = 0;

//iterate through offset nodes
for (int offsetNodeIndex = 0; offsetNodeIndex < Nodes.Count; offsetNodeIndex++)
for (int offsetNodeIndex = 0; offsetNodeIndex < offsetNodesLength; offsetNodeIndex++)
{
//get offset node
var offsetNode = Nodes[offsetNodeIndex];

OffsetNode offsetNode = OffsetNodes[offsetNodeIndex];
int i = offsetNode.Offset;
byte value = readResult.Array[i];

var node = offsetNode.Children[value];

if (node is null)
{
node = offsetNode.Children[NullStandInValue];

if (node is null)
break;
}

if ((object)node.Record != null)
match = node.Record;
Node[] prevNode = offsetNode.Children;

i++;

//iterate through the current trie
for (; i < readResult.ReadLength; i++)
while (i < readResult.ReadLength)
{
value = readResult.Array[i];

var prevNode = node;
node = node.Children[value];
int currentVal = readResult.Array[i];
Node node = prevNode[currentVal];

if (node is null)
if (node.Children == null)
{
node = prevNode.Children[NullStandInValue];
node = prevNode[NullStandInValue];

if (node is null)
if (node.Children is null)
break;
}

if ((object)node.Record != null)
//increment here
i++;

//collect the record
if (i > highestMatchingCount && (object)node.Record != null)
{
match = node.Record;
}
highestMatchingCount = i;
}

if ((object)match != null)
break;
prevNode = node.Children;
}
}

return match;
}

Expand All @@ -97,90 +85,83 @@ public void Insert(FileType type)
if (type is null)
throw new ArgumentNullException(nameof(type));

OffsetNode match = null;
ref OffsetNode match = ref OffsetNodes[0];
bool matchFound = false;

foreach (var offsetNode in Nodes)
for (int offsetNodeIndex = 0; offsetNodeIndex < offsetNodesLength; offsetNodeIndex++)
{
if (offsetNode.Offset == type.HeaderOffset)
ref var currentNode = ref OffsetNodes[offsetNodeIndex];

if (currentNode.Offset == type.HeaderOffset)
{
match = offsetNode;
match = ref currentNode;
matchFound = true;
break;
}
}

if (match is null)
if (!matchFound)
{
match = new OffsetNode(type.HeaderOffset);
Nodes.Add(match);
}

match.Insert(type);
}

private sealed class OffsetNode
{
public readonly ushort Offset;
public readonly Node[] Children;
int newNodePos = offsetNodesLength;

public OffsetNode(ushort offset)
{
if (offset > (MimeTypes.MaxHeaderSize - 1))
throw new ArgumentException("Offset cannot be greater than MaxHeaderSize - 1");
if (newNodePos >= OffsetNodes.Length)
{
int newOffsetNodeCount = OffsetNodes.Length * 2 + 1;
var newOffsetNodes = new OffsetNode[newOffsetNodeCount];
Array.Copy(OffsetNodes, newOffsetNodes, offsetNodesLength);
OffsetNodes = newOffsetNodes;
}

Offset = offset;
Children = new Node[MaxNodeSize];
match = ref OffsetNodes[newNodePos];
match = new OffsetNode(type.HeaderOffset);
offsetNodesLength++;
}

public void Insert(FileType type)
Node[] prevNode = match.Children;

for (int i = 0; i < type.Header.Length; i++)
{
int i = 0;
byte? value = type.Header[i];
int arrayPos = value ?? NullStandInValue;
ref Node node = ref prevNode[arrayPos];

var node = Children[arrayPos];

if (node is null)
if (node.Children is null)
{
node = new Node(value);
Children[arrayPos] = node;
}
FileType record = null;

i++;
if (i == type.Header.Length - 1)
record = type;

for (; i < type.Header.Length; i++)
{
value = type.Header[i];
arrayPos = value ?? NullStandInValue;
var prevNode = node;
node = node.Children[arrayPos];

if (node is null)
{
var newNode = new Node(value);
node = new Node(record);
}

if (i == type.Header.Length - 1)
newNode.Record = type;
prevNode = node.Children;
}
}

private readonly struct OffsetNode
{
public readonly ushort Offset;
public readonly Node[] Children;

node = prevNode.Children[arrayPos] = newNode;
}
}
public OffsetNode(ushort offset)
{
Offset = offset;
Children = new Node[MaxNodeSize];
}
}

private sealed class Node
private struct Node
{
public readonly Node[] Children;
public Node[] Children;

//if complete node then this not null
public FileType Record;

public readonly byte? Value;

public Node(byte? value)
public Node(FileType record)
{
Value = value;
Children = new Node[MaxNodeSize];
Record = null;
Record = record;
}
}
}
Expand Down
73 changes: 36 additions & 37 deletions src/Mime-Detective/Analyzers/DictionaryBasedTrie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,29 @@ public FileType Search(in ReadResult readResult)
{
FileType match = null;
var enumerator = Nodes.GetEnumerator();
int highestMatchingCount = 0;

while (match is null && enumerator.MoveNext())
while (enumerator.MoveNext())
{
Node node = enumerator.Current.Value;
int i = node.Value;

for (int i = node.Value; i < readResult.ReadLength; i++)
while (i < readResult.ReadLength)
{
Node prevNode = node;

if (!prevNode.Children.TryGetValue(readResult.Array[i], out node)
&& !prevNode.Children.TryGetValue(NullStandInValue, out node))
break;

if ((object)node.Record != null)
i++;

if (i > highestMatchingCount && (object)node.Record != null)
{
match = node.Record;
highestMatchingCount = i;
}
}

if ((object)match != null)
break;
}

return match;
Expand All @@ -73,50 +77,45 @@ public void Insert(FileType type)
Nodes.Add(type.HeaderOffset, offsetNode);
}

offsetNode.Insert(type);
}

private sealed class Node
{
public readonly Dictionary<ushort, Node> Children = new Dictionary<ushort, Node>();
int i = 0;
ushort value = type.Header[i] ?? NullStandInValue;

//if complete node then this not null
public FileType Record;

public readonly ushort Value;

public Node(ushort value)
if (!offsetNode.Children.TryGetValue(value, out Node node))
{
Value = value;
node = new Node(value);
offsetNode.Children.Add(value, node);
}

public void Insert(FileType type)
i++;

for (; i < type.Header.Length; i++)
{
int i = 0;
ushort value = type.Header[i] ?? NullStandInValue;
value = type.Header[i] ?? NullStandInValue;

if (!Children.TryGetValue(value, out Node node))
if (!node.Children.ContainsKey(value))
{
node = new Node(value);
Children.Add(value, node);
Node newNode = new Node(value);
node.Children.Add(value, newNode);
}

i++;
node = node.Children[value];
}

for (; i < type.Header.Length; i++)
{
value = type.Header[i] ?? NullStandInValue;
node.Record = type;
}

if (!node.Children.ContainsKey(value))
{
Node newNode = new Node(value);
node.Children.Add(value, newNode);
}
private sealed class Node
{
public Dictionary<ushort, Node> Children = new Dictionary<ushort, Node>();

node = node.Children[value];
}
//if complete node then this not null
public FileType Record;

public ushort Value;

node.Record = type;
public Node(ushort value)
{
Value = value;
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/Mime-Detective/Analyzers/Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace MimeDetective.Analyzers
{
internal static class ThrowHelpers
{
public static void GreaterThanMaxHeaderSize()
{
throw new ArgumentException("Offset cannot be greater than MaxHeaderSize - 1");
}
}
}
Loading

0 comments on commit 71a799a

Please sign in to comment.