a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
203 lines
4.1 KiB
C#
203 lines
4.1 KiB
C#
// ZipStream.cs created with MonoDevelop
|
||
// User: alan at 15:16 20/10/2008
|
||
//
|
||
// To change standard headers go to Edit->Preferences->Coding->Standard Headers
|
||
//
|
||
|
||
using System;
|
||
using System.IO;
|
||
using System.Runtime.InteropServices;
|
||
|
||
namespace zipsharp
|
||
{
|
||
class ZipStream : Stream
|
||
{
|
||
const int ZLIB_FILEFUNC_SEEK_CUR = 1;
|
||
const int ZLIB_FILEFUNC_SEEK_END = 2;
|
||
const int ZLIB_FILEFUNC_SEEK_SET = 0;
|
||
|
||
bool canRead;
|
||
bool canSeek;
|
||
bool canWrite;
|
||
|
||
public override bool CanRead {
|
||
get { return canRead; }
|
||
}
|
||
|
||
public override bool CanSeek {
|
||
get { return canSeek; }
|
||
}
|
||
|
||
public override bool CanWrite {
|
||
get { return canWrite; }
|
||
}
|
||
|
||
public override bool CanTimeout {
|
||
get { return false; }
|
||
}
|
||
|
||
private Stream DataStream {
|
||
get; set;
|
||
}
|
||
|
||
public ZlibFileFuncDef IOFunctions {
|
||
get; set;
|
||
}
|
||
|
||
public override long Length {
|
||
get { return DataStream.Length; }
|
||
}
|
||
|
||
bool OwnsStream {
|
||
get; set;
|
||
}
|
||
|
||
public override long Position {
|
||
get { return DataStream.Position; }
|
||
set { DataStream.Position = value; }
|
||
}
|
||
|
||
public ZipStream (Stream dataStream, bool ownsStream)
|
||
{
|
||
// FIXME: Not necessarily true
|
||
canRead = true;
|
||
canSeek = true;
|
||
canWrite = true;
|
||
|
||
DataStream = dataStream;
|
||
OwnsStream = ownsStream;
|
||
|
||
ZlibFileFuncDef f = new ZlibFileFuncDef();
|
||
|
||
f.opaque = IntPtr.Zero;
|
||
f.zclose_file = CloseFile_Native;
|
||
f.zerror_file = TestError_Native;
|
||
f.zopen_file = OpenFile_Native;
|
||
f.zread_file = ReadFile_Native;
|
||
f.zseek_file = SeekFile_Native;
|
||
f.ztell_file = TellFile_Native;
|
||
f.zwrite_file = WriteFile_Native;
|
||
|
||
IOFunctions = f;
|
||
}
|
||
|
||
protected override void Dispose(bool disposing)
|
||
{
|
||
if (!disposing)
|
||
return;
|
||
|
||
DataStream.Flush ();
|
||
if (OwnsStream)
|
||
DataStream.Dispose ();
|
||
}
|
||
|
||
public override void Flush()
|
||
{
|
||
DataStream.Flush ();
|
||
}
|
||
|
||
public override int Read(byte[] buffer, int offset, int count)
|
||
{
|
||
return DataStream.Read (buffer, offset, count);
|
||
}
|
||
|
||
public override long Seek(long offset, SeekOrigin origin)
|
||
{
|
||
DataStream.Seek (offset, origin);
|
||
return DataStream.Position;
|
||
}
|
||
|
||
public override void SetLength(long value)
|
||
{
|
||
DataStream.SetLength (value);
|
||
}
|
||
|
||
public override void Write(byte[] buffer, int offset, int count)
|
||
{
|
||
DataStream.Write (buffer, offset, count);
|
||
Flush ();
|
||
}
|
||
|
||
int CloseFile_Native (IntPtr opaque, IntPtr stream)
|
||
{
|
||
Close ();
|
||
return 0;
|
||
}
|
||
|
||
IntPtr OpenFile_Native (IntPtr opaque, string filename, int mode)
|
||
{
|
||
// always success. The stream is opened in managed code
|
||
return new IntPtr (1);
|
||
}
|
||
|
||
unsafe IntPtr ReadFile_Native (IntPtr opaque, IntPtr stream, IntPtr buffer, IntPtr size)
|
||
{
|
||
int count = size.ToInt32 ();
|
||
byte[] b = new byte[count];
|
||
int read;
|
||
|
||
try {
|
||
read = Math.Max (0, Read (b, 0, count));
|
||
byte* ptrBuffer = (byte*) buffer.ToPointer ();
|
||
for (int i = 0; i < count && i < read; i ++)
|
||
ptrBuffer[i] = b[i];
|
||
} catch {
|
||
read = -1;
|
||
}
|
||
|
||
return new IntPtr (read);
|
||
}
|
||
|
||
IntPtr SeekFile_Native (IntPtr opaque, IntPtr stream, IntPtr offset, int origin)
|
||
{
|
||
SeekOrigin seek;
|
||
if (origin == ZipStream.ZLIB_FILEFUNC_SEEK_CUR)
|
||
seek = SeekOrigin.Current;
|
||
else if (origin == ZLIB_FILEFUNC_SEEK_END)
|
||
seek = SeekOrigin.End;
|
||
else if (origin == ZLIB_FILEFUNC_SEEK_SET)
|
||
seek = SeekOrigin.Begin;
|
||
else
|
||
return new IntPtr (-1);
|
||
|
||
Seek (offset.ToInt64 (), seek);
|
||
|
||
return new IntPtr (0);
|
||
}
|
||
|
||
IntPtr TellFile_Native (IntPtr opaque, IntPtr stream)
|
||
{
|
||
if (IntPtr.Size == 4)
|
||
return new IntPtr ((int)Position);
|
||
else if (IntPtr.Size == 8)
|
||
return new IntPtr (Position);
|
||
else
|
||
return new IntPtr (-1);
|
||
}
|
||
|
||
int TestError_Native (IntPtr opaque, IntPtr stream)
|
||
{
|
||
// No errors here.
|
||
return 0;
|
||
}
|
||
|
||
unsafe IntPtr WriteFile_Native (IntPtr opaque, IntPtr stream, IntPtr buffer, /* ulong */ IntPtr size)
|
||
{
|
||
int count = size.ToInt32 ();
|
||
byte[] b = new byte[count];
|
||
|
||
byte* ptrBuffer = (byte*) buffer.ToPointer ();
|
||
for (int i = 0; i < count; i ++)
|
||
b[i] = ptrBuffer[i];
|
||
|
||
try {
|
||
Write (b, 0, count);
|
||
} catch {
|
||
|
||
}
|
||
|
||
return new IntPtr (count);
|
||
}
|
||
}
|
||
}
|