194 lines
5.6 KiB
C#
194 lines
5.6 KiB
C#
|
/* PhysFSFileStream.cs - (c)2003 Gregory S. Read */
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.IO;
|
||
|
|
||
|
namespace PhysFS_NET
|
||
|
{
|
||
|
public enum PhysFSFileMode {Read, Write, Append};
|
||
|
|
||
|
// Our exception class we'll use for throwing all PhysFS API related exception
|
||
|
public class PhysFSException : IOException
|
||
|
{
|
||
|
public PhysFSException(string Message) : base(Message) {}
|
||
|
public PhysFSException() : base(PhysFS_DLL.PHYSFS_getLastError()) {}
|
||
|
}
|
||
|
|
||
|
public unsafe class PhysFSFileStream : Stream
|
||
|
{
|
||
|
// ***Public properties***
|
||
|
public override bool CanRead
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// Reading is supported
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool CanSeek
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// Seek is supported
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool CanWrite
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
// Writing is supported
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override long Length
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
long TempLength;
|
||
|
TempLength = PhysFS_DLL.PHYSFS_fileLength(pHandle);
|
||
|
|
||
|
// If call returned an error, throw an exception
|
||
|
if(TempLength == -1)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
return TempLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override long Position
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
long TempPosition;
|
||
|
TempPosition = PhysFS_DLL.PHYSFS_tell(pHandle);
|
||
|
|
||
|
// If call returned an error, throw an exception
|
||
|
if(TempPosition == -1)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
return TempPosition;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
// Seek from beginning of file using the position value
|
||
|
Seek(value, SeekOrigin.Begin);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ***Public methods***
|
||
|
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode, ulong BufferSize)
|
||
|
{
|
||
|
// Open the specified file with the appropriate file access
|
||
|
switch(FileMode)
|
||
|
{
|
||
|
case PhysFSFileMode.Read:
|
||
|
pHandle = PhysFS_DLL.PHYSFS_openRead(FileName);
|
||
|
break;
|
||
|
case PhysFSFileMode.Write:
|
||
|
pHandle = PhysFS_DLL.PHYSFS_openWrite(FileName);
|
||
|
break;
|
||
|
case PhysFSFileMode.Append:
|
||
|
pHandle = PhysFS_DLL.PHYSFS_openAppend(FileName);
|
||
|
break;
|
||
|
default:
|
||
|
throw new PhysFSException("Invalid FileMode specified");
|
||
|
}
|
||
|
|
||
|
// If handle is null, an error occured, so raise an exception
|
||
|
//!!! Does object get created if exception is thrown?
|
||
|
if(pHandle == null)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
// Set buffer size, raise an exception if an error occured
|
||
|
if(PhysFS_DLL.PHYSFS_setBuffer(pHandle, BufferSize) == 0)
|
||
|
throw new PhysFSException();
|
||
|
}
|
||
|
|
||
|
// This constructor sets the buffer size to 0 if not specified
|
||
|
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode) : this(FileName, FileMode, 0) {}
|
||
|
|
||
|
~PhysFSFileStream()
|
||
|
{
|
||
|
// Don't close the handle if they've specifically closed it already
|
||
|
if(!Closed)
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
public override void Flush()
|
||
|
{
|
||
|
if(PhysFS_DLL.PHYSFS_flush(pHandle) == 0)
|
||
|
throw new PhysFSException();
|
||
|
}
|
||
|
|
||
|
public override int Read(byte[] buffer, int offset, int count)
|
||
|
{
|
||
|
long RetValue;
|
||
|
|
||
|
fixed(byte *pbytes = &buffer[offset])
|
||
|
{
|
||
|
// Read into our allocated pointer
|
||
|
RetValue = PhysFS_DLL.PHYSFS_read(pHandle, pbytes, sizeof(byte), (uint)count);
|
||
|
}
|
||
|
|
||
|
if(RetValue == -1)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
// Return number of bytes read
|
||
|
// Note: This cast should be safe since we are only reading 'count' items, which
|
||
|
// is of type 'int'.
|
||
|
return (int)RetValue;
|
||
|
}
|
||
|
|
||
|
public override void Write(byte[] buffer, int offset, int count)
|
||
|
{
|
||
|
long RetValue;
|
||
|
|
||
|
fixed(byte* pbytes = &buffer[offset])
|
||
|
{
|
||
|
// Write buffer
|
||
|
RetValue = PhysFS_DLL.PHYSFS_write(pHandle, pbytes, sizeof(byte), (uint)count);
|
||
|
}
|
||
|
|
||
|
if(RetValue == -1)
|
||
|
throw new PhysFSException();
|
||
|
}
|
||
|
|
||
|
public override long Seek(long offset, SeekOrigin origin)
|
||
|
{
|
||
|
// Only seeking from beginning is supported by PhysFS API
|
||
|
if(origin != SeekOrigin.Begin)
|
||
|
throw new PhysFSException("Only seek origin of \"Begin\" is supported");
|
||
|
|
||
|
// Seek to specified offset, raise an exception if error occured
|
||
|
if(PhysFS_DLL.PHYSFS_seek(pHandle, (ulong)offset) == 0)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
// Since we always seek from beginning, the offset is always
|
||
|
// the absolute position.
|
||
|
return offset;
|
||
|
}
|
||
|
|
||
|
public override void SetLength(long value)
|
||
|
{
|
||
|
throw new NotSupportedException("SetLength method not supported in PhysFSFileStream objects.");
|
||
|
}
|
||
|
|
||
|
public override void Close()
|
||
|
{
|
||
|
// Close the handle
|
||
|
if(PhysFS_DLL.PHYSFS_close(pHandle) == 0)
|
||
|
throw new PhysFSException();
|
||
|
|
||
|
// File has been closed. Rock.
|
||
|
Closed = true;
|
||
|
}
|
||
|
|
||
|
// ***Private variables***
|
||
|
private void *pHandle;
|
||
|
private bool Closed = false;
|
||
|
}
|
||
|
}
|