using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
namespace CC_Functions.Core
{
///
/// Extension methods for various types
///
public static class GenericExtensions
{
///
/// Gets an element from the dictionary or adds the default
///
/// The dictionary to get from
/// The key to check
/// The default value to place
/// The key type
/// The value type
/// The element at the key
public static TValue Get(this IDictionary dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
///
/// Sets an element and returns it
///
/// The dictionary to set in
/// The key to set at
/// The value to place
/// The key type
/// The value type
/// The value that was placed
public static TValue Set(this IDictionary dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
///
/// Tries to cast an object
///
/// The object to try to parse
/// The parsed object (if successful) or the default (usually null)
/// The type to cast to
/// Whether the cast was successful
public static bool TryCast(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
///
/// Runs a function that transforms an object in-line
///
/// The object to run on
/// The function to run
/// The input type
/// The output type
///
public static TOut SelectO(this TIn self, Func func) => func.Invoke(self);
///
/// Runs a function under a condition in-line (equal to if)
///
/// The condition to check
/// The function to run
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
///
/// Parses a string to a value of an enum
///
/// The string to parse
/// The enum type (MUST be an enum)
/// The element
public static TEnum ParseToEnum(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
///
/// Parses a string to a nullable bool (defaults to null if parse fails)
///
/// The st string to parse
/// The output nullable bool
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
///
/// AND operation for nullable bools (uses True)
///
/// First bool to check
/// Second bool to check
/// The operation result
public static bool And(this bool? left, bool? right) => left.True() && right.True();
///
/// OR operation for nullable bools (uses True)
///
/// First bool to check
/// Second bool to check
/// The operation result
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
///
/// XOR operation for nullable bools (uses True)
///
/// First bool to check
/// Second bool to check
/// The operation result
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
///
/// Whether the nullable bool is true (null->false)
///
/// Value to check
/// Whether it is true
public static bool True(this bool? self) => self == true;
///
/// Whether the nullable bool is false (null->false)
///
/// Value to check
/// Whether it is false
public static bool False(this bool? self) => self == false;
///
/// Whether the nullable bool is null
///
/// Value to check
/// Whether it is null
public static bool Null(this bool? self) => self == null;
///
/// Removes an element from a dictionary by its index (not key)
///
/// The dictionary to remove from
/// The index of the value
/// The key type
/// The value type
public static void RemoveAt(this Dictionary dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
///
/// "Unshorten" (follow) an URL
///
/// The URL to unshorten
/// The unshortened URL
public static Uri Unshorten(this Uri self)
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(self);
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 100;
WebResponse resp = req.GetResponse();
return resp.ResponseUri;
}
///
/// Rounds a RectangleF to a Rectangle instead of flooring
///
/// The RectangleF to round
/// The rounded Rectangle
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
///
/// Ceilings a RectangleF to a Rectangle instead of flooring
///
/// The RectangleF to ceil (?)
/// The ceiled (?) Rectangle
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
///
/// Pings an URL to check for availability
///
/// The URL to check
/// Whether the service is online
public static bool Ping(this Uri self)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(self);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
///
/// Gets the size of a dictionary
///
/// The dictionary to check
/// The size of the dictionary
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
///
/// Adds a directory to an archive recursively
///
/// The archive to add to
/// The directory to add
/// The name of the directory in-archive
/// Extensions for files to ignore
/// Paths to exclude from adding
/// The new entry
public static ZipArchiveEntry AddDirectory(this ZipArchive archive, string folderPath, string entryName,
string[] ignoredExtensions, string[] ignoredPaths)
{
entryName = entryName.TrimEnd('/');
ZipArchiveEntry result = archive.CreateEntry($"{entryName}/");
string[] files = Directory.GetFiles(folderPath);
foreach (string t in files)
if (!ignoredExtensions.Contains(Path.GetExtension(t)) &&
!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.CreateEntryFromFile(t, $"{entryName}/{Path.GetFileName(t)}");
string[] dirs = Directory.GetDirectories(folderPath);
foreach (string t in dirs)
if (!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.AddDirectory(t, $"{entryName}/{Path.GetFileName(t)}", ignoredExtensions,
ignoredPaths);
return result;
}
}
}