// 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()); } } }