5 Commits

Author SHA1 Message Date
Matt Nadareski
897e54ca61 Bump version 2024-11-13 00:44:44 -05:00
Matt Nadareski
3af6bc8365 Add .NET 9 to target frameworks 2024-11-13 00:44:16 -05:00
Matt Nadareski
de05bae3f8 Be smarter about framework gating 2024-11-05 21:47:43 -05:00
Matt Nadareski
97d603abb7 Update Matching to 1.3.4 2024-11-05 20:57:53 -05:00
Matt Nadareski
ed32302447 Update Matching to 1.3.3 2024-10-26 19:45:12 -04:00
14 changed files with 134 additions and 256 deletions

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore

View File

@@ -11,7 +11,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
dotnet-version: 9.0.x
- name: Build
run: dotnet build

View File

@@ -1,29 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsNotAsErrors>CS0618</WarningsNotAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.IO\SabreTools.IO.csproj" />
</ItemGroup>
</Project>
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsNotAsErrors>CS0618</WarningsNotAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.IO\SabreTools.IO.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
#if NET7_0_OR_GREATER
using System.Numerics;
#endif
@@ -667,19 +664,17 @@ namespace SabreTools.IO.Extensions
/// </summary>
private static string? ReadStringType(BinaryReader reader, Encoding encoding, FieldInfo? fi)
{
#if NET20 || NET35
var attributes = fi?.GetCustomAttributes(typeof(MarshalAsAttribute), true);
MarshalAsAttribute? marshalAsAttr;
if (attributes == null || attributes.Length == 0)
marshalAsAttr = default;
else
marshalAsAttr = attributes[0] as MarshalAsAttribute;
#else
var marshalAsAttr = fi?
.GetCustomAttributes(typeof(MarshalAsAttribute), true)?
.FirstOrDefault() as MarshalAsAttribute;
#endif
// If the FieldInfo is null
if (fi == null)
return null;
// Get all MarshalAs attributes for the field, if possible
var attributes = fi.GetCustomAttributes(typeof(MarshalAsAttribute), true);
if (attributes.Length == 0)
return null;
// Use the first found attribute
var marshalAsAttr = attributes[0] as MarshalAsAttribute;
switch (marshalAsAttr?.Value)
{
case UnmanagedType.AnsiBStr:

View File

@@ -1,11 +1,5 @@
#if NETCOREAPP3_1_OR_GREATER
using System;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
namespace SabreTools.IO.Extensions
@@ -61,7 +55,7 @@ namespace SabreTools.IO.Extensions
// Read the BOM
var bom = new byte[4];
file.Read(bom, 0, 4);
int read = file.Read(bom, 0, 4);
file.Dispose();
// Disable warning about UTF7 usage
@@ -115,48 +109,33 @@ namespace SabreTools.IO.Extensions
public static List<string>? ListEmpty(this string? root)
{
// Check null or empty first
if (string.IsNullOrEmpty(root))
if (root == null)
return null;
// Then, check if the root exists
if (!Directory.Exists(root))
return null;
// If it does and it is empty, return a blank enumerable
#if NET20 || NET35
if (new List<string>(root!.SafeEnumerateFileSystemEntries("*", SearchOption.AllDirectories)).Count == 0)
#else
if (!root!.SafeEnumerateFileSystemEntries("*", SearchOption.AllDirectories).Any())
#endif
return [];
// Otherwise, get the complete list
#if NET20 || NET35
var empty = new List<string>();
foreach (var dir in root!.SafeEnumerateDirectories("*", SearchOption.AllDirectories))
foreach (var dir in SafeGetDirectories(root, "*", SearchOption.AllDirectories))
{
if (new List<string>(dir!.SafeEnumerateFileSystemEntries("*", SearchOption.AllDirectories)).Count == 0)
if (SafeGetFiles(dir).Length == 0)
empty.Add(dir);
}
return empty;
#else
return root!.SafeEnumerateDirectories("*", SearchOption.AllDirectories)
.Where(dir => !dir.SafeEnumerateFileSystemEntries("*", SearchOption.AllDirectories).Any())
.ToList();
#endif
}
#region Safe Directory Enumeration
/// <inheritdoc cref="Directory.GetDirectories(string)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetDirectories(this string path)
public static string[] SafeGetDirectories(this string path)
{
try
{
var enumerable = Directory.GetDirectories(path);
return enumerable.SafeEnumerate();
return Directory.GetDirectories(path);
}
catch
{
@@ -166,12 +145,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetDirectories(string, string)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetDirectories(this string path, string searchPattern)
public static string[] SafeGetDirectories(this string path, string searchPattern)
{
try
{
var enumerable = Directory.GetDirectories(path, searchPattern);
return enumerable.SafeEnumerate();
return Directory.GetDirectories(path, searchPattern);
}
catch
{
@@ -181,12 +159,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetDirectories(string, string, SearchOption)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetDirectories(this string path, string searchPattern, SearchOption searchOption)
public static string[] SafeGetDirectories(this string path, string searchPattern, SearchOption searchOption)
{
try
{
var enumerable = Directory.GetDirectories(path, searchPattern, searchOption);
return enumerable.SafeEnumerate();
return Directory.GetDirectories(path, searchPattern, searchOption);
}
catch
{
@@ -196,12 +173,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetFiles(string)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetFiles(this string path)
public static string[] SafeGetFiles(this string path)
{
try
{
var enumerable = Directory.GetFiles(path);
return enumerable.SafeEnumerate();
return Directory.GetFiles(path);
}
catch
{
@@ -211,12 +187,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetFiles(string, string)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetFiles(this string path, string searchPattern)
public static string[] SafeGetFiles(this string path, string searchPattern)
{
try
{
var enumerable = Directory.GetFiles(path, searchPattern);
return enumerable.SafeEnumerate();
return Directory.GetFiles(path, searchPattern);
}
catch
{
@@ -226,12 +201,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetFiles(string, string, SearchOption)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetFiles(this string path, string searchPattern, SearchOption searchOption)
public static string[] SafeGetFiles(this string path, string searchPattern, SearchOption searchOption)
{
try
{
var enumerable = Directory.GetFiles(path, searchPattern, searchOption);
return enumerable.SafeEnumerate();
return Directory.GetFiles(path, searchPattern, searchOption);
}
catch
{
@@ -241,12 +215,11 @@ namespace SabreTools.IO.Extensions
/// <inheritdoc cref="Directory.GetFileSystemEntries(string)"/>
/// <remarks>Returns an empty enumerable on any exception</remarks>
public static IEnumerable<string> SafeGetFileSystemEntries(this string path)
public static string[] SafeGetFileSystemEntries(this string path)
{
try
{
var enumerable = Directory.GetFileSystemEntries(path);
return enumerable.SafeEnumerate();
return Directory.GetFileSystemEntries(path);
}
catch
{
@@ -614,7 +587,7 @@ namespace SabreTools.IO.Extensions
private static EnumerationOptions FromSearchOption(SearchOption searchOption)
{
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
throw new ArgumentOutOfRangeException(nameof(searchOption));
throw new System.ArgumentOutOfRangeException(nameof(searchOption));
return searchOption == SearchOption.AllDirectories
? new EnumerationOptions { RecurseSubdirectories = true, MatchType = MatchType.Win32, AttributesToSkip = 0, IgnoreInaccessible = false }

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
@@ -117,21 +114,9 @@ namespace SabreTools.IO.Extensions
var nextFields = nextType.GetFields();
foreach (var field in nextFields)
{
#if NET20 || NET35
bool any = false;
foreach (var f in fieldsList)
{
if (f.Name == field.Name && f.FieldType == field.FieldType)
{
any = true;
break;
}
}
if (!any)
#else
if (!fieldsList.Any(f => f.Name == field.Name && f.FieldType == field.FieldType))
#endif
// Add fields if they aren't already included
int index = fieldsList.FindIndex(f => f.Name == field.Name && f.FieldType == field.FieldType);
if (index == -1)
fieldsList.Add(field);
}
}

View File

@@ -2,9 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
using SabreTools.IO.Readers;
using SabreTools.IO.Writers;
@@ -16,13 +13,12 @@ namespace SabreTools.IO
/// </summary>
public class IniFile : IDictionary<string, string?>
{
private Dictionary<string, string?>? _keyValuePairs = [];
private readonly Dictionary<string, string?> _keyValuePairs = [];
public string? this[string? key]
{
get
{
_keyValuePairs ??= [];
key = key?.ToLowerInvariant() ?? string.Empty;
if (_keyValuePairs.ContainsKey(key))
return _keyValuePairs[key];
@@ -31,7 +27,6 @@ namespace SabreTools.IO
}
set
{
_keyValuePairs ??= [];
key = key?.ToLowerInvariant() ?? string.Empty;
_keyValuePairs[key] = value;
}
@@ -49,7 +44,7 @@ namespace SabreTools.IO
/// </summary>
public IniFile(string path)
{
this.Parse(path);
Parse(path);
}
/// <summary>
@@ -57,7 +52,7 @@ namespace SabreTools.IO
/// </summary>
public IniFile(Stream stream)
{
this.Parse(stream);
Parse(stream);
}
/// <summary>
@@ -73,7 +68,7 @@ namespace SabreTools.IO
/// </summary>
public bool Remove(string key)
{
if (_keyValuePairs != null && _keyValuePairs.ContainsKey(key))
if (_keyValuePairs.ContainsKey(key))
{
_keyValuePairs.Remove(key.ToLowerInvariant());
return true;
@@ -156,7 +151,7 @@ namespace SabreTools.IO
public bool Write(string path)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
if (_keyValuePairs.Count == 0)
return false;
using var fileStream = File.OpenWrite(path);
@@ -169,7 +164,7 @@ namespace SabreTools.IO
public bool Write(Stream stream)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
if (_keyValuePairs.Count == 0)
return false;
// If the stream is invalid or unwritable, we can't output to it
@@ -180,41 +175,29 @@ namespace SabreTools.IO
{
using IniWriter writer = new(stream, Encoding.UTF8);
// Order the dictionary by keys to link sections together
#if NET20 || NET35
var orderedKeyValuePairs = new List<KeyValuePair<string, string?>>();
foreach (var kvp in _keyValuePairs)
{
orderedKeyValuePairs.Add(kvp);
}
orderedKeyValuePairs.Sort((x, y) => x.Key.CompareTo(y.Key));
#else
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
#endif
// Order the keys to link sections together
var orderedKeys = new string[_keyValuePairs.Keys.Count];
_keyValuePairs.Keys.CopyTo(orderedKeys, 0);
Array.Sort(orderedKeys);
string section = string.Empty;
foreach (var keyValuePair in orderedKeyValuePairs)
for (int i = 0; i < orderedKeys.Length; i++)
{
// Extract the key and value
string key = keyValuePair.Key;
string? value = keyValuePair.Value;
// Retrive the key and value
string key = orderedKeys[i];
string? value = _keyValuePairs[key];
// We assume '.' is a section name separator
if (key.Contains("."))
{
// Split the key by '.'
string[] data = keyValuePair.Key.Split('.');
string[] data = key.Split('.');
// If the key contains an '.', we need to put them back in
string newSection = data[0].Trim();
#if NET20 || NET35
string[] dataKey = new string[data.Length - 1];
Array.Copy(data, 1, dataKey, 0, dataKey.Length);
key = string.Join(".", dataKey).Trim();
#else
key = string.Join(".", data.Skip(1).ToArray()).Trim();
#endif
string[] keyArr = new string[data.Length - 1];
Array.Copy(data, 1, keyArr, 0, keyArr.Length);
key = string.Join(".", keyArr).Trim();
// If we have a new section, write it out
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
@@ -239,39 +222,9 @@ namespace SabreTools.IO
#region IDictionary Impelementations
#if NET20 || NET35
public ICollection<string> Keys
{
get
{
var keys = _keyValuePairs?.Keys;
if (keys == null || keys.Count == 0)
return [];
var keyArr = new string[keys.Count];
keys.CopyTo(keyArr, 0);
return keyArr;
}
}
public ICollection<string> Keys => _keyValuePairs.Keys;
public ICollection<string?> Values
{
get
{
var values = _keyValuePairs?.Values;
if (values == null || values.Count == 0)
return [];
var valueArr = new string[values.Count];
values.CopyTo(valueArr, 0);
return valueArr;
}
}
#else
public ICollection<string> Keys => _keyValuePairs?.Keys?.ToArray() ?? [];
public ICollection<string?> Values => _keyValuePairs?.Values?.ToArray() ?? [];
#endif
public ICollection<string?> Values => _keyValuePairs.Values;
public int Count => (_keyValuePairs as ICollection<KeyValuePair<string, string>>)?.Count ?? 0;

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
using System.Text.RegularExpressions;
@@ -297,24 +294,10 @@ namespace SabreTools.IO.Readers
s = s.Trim();
// Now we get each string, divided up as cleanly as possible
#if NET20 || NET35
var matchList = Regex.Matches(s, InternalPatternAttributesCMP);
var matchStrings = new List<string>();
foreach (Match m in matchList)
{
matchStrings.Add(m.Groups[0].Value);
}
string[] matches = matchStrings.ToArray();
#else
string[] matches = Regex
.Matches(s, InternalPatternAttributesCMP)
.Cast<Match>()
.Select(m => m.Groups[0].Value)
.ToArray();
#endif
return matches;
var matchArr = new Match[matchList.Count];
matchList.CopyTo(matchArr, 0);
return Array.ConvertAll(matchArr, m => m.Groups[0].Value);
}
/// <summary>

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
namespace SabreTools.IO.Readers
@@ -120,13 +117,9 @@ namespace SabreTools.IO.Readers
// If the value field contains an '=', we need to put them back in
string key = data[0].Trim();
#if NET20 || NET35
var valueArr = new string[data.Length - 1];
Array.Copy(data, 1, valueArr, 0, valueArr.Length);
string value = string.Join("=", valueArr).Trim();
#else
string value = string.Join("=", data.Skip(1).ToArray()).Trim();
#endif
KeyValuePair = new KeyValuePair<string, string>(key, value);
RowType = IniRowType.KeyValue;

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
using System.Text;
using System.Text.RegularExpressions;
@@ -126,11 +123,7 @@ 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>();
#if NET20 || NET35
foreach (Match? match in lineSplitRegex.Matches(fullLine))
#else
foreach (Match? match in lineSplitRegex.Matches(fullLine).Cast<Match?>())
#endif
{
string? curr = match?.Value;
if (curr == null)
@@ -149,17 +142,9 @@ namespace SabreTools.IO.Readers
// Otherwise, just split on the delimiter
else
{
#if NET20 || NET35
Line = new List<string>();
foreach (string f in fullLine.Split(Separator))
{
Line.Add(f.Trim());
}
#else
Line = fullLine.Split(Separator)
.Select(f => f.Trim())
.ToList();
#endif
var lineArr = fullLine.Split(Separator);
lineArr = Array.ConvertAll(lineArr, f => f.Trim());
Line = [.. lineArr];
}
// If we don't have a header yet and are expecting one, read this as the header

View File

@@ -1,32 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Assembly Properties -->
<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>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.4.13</Version>
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>1.5.0</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Common IO utilities by other SabreTools projects</Description>
<Copyright>Copyright (c) Matt Nadareski 2019-2024</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.IO</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>io reading writing ini csv ssv tsv</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Common IO utilities by other SabreTools projects</Description>
<Copyright>Copyright (c) Matt Nadareski 2019-2024</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.IO</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>io reading writing ini csv ssv tsv</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<None Include="../README.md" Pack="true" PackagePath="" />
</ItemGroup>
<!-- Support All Frameworks -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SabreTools.Matching" Version="1.3.2" />
</ItemGroup>
<ItemGroup>
<None Include="../README.md" Pack="true" PackagePath="" />
</ItemGroup>
</Project>
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`))">
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.Matching" Version="1.4.0" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET40_OR_GREATER || NETCOREAPP
using System.Linq;
#endif
namespace SabreTools.IO.Streams
{
@@ -112,11 +109,7 @@ namespace SabreTools.IO.Streams
/// </summary>
public ReadOnlyCompositeStream(IEnumerable<Stream> streams)
{
#if NET20 || NET35
_streams = new List<Stream>(streams);
#else
_streams = streams.ToList();
#endif
_length = 0;
_position = 0;

View File

@@ -1,7 +1,7 @@
#! /bin/bash
# This batch file assumes the following:
# - .NET 8.0 (or newer) SDK is installed and in PATH
# - .NET 9.0 (or newer) SDK is installed and in PATH
#
# If any of these are not satisfied, the operation may fail
# in an unpredictable way and result in an incomplete output.

View File

@@ -1,5 +1,5 @@
# This batch file assumes the following:
# - .NET 8.0 (or newer) SDK is installed and in PATH
# - .NET 9.0 (or newer) SDK is installed and in PATH
#
# If any of these are not satisfied, the operation may fail
# in an unpredictable way and result in an incomplete output.