// Copyright Epic Games, Inc. All Rights Reserved.
using System.Collections.Generic;
namespace EpicGames.Horde.Logs
{
///
/// Structure used for building compact instances
///
public class NgramSetBuilder
{
///
/// Node within the trie
///
class Node
{
public Node?[]? _children;
}
///
/// The root node
///
readonly Node _root;
///
/// Default constructor
///
public NgramSetBuilder()
{
_root = new Node();
}
///
/// Adds a value to the trie
///
/// Value to add
public void Add(ulong value)
{
// Loop through the tree until we've added the item
Node leaf = _root;
for (int shift = (sizeof(ulong) * 8) - 4; shift >= 0; shift -= 4)
{
int index = (int)(value >> shift) & 15;
leaf._children ??= new Node[16];
leaf._children[index] ??= new Node();
leaf = leaf._children[index]!;
}
}
///
/// Searches for the given item in the trie
///
/// Value to add
public bool Contains(ulong value)
{
// Loop through the tree until we've added the item
Node leaf = _root;
for (int shift = (sizeof(ulong) * 8) - 4; shift >= 0; shift -= 4)
{
int index = (int)(value >> shift) & 15;
if (leaf._children == null)
{
return false;
}
if (leaf._children[index] == null)
{
return false;
}
leaf = leaf._children[index]!;
}
return true;
}
///
/// Creates a from this data
///
///
public NgramSet ToNgramSet()
{
List values = new List();
List nodes = new List();
nodes.Add(_root);
for (int bits = 0; bits < (sizeof(ulong) * 8); bits += 4)
{
List nextNodes = new List();
foreach (Node node in nodes)
{
ushort value = 0;
if (node._children != null)
{
for (int idx = 0; idx < node._children.Length; idx++)
{
if (node._children[idx] != null)
{
value |= (ushort)(1 << idx);
nextNodes.Add(node._children[idx]!);
}
}
}
values.Add(value);
}
nodes = nextNodes;
}
return new NgramSet(values.ToArray());
}
}
}