2023-04-19 17:35:20 -04:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
2020-09-18 01:50:44 -07:00
|
|
|
|
using System.Text.RegularExpressions;
|
2020-08-28 22:21:35 -07:00
|
|
|
|
|
2020-12-08 16:37:08 -08:00
|
|
|
|
namespace SabreTools.Core.Tools
|
2020-07-15 09:41:59 -07:00
|
|
|
|
{
|
|
|
|
|
|
public static class Converters
|
|
|
|
|
|
{
|
2020-08-24 13:21:59 -07:00
|
|
|
|
#region String to Enum
|
|
|
|
|
|
|
2020-12-12 21:33:26 -08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get DatHeaderField value from input string
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="DatHeaderField">String to get value from</param>
|
|
|
|
|
|
/// <returns>DatHeaderField value corresponding to the string</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
public static DatHeaderField AsDatHeaderField(this string? input)
|
2020-12-12 21:33:26 -08:00
|
|
|
|
{
|
|
|
|
|
|
// If the input is empty, we return null
|
|
|
|
|
|
if (string.IsNullOrEmpty(input))
|
|
|
|
|
|
return DatHeaderField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Normalize the input
|
2024-02-28 19:49:09 -05:00
|
|
|
|
input = input!.ToLowerInvariant();
|
2020-12-12 21:33:26 -08:00
|
|
|
|
|
|
|
|
|
|
// Create regex
|
|
|
|
|
|
string headerRegex = @"^(dat|header|datheader)[.\-_\s]";
|
|
|
|
|
|
|
|
|
|
|
|
// If we don't have a header field, skip
|
|
|
|
|
|
if (!Regex.IsMatch(input, headerRegex))
|
|
|
|
|
|
return DatHeaderField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Replace the match and re-normalize
|
|
|
|
|
|
string headerInput = Regex.Replace(input, headerRegex, string.Empty)
|
|
|
|
|
|
.Replace(' ', '_')
|
|
|
|
|
|
.Replace('-', '_')
|
|
|
|
|
|
.Replace('.', '_');
|
|
|
|
|
|
|
2023-04-20 10:34:37 -04:00
|
|
|
|
return AsEnumValue<DatHeaderField>(headerInput);
|
2020-12-12 21:33:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get DatItemField value from input string
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input">String to get value from</param>
|
|
|
|
|
|
/// <returns>DatItemField value corresponding to the string</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
public static DatItemField AsDatItemField(this string? input)
|
2020-12-12 21:33:26 -08:00
|
|
|
|
{
|
|
|
|
|
|
// If the input is empty, we return null
|
|
|
|
|
|
if (string.IsNullOrEmpty(input))
|
|
|
|
|
|
return DatItemField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Normalize the input
|
2024-02-28 19:49:09 -05:00
|
|
|
|
input = input!.ToLowerInvariant();
|
2020-12-12 21:33:26 -08:00
|
|
|
|
|
|
|
|
|
|
// Create regex
|
|
|
|
|
|
string datItemRegex = @"^(item|datitem)[.\-_\s]";
|
|
|
|
|
|
|
|
|
|
|
|
// If we don't have an item field, skip
|
|
|
|
|
|
if (!Regex.IsMatch(input, datItemRegex))
|
|
|
|
|
|
return DatItemField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Replace the match and re-normalize
|
|
|
|
|
|
string itemInput = Regex.Replace(input, datItemRegex, string.Empty)
|
|
|
|
|
|
.Replace(' ', '_')
|
|
|
|
|
|
.Replace('-', '_')
|
|
|
|
|
|
.Replace('.', '_');
|
|
|
|
|
|
|
2023-04-20 10:34:37 -04:00
|
|
|
|
return AsEnumValue<DatItemField>(itemInput);
|
2020-07-15 09:41:59 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-03 10:09:40 -08:00
|
|
|
|
/// <summary>
|
2020-12-12 21:33:26 -08:00
|
|
|
|
/// Get MachineField value from input string
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="input">String to get value from</param>
|
|
|
|
|
|
/// <returns>MachineField value corresponding to the string</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
public static MachineField AsMachineField(this string? input)
|
2020-12-12 21:33:26 -08:00
|
|
|
|
{
|
|
|
|
|
|
// If the input is empty, we return null
|
|
|
|
|
|
if (string.IsNullOrEmpty(input))
|
|
|
|
|
|
return MachineField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Normalize the input
|
2024-02-28 19:49:09 -05:00
|
|
|
|
input = input!.ToLowerInvariant();
|
2020-12-12 21:33:26 -08:00
|
|
|
|
|
|
|
|
|
|
// Create regex
|
|
|
|
|
|
string machineRegex = @"^(game|machine)[.\-_\s]";
|
|
|
|
|
|
|
|
|
|
|
|
// If we don't have a machine field, skip
|
|
|
|
|
|
if (!Regex.IsMatch(input, machineRegex))
|
|
|
|
|
|
return MachineField.NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// Replace the match and re-normalize
|
|
|
|
|
|
string machineInput = Regex.Replace(input, machineRegex, string.Empty)
|
|
|
|
|
|
.Replace(' ', '_')
|
|
|
|
|
|
.Replace('-', '_')
|
|
|
|
|
|
.Replace('.', '_');
|
|
|
|
|
|
|
2023-04-20 10:34:37 -04:00
|
|
|
|
return AsEnumValue<MachineField>(machineInput);
|
2020-12-12 21:33:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-15 09:41:59 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get bool? value from input string
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="yesno">String to get value from</param>
|
|
|
|
|
|
/// <returns>bool? corresponding to the string</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
public static bool? AsYesNo(this string? yesno)
|
2020-07-15 09:41:59 -07:00
|
|
|
|
{
|
|
|
|
|
|
return yesno?.ToLowerInvariant() switch
|
|
|
|
|
|
{
|
2023-04-20 10:34:37 -04:00
|
|
|
|
"yes" or "true" => true,
|
|
|
|
|
|
"no" or "false" => false,
|
2020-08-23 22:54:09 -07:00
|
|
|
|
_ => null,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2023-04-20 10:34:37 -04:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the enum value for an input string, if possible
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value">String value to parse/param>
|
|
|
|
|
|
/// <typeparam name="T">Enum type that is expected</typeparam>
|
|
|
|
|
|
/// <returns>Enum value representing the input, default on error</returns>
|
2024-03-05 15:24:11 -05:00
|
|
|
|
public static T? AsEnumValue<T>(this string? value)
|
2023-04-20 10:34:37 -04:00
|
|
|
|
{
|
|
|
|
|
|
// Get the mapping dictionary
|
|
|
|
|
|
var mappings = GenerateToEnum<T>();
|
|
|
|
|
|
|
|
|
|
|
|
// Normalize the input value
|
|
|
|
|
|
value = value?.ToLowerInvariant();
|
|
|
|
|
|
if (value == null)
|
|
|
|
|
|
return default;
|
|
|
|
|
|
|
|
|
|
|
|
// Try to get the value from the mappings
|
|
|
|
|
|
if (mappings.ContainsKey(value))
|
|
|
|
|
|
return mappings[value];
|
|
|
|
|
|
|
|
|
|
|
|
// Otherwise, return the default value for the enum
|
|
|
|
|
|
return default;
|
|
|
|
|
|
}
|
2023-04-20 13:54:59 -04:00
|
|
|
|
|
2023-04-19 17:35:20 -04:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get a set of mappings from strings to enum values
|
|
|
|
|
|
/// </summary>
|
2023-04-20 10:34:37 -04:00
|
|
|
|
/// <typeparam name="T">Enum type that is expected</typeparam>
|
2023-04-19 17:35:20 -04:00
|
|
|
|
/// <returns>Dictionary of string to enum values</returns>
|
2023-04-20 13:54:59 -04:00
|
|
|
|
internal static Dictionary<string, T> GenerateToEnum<T>()
|
2023-04-19 17:35:20 -04:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get all of the values for the enum type
|
2023-04-20 10:34:37 -04:00
|
|
|
|
var values = Enum.GetValues(typeof(T));
|
2023-04-19 17:35:20 -04:00
|
|
|
|
|
|
|
|
|
|
// Build the output dictionary
|
2024-02-28 19:19:50 -05:00
|
|
|
|
Dictionary<string, T> mappings = [];
|
2024-02-28 19:49:09 -05:00
|
|
|
|
foreach (T? value in values)
|
2023-04-19 17:35:20 -04:00
|
|
|
|
{
|
2024-02-28 19:49:09 -05:00
|
|
|
|
// If the value is null
|
|
|
|
|
|
if (value == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2023-04-19 17:35:20 -04:00
|
|
|
|
// Try to get the mapping attribute
|
2023-08-12 00:55:41 -04:00
|
|
|
|
MappingAttribute? attr = AttributeHelper<T>.GetAttribute(value);
|
2023-04-19 17:35:20 -04:00
|
|
|
|
if (attr?.Mappings == null || !attr.Mappings.Any())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// Loop through the mappings and add each
|
|
|
|
|
|
foreach (string mapString in attr.Mappings)
|
|
|
|
|
|
{
|
2023-04-20 12:12:56 -04:00
|
|
|
|
if (mapString != null)
|
|
|
|
|
|
mappings[mapString] = value;
|
2023-04-19 17:35:20 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Return the output dictionary
|
|
|
|
|
|
return mappings;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
// This should not happen, only if the type was not an enum
|
2024-02-28 19:19:50 -05:00
|
|
|
|
return [];
|
2023-04-19 17:35:20 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-08-23 22:54:09 -07:00
|
|
|
|
|
2020-08-24 13:21:59 -07:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Enum to String
|
|
|
|
|
|
|
2020-08-23 22:54:09 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get string value from input bool?
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="yesno">bool? to get value from</param>
|
2020-08-24 13:21:59 -07:00
|
|
|
|
/// <returns>String corresponding to the bool?</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
public static string? FromYesNo(this bool? yesno)
|
2020-08-23 22:54:09 -07:00
|
|
|
|
{
|
|
|
|
|
|
return yesno switch
|
|
|
|
|
|
{
|
|
|
|
|
|
true => "yes",
|
|
|
|
|
|
false => "no",
|
2020-07-15 09:41:59 -07:00
|
|
|
|
_ => null,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2020-08-24 13:21:59 -07:00
|
|
|
|
|
2023-04-20 10:34:37 -04:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get the string value for an input enum, if possible
|
|
|
|
|
|
/// </summary>
|
2023-04-20 12:12:56 -04:00
|
|
|
|
/// <param name="value">Enum value to parse/param>
|
|
|
|
|
|
/// <param name="useSecond">True to use the second mapping option, if it exists</param>
|
2023-04-20 10:34:37 -04:00
|
|
|
|
/// <typeparam name="T">Enum type that is expected</typeparam>
|
|
|
|
|
|
/// <returns>String value representing the input, default on error</returns>
|
2024-03-05 15:24:11 -05:00
|
|
|
|
public static string? AsStringValue<T>(this T value, bool useSecond = false) where T : notnull
|
2023-04-20 10:34:37 -04:00
|
|
|
|
{
|
|
|
|
|
|
// Get the mapping dictionary
|
2023-04-20 12:12:56 -04:00
|
|
|
|
var mappings = GenerateToString<T>(useSecond);
|
2023-04-20 10:34:37 -04:00
|
|
|
|
|
|
|
|
|
|
// Try to get the value from the mappings
|
|
|
|
|
|
if (mappings.ContainsKey(value))
|
|
|
|
|
|
return mappings[value];
|
|
|
|
|
|
|
|
|
|
|
|
// Otherwise, return null
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2023-04-20 13:54:59 -04:00
|
|
|
|
|
2023-04-19 17:35:20 -04:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get a set of mappings from enum values to string
|
|
|
|
|
|
/// </summary>
|
2023-04-20 12:12:56 -04:00
|
|
|
|
/// <param name="useSecond">True to use the second mapping option, if it exists</param>
|
|
|
|
|
|
/// <typeparam name="T">Enum type that is expected</typeparam>
|
2023-04-19 17:35:20 -04:00
|
|
|
|
/// <returns>Dictionary of enum to string values</returns>
|
2023-08-12 00:55:41 -04:00
|
|
|
|
internal static Dictionary<T, string> GenerateToString<T>(bool useSecond) where T : notnull
|
2023-04-19 17:35:20 -04:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get all of the values for the enum type
|
2023-04-20 10:34:37 -04:00
|
|
|
|
var values = Enum.GetValues(typeof(T));
|
2023-04-19 17:35:20 -04:00
|
|
|
|
|
|
|
|
|
|
// Build the output dictionary
|
2024-02-28 19:19:50 -05:00
|
|
|
|
Dictionary<T, string> mappings = [];
|
2024-02-28 19:49:09 -05:00
|
|
|
|
foreach (T? value in values)
|
2023-04-19 17:35:20 -04:00
|
|
|
|
{
|
2024-02-28 19:49:09 -05:00
|
|
|
|
// If the value is null
|
|
|
|
|
|
if (value == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2023-04-19 17:35:20 -04:00
|
|
|
|
// Try to get the mapping attribute
|
2023-08-12 00:55:41 -04:00
|
|
|
|
MappingAttribute? attr = AttributeHelper<T>.GetAttribute(value);
|
2023-04-19 17:35:20 -04:00
|
|
|
|
if (attr?.Mappings == null || !attr.Mappings.Any())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2023-04-20 12:12:56 -04:00
|
|
|
|
// Use either the first or second item in the list
|
|
|
|
|
|
if (attr.Mappings.Length > 1 && useSecond)
|
|
|
|
|
|
mappings[value] = attr.Mappings[1];
|
|
|
|
|
|
else
|
|
|
|
|
|
mappings[value] = attr.Mappings[0];
|
2023-04-19 17:35:20 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Return the output dictionary
|
|
|
|
|
|
return mappings;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
// This should not happen, only if the type was not an enum
|
2024-02-28 19:19:50 -05:00
|
|
|
|
return [];
|
2023-04-19 17:35:20 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-24 13:21:59 -07:00
|
|
|
|
#endregion
|
2020-07-15 09:41:59 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|