Initial structure for replacable allocator work.
This commit is contained in:
parent
d9675edf4b
commit
c0acfc0118
|
@ -182,6 +182,47 @@ const DirFunctions __PHYSFS_DirFunctions_ZIP =
|
|||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Bridge physfs allocation functions to zlib's format...
|
||||
*/
|
||||
static voidpf zlibPhysfsAlloc(voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
/* must lock the whole time, since zlib doesn't deal with that. :( */
|
||||
PHYSFS_allocator *allocator = __PHYSFS_getAllocator();
|
||||
size_t total = (items * size) + sizeof (PHYSFS_memhandle);
|
||||
PHYSFS_memhandle h = allocator->malloc(total);
|
||||
char *ptr = (char *) allocator->lock(h);
|
||||
PHYSFS_memhandle *ph = (PHYSFS_memhandle *) ptr;
|
||||
*ph = h; /* tuck the memhandle in front of the memory block... */
|
||||
return(ptr + sizeof (PHYSFS_memhandle));
|
||||
} /* zlibPhysfsAlloc */
|
||||
|
||||
|
||||
/*
|
||||
* Bridge physfs allocation functions to zlib's format...
|
||||
*/
|
||||
static void zlibPhysfsFree(voidpf opaque, voidpf address)
|
||||
{
|
||||
char *ptr = ((char *) address) - (sizeof (PHYSFS_memhandle));
|
||||
PHYSFS_allocator *allocator = __PHYSFS_getAllocator();
|
||||
PHYSFS_memhandle *ph = (PHYSFS_memhandle *) ptr;
|
||||
allocator->unlock(*ph);
|
||||
allocator->free(*ph);
|
||||
} /* zlibPhysfsFree */
|
||||
|
||||
|
||||
/*
|
||||
* Construct a new z_stream to a sane state.
|
||||
*/
|
||||
static void initializeZStream(z_stream *pstr)
|
||||
{
|
||||
memset(pstr, '\0', sizeof (z_stream));
|
||||
pstr->zalloc = zlibPhysfsAlloc;
|
||||
pstr->zfree = zlibPhysfsFree;
|
||||
} /* initializeZStream */
|
||||
|
||||
|
||||
static const char *zlib_error_string(int rc)
|
||||
{
|
||||
switch (rc)
|
||||
|
@ -360,7 +401,7 @@ static int ZIP_seek(FileHandle *handle, PHYSFS_uint64 offset)
|
|||
{
|
||||
/* we do a copy so state is sane if inflateInit2() fails. */
|
||||
z_stream str;
|
||||
memset(&str, '\0', sizeof (z_stream));
|
||||
initializeZStream(&str);
|
||||
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
|
||||
return(0);
|
||||
|
||||
|
@ -728,7 +769,7 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry)
|
|||
{
|
||||
if (__PHYSFS_platformRead(in, compressed, compsize, 1) == 1)
|
||||
{
|
||||
memset(&stream, '\0', sizeof (z_stream));
|
||||
initializeZStream(&stream);
|
||||
stream.next_in = compressed;
|
||||
stream.avail_in = compsize;
|
||||
stream.next_out = (unsigned char *) path;
|
||||
|
@ -1404,6 +1445,7 @@ static FileHandle *ZIP_openRead(DirHandle *h, const char *fnm, int *fileExists)
|
|||
memset(finfo, '\0', sizeof (ZIPfileinfo));
|
||||
finfo->handle = in;
|
||||
finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);
|
||||
initializeZStream(&finfo->stream);
|
||||
if (finfo->entry->compression_method != COMPMETH_NONE)
|
||||
{
|
||||
if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
|
||||
|
|
39
physfs.c
39
physfs.c
|
@ -171,6 +171,10 @@ static int allowSymLinks = 0;
|
|||
static void *errorLock = NULL; /* protects error message list. */
|
||||
static void *stateLock = NULL; /* protects other PhysFS static state. */
|
||||
|
||||
/* allocator ... */
|
||||
static int externalAllocator = 0;
|
||||
static PHYSFS_allocator allocator;
|
||||
|
||||
|
||||
/* functions ... */
|
||||
|
||||
|
@ -752,11 +756,17 @@ initializeMutexes_failed:
|
|||
} /* initializeMutexes */
|
||||
|
||||
|
||||
static void setDefaultAllocator(void);
|
||||
|
||||
int PHYSFS_init(const char *argv0)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
||||
|
||||
if (!externalAllocator)
|
||||
setDefaultAllocator();
|
||||
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
|
||||
|
||||
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
|
||||
|
@ -1995,5 +2005,34 @@ LinkedStringList *__PHYSFS_addToLinkedStringList(LinkedStringList *retval,
|
|||
return(retval);
|
||||
} /* __PHYSFS_addToLinkedStringList */
|
||||
|
||||
|
||||
int PHYSFS_setAllocator(PHYSFS_allocator *a)
|
||||
{
|
||||
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
||||
externalAllocator = (a != NULL);
|
||||
if (externalAllocator)
|
||||
memcpy(&allocator, a, sizeof (PHYSFS_allocator));
|
||||
|
||||
return(1);
|
||||
} /* PHYSFS_setAllocator */
|
||||
|
||||
|
||||
static void setDefaultAllocator(void)
|
||||
{
|
||||
assert(!externalAllocator);
|
||||
allocator.malloc = __PHYSFS_platformMalloc;
|
||||
allocator.realloc = __PHYSFS_platformRealloc;
|
||||
allocator.free = __PHYSFS_platformFree;
|
||||
allocator.lock = __PHYSFS_platformLock;
|
||||
allocator.unlock = __PHYSFS_platformUnlock;
|
||||
} /* setDefaultAllocator */
|
||||
|
||||
|
||||
PHYSFS_allocator *__PHYSFS_getAllocator(void)
|
||||
{
|
||||
return(&allocator);
|
||||
} /* __PHYFS_getAllocator */
|
||||
|
||||
|
||||
/* end of physfs.c ... */
|
||||
|
||||
|
|
86
physfs.h
86
physfs.h
|
@ -1820,6 +1820,92 @@ __EXPORT__ int PHYSFS_writeSBE64(PHYSFS_file *file, PHYSFS_sint64 val);
|
|||
__EXPORT__ int PHYSFS_writeUBE64(PHYSFS_file *file, PHYSFS_uint64 val);
|
||||
|
||||
|
||||
/* Everything above this line is part of the PhysicsFS 1.0 API. */
|
||||
|
||||
|
||||
/**
|
||||
* \typedef PHYSFS_memhandle
|
||||
* \brief Used to represent memory blocks.
|
||||
*
|
||||
* (This is for limited, hardcore use. If you don't immediately see a need
|
||||
* for it, you can probably ignore this forever.)
|
||||
*
|
||||
* The allocator routines will pass these around. They are void pointers
|
||||
* because it's convenient for systems to have handles be the same size
|
||||
* as a pointer, but they shouldn't be assumed to point to valid memory
|
||||
* (or to memory at all). The allocator in use will convert from memhandles
|
||||
* to valid pointers to allocated memory.
|
||||
*
|
||||
* \sa PHYSFS_allocator
|
||||
* \sa PHYSFS_setAllocator
|
||||
*/
|
||||
typedef void *PHYSFS_memhandle;
|
||||
|
||||
|
||||
/**
|
||||
* \struct PHYSFS_allocator
|
||||
* \brief PhysicsFS allocation function pointers.
|
||||
*
|
||||
* (This is for limited, hardcore use. If you don't immediately see a need
|
||||
* for it, you can probably ignore this forever.)
|
||||
*
|
||||
* You create one of these structures for use with PHYSFS_setAllocator.
|
||||
* It should be noted that, in order to accomodate platforms like PalmOS,
|
||||
* we don't just ask for a block of memory and get a pointer. We work on
|
||||
* a "handle" system, which requires PhysicsFS to "lock" before accessing,
|
||||
* and "unlock" when not using. This is also useful for systems that are
|
||||
* concerned about memory fragmentation; you can rearrange unlocked memory
|
||||
* blocks in your address space, since PhysicsFS will re-request the pointer
|
||||
* by relocking the block.
|
||||
*
|
||||
* Locked memory is assumed to be non-reentrant, and locking an already-locked
|
||||
* handle (and unlocking an unlocked handle) has undefined results. Use
|
||||
* mutexes if not sure.
|
||||
*
|
||||
* \sa PHYSFS_memhandle
|
||||
* \sa PHYSFS_setAllocator
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PHYSFS_memhandle (*malloc)(size_t);
|
||||
PHYSFS_memhandle (*realloc)(PHYSFS_memhandle, size_t);
|
||||
void (*free)(PHYSFS_memhandle);
|
||||
void *(*lock)(PHYSFS_memhandle);
|
||||
void *(*unlock)(PHYSFS_memhandle);
|
||||
} PHYSFS_allocator;
|
||||
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_setAllocator(PHYSFS_allocator *allocator)
|
||||
* \brief Hook your own allocation routines into PhysicsFS.
|
||||
*
|
||||
* (This is for limited, hardcore use. If you don't immediately see a need
|
||||
* for it, you can probably ignore this forever.)
|
||||
*
|
||||
* By default, PhysicsFS will use ANSI C malloc/realloc/calloc/free calls
|
||||
* to manage dynamic memory, but in some uncommon cases, the app might want
|
||||
* more control over the library's memory management. This lets you redirect
|
||||
* physfs to use your own allocation routines instead. You can only call this
|
||||
* function before PHYSFS_init(); if the library is initialized, it'll
|
||||
* reject your efforts to change the allocator mid-stream. You may call this
|
||||
* function after PHYSFS_deinit() if you are willing to shutdown the library
|
||||
* and restart it with a new allocator; this is a safe and supported
|
||||
* operation. The allocator remains intact between deinit/init calls.
|
||||
* If you want to return to the default allocator, pass a NULL in here.
|
||||
*
|
||||
* If you aren't immediately sure what to do with this function, you can
|
||||
* safely ignore it altogether.
|
||||
*
|
||||
* \param allocator Structure containing your allocator's entry points.
|
||||
* \return zero on failure, non-zero on success. This call only fails
|
||||
* when used between PHYSFS_init() and PHYSFS_deinit() calls.
|
||||
*/
|
||||
__EXPORT__ int PHYSFS_setAllocator(PHYSFS_allocator *allocator);
|
||||
|
||||
|
||||
/* Everything above this line is part of the PhysicsFS 2.0 API. */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1295,6 +1295,10 @@ void __PHYSFS_sort(void *entries, PHYSFS_uint32 max,
|
|||
#define BAIL_IF_MACRO_MUTEX(c, e, m, r) if (c) { __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; }
|
||||
|
||||
|
||||
/*
|
||||
* Get the current allocator. Not valid before PHYSFS_init is called!
|
||||
*/
|
||||
PHYSFS_allocator *__PHYSFS_getAllocator(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -1694,6 +1698,35 @@ int __PHYSFS_platformGrabMutex(void *mutex);
|
|||
*/
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex);
|
||||
|
||||
/*
|
||||
* Implement malloc. It's safe to just pass through from the C runtime.
|
||||
*/
|
||||
PHYSFS_memhandle __PHYSFS_platformMalloc(size_t s);
|
||||
|
||||
/*
|
||||
* Implement realloc. It's safe to just pass through from the C runtime.
|
||||
*/
|
||||
PHYSFS_memhandle __PHYSFS_platformRealloc(PHYSFS_memhandle h, size_t s);
|
||||
|
||||
/*
|
||||
* Implement free. It's safe to just pass through from the C runtime.
|
||||
*/
|
||||
void __PHYSFS_platformFree(PHYSFS_memhandle h);
|
||||
|
||||
/*
|
||||
* Lock a memhandle. If you are just passing through from the C runtime,
|
||||
* it is safe to make this a no-op. Otherwise, convert to a real pointer
|
||||
* in the address space and return it.
|
||||
*/
|
||||
void *__PHYSFS_platformLock(PHYSFS_memhandle h);
|
||||
|
||||
/*
|
||||
* Unlock a memhandle. If you are just passing through from the C runtime,
|
||||
* it is safe to make this a no-op. Otherwise, you can consider the data in
|
||||
* the address space safe to move around until the handle is relocked.
|
||||
*/
|
||||
void __PHYSFS_platformUnlock(PHYSFS_memhandle h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -500,6 +500,37 @@ PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
|||
return statbuf.st_mtime;
|
||||
} /* __PHYSFS_platformGetLastModTime */
|
||||
|
||||
|
||||
PHYSFS_memhandle __PHYSFS_platformMalloc(size_t s)
|
||||
{
|
||||
assert(sizeof (h) == sizeof (void *));
|
||||
return((PHYSFS_memhandle) malloc(s));
|
||||
} /* __PHYSFS_platformMalloc */
|
||||
|
||||
|
||||
PHYSFS_memhandle __PHYSFS_platformRealloc(PHYSFS_memhandle h, size_t s)
|
||||
{
|
||||
return((PHYSFS_memhandle) realloc((void *) h, s));
|
||||
} /* __PHYSFS_platformRealloc */
|
||||
|
||||
|
||||
void __PHYSFS_platformFree(PHYSFS_memhandle h)
|
||||
{
|
||||
free((void *) h);
|
||||
} /* __PHYSFS_platformFree */
|
||||
|
||||
|
||||
void *__PHYSFS_platformLock(PHYSFS_memhandle h)
|
||||
{
|
||||
return((void *) h);
|
||||
} /* __PHYSFS_platformLock */
|
||||
|
||||
|
||||
void __PHYSFS_platformUnlock(PHYSFS_memhandle h)
|
||||
{
|
||||
/* no-op. */
|
||||
} /* __PHYSFS_platformUnlock */
|
||||
|
||||
#endif /* !defined WIN32 */
|
||||
|
||||
/* end of posix.c ... */
|
||||
|
|
Loading…
Reference in New Issue