Skip to content

Commit

Permalink
v4.0.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
sahlaysta committed Sep 4, 2024
1 parent 0ad241d commit 9fe08bc
Show file tree
Hide file tree
Showing 26 changed files with 2,247 additions and 683 deletions.
14 changes: 7 additions & 7 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"configurations": [
"configurations": [,
{
"name": "x86-Debug",
"name": "x86-Release",
"generator": "Visual Studio 17 2022",
"configurationType": "Debug",
"configurationType": "Release",
"buildRoot": "${projectDir}\\out\\${name}\\_build\\msbuild",
"installRoot": "${projectDir}\\out\\${name}\\_install",
"cmakeCommandArgs": "-DDEBUGFLAG=ON",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
"variables": []
},
{
"name": "x86-Release",
"name": "x86-Debug",
"generator": "Visual Studio 17 2022",
"configurationType": "Release",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\${name}\\_build\\msbuild",
"installRoot": "${projectDir}\\out\\${name}\\_install",
"cmakeCommandArgs": "",
"cmakeCommandArgs": "-DDEBUGFLAG=ON",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86" ],
Expand Down
1 change: 1 addition & 0 deletions CSharp_Project.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function(CSharp_Project)
add_executable(${PARSED_ARGS_PROJECT_NAME} ${APPLICATIONTYPE} ${PARSED_ARGS_PROJECT_SOURCEFILES} ${PLACEHOLDER_EMBEDDEDRESOURCE_FILES})
set(CMAKE_CSharp_FLAGS "/langversion:latest")
set(CMAKE_CSharp_FLAGS "/platform:x86")
target_compile_options(${PARSED_ARGS_PROJECT_NAME} PUBLIC "/unsafe")
if(PARSED_ARGS_PROJECT_DEPENDS)
add_dependencies(${PARSED_ARGS_PROJECT_NAME} ${PARSED_ARGS_PROJECT_DEPENDS})
endif()
Expand Down
79 changes: 41 additions & 38 deletions Sahlaysta.PortableTerrariaCommon/Cecil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

namespace Sahlaysta.PortableTerrariaCommon
{

/// <summary>
/// Uses the Mono.Cecil library to rewrite the embedded resources of an assembly.
/// </summary>
internal static class Cecil
{

Expand All @@ -28,25 +32,20 @@ public static void AssemblyRewriteEmbeddedResources(
{
if (cecilAssembly == null || assemblyIn == null || assemblyOut == null)
{
throw new ArgumentException("Null");
throw new ArgumentNullException();
}

addResourceNames = (string[])(addResourceNames ?? new string[] { }).Clone();
removeResourceNames = (string[])(removeResourceNames ?? new string[] { }).Clone();

if (addResourceNames.Length > 0 && resourceReader == null)
{
throw new ArgumentException("Null");
}
if (addResourceNames.Contains(null) || removeResourceNames.Contains(null))
throw new ArgumentNullException();

if (addResourceNames.Length == 0 && removeResourceNames.Length == 0)
{
throw new ArgumentException("Empty");
}

if (addResourceNames.Contains(null) || removeResourceNames.Contains(null))
throw new ArgumentException("Null");

foreach (string addResourceName in addResourceNames)
if (addResourceNames.Count(x => x == addResourceName) > 1)
throw new ArgumentException("Add duplicate resource: " + addResourceName);
Expand All @@ -55,6 +54,11 @@ public static void AssemblyRewriteEmbeddedResources(
if (removeResourceNames.Contains(addResourceName))
throw new ArgumentException("Cannot both add and remove resource: " + addResourceName);

if (addResourceNames.Length > 0 && resourceReader == null)
{
throw new ArgumentNullException();
}

if (overrideCecilMemoryStream == null)
{
overrideCecilMemoryStream = (out Stream stream, out bool closeStream) =>
Expand Down Expand Up @@ -170,7 +174,7 @@ private class StreamDelegator : Stream

private void NullCheck()
{
if (stream == null) throw new ArgumentException("Null");
if (stream == null) { throw new ArgumentNullException(); }
}

protected override void Dispose(bool disposing)
Expand All @@ -185,7 +189,7 @@ protected override void Dispose(bool disposing)

private Stream GetStream()
{
if (disposed) throw new ObjectDisposedException(GetType().FullName);
if (disposed) { throw new ObjectDisposedException(GetType().FullName); }
return stream;
}

Expand All @@ -198,9 +202,9 @@ public override long Seek(long offset, SeekOrigin origin) {
return GetStream().Seek(offset, origin); }
public override void SetLength(long value) { GetStream().SetLength(value); }
public override long Length { get { return GetStream().Length; } }
public override bool CanRead { get { return GetStream().CanRead; } }
public override bool CanWrite { get { return GetStream().CanWrite; } }
public override bool CanSeek { get { return GetStream().CanSeek; } }
public override bool CanRead { get { return !disposed && GetStream().CanRead; } }
public override bool CanWrite { get { return !disposed && GetStream().CanWrite; } }
public override bool CanSeek { get { return !disposed && GetStream().CanSeek; } }
public override long Position {
get { return GetStream().Position; } set { GetStream().Position = value; } }

Expand All @@ -220,7 +224,7 @@ public StreamManager(DelegateReadResource drr)

public Stream NewStream(string resourceName)
{
if (disposed) throw new ObjectDisposedException(GetType().FullName);
if (disposed) { throw new ObjectDisposedException(GetType().FullName); }
return new StreamManagerStream(this, resourceName);
}

Expand All @@ -229,18 +233,20 @@ void IDisposable.Dispose()
if (disposed) return;
disposed = true;
drr = null;
current?.Close();
current = null;
using (current)
{
current = null;
}
}

private class StreamManagerStream : Stream
{

public readonly StreamManager streamManager;
public readonly string resourceName;
public Stream stream;
public bool closeStream;
public bool disposed;
private readonly StreamManager streamManager;
private readonly string resourceName;
private Stream stream;
private bool closeStream;
private bool disposed;

public StreamManagerStream(StreamManager streamManager, string resourceName)
{
Expand All @@ -250,24 +256,18 @@ public StreamManagerStream(StreamManager streamManager, string resourceName)

private Stream GetStream()
{
if (disposed) throw new ObjectDisposedException(GetType().FullName);
if (disposed) { throw new ObjectDisposedException(GetType().FullName); }

StreamManagerStream current = streamManager.current;
if (object.ReferenceEquals(current, this))
{
return stream;
}
else if (current == null)
{
streamManager.drr(resourceName, out stream, out closeStream);
if (stream == null) throw new ArgumentException("Null");
streamManager.current = this;
return stream;
}
else
{
current.Close();
current?.Close();
streamManager.drr(resourceName, out stream, out closeStream);
if (stream == null) throw new ArgumentException("Null");
if (stream == null) { throw new ArgumentNullException(); }
streamManager.current = this;
return stream;
}
Expand All @@ -279,11 +279,14 @@ protected override void Dispose(bool disposing)
disposed = true;
if (disposing)
streamManager.current = null;
Stream theStream = stream;
stream = null;
if (disposing && closeStream)
if (stream != null)
{
theStream?.Close();
Stream theStream = stream;
stream = null;
if (disposing && closeStream)
{
theStream.Close();
}
}
}

Expand All @@ -296,9 +299,9 @@ public override long Seek(long offset, SeekOrigin origin) {
return GetStream().Seek(offset, origin); }
public override void SetLength(long value) { GetStream().SetLength(value); }
public override long Length { get { return GetStream().Length; } }
public override bool CanRead { get { return GetStream().CanRead; } }
public override bool CanWrite { get { return GetStream().CanWrite; } }
public override bool CanSeek { get { return GetStream().CanSeek; } }
public override bool CanRead { get { return !disposed && GetStream().CanRead; } }
public override bool CanWrite { get { return !disposed && GetStream().CanWrite; } }
public override bool CanSeek { get { return !disposed && GetStream().CanSeek; } }
public override long Position {
get { return GetStream().Position; } set { GetStream().Position = value; } }

Expand Down
132 changes: 128 additions & 4 deletions Sahlaysta.PortableTerrariaCommon/DotNetZip.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Sahlaysta.PortableTerrariaCommon
{

/// <summary>
/// Uses the DotNetZip library to create and extract zip files.
/// </summary>
internal static class DotNetZip
{

public delegate void DelegateWriteEntry(string entryName, Stream stream);

public delegate void ProgressCallback(int nEntriesProcessed, int nEntriesTotal);
public delegate void DelegateExtractEntry(string entryName, out Stream stream, out bool closeStream);

public delegate void ProgressCallback(int entriesProcessed, int entriesTotal);

public static void WriteZipArchive(
Assembly dotNetZipAssembly,
Expand All @@ -22,19 +29,19 @@ public static void WriteZipArchive(
{
if (dotNetZipAssembly == null || outStream == null)
{
throw new ArgumentException("Null");
throw new ArgumentNullException();
}

entryNames = (string[])(entryNames ?? new string[] { }).Clone();

if (entryNames.Length > 0 && entryWriter == null)
{
throw new ArgumentException("Null");
throw new ArgumentNullException();
}

if (entryNames.Contains(null))
{
throw new ArgumentException("Null");
throw new ArgumentNullException();
}

Type zipFileType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipFile");
Expand Down Expand Up @@ -83,6 +90,123 @@ public static void WriteZipArchive(

}

public static void ExtractZipArchive(
Assembly dotNetZipAssembly,
Stream inStream,
string[] entryNames,
DelegateExtractEntry entryExtractor,
ProgressCallback progressCallback)
{
if (dotNetZipAssembly == null || inStream == null)
{
throw new ArgumentNullException();
}

entryNames = (string[])(entryNames ?? new string[] { }).Clone();

if (entryNames.Contains(null))
{
throw new ArgumentNullException();
}

if (entryNames.Length > 0 && entryExtractor == null)
{
throw new ArgumentNullException();
}

HashSet<string> entryNameSet = new HashSet<string>(entryNames);

Type zipFileType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipFile");
Type zipEntryType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipEntry");
MethodInfo readMethod = ReflectionHelper.GetMethod(zipFileType, "Read", new Type[] { typeof(Stream) });
PropertyInfo entriesProperty = ReflectionHelper.GetProperty(zipFileType, "Entries");
PropertyInfo fileNameProperty = ReflectionHelper.GetProperty(zipEntryType, "FileName");
MethodInfo extractMethod = ReflectionHelper.GetMethod(
zipEntryType, "Extract", new Type[] { typeof(Stream) });

IDisposable zipEntry = (IDisposable)readMethod.Invoke(null, new object[] { inStream });
using (zipEntry)
{
IEnumerable entries = (IEnumerable)entriesProperty.GetValue(zipEntry);

HashSet<string> zipEntryNames = new HashSet<string>(
entries.Cast<object>().Select(x => (string)fileNameProperty.GetValue(x)));
foreach (string entryName in entryNames)
{
if (!zipEntryNames.Contains(entryName))
{
throw new Exception("Entry name not found in archive: " + entryName);
}
if (entryName.EndsWith("/"))
{
throw new Exception("Entry name cannot be a folder: " + entryName);
}
}

IEnumerator entryEnumerator = entries.GetEnumerator();
int entriesProcessed = 0;
int entriesTotal = entryNames.Length;
while (entryEnumerator.MoveNext())
{
object entry = entryEnumerator.Current;
string entryName = (string)fileNameProperty.GetValue(entry);
if (entryNameSet.Contains(entryName))
{
Stream stream;
bool closeStream;
entryExtractor(entryName, out stream, out closeStream);
if (stream == null) { throw new ArgumentNullException(); }
try
{
extractMethod.Invoke(entry, new object[] { stream });
}
finally
{
if (closeStream)
{
stream.Close();
}
}
if (progressCallback != null)
{
progressCallback(entriesProcessed++, entriesTotal);
}
}
}
}
}

public static string[] ReadZipArchiveEntryNames(Assembly dotNetZipAssembly, Stream inStream)
{
if (dotNetZipAssembly == null || inStream == null)
{
throw new ArgumentNullException();
}

Type zipFileType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipFile");
Type zipEntryType = ReflectionHelper.GetType(dotNetZipAssembly, "Ionic.Zip.ZipEntry");
MethodInfo readMethod = ReflectionHelper.GetMethod(zipFileType, "Read", new Type[] { typeof(Stream) });
PropertyInfo entriesProperty = ReflectionHelper.GetProperty(zipFileType, "Entries");
PropertyInfo fileNameProperty = ReflectionHelper.GetProperty(zipEntryType, "FileName");
MethodInfo extractMethod = ReflectionHelper.GetMethod(
zipEntryType, "Extract", new Type[] { typeof(Stream) });

IDisposable zipEntry = (IDisposable)readMethod.Invoke(null, new object[] { inStream });
List<string> entryNames = new List<string>();
using (zipEntry)
{
IEnumerable entries = (IEnumerable)entriesProperty.GetValue(zipEntry);
IEnumerator entryEnumerator = entries.GetEnumerator();
while (entryEnumerator.MoveNext())
{
object entry = entryEnumerator.Current;
string entryName = (string)fileNameProperty.GetValue(entry);
entryNames.Add(entryName);
}
}
return entryNames.ToArray();
}

private class WriteDelegateImpl
{

Expand Down
Loading

0 comments on commit 9fe08bc

Please sign in to comment.