mirror of https://github.com/duggerd/KFDtool.git
157 lines
4.8 KiB
C#
157 lines
4.8 KiB
C#
using KFDtool.P25.TransferConstructs;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace KFDtool.P25.Partition
|
|
{
|
|
public class KeyPartitioner
|
|
{
|
|
private static void CheckForDifferentKeyLengths(List<CmdKeyItem> inKeys)
|
|
{
|
|
Dictionary<int, int> len = new Dictionary<int, int>();
|
|
|
|
foreach (CmdKeyItem key in inKeys)
|
|
{
|
|
if (!len.ContainsKey(key.AlgorithmId))
|
|
{
|
|
len.Add(key.AlgorithmId, key.Key.Count);
|
|
}
|
|
else
|
|
{
|
|
if (len[key.AlgorithmId] != key.Key.Count)
|
|
{
|
|
throw new Exception("more than one length of key per algorithm id");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int CalcMaxKeysPerKmm(int keyLength)
|
|
{
|
|
// TODO make this calc more dynamic
|
|
|
|
int maxBytes = 512;
|
|
int availBytes = maxBytes - 27;
|
|
|
|
int keyItemBytes = 5 + keyLength;
|
|
|
|
int maxKeys = availBytes / keyItemBytes;
|
|
|
|
if (maxKeys < 1)
|
|
{
|
|
throw new Exception("key too large for kmm");
|
|
}
|
|
|
|
return maxKeys;
|
|
}
|
|
|
|
private static void PartitionByAlg(List<CmdKeyItem> inKeys, List<List<CmdKeyItem>> outKeys)
|
|
{
|
|
Dictionary<int, List<CmdKeyItem>> alg = new Dictionary<int, List<CmdKeyItem>>();
|
|
|
|
foreach (CmdKeyItem keyItem in inKeys)
|
|
{
|
|
if (!alg.ContainsKey(keyItem.AlgorithmId))
|
|
{
|
|
alg.Add(keyItem.AlgorithmId, new List<CmdKeyItem>());
|
|
}
|
|
|
|
alg[keyItem.AlgorithmId].Add(keyItem);
|
|
}
|
|
|
|
foreach (KeyValuePair<int, List<CmdKeyItem>> algGroup in alg)
|
|
{
|
|
int maxKeys = CalcMaxKeysPerKmm(algGroup.Value[0].Key.Count);
|
|
|
|
PartitionByType(maxKeys, algGroup.Value, outKeys);
|
|
}
|
|
}
|
|
|
|
private static void PartitionByType(int maxKeys, List<CmdKeyItem> inKeys, List<List<CmdKeyItem>> outKeys)
|
|
{
|
|
List<CmdKeyItem> tek = new List<CmdKeyItem>();
|
|
List<CmdKeyItem> kek = new List<CmdKeyItem>();
|
|
|
|
foreach (CmdKeyItem keyItem in inKeys)
|
|
{
|
|
if (keyItem.IsKek)
|
|
{
|
|
kek.Add(keyItem);
|
|
}
|
|
else
|
|
{
|
|
tek.Add(keyItem);
|
|
}
|
|
}
|
|
|
|
PartitionByActive(maxKeys, tek, outKeys);
|
|
|
|
PartitionByActive(maxKeys, kek, outKeys);
|
|
}
|
|
|
|
private static void PartitionByActive(int maxKeys, List<CmdKeyItem> inKeys, List<List<CmdKeyItem>> outKeys)
|
|
{
|
|
List<CmdKeyItem> act = new List<CmdKeyItem>();
|
|
List<CmdKeyItem> def = new List<CmdKeyItem>();
|
|
|
|
foreach (CmdKeyItem keyItem in inKeys)
|
|
{
|
|
if (keyItem.UseActiveKeyset)
|
|
{
|
|
act.Add(keyItem);
|
|
}
|
|
else
|
|
{
|
|
def.Add(keyItem);
|
|
}
|
|
}
|
|
|
|
PartitionByLength(maxKeys, act, outKeys);
|
|
|
|
PartitionByKeyset(maxKeys, def, outKeys);
|
|
}
|
|
|
|
private static void PartitionByKeyset(int maxKeys, List<CmdKeyItem> inKeys, List<List<CmdKeyItem>> outKeys)
|
|
{
|
|
Dictionary<int, List<CmdKeyItem>> kset = new Dictionary<int, List<CmdKeyItem>>();
|
|
|
|
foreach (CmdKeyItem keyItem in inKeys)
|
|
{
|
|
if (!kset.ContainsKey(keyItem.KeysetId))
|
|
{
|
|
kset.Add(keyItem.KeysetId, new List<CmdKeyItem>());
|
|
}
|
|
|
|
kset[keyItem.KeysetId].Add(keyItem);
|
|
}
|
|
|
|
foreach (KeyValuePair<int, List<CmdKeyItem>> ksetGroup in kset)
|
|
{
|
|
PartitionByLength(maxKeys, ksetGroup.Value, outKeys);
|
|
}
|
|
}
|
|
|
|
private static void PartitionByLength(int maxKeys, List<CmdKeyItem> inKeys, List<List<CmdKeyItem>> outKeys)
|
|
{
|
|
for (int i = 0; i < inKeys.Count; i += maxKeys)
|
|
{
|
|
outKeys.Add(inKeys.GetRange(i, Math.Min(maxKeys, inKeys.Count - i)));
|
|
}
|
|
}
|
|
|
|
public static List<List<CmdKeyItem>> PartitionKeys(List<CmdKeyItem> inKeys)
|
|
{
|
|
CheckForDifferentKeyLengths(inKeys);
|
|
|
|
List<List<CmdKeyItem>> outKeys = new List<List<CmdKeyItem>>();
|
|
|
|
PartitionByAlg(inKeys, outKeys);
|
|
|
|
return outKeys;
|
|
}
|
|
}
|
|
}
|