Innovenergy_trunk/csharp/Lib/Utils/Utils.cs

227 lines
6.2 KiB
C#

using System.Diagnostics;
using System.Runtime.CompilerServices;
using static System.Runtime.CompilerServices.MethodImplOptions;
namespace InnovEnergy.Lib.Utils;
public static class Utils
{
public static IEnumerable<String> GetEnumStrings<T>(this T e) where T : Enum
{
return GetEnumValues<T>().Select(v => v.ToString());
}
public static IReadOnlyList<TEnum> GetEnumValues<TEnum>() where TEnum : Enum
{
return (TEnum[]) Enum.GetValues(typeof(TEnum));
}
[DebuggerStepThrough][MethodImpl(AggressiveInlining)]
public static T ConvertTo<T>(this IConvertible c) where T : IConvertible
{
var t = typeof (T);
var type = t.IsEnum
? Enum.GetUnderlyingType(t)
: t;
return (T) Convert.ChangeType(c, type);
}
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static void Nop<T>(T _) {}
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static T Id<T>(T t) => t;
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static T CastTo<T>(this Object source) => (T) source;
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static T Apply<T>(this T t, Action<T> f)
{
f(t);
return t;
}
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static R Apply<T, R>(this T t, Func<T, R> f) => f(t);
[DebuggerStepThrough]
[MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static R Apply<T1, T2, R>(this (T1 p1, T2 p2) t, Func<T1, T2, R> f) => f(t.p1, t.p2);
[DebuggerStepThrough]
[MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static R Apply<T1, T2, T3, R>(this (T1 p1, T2 p2, T3 p3) t, Func<T1, T2, T3, R> f) => f(t.p1, t.p2, t.p3);
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
public static R ApplyOrDefault<T, R>(this T t, Func<T, R> f, R @default)
{
try
{
return f(t);
}
catch
{
return @default;
}
}
public static Int32 Modulo(this Int32 index, Int32 length)
{
var res = index % length;
return res >= 0
? res
: res + length;
}
public static IEnumerable<T> Traverse<T>(this T root, Func<T, IEnumerable<T>> getChildren)
{
var stack = new Stack<IEnumerator<T>>();
var it = root.AsSingleEnumerator();
it.MoveNext();
while (true)
{
//////// going down ////////
while (true)
{
var cit = getChildren(it.Current).GetEnumerator();
if (cit.MoveNext()) // node has children, must be a branch
{
yield return it.Current;
stack.Push(it);
it = cit;
}
else // no children, hence a leaf
{
var node = it.Current;
yield return node;
if (!it.MoveNext())
break; // no more siblings: goto parent
}
}
//////// going up ////////
while (true)
{
it.Dispose();
if (stack.Count == 0)
yield break; // we got to the bottom of the stack, were done
it = stack.Pop();
if (it.MoveNext())
break;
}
}
}
public static Int32 Clamp(this Int32 value, Int32 minValue, Int32 maxValue)
{
var clamped = Math.Min(maxValue, value);
clamped = Math.Max(minValue, clamped);
return clamped;
}
public static Double Clamp(this Double value, Double minValue, Double maxValue)
{
var clamped = Math.Min(maxValue, value);
clamped = Math.Max(minValue, clamped);
return clamped;
}
public static Decimal Clamp(this Decimal value, Decimal minValue, Decimal maxValue)
{
var clamped = Math.Min(maxValue, value);
clamped = Math.Max(minValue, clamped);
return clamped;
}
#pragma warning disable 8714
public static async Task<R> ApplyOrDefault<T, R>(this T t, Func<T, Task<R>> f, R @default)
{
try
{
return await f(t);
}
catch
{
return @default;
}
}
public static R ValueOrDefault<T, R>(this Dictionary<T, R> dict, T key, R defaultValue)
{
return dict.TryGetValue(key, out var value)
? value
: defaultValue;
}
public static Dictionary<K, V> CombineDicts<K,V>(params IEnumerable<KeyValuePair<K,V>>[] dicts)
{
return dicts.Flatten().ToDictionary(kv => kv.Key, kv => kv.Value);
}
#pragma warning restore 8714
public static void CopyFilesRecursively(String source, String target)
{
CopyFilesRecursively(new DirectoryInfo(source), new DirectoryInfo(target));
}
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
foreach (var file in source.GetFiles())
file.CopyTo(Path.Combine(target.FullName, file.Name));
foreach (var dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
}
public static String ExecutingProcessName => Process.GetCurrentProcess().ProcessName;
public static IEnumerable<IEnumerable<T>> TraverseWithPath<T>(this T root, Func<T, IEnumerable<T>> getChildren)
{
var stack = new Stack<IEnumerator<T>>();
stack.Push(root.AsSingleEnumerator());
do
{
for (var top = stack.Peek(); top.MoveNext(); top = Push(top))
yield return stack.Select(p => p.Current);
var popped = stack.Pop();
popped.Dispose();
}
while (stack.Count > 0);
IEnumerator<T> Push(IEnumerator<T> node)
{
var top = getChildren(node.Current).GetEnumerator();
stack.Push(top);
return top;
}
}
}