Compare commits

...

43 Commits

Author SHA1 Message Date
JFronny baffd311ce Make DB info public 2020-11-19 19:55:41 +01:00
JFronny 5b5e359efb Because of CI there cant be net5. sad. 2020-11-19 19:43:47 +01:00
JFronny cae077a5cf netstandard2.1 because the world apparently isn't ready yet 2020-11-19 19:37:33 +01:00
JFronny d80c1ac5a0 Add AspNet GenericExtensions 2020-11-19 19:35:17 +01:00
JFronny 9d87c47f1c AspNet extensions 2020-11-19 19:26:36 +01:00
JFronny bb5ea72041 .NET Standard 2.1 & .NET 5.0 2020-11-11 16:37:40 +01:00
J. Fronny 454d902f04 Merge branch 'renovate/system.management-5.x' into 'master'
Update dependency System.Management to v5

See merge request JFronny/CC-Functions!2
2020-11-10 15:21:36 +00:00
Renovate Bot fc68a0f6f7
Update dependency System.Management to v5 2020-11-10 12:17:13 +00:00
J. Fronny dba8d63af5 Merge branch 'renovate/system.security.cryptography.protecteddata-5.x' into 'master'
Update dependency System.Security.Cryptography.ProtectedData to v5

See merge request JFronny/CC-Functions!3
2020-11-10 12:01:40 +00:00
Renovate Bot 65ae6b84e7
Update dependency System.Security.Cryptography.ProtectedData to v5 2020-11-10 01:18:08 +00:00
JFronny 1e451b78f9 Add initial argument parsing capabilites to CC_Functions.CommandLine 2020-09-11 11:41:08 +02:00
JFronny 7c9a5aa73d Include CC_Functions.Core in README and nugets artifact 2020-09-11 10:46:29 +02:00
JFronny 85a67cd64a [Attempt] introduce CC_Functions.Core 2020-09-11 10:38:55 +02:00
J. Fronny 0fa5fd6e82 Update .gitlab-ci.yml 2020-08-31 19:14:46 +00:00
J. Fronny ea2572d585 Update .gitlab-ci.yml 2020-08-31 19:01:19 +00:00
J. Fronny 0743b09941 Update .gitlab-ci.yml 2020-07-31 13:36:39 +00:00
J. Fronny 45b7c9263c Add LICENSE 2020-06-27 16:23:37 +00:00
J. Fronny 94bd0fa189 Merge branch 'renovate/configure' into 'master'
Configure Renovate

See merge request JFronny/CC-Functions!1
2020-06-23 12:09:01 +00:00
Renovate Bot 3fc3cd61b5
Add renovate.json 2020-06-23 08:48:43 +00:00
J. Fronny 282a249f3f Update README.md 2020-06-18 20:02:24 +00:00
J. Fronny a24905c884 Update README.md 2020-06-18 20:01:33 +00:00
J. Fronny eb4d7fe2ec Delete main.yml 2020-06-18 20:00:14 +00:00
J. Fronny fdf8afb388 Update .gitlab-ci.yml 2020-06-18 19:59:55 +00:00
J. Fronny 622d1aa130 Update .gitlab-ci.yml 2020-06-18 19:54:12 +00:00
J. Fronny 4969a420ee Update .gitlab-ci.yml 2020-06-18 19:47:23 +00:00
J. Fronny f3cb5e136c Update .gitlab-ci.yml 2020-06-18 18:46:14 +00:00
J. Fronny 5cb6fd677a Update .gitlab-ci.yml 2020-06-18 18:40:59 +00:00
J. Fronny f6644550a6 Update .gitlab-ci.yml 2020-06-18 18:32:38 +00:00
J. Fronny 21ab015742 Update .gitlab-ci.yml 2020-06-18 18:23:05 +00:00
J. Fronny 87b4f3fd08 Update .gitlab-ci.yml 2020-06-18 18:15:20 +00:00
J. Fronny d7fdd3a711 Update .gitlab-ci.yml 2020-06-18 18:09:19 +00:00
J. Fronny 6b46c7950e Update .gitlab-ci.yml 2020-06-18 17:58:54 +00:00
J. Fronny db42601eba Update .gitlab-ci.yml 2020-06-18 17:47:33 +00:00
J. Fronny 6b747bdbe8 Update .gitlab-ci.yml 2020-06-18 17:41:37 +00:00
J. Fronny 4dfb57fc2f Add .gitlab-ci.yml 2020-06-18 17:34:06 +00:00
JFronny 7699deb82c Slightly hacky fixes (most likely breaks something) 2020-06-12 19:48:31 +02:00
JFronny 30e27b9a21 No longer broken 2020-06-12 18:24:35 +02:00
JFronny 9e6b441169 ActualSize executes CalculatePosition 2020-06-12 18:16:47 +02:00
JFronny 5d380112ac Run events on all inputs 2020-06-12 16:39:02 +02:00
JFronny d562ea5295 I am officially stupid 2020-06-12 15:49:38 +02:00
JFronny 4abc39d48b I don't know how it works, I don't want to know but it works so I won't touch it from now 2020-06-12 15:40:08 +02:00
JFronny b56fb7db78 Remove DiffDraw.FullDraw (merged with DiffDraw.Draw) 2020-06-12 15:21:58 +02:00
JFronny c5fc9874b1 More null proofing 2020-06-12 15:12:13 +02:00
32 changed files with 1087 additions and 419 deletions

View File

@ -1,87 +0,0 @@
name: CD
on:
push:
branches:
- master
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Build
id: base_init
run: |
$(new-object System.Net.WebClient).DownloadFile("https://www.github.com/JFronny/UpTool2/releases/latest/download/Tools.zip", "$($(pwd).Path)\Tools.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Tools.zip
rm Tools.zip
rm Install.bat
rm Remove.bat
dotnet build --verbosity:m -p:Configuration=Release
cp W32.Test\bin\Release\netcoreapp3.1\package.zip .
$file = Get-Item $(Resolve-Path W32.Test\bin\Release\netcoreapp3.1\*.exe).Path
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
echo "::set-output name=vers::$asmver"
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.base_init.outputs.vers }}
release_name: Release ${{ steps.base_init.outputs.vers }}
draft: false
prerelease: false
- name: Upload Release Asset
id: upload_release_asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./package.zip
asset_name: package.zip
asset_content_type: application/zip
- name: Generate XML
run: |
$file = Get-Item $(Resolve-Path W32.Test\bin\Release\netcoreapp3.1\*.exe).Path
$asm = [Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll")
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Collection of Utilities for manipulating Windows"
$app.appendChild($xml.CreateElement("Version")).InnerText = "${{ steps.base_init.outputs.vers }}"
$app.appendChild($xml.CreateElement("ID")).InnerText = "3191d2f3-bf48-48ea-97a2-59fb32722d0a"
$app.appendChild($xml.CreateElement("File")).InnerText = "${{ steps.upload_release_asset.outputs.browser_download_url }}"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
- name: Upload XML
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app.xml
asset_name: app.xml
asset_content_type: text/xml
- name: Publish nugets
run: |
$tmp = "${{ steps.base_init.outputs.vers }}"
$tmp1 = $tmp.split('.')[2]
$tmp2 = $tmp.split('.')[3]
$suffix = "$tmp1.$tmp2"
cd Misc
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..\W32
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..\Commandline
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..

85
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,85 @@
.shared_windows_runners:
tags:
- windows
image: mcr.microsoft.com/dotnet/sdk
uptool:
extends:
- .shared_windows_runners
stage: deploy
script: |
mkdir i
cd i
$(new-object System.Net.WebClient).DownloadFile("https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/Installer-generic.zip?job=uptool", "$($(pwd).Path)\Install.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Install.zip
.\Installer.exe --basic i -p
cd ..
rm -R i
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Install"
uptool --basic add-repo DevTools https://gitlab.com/JFronny/UpTool2/-/snippets/2010392/raw
uptool --basic update
uptool --basic install "UpTool2 package tools"
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app"
mkdir .\build
cd W32.Test
dotnet publish -o ..\build -c Release
cd ..
$file = Get-Item $(Resolve-Path .\build\*.exe).Path
pkgtool build --binDir build --mainBin $file --packageFile .\package.zip --noLogo
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Collection of Utilities for manipulating Windows"
$app.appendChild($xml.CreateElement("Version")).InnerText = $asmver
$app.appendChild($xml.CreateElement("ID")).InnerText = "3191d2f3-bf48-48ea-97a2-59fb32722d0a"
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/package.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
$tmp1 = $asmver.split('.')[2]
$tmp2 = $asmver.split('.')[3]
$suffix = "$tmp1.$tmp2"
cd Core
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Misc
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\AspNet
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\W32
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Commandline
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..
mkdir nugets
cp .\Core\*.nupkg .\nugets\
cp .\Misc\*.nupkg .\nugets\
cp .\W32\*.nupkg .\nugets\
cp .\Commandline\*.nupkg .\nugets\
artifacts:
paths:
- package.zip
- app.xml
- nugets
only:
- master

33
AspNet/AspNet.csproj Normal file
View File

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.AspNet</RootNamespace>
<AssemblyName>CC_Functions.AspNet</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.AspNet</PackageId>
<Title>CC-Functions.AspNet</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code for Asp.Net, including my SerialDict integrated Database</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="protobuf-net" Version="3.0.62" />
<PackageReference Include="System.Text.Json" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides serializing dictionary with Guid keys
/// </summary>
public class DictionaryGuidConverter : JsonConverterFactory
{
/// <inheritdoc />
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
{
return false;
}
if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>))
{
return false;
}
return typeToConvert.GetGenericArguments()[0] == typeof(Guid);
}
/// <inheritdoc />
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type valueType = typeToConvert.GetGenericArguments()[1];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(DictionaryGuidConverterInner<>).MakeGenericType(valueType),
BindingFlags.Instance | BindingFlags.Public,
null,
new object[] { options },
null);
return converter;
}
private class DictionaryGuidConverterInner<TValue> : JsonConverter<Dictionary<Guid, TValue>>
{
private readonly JsonConverter<TValue> _valueConverter;
private Type _valueType;
public DictionaryGuidConverterInner(JsonSerializerOptions options)
{
// For performance, use the existing converter if available.
_valueConverter = (JsonConverter<TValue>)options
.GetConverter(typeof(TValue));
// Cache the key and value types.
_valueType = typeof(TValue);
}
public override Dictionary<Guid, TValue> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
Dictionary<Guid, TValue> dictionary = new Dictionary<Guid, TValue>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}
// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string propertyName = reader.GetString();
// For performance, parse with ignoreCase:false first.
if (!Guid.TryParse(propertyName, out Guid key))
{
throw new JsonException(
$"Unable to convert \"{propertyName}\" to Guid.");
}
// Get the value.
TValue v;
if (_valueConverter != null)
{
reader.Read();
v = _valueConverter.Read(ref reader, _valueType, options);
}
else
{
v = JsonSerializer.Deserialize<TValue>(ref reader, options);
}
// Add to dictionary.
dictionary.Add(key, v);
}
throw new JsonException();
}
public override void Write(
Utf8JsonWriter writer,
Dictionary<Guid, TValue> dictionary,
JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (KeyValuePair<Guid, TValue> kvp in dictionary)
{
writer.WritePropertyName(kvp.Key.ToString());
if (_valueConverter != null)
{
_valueConverter.Write(writer, kvp.Value, options);
}
else
{
JsonSerializer.Serialize(writer, kvp.Value, options);
}
}
writer.WriteEndObject();
}
}
}
}

View File

@ -0,0 +1,21 @@
using System.Text.Json;
namespace CC_Functions.AspNet
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Include CCF json extensions for this serializer
/// </summary>
/// <param name="options">The options to include CCF in</param>
/// <returns>The options including CCF</returns>
public static JsonSerializerOptions AddCcf(this JsonSerializerOptions options)
{
options.Converters.Add(new DictionaryGuidConverter());
return options;
}
}
}

164
AspNet/SaveLoadDict.cs Normal file
View File

@ -0,0 +1,164 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides synchronizing for dictionaries with saving/loading backends
/// </summary>
/// <typeparam name="T">The key type</typeparam>
/// <typeparam name="U">The param type</typeparam>
public abstract class SaveLoadDict<T, U> : IDictionary<T, U>
{
/// <inheritdoc />
public IEnumerator<KeyValuePair<T, U>> GetEnumerator()
{
lock (this) return Load().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (this) return GetEnumerator();
}
/// <inheritdoc />
public void Add(KeyValuePair<T, U> item)
{
lock (this) Add(item.Key, item.Value);
}
/// <inheritdoc />
public void Clear()
{
lock (this) Save(new Dictionary<T, U>());
}
/// <inheritdoc />
public bool Contains(KeyValuePair<T, U> item)
{
lock (this) return Load().Contains(item);
}
/// <inheritdoc />
public void CopyTo(KeyValuePair<T, U>[] array, int arrayIndex)
{
lock (this) Load().CopyTo(array, arrayIndex);
}
/// <inheritdoc />
public bool Remove(KeyValuePair<T, U> item)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(item);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public int Count
{
get { lock (this) return Load().Count; }
}
/// <inheritdoc />
public bool IsReadOnly => false;
/// <inheritdoc />
public void Add(T key, U value)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary.Add(key, value);
Save(dictionary);
}
}
/// <inheritdoc />
public bool ContainsKey(T key)
{
lock (this) return Load().ContainsKey(key);
}
/// <inheritdoc />
public bool Remove(T key)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(key);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public bool TryGetValue(T key, out U value)
{
lock (this) return Load().TryGetValue(key, out value);
}
/// <inheritdoc />
public U this[T key]
{
get
{
lock (this) return Load()[key];
}
set
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary[key] = value;
Save(dictionary);
}
}
}
/// <inheritdoc />
public ICollection<T> Keys
{
get { lock (this) return Load().Keys; }
}
/// <inheritdoc />
public ICollection<U> Values
{
get { lock (this) return Load().Values; }
}
/// <summary>
/// Replace the current content based on the current state
/// </summary>
/// <param name="f">Function to mutate the content</param>
public void Mutate(Func<IDictionary<T, U>, IDictionary<T, U>> f)
{
lock (this) Save(f(Load()));
}
/// <summary>
/// Save the dictionary content
/// </summary>
/// <param name="v">Dictionary content to save</param>
protected abstract void Save(IDictionary<T, U> v);
/// <summary>
/// Load the content to a dictionary
/// </summary>
/// <returns>The loaded content</returns>
protected abstract IDictionary<T, U> Load();
}
}

73
AspNet/SerialDict.cs Normal file
View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ProtoBuf;
namespace CC_Functions.AspNet
{
/// <summary>
/// An implementation of SaveLoadDict that uses Protobuf-net for serialization and Guid keys
/// </summary>
/// <typeparam name="T">The data type</typeparam>
public abstract class SerialDict<T> : SaveLoadDict<Guid, T>
{
//Interface
/// <summary>
/// Gets the directory containing databases
/// </summary>
public abstract string DatabasesDir { get; }
/// <summary>
/// Gets the file name for this database. Must not contain the path
/// </summary>
public abstract string DatabaseFileName { get; }
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
public event LoadedD Loaded;
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
/// <param name="v">The current dictionary content</param>
public delegate void LoadedD(IDictionary<Guid, T> v);
/// <summary>
/// Loads the dictionary and replaces Guids with strings. Use for sending
/// </summary>
/// <returns>The simplified dictionary</returns>
public IDictionary<string, T> GetSendable() => Load().ToDictionary(s => s.Key.ToString(), s => s.Value);
//Internal
private string GetRel() => Path.Combine(DatabasesDir, DatabaseFileName);
/// <inheritdoc />
protected override IDictionary<Guid, T> Load()
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
IDictionary<Guid, T> v;
if (File.Exists(GetRel()))
{
using (FileStream file = File.OpenRead(GetRel()))
v = Serializer.Deserialize<Dictionary<Guid, T>>(file);
Loaded?.Invoke(v);
return v;
}
else
{
v = new Dictionary<Guid, T>();
Loaded?.Invoke(v);
Save(v);
return v;
}
}
/// <inheritdoc />
protected override void Save(IDictionary<Guid, T> dict)
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
using FileStream file = File.Create(GetRel());
Serializer.Serialize(file, dict);
}
}
}

View File

@ -13,6 +13,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commandline", "Commandline\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLITest", "CLITest\CLITest.csproj", "{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{780EC190-E223-46DE-B6FB-1CF56ABDF34E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNet", "AspNet\AspNet.csproj", "{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -39,6 +43,14 @@ Global
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.Build.0 = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,14 +1,32 @@
using System;
using System.Drawing;
using System.Threading;
using CC_Functions.Commandline;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
namespace CLITest
{
internal class Program
{
private static void Main(string[] args)
private static void Main()
{
Thread.CurrentThread.ForceInvariantCulture();
//Parse test
if (new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" })["meme"] != "yote")
throw new Exception("ArgsParse error 1");
if (!new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" }).GetBool("meme"))
throw new Exception("ArgsParse error 2");
if (new ArgsParse(new[] {"--meme:"}).GetBool("meme"))
throw new Exception("ArgsParse error 3");
if (!new ArgsParse(new[] {"--meme:true"}).GetBool("mEme"))
throw new Exception("ArgsParse error 4");
if (new ArgsParse(new[] {"--meme:1.1.2019"}).Get<DateTime>("meme") != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 5");
if (new ArgsParse(new[] {"--meme:2019"}).Get("meme", s => s == null ? DateTime.Now : DateTime.Parse("1.1." + s)) != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 6");
//Display test
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
@ -20,7 +38,7 @@ namespace CLITest
BackColor = ConsoleColor.DarkGreen
};
screen.Controls.Add(btn1);
btn1.Click += (screen1, eventArgs) => { DiffDraw.FullDraw(true); };
btn1.Click += (screen1, eventArgs) => { DiffDraw.Draw(true, true); };
Label lab1 = new Label("Meem")
{
Point = new Point(2, 1),
@ -79,6 +97,11 @@ namespace CLITest
}
Console.ResetColor();
Console.Clear();
Console.WriteLine("Test2");
Thread.Sleep(100);
DiffDraw.Clear(10, 10);
DiffDraw.Draw(true, false);
Console.Clear();
Console.WriteLine("Bye");
}
}

98
Commandline/ArgsParse.cs Normal file
View File

@ -0,0 +1,98 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace CC_Functions.Commandline
{
/// <summary>
/// A class to provide basic parsing for program arguments
/// </summary>
public class ArgsParse : IEnumerable<string>
{
private readonly string[] _args;
/// <summary>
/// Create a new instance based on the specified args
/// </summary>
/// <param name="args">The inputted args. Should be a parameter of the main method</param>
public ArgsParse(string[] args) => _args = args ?? throw new NullReferenceException();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <param name="i">The index in the base args</param>
public string this[int i]
{
get => _args[i];
set => _args[i] = value;
}
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns>An enumerator for the base args</returns>
IEnumerator<string> IEnumerable<string>.GetEnumerator() => ((IEnumerable<string>)_args).GetEnumerator();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator() => _args.GetEnumerator();
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
public string? this[string i]
{
get
{
string? selected = null;
foreach (string s in _args)
if (s.TrimStart('-', '/').ToLower().StartsWith($"{i.ToLower()}:"))
selected = string.Join("", s.TrimStart('-', '/').Skip(i.Length + 1));
return selected;
}
}
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value or null</returns>
public string? GetString(string i) => this[i];
/// <summary>
/// Gets a boolean value with the specified name. Either specified as --i or --i:true
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value</returns>
public bool GetBool(string i) => _args.Any(s => s.ToLower().TrimStart('-', '/') == i.ToLower()) || bool.TryParse(this[i], out bool res) && res;
/// <summary>
/// Gets an arg using a transformer specified by you. The value passed will be the same as this[i]
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <param name="func">A null-safe function to convert a string to the expected type</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i, Func<string?, T> func) => func(this[i]);
/// <summary>
/// Uses reflection to call the Parse method on types providing it. Use Get() with a func param for other types
/// This will return null if the type is not found
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i)
{
MethodInfo[] parse = typeof(T).GetMethods().Where(s => s.Name.ToLower() == "parse"
&& s.GetParameters().Length == 1
&& s.GetParameters()[0].ParameterType == typeof(string)
&& s.ReturnType == typeof(T)
&& !s.IsAbstract && !s.IsPrivate && s.IsStatic).ToArray();
if (parse.Length == 0)
throw new InvalidOperationException("Could not find a valid parse method");
string? v = this[i];
if (v == null)
return default;
return (T) parse[0].Invoke(null, new object[] {v});
}
}
}

View File

@ -9,16 +9,17 @@
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Commandline</PackageId>
<Title>CC-Functions.Commandline</Title>
<Authors>CC24</Authors>
<Authors>JFronny</Authors>
<Description>Random pieces of code used across my projects. CLI/TUI extensions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@ -30,7 +31,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Misc\Misc.csproj" />
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>

View File

@ -1,8 +1,9 @@
using System;
using System.Drawing;
using CC_Functions.Misc;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
namespace CC_Functions.Commandline
{
/// <summary>
/// Provides differential drawing of a char[,] Do not use in combination with System.Console
@ -26,12 +27,14 @@ namespace CC_Functions.Commandline.TUI
/// Draws to the console
/// </summary>
/// <param name="color">Whether to use color</param>
public static void Draw(bool color)
/// <param name="full">Whether to redraw the entire screen (should be done from time to time to prevent corruption)</param>
public static void Draw(bool color, bool full = false)
{
Console.CursorTop = 0;
Console.CursorLeft = 0;
ConsoleColor fcol = Console.ForegroundColor;
ConsoleColor bcol = Console.BackgroundColor;
ConsoleColor fCol = Console.ForegroundColor;
ConsoleColor bCol = Console.BackgroundColor;
if (full) Console.Clear();
int width = Width;
int height = Height;
for (int y = 0; y < height; y++)
@ -39,8 +42,8 @@ namespace CC_Functions.Commandline.TUI
for (int x = 0; x < width; x++)
{
Pixel tmp1 = Screen[y, x];
if (tmp1 == _last[y, x]) continue;
if (color)
if (!full && tmp1 == _last[y, x]) continue;
if (!ReferenceEquals(tmp1, null) && color)
{
if (Console.ForegroundColor != tmp1.ForeColor)
Console.ForegroundColor = tmp1.ForeColor;
@ -48,49 +51,13 @@ namespace CC_Functions.Commandline.TUI
Console.BackgroundColor = tmp1.BackColor;
}
Console.CursorLeft = x;
Console.Write(tmp1);
Console.Write(tmp1 ?? Pixel.Empty);
}
Console.WriteLine();
Console.CursorLeft = 0;
}
Console.ForegroundColor = fcol;
Console.BackgroundColor = bcol;
_last = Screen;
}
/// <summary>
/// Redraws the entire screen (should be done from time to time to prevent corruption)
/// </summary>
/// <param name="color">Whether to use color</param>
public static void FullDraw(bool color)
{
Console.CursorTop = 0;
Console.CursorLeft = 0;
ConsoleColor fcol = Console.ForegroundColor;
ConsoleColor bcol = Console.BackgroundColor;
Console.Clear();
int width = Width;
int height = Height;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Pixel tmp1 = Screen[y, x];
if (color)
{
if (Console.ForegroundColor != tmp1.ForeColor)
Console.ForegroundColor = tmp1.ForeColor;
if (Console.BackgroundColor != tmp1.BackColor)
Console.BackgroundColor = tmp1.BackColor;
}
Console.CursorLeft = x;
Console.Write(tmp1);
}
Console.WriteLine();
Console.CursorLeft = 0;
}
Console.ForegroundColor = fcol;
Console.BackgroundColor = bcol;
Console.ForegroundColor = fCol;
Console.BackgroundColor = bCol;
_last = Screen;
}

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{

View File

@ -1,6 +1,6 @@
using System;
using System.Drawing;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
@ -10,11 +10,7 @@ namespace CC_Functions.Commandline.TUI
public class CenteredScreen : Screen
{
private bool _resizing;
/// <summary>
/// The actual size of this control. The "Size" property is assigned automatically
/// </summary>
public Size ActualSize;
private Size _actualSize;
/// <summary>
/// The panel used for storing and rendering the actual controls
@ -33,9 +29,9 @@ namespace CC_Functions.Commandline.TUI
/// <param name="color">Whether to use color when drawing</param>
public CenteredScreen(int width, int height, ConsoleColor contentBack, bool color = true) : base(width, height, color)
{
_titleLabel = new Label(Title);
ContentPanel = new Panel {BackColor = contentBack};
ActualSize = new Size(width, height);
_titleLabel = new Label(Title);
Controls.Add(ContentPanel);
Controls.Add(_titleLabel);
WindowResize += (screen, args) => CalculatePosition();
@ -59,6 +55,22 @@ namespace CC_Functions.Commandline.TUI
}
}
/// <summary>
/// The actual size of this control. The "Size" property is assigned automatically
/// </summary>
public Size ActualSize
{
get => _actualSize;
set
{
if (_actualSize != value)
{
_actualSize = value;
CalculatePosition(true);
}
}
}
/// <summary>
/// Calculates the Size variable, Title and ContentPanel position/size
/// </summary>
@ -76,7 +88,7 @@ namespace CC_Functions.Commandline.TUI
if (!initial)
{
Console.Clear();
DiffDraw.FullDraw(Color);
DiffDraw.Draw(Color, true);
}
_resizing = false;
}

View File

@ -1,6 +1,6 @@
using System;
using System.Drawing;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{

View File

@ -1,5 +1,5 @@
using System.Drawing;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
@ -8,20 +8,40 @@ namespace CC_Functions.Commandline.TUI
/// </summary>
public class Label : Control
{
/// <summary>
/// The text inside this label
/// </summary>
public string Content;
private string _content;
/// <summary>
/// Creates a new label
/// </summary>
/// <param name="content">The text inside this label</param>
public Label(string content) => Content = content;
public Label(string content)
{
_content = "";
Content = content;
}
/// <inheritdoc />
public override bool Selectable { get; } = false;
/// <summary>
/// The text inside this label
/// </summary>
public string Content
{
get => _content;
set
{
if (_content != value)
{
_content = value;
char[,] inp = Content.ToNdArray2D();
int w = inp.GetLength(1);
int h = inp.GetLength(0);
Size = new Size(w, h);
}
}
}
/// <inheritdoc />
public override Pixel[,] Render()
{
@ -32,7 +52,6 @@ namespace CC_Functions.Commandline.TUI
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
output[x, y] = new Pixel(BackColor, ForeColor, inp[x, y]);
Size = new Size(w, h);
return output;
}
}

View File

@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{

View File

@ -8,6 +8,8 @@ namespace CC_Functions.Commandline.TUI
/// </summary>
public class Pixel
{
public static readonly Pixel Empty = new Pixel();
/// <summary>
/// This pixels background color
/// </summary>

View File

@ -48,13 +48,26 @@ namespace CC_Functions.Commandline.TUI
}
}
private int _wndHeight = Console.WindowHeight;
private int _wndWidth = Console.WindowWidth;
/// <summary>
/// The current index of the tab-selected control in an array of selectable controls
/// </summary>
public int TabPoint;
public int TabPoint
{
get => _tabPoint;
set
{
if (_tabPoint != value)
{
_tabPoint = value;
}
}
}
private int _wndHeight = Console.WindowHeight;
private int _wndWidth = Console.WindowWidth;
private int _tabPoint;
/// <summary>
/// Creates a screen object. Multiple can be instantiated but drawing one overrides others. Use panels for that
@ -87,6 +100,7 @@ namespace CC_Functions.Commandline.TUI
/// <returns>The new state of the screen</returns>
public new Pixel[,] Render()
{
FixSelection();
Pixel[,] tmp = base.Render();
DiffDraw.Clear(tmp);
DiffDraw.Draw(Color);
@ -115,23 +129,18 @@ namespace CC_Functions.Commandline.TUI
break;
case ConsoleKey.Enter:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
{
selectable[TabPoint].InvokeClick(this);
render = true;
}
break;
case ConsoleKey.Escape:
Close?.Invoke(this, new EventArgs());
break;
default:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
{
InvokeInput(this, input);
selectable[TabPoint].InvokeInput(this, input);
render = true;
}
InvokeInput(this, input);
break;
}
render = true;
}
if (_wndWidth != Console.WindowWidth || _wndHeight != Console.WindowHeight)
{
@ -142,6 +151,8 @@ namespace CC_Functions.Commandline.TUI
}
if (canRedraw && render)
Render();
else
FixSelection();
}
/// <summary>
@ -174,10 +185,21 @@ namespace CC_Functions.Commandline.TUI
TabPoint--;
if (TabPoint < 0) TabPoint = selectable.Length - 1;
}
FixSelection(true);
}
}
private void FixSelection(bool draw = false)
{
Control[] controls = EnumerateRecursive();
Control[] selectable = controls.Where(s => s.Selectable).ToArray();
if (selectable.Any())
{
foreach (Control control in selectable) control.Selected = false;
selectable[TabPoint].Selected = true;
TabChanged?.Invoke(this, new EventArgs());
Render();
if (draw)
Render();
}
}

View File

@ -1,5 +1,5 @@
using System;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Misc;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
@ -135,7 +135,6 @@ namespace CC_Functions.Commandline.TUI
case ConsoleKey.Enter:
if (lines.Length < Size.Height)
{
tmp = lines.ToList();
lines[Cursor.Y] = lines[Cursor.Y].Insert(Math.Max(Cursor.X, 0), "\n");
Cursor.Y++;
Cursor.X = 0;

View File

@ -2,7 +2,7 @@
using System.Drawing;
using System.Linq;
namespace CC_Functions.Misc
namespace CC_Functions.Core
{
/// <summary>
/// Contains extension functions to work with 1D and 2D arrays

28
Core/Core.csproj Normal file
View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.Core</RootNamespace>
<AssemblyName>CC_Functions.Core</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Core</PackageId>
<Title>CC-Functions.Core</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code without external dependencies. Used in other CC_Functions packages</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
</Project>

255
Core/GenericExtensions.cs Normal file
View File

@ -0,0 +1,255 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Threading;
namespace CC_Functions.Core
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Gets an element from the dictionary or adds the default
/// </summary>
/// <param name="dict">The dictionary to get from</param>
/// <param name="key">The key to check</param>
/// <param name="def">The default value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The element at the key</returns>
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
/// <summary>
/// Sets an element and returns it
/// </summary>
/// <param name="dict">The dictionary to set in</param>
/// <param name="key">The key to set at</param>
/// <param name="val">The value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The value that was placed</returns>
public static TValue Set<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
/// <summary>
/// Tries to cast an object
/// </summary>
/// <param name="o">The object to try to parse</param>
/// <param name="parsed">The parsed object (if successful) or the default (usually null)</param>
/// <typeparam name="T">The type to cast to</typeparam>
/// <returns>Whether the cast was successful</returns>
public static bool TryCast<T>(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
/// <summary>
/// Runs a function that transforms an object in-line
/// </summary>
/// <param name="self">The object to run on</param>
/// <param name="func">The function to run</param>
/// <typeparam name="TIn">The input type</typeparam>
/// <typeparam name="TOut">The output type</typeparam>
/// <returns></returns>
public static TOut SelectO<TIn, TOut>(this TIn self, Func<TIn, TOut> func) => func.Invoke(self);
/// <summary>
/// Runs a function under a condition in-line (equal to if)
/// </summary>
/// <param name="condition">The condition to check</param>
/// <param name="func">The function to run</param>
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
/// <summary>
/// Parses a string to a value of an enum
/// </summary>
/// <param name="value">The string to parse</param>
/// <typeparam name="TEnum">The enum type (MUST be an enum)</typeparam>
/// <returns>The element</returns>
public static TEnum ParseToEnum<TEnum>(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
/// <summary>
/// Parses a string to a nullable bool (defaults to null if parse fails)
/// </summary>
/// <param name="value">The st string to parse</param>
/// <returns>The output nullable bool</returns>
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
/// <summary>
/// AND operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool And(this bool? left, bool? right) => left.True() && right.True();
/// <summary>
/// OR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
/// <summary>
/// XOR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
/// <summary>
/// Whether the nullable bool is true (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is true</returns>
public static bool True(this bool? self) => self == true;
/// <summary>
/// Whether the nullable bool is false (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is false</returns>
public static bool False(this bool? self) => self == false;
/// <summary>
/// Whether the nullable bool is null
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is null</returns>
public static bool Null(this bool? self) => self == null;
/// <summary>
/// Removes an element from a dictionary by its index (not key)
/// </summary>
/// <param name="dict">The dictionary to remove from</param>
/// <param name="index">The index of the value</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void RemoveAt<TKey, TValue>(this Dictionary<TKey, TValue> dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
/// <summary>
/// "Unshorten" (follow) an URL
/// </summary>
/// <param name="self">The URL to unshorten</param>
/// <returns>The unshortened URL</returns>
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;
}
/// <summary>
/// Rounds a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to round</param>
/// <returns>The rounded Rectangle</returns>
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
/// <summary>
/// Ceilings a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to ceil (?)</param>
/// <returns>The ceiled (?) Rectangle</returns>
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
/// <summary>
/// Pings an URL to check for availability
/// </summary>
/// <param name="self">The URL to check</param>
/// <returns>Whether the service is online</returns>
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;
}
}
/// <summary>
/// Gets the size of a dictionary
/// </summary>
/// <param name="directory">The dictionary to check</param>
/// <returns>The size of the dictionary</returns>
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
/// <summary>
/// Adds a directory to an archive recursively
/// </summary>
/// <param name="archive">The archive to add to</param>
/// <param name="folderPath">The directory to add</param>
/// <param name="entryName">The name of the directory in-archive</param>
/// <param name="ignoredExtensions">Extensions for files to ignore</param>
/// <param name="ignoredPaths">Paths to exclude from adding</param>
/// <returns>The new entry</returns>
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;
}
/// <summary>
/// Sets the threads cultureInfo properties to InvariantCulture. For testing
/// </summary>
/// <param name="thread">The thread to modify</param>
public static void ForceInvariantCulture(this Thread thread)
{
thread.CurrentCulture = CultureInfo.InvariantCulture;
thread.CurrentUICulture = CultureInfo.InvariantCulture;
}
}
}

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
namespace CC_Functions.Misc
namespace CC_Functions.Core
{
/// <summary>
/// IO functions

View File

@ -1,4 +1,4 @@
namespace CC_Functions.Misc
namespace CC_Functions.Core
{
/// <summary>
/// Characters for use in CC-Functions.CommandLine

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 J. Fronny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using CC_Functions.Core;
namespace CC_Functions.Misc
{
@ -13,234 +12,6 @@ namespace CC_Functions.Misc
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Gets an element from the dictionary or adds the default
/// </summary>
/// <param name="dict">The dictionary to get from</param>
/// <param name="key">The key to check</param>
/// <param name="def">The default value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The element at the key</returns>
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
/// <summary>
/// Sets an element and returns it
/// </summary>
/// <param name="dict">The dictionary to set in</param>
/// <param name="key">The key to set at</param>
/// <param name="val">The value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The value that was placed</returns>
public static TValue Set<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
/// <summary>
/// Tries to cast an object
/// </summary>
/// <param name="o">The object to try to parse</param>
/// <param name="parsed">The parsed object (if successful) or the default (usually null)</param>
/// <typeparam name="T">The type to cast to</typeparam>
/// <returns>Whether the cast was successful</returns>
public static bool TryCast<T>(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
/// <summary>
/// Runs a function that transforms an object in-line
/// </summary>
/// <param name="self">The object to run on</param>
/// <param name="func">The function to run</param>
/// <typeparam name="TIn">The input type</typeparam>
/// <typeparam name="TOut">The output type</typeparam>
/// <returns></returns>
public static TOut SelectO<TIn, TOut>(this TIn self, Func<TIn, TOut> func) => func.Invoke(self);
/// <summary>
/// Runs a function under a condition in-line (equal to if)
/// </summary>
/// <param name="condition">The condition to check</param>
/// <param name="func">The function to run</param>
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
/// <summary>
/// Parses a string to a value of an enum
/// </summary>
/// <param name="value">The string to parse</param>
/// <typeparam name="TEnum">The enum type (MUST be an enum)</typeparam>
/// <returns>The element</returns>
public static TEnum ParseToEnum<TEnum>(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
/// <summary>
/// Parses a string to a nullable bool (defaults to null if parse fails)
/// </summary>
/// <param name="value">The st string to parse</param>
/// <returns>The output nullable bool</returns>
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
/// <summary>
/// AND operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool And(this bool? left, bool? right) => left.True() && right.True();
/// <summary>
/// OR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
/// <summary>
/// XOR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
/// <summary>
/// Whether the nullable bool is true (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is true</returns>
public static bool True(this bool? self) => self == true;
/// <summary>
/// Whether the nullable bool is false (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is false</returns>
public static bool False(this bool? self) => self == false;
/// <summary>
/// Whether the nullable bool is null
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is null</returns>
public static bool Null(this bool? self) => self == null;
/// <summary>
/// Removes an element from a dictionary by its index (not key)
/// </summary>
/// <param name="dict">The dictionary to remove from</param>
/// <param name="index">The index of the value</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void RemoveAt<TKey, TValue>(this Dictionary<TKey, TValue> dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
/// <summary>
/// Gets the size of a dictionary
/// </summary>
/// <param name="directory">The dictionary to check</param>
/// <returns>The size of the dictionary</returns>
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
/// <summary>
/// Adds a directory to an archive recursively
/// </summary>
/// <param name="archive">The archive to add to</param>
/// <param name="folderPath">The directory to add</param>
/// <param name="entryName">The name of the directory in-archive</param>
/// <param name="ignoredExtensions">Extensions for files to ignore</param>
/// <param name="ignoredPaths">Paths to exclude from adding</param>
/// <returns>The new entry</returns>
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;
}
/// <summary>
/// "Unshorten" (follow) an URL
/// </summary>
/// <param name="self">The URL to unshorten</param>
/// <returns>The unshortened URL</returns>
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;
}
/// <summary>
/// Pings an URL to check for availability
/// </summary>
/// <param name="self">The URL to check</param>
/// <returns>Whether the service is online</returns>
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;
}
}
/// <summary>
/// Rounds a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to round</param>
/// <returns>The rounded Rectangle</returns>
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
/// <summary>
/// Ceilings a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to ceil (?)</param>
/// <returns>The ceiled (?) Rectangle</returns>
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
/// <summary>
/// Extension method for <see cref="Crypto">Crypto's</see> Encrypt
/// </summary>

View File

@ -7,17 +7,17 @@
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Misc</PackageId>
<Title>CC-Functions.Misc</Title>
<Authors>CC24</Authors>
<Authors>JFronny</Authors>
<Description>Random pieces of code used across my projects. I do NOT recommend using this in your own project!</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Misc.xml</DocumentationFile>
@ -29,11 +29,14 @@
<EmbeddedResource Include="HIDClasses.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Management" Version="4.7.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.IO.Compression" Condition="'$(TargetFramework)' == 'net461'" />
<Reference Include="System.IO.Compression.FileSystem" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup>
</Project>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>

View File

@ -1,2 +1,6 @@
# CC-Functions
[![UpTool2](https://img.shields.io/github/v/tag/JFronny/CC-Functions?color=informational&label=UpTool2)](https://jfronny.github.io/home/uptool) [![Nuget](https://img.shields.io/nuget/v/CC-Functions.Misc?label=CC-Functions.Misc)](https://www.nuget.org/packages/CC-Functions.Misc/) [![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.W32)](https://www.nuget.org/packages/CC-Functions.W32/)
# CC-Functions
[![UpTool2](https://img.shields.io/badge/Get%20it-on%20UpTool2-blue)](https://jfronny.gitlab.io/home/uptool)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.Core?label=CC-Functions.Core)](https://www.nuget.org/packages/CC-Functions.Core/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.Misc?label=CC-Functions.Misc)](https://www.nuget.org/packages/CC-Functions.Misc/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.W32)](https://www.nuget.org/packages/CC-Functions.W32/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.Commandline)](https://www.nuget.org/packages/CC-Functions.Commandline/)

View File

@ -5,13 +5,13 @@
<AssemblyName>CC-Functions.W32</AssemblyName>
<LangVersion>8</LangVersion>
<UseWindowsForms>true</UseWindowsForms>
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Deterministic>false</Deterministic>
<Authors>CC24</Authors>
<Authors>JFronny</Authors>
<Description>W32 Additions for CC-Functions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>

5
renovate.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": [
"config:base"
]
}