using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace SabreTools.Core.Tools
{
public static class Converters
{
#region String to Enum
///
/// Get DatHeaderField value from input string
///
/// String to get value from
/// DatHeaderField value corresponding to the string
public static DatHeaderField AsDatHeaderField(this string? input)
{
// If the input is empty, we return null
if (string.IsNullOrEmpty(input))
return DatHeaderField.NULL;
// Normalize the input
input = input!.ToLowerInvariant();
// 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('.', '_');
return AsEnumValue(headerInput);
}
///
/// Get DatItemField value from input string
///
/// String to get value from
/// DatItemField value corresponding to the string
public static DatItemField AsDatItemField(this string? input)
{
// If the input is empty, we return null
if (string.IsNullOrEmpty(input))
return DatItemField.NULL;
// Normalize the input
input = input!.ToLowerInvariant();
// 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('.', '_');
return AsEnumValue(itemInput);
}
///
/// Get bool? value from input string
///
/// String to get value from
/// bool? corresponding to the string
public static bool? AsYesNo(this string? yesno)
{
return yesno?.ToLowerInvariant() switch
{
"yes" or "true" => true,
"no" or "false" => false,
_ => null,
};
}
///
/// Get the enum value for an input string, if possible
///
/// String value to parse/param>
/// Enum type that is expected
/// Enum value representing the input, default on error
public static T? AsEnumValue(this string? value)
{
// Get the mapping dictionary
var mappings = GenerateToEnum();
// 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;
}
///
/// Get a set of mappings from strings to enum values
///
/// Enum type that is expected
/// Dictionary of string to enum values
internal static Dictionary GenerateToEnum()
{
try
{
// Get all of the values for the enum type
var values = Enum.GetValues(typeof(T));
// Build the output dictionary
Dictionary mappings = [];
foreach (T? value in values)
{
// If the value is null
if (value == null)
continue;
// Try to get the mapping attribute
MappingAttribute? attr = AttributeHelper.GetAttribute(value);
if (attr?.Mappings == null || !attr.Mappings.Any())
continue;
// Loop through the mappings and add each
foreach (string mapString in attr.Mappings)
{
if (mapString != null)
mappings[mapString] = value;
}
}
// Return the output dictionary
return mappings;
}
catch
{
// This should not happen, only if the type was not an enum
return [];
}
}
#endregion
#region Enum to String
///
/// Get string value from input bool?
///
/// bool? to get value from
/// String corresponding to the bool?
public static string? FromYesNo(this bool? yesno)
{
return yesno switch
{
true => "yes",
false => "no",
_ => null,
};
}
///
/// Get the string value for an input enum, if possible
///
/// Enum value to parse/param>
/// True to use the second mapping option, if it exists
/// Enum type that is expected
/// String value representing the input, default on error
public static string? AsStringValue(this T value, bool useSecond = false) where T : notnull
{
// Get the mapping dictionary
var mappings = GenerateToString(useSecond);
// Try to get the value from the mappings
if (mappings.ContainsKey(value))
return mappings[value];
// Otherwise, return null
return null;
}
///
/// Get a set of mappings from enum values to string
///
/// True to use the second mapping option, if it exists
/// Enum type that is expected
/// Dictionary of enum to string values
internal static Dictionary GenerateToString(bool useSecond) where T : notnull
{
try
{
// Get all of the values for the enum type
var values = Enum.GetValues(typeof(T));
// Build the output dictionary
Dictionary mappings = [];
foreach (T? value in values)
{
// If the value is null
if (value == null)
continue;
// Try to get the mapping attribute
MappingAttribute? attr = AttributeHelper.GetAttribute(value);
if (attr?.Mappings == null || !attr.Mappings.Any())
continue;
// 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];
}
// Return the output dictionary
return mappings;
}
catch
{
// This should not happen, only if the type was not an enum
return [];
}
}
#endregion
}
}