Files
2025-03-13 12:04:22 -07:00

84 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
namespace Raytheon.Units
{
/// <summary>
/// Contains info related to a unit: to parse, print, and convert values
/// </summary>
internal class UnitInfo<T>
{
public UnitInfo( List<string> abbreviation,
Func<double, T> conversionMethod,
MethodInfo propertyGetter )
{
Abbreviation = abbreviation;
ConversionMethod = conversionMethod;
PropertyGetter = propertyGetter;
}
/// <summary>
/// standard text abbreviation for this unit
/// </summary>
public List<string> Abbreviation { get; private set; }
/// <summary>
/// method for converting string to this unit
/// </summary>
public Func<double, T> ConversionMethod { get; private set; }
/// <summary>
/// get method for the property associated with this unit
/// </summary>
public MethodInfo PropertyGetter { get; set; }
}
internal class Common
{
/// <summary>
/// Converts a string that represents a number with a unit to the actual
/// unit type.
/// </summary>
/// <typeparam name="E">Enumeration of the Unit abbreviation</typeparam>
/// <typeparam name="T">The actual unit type, i.e Current</typeparam>
/// <param name="s">String that represents a unit value, i.e 1.23 Amps</param>
/// <param name="unitInfo">Look up table for how to convert the units</param>
/// <returns>
/// The converted number to the correct unit type. If unable to parse, will return the first
/// <see cref="UnitInfo{T}.ConversionMethod"/> with a value of <see cref="double.NaN"/>
/// </returns>
public static T Parse<E, T>( string s, IDictionary<E, UnitInfo<T>> unitInfo )
{
const string FloatingPointPattern = @"([-+]?[0-9]+(\.[0-9]+)?([Ee][+-][0-9]+)?)";
const string AbbreviationPattern = @"([\w/\^]*)";
string pattern = FloatingPointPattern + @"\s*" + AbbreviationPattern;
Regex regEx = new Regex( pattern );
Match match = regEx.Match( s );
if(!match.Success || match.Groups.Count == 0 )
{
throw new FormatException( $"UUnknown value : {s}" );
}
string abbreviation = match.Groups[match.Groups.Count - 1].Value;
IEnumerable<UnitInfo<T>> x = unitInfo.Where( kvp => kvp.Value.Abbreviation.Contains( abbreviation, StringComparer.CurrentCultureIgnoreCase ) )
.Select( kvp => kvp.Value );
// abbreviation not found?
if ( x.Count( ) == 0 )
{
throw new FormatException( $"Unknown units: '{abbreviation}'" );
}
double value = double.Parse( match.Groups[1].Value );
return x.First( ).ConversionMethod( value );
}
}
}