dxx-rebirth/d2x-rebirth/misc/physfsrwops.cpp

175 lines
5 KiB
C++
Raw Normal View History

2014-06-01 17:55:23 +00:00
/*
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
2006-03-20 17:12:09 +00:00
/*
* This code provides a glue layer between PhysicsFS and Simple Directmedia
* Layer's (SDL) RWops i/o abstraction.
*
* License: this code is public domain. I make no warranty that it is useful,
* correct, harmless, or environmentally safe.
*
* This particular file may be used however you like, including copying it
* verbatim into a closed-source project, exploiting it commercially, and
* removing any trace of my name from the source (although I hope you won't
* do that). I welcome enhancements and corrections to this file, but I do
* not require you to send me patches if you make changes. This code has
* NO WARRANTY.
*
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
* Please see LICENSE in the root of the source tree.
*
* SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/
*
* This file was written by Ryan C. Gordon. (icculus@clutteredmind.org).
*/
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
#include "physfsrwops.h"
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
{
PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
2006-03-20 17:12:09 +00:00
int pos = 0;
if (whence == SEEK_SET)
{
pos = offset;
} /* if */
else if (whence == SEEK_CUR)
{
PHYSFS_sint64 current = PHYSFS_tell(handle);
if (current == -1)
{
SDL_SetError("Can't find position in file: %s",
PHYSFS_getLastError());
return(-1);
} /* if */
pos = static_cast<int>(current);
if (static_cast<PHYSFS_sint64>(pos) != current)
2006-03-20 17:12:09 +00:00
{
SDL_SetError("Can't fit current file position in an int!");
return(-1);
} /* if */
if (offset == 0) /* this is a "tell" call. We're done. */
return(pos);
pos += offset;
} /* else if */
else if (whence == SEEK_END)
{
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
if (len == -1)
{
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
return(-1);
} /* if */
pos = static_cast<int>(len);
if (static_cast<PHYSFS_sint64>(pos) != len)
2006-03-20 17:12:09 +00:00
{
SDL_SetError("Can't fit end-of-file position in an int!");
return(-1);
} /* if */
pos += offset;
} /* else if */
else
{
SDL_SetError("Invalid 'whence' parameter.");
return(-1);
} /* else */
if ( pos < 0 )
{
SDL_SetError("Attempt to seek past start of file.");
return(-1);
} /* if */
if (!PHYSFS_seek(handle, static_cast<PHYSFS_uint64>(pos)))
2006-03-20 17:12:09 +00:00
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return(-1);
} /* if */
return(pos);
} /* physfsrwops_seek */
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
{
PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
PHYSFS_sint64 rc = (PHYSFS_read)(handle, ptr, size, maxnum);
2006-03-20 17:12:09 +00:00
if (rc != maxnum)
{
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
} /* if */
return(static_cast<int>(rc));
2006-03-20 17:12:09 +00:00
} /* physfsrwops_read */
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
{
PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
PHYSFS_sint64 rc = (PHYSFS_write)(handle, reinterpret_cast<const uint8_t *>(ptr), size, num);
2006-03-20 17:12:09 +00:00
if (rc != num)
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return(static_cast<int>(rc));
2006-03-20 17:12:09 +00:00
} /* physfsrwops_write */
static int physfsrwops_close(SDL_RWops *rw)
{
PHYSFS_File *handle = reinterpret_cast<PHYSFS_File *>(rw->hidden.unknown.data1);
2006-03-20 17:12:09 +00:00
if (!PHYSFS_close(handle))
{
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
return(-1);
} /* if */
SDL_FreeRW(rw);
return(0);
} /* physfsrwops_close */
static RWops_ptr create_rwops(PHYSFS_File *handle)
2006-03-20 17:12:09 +00:00
{
if (handle == NULL)
2015-02-08 17:43:29 +00:00
{
2006-03-20 17:12:09 +00:00
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
2015-02-08 17:43:29 +00:00
return nullptr;
}
2006-03-20 17:12:09 +00:00
else
{
2015-02-08 17:43:29 +00:00
RWops_ptr retval{SDL_AllocRW()};
if (retval)
2006-03-20 17:12:09 +00:00
{
retval->seek = physfsrwops_seek;
retval->read = physfsrwops_read;
retval->write = physfsrwops_write;
retval->close = physfsrwops_close;
retval->hidden.unknown.data1 = handle;
} /* if */
2015-02-08 17:43:29 +00:00
return retval;
2006-03-20 17:12:09 +00:00
} /* else */
} /* create_rwops */
2015-02-08 17:43:29 +00:00
RWops_ptr PHYSFSRWOPS_openRead(const char *fname)
2006-03-20 17:12:09 +00:00
{
return(create_rwops(PHYSFS_openRead(fname)));
} /* PHYSFSRWOPS_openRead */
/* end of physfsrwops.c ... */