19 Commits
0.2.0 ... 0.4.3

Author SHA1 Message Date
Matt Nadareski
a0f602ed6f Bump version the correct way 2024-04-16 12:07:15 -04:00
Matt Nadareski
4bc7f53c9f Bump version 2024-04-16 12:05:46 -04:00
Matt Nadareski
049a8cf499 Minor fixes and tweaks 2024-04-16 12:04:58 -04:00
Matt Nadareski
9a8875f1e0 Update SabreTools.IO 2024-04-16 12:03:05 -04:00
Matt Nadareski
a916cb9954 Bump version 2024-04-03 22:51:17 -04:00
Matt Nadareski
a6ef762a73 Update SabreTools.Models 2024-04-03 22:49:32 -04:00
Matt Nadareski
7aac1e0bed Bump version 2024-04-02 16:08:42 -04:00
Matt Nadareski
bc569964d8 Update packages 2024-04-02 16:08:17 -04:00
Matt Nadareski
a3ac98a9f4 Bump version 2024-03-24 23:00:41 -04:00
Matt Nadareski
57c0f9b747 Import zlib port, with apologies to Nanook 2024-03-24 22:51:55 -04:00
Matt Nadareski
38f3ea1c98 Bump version 2024-03-12 16:48:36 -04:00
Matt Nadareski
ab36802840 Update packages 2024-03-12 16:34:07 -04:00
Matt Nadareski
422bda1830 Update SabreTools.IO 2024-03-05 11:11:07 -05:00
Matt Nadareski
1c989985d9 Update copyright date 2024-02-27 19:08:56 -05:00
Matt Nadareski
62c6e79ad3 Add nuget package and PR workflows 2024-02-27 19:08:42 -05:00
Matt Nadareski
6bbf521828 Fix repository URL 2023-11-22 09:40:32 -05:00
Matt Nadareski
7a4e2f0ee0 Bump version 2023-11-22 09:39:29 -05:00
Matt Nadareski
1d1a6f5976 Support .NET Framework 2.0 2023-11-22 09:39:18 -05:00
Matt Nadareski
065b68124b Update SabreTools libraries 2023-11-22 09:36:36 -05:00
17 changed files with 7989 additions and 12 deletions

43
.github/workflows/build_nupkg.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Nuget Pack
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Pack
run: dotnet pack
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: 'Nuget Package'
path: 'bin/Release/*.nupkg'
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: 'bin/Release/*.nupkg'
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

17
.github/workflows/check_pr.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Build
run: dotnet build

View File

@@ -2,6 +2,7 @@ using System;
using System.IO;
using SabreTools.IO;
// TODO: Add more complete implementation to SabreTools.IO
namespace SabreTools.Compression
{
/// <summary>
@@ -18,7 +19,7 @@ namespace SabreTools.Compression
/// <summary>
/// Original stream source
/// </summary>
private Stream _source;
private readonly Stream _source;
/// <summary>
/// Last read byte value from the stream

View File

@@ -57,7 +57,7 @@ namespace SabreTools.Compression.LZ
long read = lz.CopyTo(sourceState, destState, out LZERROR error);
// Copy the data to the buffer
var decompressed = new byte[0];
byte[]? decompressed;
if (read == 0 || (error != LZERROR.LZERROR_OK && error != LZERROR.LZERROR_NOT_LZ))
{
decompressed = null;
@@ -91,7 +91,7 @@ namespace SabreTools.Compression.LZ
string inputExtension = Path.GetExtension(input).TrimStart('.');
// If we have no extension
if (string.IsNullOrWhiteSpace(inputExtension))
if (string.IsNullOrEmpty(inputExtension))
return Path.GetFileNameWithoutExtension(input);
// If we have an extension of length 1
@@ -552,6 +552,6 @@ namespace SabreTools.Compression.LZ
return fileHeader;
}
#endregion
#endregion
}
}

View File

@@ -13,7 +13,7 @@ namespace SabreTools.Compression.MSZIP
/// <summary>
/// Internal bitstream to use for decompression
/// </summary>
private BitStream _bitStream;
private readonly BitStream _bitStream;
/// <summary>
/// Create a new Decompressor from a byte array

50
OldDotNet.cs Normal file
View File

@@ -0,0 +1,50 @@
#if NET20 || NET35
using System;
using System.IO;
namespace SabreTools.Compression
{
/// <summary>
/// Derived from the mscorlib code from .NET Framework 4.0
/// </summary>
internal static class OldDotNet
{
public static void CopyTo(this Stream source, Stream destination)
{
if (destination == null)
{
throw new ArgumentNullException("destination");
}
if (!source.CanRead && !source.CanWrite)
{
throw new ObjectDisposedException(null);
}
if (!destination.CanRead && !destination.CanWrite)
{
throw new ObjectDisposedException("destination");
}
if (!source.CanRead)
{
throw new NotSupportedException();
}
if (!destination.CanWrite)
{
throw new NotSupportedException();
}
byte[] array = new byte[81920];
int count;
while ((count = source.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
}
}
#endif

View File

@@ -12,3 +12,9 @@ Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTo
| MSZIP | Yes* | No |
**Note:** If something is marked with a `*` it means that it need testing.
## External Libraries
| Library Name | Use |
| --- | ---|
| [ZLibPort](https://github.com/Nanook/zlib-C-To-CSharp-Port) | Adds zlib code for internal and external use; minor edits have been made |

View File

@@ -2,33 +2,33 @@
<PropertyGroup>
<!-- Assembly Properties -->
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>0.2.0</Version>
<Version>0.4.3</Version>
<!-- Package Properties -->
<Authors>Matt Nadareski</Authors>
<Description>Clean compression implementations</Description>
<Copyright>Copyright (c) Matt Nadareski 2022-2023</Copyright>
<Copyright>Copyright (c) Matt Nadareski 2022-2024</Copyright>
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Printing</RepositoryUrl>
<RepositoryUrl>https://github.com/SabreTools/SabreTools.Compression</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>compression decompression lz mszip</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath=""/>
<None Include="README.md" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="1.2.0" />
<PackageReference Include="SabreTools.Models" Version="1.2.0" />
<PackageReference Include="SabreTools.IO" Version="1.3.4" />
<PackageReference Include="SabreTools.Models" Version="1.4.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,218 @@
using System;
using System.Runtime.InteropServices;
namespace SabreTools.Compression.zlib
{
public static unsafe class CRuntime
{
private static readonly string numbers = "0123456789";
public static void* malloc(ulong size)
{
return malloc((long)size);
}
public static void* malloc(long size)
{
var ptr = Marshal.AllocHGlobal((int)size);
MemoryStats.Allocated();
return ptr.ToPointer();
}
public static void free(void* a)
{
if (a == null)
return;
var ptr = new IntPtr(a);
Marshal.FreeHGlobal(ptr);
MemoryStats.Freed();
}
public static void memcpy(void* a, void* b, long size)
{
var ap = (byte*)a;
var bp = (byte*)b;
for (long i = 0; i < size; ++i)
*ap++ = *bp++;
}
public static void memcpy(void* a, void* b, ulong size)
{
memcpy(a, b, (long)size);
}
public static void memmove(void* a, void* b, long size)
{
void* temp = null;
try
{
temp = malloc(size);
memcpy(temp, b, size);
memcpy(a, temp, size);
}
finally
{
if (temp != null)
free(temp);
}
}
public static void memmove(void* a, void* b, ulong size)
{
memmove(a, b, (long)size);
}
public static int memcmp(void* a, void* b, long size)
{
var result = 0;
var ap = (byte*)a;
var bp = (byte*)b;
for (long i = 0; i < size; ++i)
{
if (*ap != *bp)
result += 1;
ap++;
bp++;
}
return result;
}
public static int memcmp(void* a, void* b, ulong size)
{
return memcmp(a, b, (long)size);
}
public static int memcmp(byte* a, byte[] b, ulong size)
{
fixed (void* bptr = b)
{
return memcmp(a, bptr, (long)size);
}
}
public static void memset(void* ptr, int value, long size)
{
var bptr = (byte*)ptr;
var bval = (byte)value;
for (long i = 0; i < size; ++i)
*bptr++ = bval;
}
public static void memset(void* ptr, int value, ulong size)
{
memset(ptr, value, (long)size);
}
public static uint _lrotl(uint x, int y)
{
return (x << y) | (x >> (32 - y));
}
public static void* realloc(void* a, long newSize)
{
if (a == null)
return malloc(newSize);
var ptr = new IntPtr(a);
var result = Marshal.ReAllocHGlobal(ptr, new IntPtr(newSize));
return result.ToPointer();
}
public static void* realloc(void* a, ulong newSize)
{
return realloc(a, (long)newSize);
}
public static int abs(int v)
{
return Math.Abs(v);
}
public static double pow(double a, double b)
{
return Math.Pow(a, b);
}
public static void SetArray<T>(T[] data, T value)
{
for (var i = 0; i < data.Length; ++i)
data[i] = value;
}
public static double ldexp(double number, int exponent)
{
return number * Math.Pow(2, exponent);
}
public static int strcmp(sbyte* src, string token)
{
var result = 0;
for (var i = 0; i < token.Length; ++i)
{
if (src[i] != token[i])
{
++result;
}
}
return result;
}
public static int strncmp(sbyte* src, string token, ulong size)
{
var result = 0;
for (var i = 0; i < Math.Min(token.Length, (int)size); ++i)
{
if (src[i] != token[i])
{
++result;
}
}
return result;
}
public static long strtol(sbyte* start, sbyte** end, int radix)
{
// First step - determine length
var length = 0;
sbyte* ptr = start;
while (numbers.IndexOf((char)*ptr) != -1)
{
++ptr;
++length;
}
long result = 0;
// Now build up the number
ptr = start;
while (length > 0)
{
long num = numbers.IndexOf((char)*ptr);
long pow = (long)Math.Pow(10, length - 1);
result += num * pow;
++ptr;
--length;
}
if (end != null)
{
*end = ptr;
}
return result;
}
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Threading;
namespace SabreTools.Compression.zlib
{
public unsafe static class MemoryStats
{
private static int _allocations;
public static int Allocations
{
get
{
return _allocations;
}
}
internal static void Allocated()
{
Interlocked.Increment(ref _allocations);
}
internal static void Freed()
{
Interlocked.Decrement(ref _allocations);
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Runtime.InteropServices;
namespace SabreTools.Compression.zlib
{
public unsafe class UnsafeArray1D<T> where T : struct
{
private readonly T[] _data;
private readonly GCHandle _pinHandle;
public bool IsFreed { get; private set; }
internal GCHandle PinHandle => _pinHandle;
public T this[int index]
{
get => _data[index];
set
{
_data[index] = value;
}
}
public T this[uint index]
{
get => _data[index];
set
{
_data[index] = value;
}
}
public T[] Data => _data;
public UnsafeArray1D(int size)
{
if (size < 0)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
_data = new T[size];
_pinHandle = GCHandle.Alloc(_data, GCHandleType.Pinned);
IsFreed = false;
}
public UnsafeArray1D(T[] data, int sizeOf)
{
if (sizeOf <= 0)
{
throw new ArgumentOutOfRangeException(nameof(sizeOf));
}
_data = data ?? throw new ArgumentNullException(nameof(data));
_pinHandle = GCHandle.Alloc(_data, GCHandleType.Pinned);
IsFreed = false;
}
public void Free()
{
if (!IsFreed)
{
_pinHandle.Free();
IsFreed = true;
}
}
~UnsafeArray1D()
{
if (!IsFreed)
_pinHandle.Free();
}
public void* ToPointer()
{
return _pinHandle.AddrOfPinnedObject().ToPointer();
}
public static implicit operator void*(UnsafeArray1D<T> array)
{
return array.ToPointer();
}
public static void* operator +(UnsafeArray1D<T> array, int delta)
{
return array.ToPointer();
}
}
}

View File

@@ -0,0 +1,45 @@
using System.Runtime.InteropServices;
namespace SabreTools.Compression.zlib
{
public unsafe class UnsafeArray2D<T> where T : struct
{
private readonly UnsafeArray1D<T>[] _data;
private long[] _pinAddresses;
private readonly GCHandle _pinAddressesHandle;
public UnsafeArray1D<T> this[int index]
{
get => _data[index];
set
{
_data[index] = value;
}
}
public UnsafeArray2D(int size1, int size2)
{
_data = new UnsafeArray1D<T>[size1];
_pinAddresses = new long[size1];
for (var i = 0; i < size1; ++i)
{
_data[i] = new UnsafeArray1D<T>(size2);
_pinAddresses[i] = _data[i].PinHandle.AddrOfPinnedObject().ToInt64();
}
_pinAddressesHandle = GCHandle.Alloc(_pinAddresses, GCHandleType.Pinned);
}
~UnsafeArray2D()
{
_pinAddressesHandle.Free();
}
public void* ToPointer() => _pinAddressesHandle.AddrOfPinnedObject().ToPointer();
public static implicit operator void*(UnsafeArray2D<T> array)
{
return array.ToPointer();
}
}
}

9
zlib/LICENSE Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2022 Nanook
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.

23
zlib/README.md Normal file
View File

@@ -0,0 +1,23 @@
Project to port ZLib from C to C# (CSharp).
Src zlib 1.2.12 2022-Mar-28 - https://github.com/madler/zlib
See the Stages folder
1_zlib.c - Created by running 1_zlib.c_Concat.ps1 Builds with Clang (used by hebron to convert)
- Only deflate, inflate, crc32 and adler32 code at the moment. GZip might be added if required.
- The only edits to these files are to remove any #includes that have been combined
- The file list includes a 000_ to insert any #defines etc and 100_ for a main for debugging etc
- Notice crc32.c and trees.c had to be split to allow the single file to build
2_zlib.cs_Converted - The converted output that Hebron produced - https://github.com/HebronFramework/Hebron
- This is a little app that uses Clang to read the C code as DOM and write with Roslyn
- It does a fairly decent job and removes a lot of complication
3_zlib.cs_Working - The fixed up and amended C# that actually runs and matches the C code output
- It's had minimal change so is not the prettiest C# code
- It's Unsafe in places
Deflate and Inflate streams have been added.

178
zlib/ZlibDeflateStream.cs Normal file
View File

@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace SabreTools.Compression.zlib
{
public class ZlibDeflateStream : Stream
{
private readonly bool _leaveOpen;
private ZLib.z_stream_s? _s;
private long _p;
private byte[]? _b;
public ZlibDeflateStream(int level, Stream baseStream) : this(level, false, 0, baseStream, false)
{
}
public ZlibDeflateStream(int level, Stream baseStream, bool leaveOpen) : this(level, false, 0, baseStream, leaveOpen)
{
}
public ZlibDeflateStream(int level, bool headerless, Stream baseStream, bool leaveOpen) : this(level, headerless, 0, baseStream, leaveOpen)
{
}
public ZlibDeflateStream(int level, int bufferSize, Stream baseStream, bool leaveOpen) : this(level, false, bufferSize, baseStream, leaveOpen)
{
}
public ZlibDeflateStream(int level, bool headerless, int bufferSize, Stream baseStream, bool leaveOpen)
{
this.Level = level;
this.Headerless = headerless;
this.BaseStream = baseStream;
_leaveOpen = leaveOpen;
_s = null;
_b = new byte[bufferSize == 0 ? 0x10000 : bufferSize];
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => _p;
public override long Position { get => _p; set => throw new NotImplementedException(); }
public int Level { get; }
public bool Headerless { get; }
public Stream BaseStream { get; }
public string Version { get => ZLib.zlibVersion(); }
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
unsafe public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException();
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
if ((offset + count) > buffer.Length) throw new ArgumentException();
int err = 0;
int hdr = 0;
if (_s == null)
{
_s = new ZLib.z_stream_s();
ZLib.deflateInit_(_s, this.Level, this.Version, 0); //0 = sizeof(z_stream_s) not used
if (this.Headerless)
hdr = 2;
_s.total_in = 0u;
_s.total_out = 0u;
_s.avail_in = 0u;
_s.avail_out = 0u;
}
_s.avail_in = (uint)count;
fixed (byte* i = buffer, o = _b)
{
_s.next_in = i;
_s.next_out = o + _s.total_out;
while (err >= 0 && _s.avail_in != 0) //process the buffer
{
if (_s.avail_out == 0) //get more data
{
if (_s.total_out != 0)
{
if (hdr != 0)
{
BaseStream.Write(_b!, hdr, (int)_s.total_out - hdr);
_s.total_out -= (uint)hdr;
hdr = 0;
}
else
BaseStream.Write(_b!, 0, (int)_s.total_out);
}
_p += _s.total_out;
_s.avail_out = (uint)_b!.Length;
_s.next_out = o;
_s.total_out = 0;
}
if (_s.avail_in != 0 || _s.avail_out != 0)
err = ZLib.deflate(_s, 2);
}
}
}
/// <summary>
/// Allow blocks to be written to the base stream. Call when write is finished with.
/// Used for creating block seekable files. The caller must manage blocks, indexes and lengths
/// </summary>
unsafe public long BlockFlush()
{
//finish previous stream
if (_s != null)
{
int err = 0;
fixed (byte* o = _b)
{
_s.next_in = null;
_s.avail_in = 0;
_s.next_out = o + _s.total_out; //point to correct location
int hdr = _p == 0 && Headerless ? 2 : 0;
while (err == 0 && (_s.total_out != 0 || _s.state!.pending != 0))
{
this.BaseStream.Write(_b!, hdr, (int)_s.total_out - hdr);
_s.avail_out = (uint)_b!.Length;
_p += _s.total_out - hdr;
hdr = 0;
_s.next_out = o;
_s.total_out = 0;
if (_s.state!.pending != 0)
err = ZLib.deflate(_s, 2);
}
err = ZLib.deflate(_s, 4);
}
ZLib.deflateEnd(_s);
_s = null;
}
long ret = _p;
_p = 0;
return ret;
}
unsafe protected override void Dispose(bool disposing)
{
this.BlockFlush();
_b = null;
if (!_leaveOpen)
this.BaseStream.Dispose();
}
}
}

170
zlib/ZlibInflateStream.cs Normal file
View File

@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace SabreTools.Compression.zlib
{
public class ZlibInflateStream : Stream
{
private readonly bool _leaveOpen;
private ZLib.z_stream_s? _s;
private long _p;
private byte[]? _b;
private bool _complete;
public ZlibInflateStream(Stream baseStream) : this(0, false, 0, baseStream, false)
{
}
public ZlibInflateStream(Stream baseStream, bool leaveOpen) : this(0, false, 0, baseStream, leaveOpen)
{
}
public ZlibInflateStream(bool headerless, Stream baseStream, bool leaveOpen) : this(0, headerless, 0, baseStream, leaveOpen)
{
}
public ZlibInflateStream(bool headerless, int bufferSize, Stream baseStream, bool leaveOpen) : this(0, headerless, bufferSize, baseStream, leaveOpen)
{
}
public ZlibInflateStream(int bufferSize, Stream baseStream, bool leaveOpen) : this(0, false, bufferSize, baseStream, leaveOpen)
{
}
public ZlibInflateStream(long maxRead, bool headerless, int bufferSize, Stream baseStream, bool leaveOpen)
{
this.MaxRead = maxRead == 0 ? int.MaxValue : maxRead;
this.Headerless = headerless;
this.BaseStream = baseStream;
_leaveOpen = leaveOpen;
_s = null;
_b = new byte[bufferSize == 0 ? 0x10000 : bufferSize];
_complete = false;
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => _p;
public override long Position { get => _p; set => throw new NotImplementedException(); }
public long MaxRead { get; private set; }
public bool Headerless { get; }
public Stream BaseStream { get; }
public string Version { get => ZLib.zlibVersion(); }
public override void Flush()
{
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
unsafe public override int Read(byte[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException();
if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException();
if ((offset + count) > buffer.Length) throw new ArgumentException();
if (_complete)
return 0;
int err = 0;
int hdr = 0;
if (_s == null)
{
_s = new ZLib.z_stream_s();
ZLib.inflateInit_(_s, this.Version, 0); //0 = sizeof(z_stream_s) not used
if (this.Headerless)
{
_b![0] = 0x78;
_b[1] = 0x9c; //da
hdr = 2;
}
_s.total_in = 0u;
_s.total_out = 0u;
_s.avail_in = 0u;
_s.avail_out = 0u;
}
int read;
_s.avail_out = (uint)count;
fixed (byte* i = _b, o = buffer)
{
_s.next_in = i + _s.total_in;
_s.next_out = o;
while (err == 0 && (_s.avail_out != 0 && !_complete)) //process the buffer
{
if (_s.avail_in == 0) //get more data
{
_s.total_in = 0;
read = (int)Math.Min(this.MaxRead - _p, (long)_b!.Length);
if (hdr != 0) //test once to save on the extra calculations
{
_s.avail_in = (uint)(hdr + (read = BaseStream.Read(_b, hdr, Math.Min(read, _b.Length - hdr))));
hdr = 0;
}
else
_s.avail_in = (uint)(read = BaseStream.Read(_b, 0, read));
_complete = read == 0;
_p += (long)read;
_s.next_in = i;
}
if (_s.avail_in != 0 || (!_complete && _s.total_out != 0))
err = ZLib.inflate(_s, 2);
}
}
uint ret = _s.total_out;
_s.total_out = 0u;
return (int)ret;
}
/// <summary>
/// Allow blocks to be read from the base stream without overreading. Call when write is finished with.
/// Used for reading block seekable files. The caller must manage blocks, indexes and lengths. Seek the BaseStream
/// </summary>
public long BlockFlush(int maxRead)
{
this.MaxRead = maxRead;
if (_s != null)
{
ZLib.deflateEnd(_s);
_s = null;
}
_complete = false;
long ret = _p;
_p = 0;
return ret;
}
protected override void Dispose(bool disposing)
{
BlockFlush(0);
_complete = true;
_b = null;
if (!_leaveOpen)
this.BaseStream.Dispose();
}
}
}

7101
zlib/zlib.cs Normal file

File diff suppressed because one or more lines are too long