131 lines
4.2 KiB
C++
131 lines
4.2 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "filesystem/io_buffer.h"
|
|
#include "log/log.h"
|
|
#include "ntypes.h"
|
|
|
|
using namespace GS::IO;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
uint Buffer::GetCaps() const { return io->GetCaps(); }
|
|
|
|
Handle *Buffer::Open(const char *path, Mode mode)
|
|
{
|
|
AutoPtr <Handle> io_h(io->Open(path, mode));
|
|
if (io_h.IsNull())
|
|
return NULL;
|
|
|
|
AutoPtr <BufferHandle> b_h(new BufferHandle(this, io_h));
|
|
if (b_h.IsNull())
|
|
return NULL;
|
|
|
|
if (!b_h->read_buffer.buffer.Allocate(read_buffer_size))
|
|
return NULL;
|
|
|
|
b_h->size = io_h->GetSize();
|
|
|
|
io_h.Detach();
|
|
return b_h.Detach();
|
|
}
|
|
void Buffer::Close(Handle *h)
|
|
{
|
|
if (BufferHandle *b_h = (BufferHandle *)h)
|
|
b_h->handle = NULL;
|
|
}
|
|
|
|
bool Buffer::Delete(const char *path) { return io->Delete(path); }
|
|
|
|
size_t Buffer::Tell(Handle *h) { return ((BufferHandle *)h)->pos; }
|
|
size_t Buffer::Seek(Handle *h, ptrdiff_t offset, SeekRef seek)
|
|
{
|
|
if (BufferHandle *c_h = (BufferHandle *)h)
|
|
{
|
|
switch (seek)
|
|
{
|
|
case SeekStart:
|
|
c_h->pos = Types::Clamp <ptrdiff_t> (offset, 0, c_h->size);
|
|
break;
|
|
case SeekCurrent:
|
|
c_h->pos = Types::Clamp <ptrdiff_t> (c_h->pos + offset, 0, c_h->size);
|
|
break;
|
|
case SeekEnd:
|
|
c_h->pos = Types::Clamp <ptrdiff_t> (c_h->size + offset, 0, c_h->size);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
return size_t(-1);
|
|
}
|
|
size_t Buffer::Read(Handle *h, void *data, size_t size)
|
|
{
|
|
// __LOG_V__ << "Buffer::Read: size = " << size << ".\n";
|
|
|
|
size_t read_size = 0;
|
|
if (BufferHandle *b_h = (BufferHandle *)h)
|
|
{
|
|
while (read_size < size)
|
|
{
|
|
ptrdiff_t buffer_pos = (b_h->pos + read_size) - b_h->read_buffer.start_pos;
|
|
|
|
if ((buffer_pos >= 0) && (buffer_pos < ptrdiff_t(b_h->read_buffer.usage)))
|
|
{
|
|
ptrdiff_t copy_size = Types::Min <ptrdiff_t> (b_h->read_buffer.usage - buffer_pos, size - read_size);
|
|
Memory::Copy((char *)data + read_size, b_h->read_buffer.buffer.c_ptr() + buffer_pos, copy_size);
|
|
// __LOG_V__ << "Buffer read: pos = " << buffer_pos << ", size = " << copy_size << ".\n";
|
|
read_size += copy_size;
|
|
}
|
|
else // refill cache
|
|
{
|
|
b_h->read_buffer.start_pos = b_h->pos + read_size;
|
|
if (b_h->read_buffer.start_pos >= b_h->size)
|
|
{
|
|
b_h->read_buffer.usage = 0;
|
|
break; // EJ 01/05: Improves EOF performance for the OGG streaming interface which makes many out of bound calls.
|
|
}
|
|
|
|
io->Seek(b_h->handle, b_h->read_buffer.start_pos, SeekStart);
|
|
b_h->read_buffer.usage = io->Read(b_h->handle, b_h->read_buffer.buffer.c_ptr(), b_h->read_buffer.buffer.GetSize());
|
|
// __LOG_V__ << "Buffer fill: pos = " << b_h->read_buffer.start_pos << ", size = " << b_h->read_buffer.usage << ".\n";
|
|
if (b_h->read_buffer.usage == 0)
|
|
break; // EOF
|
|
}
|
|
}
|
|
b_h->pos += read_size;
|
|
}
|
|
return read_size;
|
|
}
|
|
size_t Buffer::Write(Handle *h, const void *data, size_t size)
|
|
{
|
|
if (BufferHandle *b_h = (BufferHandle *)h)
|
|
{
|
|
size_t write_size = io->Write(b_h->handle, data, size);
|
|
b_h->pos += write_size;
|
|
return write_size;
|
|
}
|
|
return 0;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
GS::String Buffer::Hash(const char *path)
|
|
{ return io->Hash(path); } // [EJ] Do not perform a FileLoad here, IO::Buffer is typically sitting in front of a slow IO backend which potentially optimizes hash transfer.
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Buffer::MkDir(const char *path)
|
|
{ return io->MkDir(path); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Buffer::Buffer(Base *base, size_t read_size, size_t write_size) : io(base)
|
|
{
|
|
read_buffer_size = Types::Clamp <size_t> (read_size, 0, Units::MB(16));
|
|
write_buffer_size = Types::Clamp <size_t> (write_size, 0, Units::MB(16));
|
|
}
|
|
//------------------------------------------------------------------------------
|