1
0
mirror of https://github.com/Halofreak1990/XFXFramework synced 2024-12-26 13:49:34 +01:00
XFXFramework/src/libmscorlib/FileStream.cpp
Halofreak1990 1bf933432b List class now works.
TextureCollection is broken because it can somehow not resolve Texture as template argument for the List it uses.
Added missing BinaryWriter and TextWriter classes to System::IO namespace
Modified BinaryReader
Added PacketReader and PacketWriter classes to XFX::Net namespace
2011-03-10 22:55:43 +00:00

301 lines
8.8 KiB
C++

// Copyright (C) 2010-2012, XFX Team
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the copyright holder nor the names of any
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <System/IO/FileStream.h>
#include <System/IO/IOException.h>
extern "C"
{
#include <hal/fileio.h>
}
namespace System
{
namespace IO
{
bool FileStream::CanRead()
{
return _access == FileAccess::Read || _access == FileAccess::ReadWrite;
}
bool FileStream::CanSeek()
{
return canSeek;
}
bool FileStream::CanWrite()
{
return _access == FileAccess::Write || _access == FileAccess::ReadWrite;
}
Int64 FileStream::Length()
{
if(handle == -1)
throw ObjectDisposedException("FileStream", "The stream has been closed.");
if(!canSeek)
throw NotSupportedException("The stream does not support seeking.");
Int64 length;
if(XGetFileSize(handle, (unsigned int *)length) != STATUS_SUCCESS)
throw IOException("Could not determine file size. The file may be corrupt.");
if ((_writePos > 0) && ((_pos + _writePos) > length))
{
length = _writePos + _pos;
}
return length;
}
Int64 FileStream::Position()
{
if (handle == -1)
throw ObjectDisposedException("FileStream", "The stream has been closed.");
if (!canSeek)
throw NotSupportedException("The stream does not support seeking.");
return (_pos + ((_readPos - _readLen) + _writePos));
}
void FileStream::Position(Int64 newPosition)
{
if(canSeek == false)
throw NotSupportedException("The stream does not support seeking");
if(newPosition < 0)
throw ArgumentOutOfRangeException("newPosition", "Attempt to set the position to a negative value.");
Seek(newPosition, SeekOrigin::Begin);
}
FileStream::FileStream()
{
handle = -1;
}
FileStream::FileStream(char* path, FileMode_t mode)
{
if(path == null || path == "")
throw ArgumentNullException("path", "path was either NULL or an empty string.");
_access = (mode == FileMode::Append ? FileAccess::Write : FileAccess::ReadWrite);
XCreateFile(&handle, path, _access, FileShare::Read, mode, FILE_ATTRIBUTE_NORMAL);
}
FileStream::FileStream(char* path, FileMode_t mode, FileAccess_t access)
{
if(path == null || path == "")
throw ArgumentNullException("path", "path was either NULL, or an empty string.");
_access = access;
XCreateFile(&handle, path, access, FILE_SHARE_READ | FILE_SHARE_WRITE, mode, FILE_ATTRIBUTE_NORMAL);
}
FileStream::FileStream(char* path, FileMode_t mode, FileAccess_t access, FileShare_t share)
{
if(path == null || path == "")
throw ArgumentNullException("path", "path was either NULL, or an empty string.");
XCreateFile(&handle, path, access, share, mode, FILE_ATTRIBUTE_NORMAL);
}
FileStream::FileStream(char* path, FileMode_t mode, FileAccess_t access, FileShare_t share, int bufferSize)
{
FileStream(path, mode, access, share, bufferSize, false);
}
FileStream::FileStream(char* path, FileMode_t mode, FileAccess_t access, FileShare_t share, int bufferSize, bool useAsync)
{
if (bufferSize <= 0)
throw ArgumentOutOfRangeException("bufferSize", "Positive number required.");
XCreateFile(&handle, path, access, share, mode, FILE_ATTRIBUTE_NORMAL);
}
FileStream::~FileStream()
{
Dispose(false);
}
void FileStream::Dispose(bool disposing)
{
try
{
if((handle != -1) && (_writePos > 0))
{
FlushWrite(!disposing);
}
}
catch(Exception)
{
}
if((handle != -1))
{
// ! Invalidate the handle
handle = -1;
}
}
void FileStream::Flush()
{
if(handle == -1)
throw ObjectDisposedException("FileStream", "The stream has been closed.");
if (_writePos > 0)
{
FlushWrite(false);
}
else if ((_readPos < _readLen) && canSeek)
{
FlushRead();
}
_readPos = 0;
_readLen = 0;
}
void FileStream::FlushWrite(bool calledFromFinalizer)
{
Write(_buffer, 0, _writePos);
_writePos = 0;
}
int FileStream::Read(byte array[], int offset, int count)
{
if(handle == -1)
throw ObjectDisposedException("FileStream", "The stream has been closed.");
if(array == null)
throw ArgumentNullException("array");
if (!CanRead())
throw NotSupportedException("Stream does not support reading");
int len = (sizeof(array)/sizeof(byte));
if (offset < 0)
throw ArgumentOutOfRangeException("offset", "< 0");
if (count < 0)
throw ArgumentOutOfRangeException("count", "< 0");
if (offset > len)
throw ArgumentException("destination offset is beyond array size");
// reordered to avoid possible integer overflow
if (offset > len - count)
throw ArgumentException("Reading would overrun buffer");
UInt32 bytesRead;
XReadFile(handle, &array[offset], count, &bytesRead);
return bytesRead;
}
int FileStream::ReadByte()
{
void* data;
UInt32 bytesRead;
XReadFile(handle, data, 1, &bytesRead);
if(bytesRead != 1)
return -1;
return (int)data;
}
long long FileStream::Seek(long long offset, SeekOrigin_t origin)
{
if(handle == -1)
throw ObjectDisposedException("FileStream", "The stream has been closed.");
FILE_POSITION_INFORMATION positionInfo;
LARGE_INTEGER targetPointer;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
UInt32 filesize;
// Calculate the target pointer
switch (origin)
{
case SeekOrigin::Begin: // From the beginning of the file
targetPointer.QuadPart = offset;
break;
case SeekOrigin::Current: // From the current position
status = NtQueryInformationFile((void*)handle, &ioStatusBlock, &positionInfo, sizeof(positionInfo), FilePositionInformation);
if (!NT_SUCCESS(status))
return RtlNtStatusToDosError(status);
targetPointer.QuadPart = positionInfo.CurrentByteOffset.QuadPart + offset;
break;
case SeekOrigin::End: // From the end of the file
status = XGetFileSize(handle, &filesize);
if (!NT_SUCCESS(status))
return RtlNtStatusToDosError(status);
targetPointer.QuadPart -= offset;
break;
}
// Fill in the new position information
positionInfo.CurrentByteOffset.u.HighPart = targetPointer.u.HighPart;
positionInfo.CurrentByteOffset.u.LowPart= targetPointer.u.LowPart;
// Set the new position
status = NtSetInformationFile((void*)handle, &ioStatusBlock, &positionInfo, sizeof(positionInfo), FilePositionInformation);
if (!NT_SUCCESS(status))
return RtlNtStatusToDosError(status);
else
{
return targetPointer.QuadPart;
}
}
void FileStream::SetLength(long long value)
{
if(!CanSeek())
throw NotSupportedException("The stream does not support seeking.");
if(!CanWrite())
throw NotSupportedException("The stream does not support writing.");
if(value < 0)
throw ArgumentOutOfRangeException("value is less than 0");
Flush();
if (Position() > value)
Position(value);
}
void FileStream::Write(byte array[], int offset, int count)
{
XWriteFile(handle, &array[offset], count, null);
}
void FileStream::WriteByte(byte value)
{
XWriteFile(handle, (void*)value, 1, null);
}
}
}