Support ancient .NET

This commit is contained in:
Matt Nadareski
2023-11-08 01:01:15 -05:00
parent 5221546af9
commit 9b3553e43f
13 changed files with 284 additions and 51 deletions

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
namespace SabreTools.IO
@@ -19,7 +21,7 @@ namespace SabreTools.IO
public static string Ensure(this string dir, bool create = false)
{
// If the output directory is invalid
if (string.IsNullOrWhiteSpace(dir))
if (string.IsNullOrEmpty(dir))
dir = PathTool.GetRuntimeDirectory();
// Get the full path for the output directory
@@ -60,7 +62,7 @@ namespace SabreTools.IO
file.Dispose();
// Disable warning about UTF7 usage
#pragma warning disable SYSLIB0001
#pragma warning disable SYSLIB0001
// Analyze the BOM
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76) return Encoding.UTF7;
@@ -70,7 +72,7 @@ namespace SabreTools.IO
if (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff) return Encoding.UTF32;
return Encoding.Default;
#pragma warning restore SYSLIB0001
#pragma warning restore SYSLIB0001
}
catch
{
@@ -86,14 +88,14 @@ namespace SabreTools.IO
public static string? GetNormalizedExtension(this string? path)
{
// Check null or empty first
if (string.IsNullOrWhiteSpace(path))
if (string.IsNullOrEmpty(path))
return null;
// Get the extension from the path, if possible
string? ext = Path.GetExtension(path)?.ToLowerInvariant();
// Check if the extension is null or empty
if (string.IsNullOrWhiteSpace(ext))
if (string.IsNullOrEmpty(ext))
return null;
// Make sure that extensions are valid
@@ -118,13 +120,23 @@ namespace SabreTools.IO
return null;
// If it does and it is empty, return a blank enumerable
#if NET20 || NET35
if (Directory.GetFileSystemEntries(root, "*").Length == 0)
#else
if (!Directory.EnumerateFileSystemEntries(root, "*", SearchOption.AllDirectories).Any())
#endif
return new List<string>();
// Otherwise, get the complete list
#if NET20 || NET35
return Directory.GetDirectories(root, "*")
.Where(dir => Directory.GetFileSystemEntries(dir, "*").Length != 0)
.ToList();
#else
return Directory.EnumerateDirectories(root, "*", SearchOption.AllDirectories)
.Where(dir => !Directory.EnumerateFileSystemEntries(dir, "*", SearchOption.AllDirectories).Any())
.ToList();
#endif
}
}
}

View File

@@ -2,7 +2,9 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
using SabreTools.IO.Readers;
using SabreTools.IO.Writers;
@@ -198,14 +200,14 @@ namespace SabreTools.IO
string? value = keyValuePair.Value;
// We assume '.' is a section name separator
if (key.Contains('.'))
if (key.Contains("."))
{
// Split the key by '.'
string[] data = keyValuePair.Key.Split('.');
// If the key contains an '.', we need to put them back in
string newSection = data[0].Trim();
key = string.Join(".", data.Skip(1)).Trim();
key = string.Join(".", data.Skip(1).ToArray()).Trim();
// If we have a new section, write it out
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
@@ -231,9 +233,18 @@ namespace SabreTools.IO
#region IDictionary Impelementations
#if NET20 || NET35 || NET40 || NET452
public ICollection<string> Keys => _keyValuePairs?.Keys?.ToArray() ?? new string[0];
#else
public ICollection<string> Keys => _keyValuePairs?.Keys?.ToArray() ?? Array.Empty<string>();
#endif
#if NET20 || NET35 || NET40 || NET452
public ICollection<string?> Values => _keyValuePairs?.Values?.ToArray() ?? new string[0];
#else
public ICollection<string?> Values => _keyValuePairs?.Values?.ToArray() ?? Array.Empty<string?>();
#endif
public int Count => (_keyValuePairs as ICollection<KeyValuePair<string, string>>)?.Count ?? 0;

View File

@@ -11,8 +11,13 @@
using System;
using System.Collections.Generic;
#if !NET20
using System.Linq;
#endif
using System.Text.RegularExpressions;
#if NET20
using SabreTools.IO;
#endif
/// TODO: Make this namespace a separate library
namespace NaturalSort
@@ -49,13 +54,13 @@ namespace NaturalSort
if (!table.TryGetValue(x, out string[]? x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(y, y1);
}

View File

@@ -11,8 +11,13 @@
using System;
using System.Collections.Generic;
#if !NET20
using System.Linq;
#endif
using System.Text.RegularExpressions;
#if NET20
using SabreTools.IO;
#endif
/// TODO: Make this namespace a separate library
namespace NaturalSort
@@ -49,13 +54,13 @@ namespace NaturalSort
if (!table.TryGetValue(x, out string[]? x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(x, x1);
}
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
y1 = Regex.Split(y.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(y, y1);
}

194
OldDotNet.cs Normal file
View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
#if NET20
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
internal sealed class ExtensionAttribute : Attribute {}
}
namespace SabreTools.IO
{
internal delegate U LinqSelectDelegate<T, U>(T str);
internal delegate bool LinqWhereDelegate<T>(T str);
internal static partial class EnumerationExtensions
{
public static IEnumerable<T> Cast<T>(this MatchCollection arr)
{
var output = new List<T>();
foreach (var val in arr)
{
output.Add((T)val);
}
return output;
}
public static IEnumerable<U> Select<T, U>(this T[] arr, LinqSelectDelegate<T, U> func)
{
var output = new List<U>();
for (int i = 0; i < arr.Length; i++)
{
output.Add(func(arr[i]));
}
return output;
}
public static IEnumerable<U> Select<T, U>(this IEnumerable<T> arr, LinqSelectDelegate<T, U> func)
{
var output = new List<U>();
foreach (var s in arr)
{
output.Add(func(s));
}
return output;
}
public static IEnumerable<T> Skip<T>(this T[] arr, int skip)
{
var output = new List<T>();
for (int i = 0; i < arr.Length; i++)
{
if (i < skip)
continue;
output.Add(arr[i]);
}
return output;
}
public static IEnumerable<T> Skip<T>(this IEnumerable<T> arr, int skip)
{
var output = new List<T>();
int index = 0;
foreach (var s in arr)
{
if (index++ < skip)
continue;
output.Add(s);
}
return output;
}
public static T[] ToArray<T>(this IEnumerable<T> arr)
{
var list = arr.ToList();
var output = new T[list.Count];
int index = 0;
foreach (var s in list)
{
output[index++] = s;
}
return output;
}
public static U[] ToArray<T, U>(this Dictionary<T, U>.ValueCollection arr)
{
var list = arr.ToList();
var output = new U[list.Count];
int index = 0;
foreach (var s in list)
{
output[index++] = s;
}
return output;
}
public static List<T> ToList<T>(this IEnumerable<T> arr)
{
var output = new List<T>();
foreach (var s in arr)
{
output.Add(s);
}
return output;
}
public static List<U> ToList<T, U>(this Dictionary<T, U>.ValueCollection arr)
{
var output = new List<U>();
foreach (var s in arr)
{
output.Add(s);
}
return output;
}
public static IEnumerable<T> Where<T>(this T[] arr, LinqWhereDelegate<T> func)
{
var output = new List<T>();
for (int i = 0; i < arr.Length; i++)
{
if (func(arr[i]))
output.Add(arr[i]);
}
return output;
}
public static IEnumerable<T> Where<T>(this IEnumerable<T> arr, LinqWhereDelegate<T> func)
{
var output = new List<T>();
foreach (var s in arr)
{
if (func(s))
output.Add(s);
}
return output;
}
}
}
#endif
#if NET20 || NET35
namespace SabreTools.IO
{
internal static partial class EnumerationExtensions
{
public static bool SequenceEqual<T>(this T[] arr1, T[] arr2)
{
if (arr1 == null || arr2 == null)
return false;
if (arr1.Length != arr2.Length)
return false;
for (int i = 0; i < arr1.Length; i++)
{
if (arr1[i] == null || !arr1![i]!.Equals(arr2[i]))
return false;
}
return true;
}
}
}
#endif
#if NET20 || NET35 || NET40
namespace SabreTools.IO
{
internal delegate U LinqOrderByDelegate<T, U>(T str);
internal static partial class EnumerationExtensions
{
public static IEnumerable<T> OrderBy<T, U>(this IEnumerable<T> arr, LinqOrderByDelegate<T, U> func)
{
// TODO: Implement ordering
return arr;
}
}
internal static partial class StringExtensions
{
}
}
#endif

View File

@@ -32,14 +32,14 @@ namespace SabreTools.IO
public string? GetNormalizedFileName(bool sanitize)
{
// If the current path is empty, we can't do anything
if (string.IsNullOrWhiteSpace(CurrentPath))
if (string.IsNullOrEmpty(CurrentPath))
return null;
// Assume the current path is the filename
string filename = Path.GetFileName(CurrentPath);
// If we have a true ParentPath, remove it from CurrentPath and return the remainder
if (!string.IsNullOrWhiteSpace(ParentPath) && !string.Equals(CurrentPath, ParentPath, StringComparison.Ordinal))
if (string.IsNullOrEmpty(ParentPath) && !string.Equals(CurrentPath, ParentPath, StringComparison.Ordinal))
filename = CurrentPath.Remove(0, ParentPath!.Length + 1);
// If we're sanitizing the path after, do so
@@ -58,15 +58,15 @@ namespace SabreTools.IO
public string? GetOutputPath(string outDir, bool inplace)
{
// If the current path is empty, we can't do anything
if (string.IsNullOrWhiteSpace(CurrentPath))
if (string.IsNullOrEmpty(CurrentPath))
return null;
// If the output dir is empty (and we're not inplace), we can't do anything
if (string.IsNullOrWhiteSpace(outDir) && !inplace)
if (string.IsNullOrEmpty(outDir) && !inplace)
return null;
// Check if we have a split path or not
bool splitpath = !string.IsNullOrWhiteSpace(ParentPath);
bool splitpath = !string.IsNullOrEmpty(ParentPath);
// If we have an inplace output, use the directory name from the input path
if (inplace)
@@ -85,15 +85,9 @@ namespace SabreTools.IO
workingParent = Path.GetDirectoryName(ParentPath ?? string.Empty) ?? string.Empty;
// Determine the correct subfolder based on the working parent directory
#if NETFRAMEWORK
int extraLength = workingParent.EndsWith(":")
|| workingParent.EndsWith(Path.DirectorySeparatorChar.ToString())
|| workingParent.EndsWith(Path.AltDirectorySeparatorChar.ToString()) ? 0 : 1;
#else
int extraLength = workingParent.EndsWith(':')
|| workingParent.EndsWith(Path.DirectorySeparatorChar)
|| workingParent.EndsWith(Path.AltDirectorySeparatorChar) ? 0 : 1;
#endif
return Path.GetDirectoryName(Path.Combine(outDir, CurrentPath.Remove(0, workingParent.Length + extraLength)));
}

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using NaturalSort;
namespace SabreTools.IO
@@ -29,14 +31,10 @@ namespace SabreTools.IO
// If we have a wildcard
string pattern = "*";
if (input.Contains('*') || input.Contains('?'))
if (input.Contains("*") || input.Contains("?"))
{
pattern = Path.GetFileName(input);
#if NETFRAMEWORK
input = input.Substring(0, input.Length - pattern.Length);
#else
input = input[..^pattern.Length];
#endif
}
// Get the parent path in case of appending
@@ -75,7 +73,11 @@ namespace SabreTools.IO
private static List<string> GetDirectoriesOrderedHelper(string dir, List<string> infiles, string pattern)
{
// Take care of the files in the top directory
#if NET20 || NET35
List<string> toadd = Directory.GetDirectories(dir, pattern).ToList();
#else
List<string> toadd = Directory.EnumerateDirectories(dir, pattern, SearchOption.TopDirectoryOnly).ToList();
#endif
toadd.Sort(new NaturalComparer());
infiles.AddRange(toadd);
@@ -108,14 +110,10 @@ namespace SabreTools.IO
// If we have a wildcard
string pattern = "*";
if (input.Contains('*') || input.Contains('?'))
if (input.Contains("*") || input.Contains("?"))
{
pattern = Path.GetFileName(input);
#if NETFRAMEWORK
input = input.Substring(0, input.Length - pattern.Length);
#else
input = input[..^pattern.Length];
#endif
}
// Get the parent path in case of appending
@@ -158,12 +156,20 @@ namespace SabreTools.IO
private static List<string> GetFilesOrderedHelper(string dir, List<string> infiles, string pattern)
{
// Take care of the files in the top directory
#if NET20 || NET35
List<string> toadd = Directory.GetFiles(dir, pattern).ToList();
#else
List<string> toadd = Directory.EnumerateFiles(dir, pattern, SearchOption.TopDirectoryOnly).ToList();
#endif
toadd.Sort(new NaturalComparer());
infiles.AddRange(toadd);
// Then recurse through and add from the directories
#if NET20 || NET35
List<string> subDirs = Directory.GetDirectories(dir, pattern).ToList();
#else
List<string> subDirs = Directory.EnumerateDirectories(dir, pattern, SearchOption.TopDirectoryOnly).ToList();
#endif
subDirs.Sort(new NaturalComparer());
foreach (string subdir in subDirs)
{
@@ -173,7 +179,7 @@ namespace SabreTools.IO
// Return the new list
return infiles;
}
/// <summary>
/// Get the current runtime directory
/// </summary>

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
using System.Text.RegularExpressions;
@@ -131,11 +133,7 @@ namespace SabreTools.IO.Readers
// Standalone (special case for DC dats)
if (CurrentLine.StartsWith("Name:"))
{
#if NETFRAMEWORK
string temp = CurrentLine.Substring("Name:".Length).Trim();
#else
string temp = CurrentLine["Name:".Length..].Trim();
#endif
CurrentLine = $"Name: {temp}";
}
@@ -172,7 +170,7 @@ namespace SabreTools.IO.Readers
for (int i = 0; i < linegc.Length; i++)
{
string key = linegc[i].Replace("\"", string.Empty);
if (string.IsNullOrWhiteSpace(key))
if (string.IsNullOrEmpty(key))
continue;
string value = string.Empty;

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
namespace SabreTools.IO.Readers
@@ -111,14 +113,14 @@ namespace SabreTools.IO.Readers
}
// KeyValuePair
else if (CurrentLine.Contains('='))
else if (CurrentLine.Contains("="))
{
// Split the line by '=' for key-value pairs
string[] data = CurrentLine.Split('=');
// If the value field contains an '=', we need to put them back in
string key = data[0].Trim();
string value = string.Join("=", data.Skip(1)).Trim();
string value = string.Join("=", data.Skip(1).ToArray()).Trim();
KeyValuePair = new KeyValuePair<string, string>(key, value);
RowType = IniRowType.KeyValue;

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
using System.Text.RegularExpressions;
@@ -124,9 +126,11 @@ namespace SabreTools.IO.Readers
// https://stackoverflow.com/questions/3776458/split-a-comma-separated-string-with-both-quoted-and-unquoted-strings
var lineSplitRegex = new Regex($"(?:^|{Separator})(\"(?:[^\"]+|\"\")*\"|[^{Separator}]*)");
var temp = new List<string>();
foreach (Match match in lineSplitRegex.Matches(fullLine))
foreach (Match? match in lineSplitRegex.Matches(fullLine))
{
string curr = match.Value;
string? curr = match?.Value;
if (curr == null)
continue;
if (curr.Length == 0)
temp.Add("");
@@ -137,7 +141,7 @@ namespace SabreTools.IO.Readers
Line = temp;
}
// Otherwise, just split on the delimiter
else
{

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
#if !NET20
using System.Linq;
#endif
using System.Text;
namespace SabreTools.IO

View File

@@ -34,8 +34,8 @@ namespace SabreTools.IO.Writers
{
if (sw?.BaseStream == null)
return;
if (string.IsNullOrWhiteSpace(value))
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Section tag cannot be null or empty", nameof(value));
sw.WriteLine($"[{value!.TrimStart('[').TrimEnd(']')}]");
@@ -48,8 +48,8 @@ namespace SabreTools.IO.Writers
{
if (sw?.BaseStream == null)
return;
if (string.IsNullOrWhiteSpace(key))
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
value ??= string.Empty;
@@ -63,7 +63,7 @@ namespace SabreTools.IO.Writers
{
if (sw?.BaseStream == null)
return;
value ??= string.Empty;
sw.WriteLine($";{value}");
}
@@ -75,7 +75,7 @@ namespace SabreTools.IO.Writers
{
if (sw?.BaseStream == null)
return;
value ??= string.Empty;
sw.Write(value);
}
@@ -87,7 +87,7 @@ namespace SabreTools.IO.Writers
{
if (sw?.BaseStream == null)
return;
sw.WriteLine();
}