mirror of
https://github.com/AssetRipper/Cpp2IL.git
synced 2026-11-13 12:41:25 -10:00
88 lines
3.1 KiB
C#
88 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace StableNameDotNet;
|
|
|
|
/// <summary>
|
|
/// Generates a string, based on input, that can be used to somewhat distinguish between otherwise-similar types, based off of
|
|
/// type references occuring within it, and how many times they occur.
|
|
/// </summary>
|
|
public class UniqueIdentifierGenerator
|
|
{
|
|
/// <summary>
|
|
/// The number of characters from each input to use in the unique name. Do NOT change this without also calling <see cref="StableNameGenerator.ResetForNewConfig"/>
|
|
/// </summary>
|
|
public static int NumCharsToTakeFromEachInput = 2;
|
|
|
|
public static int MaxInputs = 10;
|
|
|
|
private readonly object _lock = new();
|
|
|
|
private readonly Dictionary<string, int> _inputOccurrenceCounts = new();
|
|
private readonly SortedSet<Input> _resultSet = [];
|
|
|
|
/// <summary>
|
|
/// Returns true if the generator is full, and will not process any more inputs.
|
|
/// </summary>
|
|
public bool IsFull => _inputOccurrenceCounts.Count >= MaxInputs;
|
|
|
|
/// <summary>
|
|
/// Adds an input to the generator.
|
|
/// </summary>
|
|
/// <param name="input">The input to add</param>
|
|
/// <returns>True if this generator can still accept more input, based on the <see cref="MaxInputs"/> field, false if it is full.</returns>
|
|
public bool PushInput(string input)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
//We can't actually abort on full because unhollower doesn't, and we have to match its names.
|
|
// if (IsFull)
|
|
// return false;
|
|
|
|
if (input.ContainsAnyInvalidSourceCodeChars())
|
|
return true; //Not full
|
|
|
|
var key = input.Substring(0, Math.Min(input.Length, NumCharsToTakeFromEachInput));
|
|
var numTimesKeyOccurred = _inputOccurrenceCounts[key] = _inputOccurrenceCounts.GetOrCreate(key, () => 0) + 1;
|
|
var numKeysSeen = _inputOccurrenceCounts.Count;
|
|
var chronologicalOrderFactor = _resultSet.Count / 100f;
|
|
|
|
var weight = numKeysSeen + numTimesKeyOccurred * 2 + chronologicalOrderFactor;
|
|
|
|
_resultSet.Add(new(key, weight));
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds all of the inputs in the given collection to the generator.
|
|
/// </summary>
|
|
/// <param name="inputs">The inputs to add</param>
|
|
/// <returns>True if, after adding all the inputs, the generator still has room for more. False if it full, as determined by the <see cref="MaxInputs"/> field.</returns>
|
|
public bool PushInputs(List<string> inputs) => inputs.All(PushInput);
|
|
|
|
/// <summary>
|
|
/// Generates the final string, based on the inputs that have been added to the generator.
|
|
/// </summary>
|
|
public string GenerateUniqueName()
|
|
=> string.Join("", _resultSet.Take(MaxInputs).Select(x => x.Value));
|
|
|
|
private struct Input(string value, float weight) : IComparable<Input>
|
|
{
|
|
public string Value = value;
|
|
public float Weight = weight;
|
|
|
|
public int CompareTo(Input other)
|
|
{
|
|
return Weight.CompareTo(other.Weight);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{{{Value}, {Weight}}}";
|
|
}
|
|
}
|
|
}
|