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)
|
static const char *zlib_error_string(int rc)
|
||||||
{
|
{
|
||||||
switch (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. */
|
/* we do a copy so state is sane if inflateInit2() fails. */
|
||||||
z_stream str;
|
z_stream str;
|
||||||
memset(&str, '\0', sizeof (z_stream));
|
initializeZStream(&str);
|
||||||
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
|
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
|
||||||
return(0);
|
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)
|
if (__PHYSFS_platformRead(in, compressed, compsize, 1) == 1)
|
||||||
{
|
{
|
||||||
memset(&stream, '\0', sizeof (z_stream));
|
initializeZStream(&stream);
|
||||||
stream.next_in = compressed;
|
stream.next_in = compressed;
|
||||||
stream.avail_in = compsize;
|
stream.avail_in = compsize;
|
||||||
stream.next_out = (unsigned char *) path;
|
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));
|
memset(finfo, '\0', sizeof (ZIPfileinfo));
|
||||||
finfo->handle = in;
|
finfo->handle = in;
|
||||||
finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);
|
finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);
|
||||||
|
initializeZStream(&finfo->stream);
|
||||||
if (finfo->entry->compression_method != COMPMETH_NONE)
|
if (finfo->entry->compression_method != COMPMETH_NONE)
|
||||||
{
|
{
|
||||||
if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
|
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 *errorLock = NULL; /* protects error message list. */
|
||||||
static void *stateLock = NULL; /* protects other PhysFS static state. */
|
static void *stateLock = NULL; /* protects other PhysFS static state. */
|
||||||
|
|
||||||
|
/* allocator ... */
|
||||||
|
static int externalAllocator = 0;
|
||||||
|
static PHYSFS_allocator allocator;
|
||||||
|
|
||||||
|
|
||||||
/* functions ... */
|
/* functions ... */
|
||||||
|
|
||||||
|
@ -752,11 +756,17 @@ initializeMutexes_failed:
|
||||||
} /* initializeMutexes */
|
} /* initializeMutexes */
|
||||||
|
|
||||||
|
|
||||||
|
static void setDefaultAllocator(void);
|
||||||
|
|
||||||
int PHYSFS_init(const char *argv0)
|
int PHYSFS_init(const char *argv0)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
||||||
|
|
||||||
|
if (!externalAllocator)
|
||||||
|
setDefaultAllocator();
|
||||||
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
|
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
|
||||||
|
|
||||||
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
|
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
|
||||||
|
@ -1995,5 +2005,34 @@ LinkedStringList *__PHYSFS_addToLinkedStringList(LinkedStringList *retval,
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* __PHYSFS_addToLinkedStringList */
|
} /* __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 ... */
|
/* 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);
|
__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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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; }
|
#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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -500,6 +500,37 @@ PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
|
||||||
return statbuf.st_mtime;
|
return statbuf.st_mtime;
|
||||||
} /* __PHYSFS_platformGetLastModTime */
|
} /* __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 */
|
#endif /* !defined WIN32 */
|
||||||
|
|
||||||
/* end of posix.c ... */
|
/* end of posix.c ... */
|
||||||
|
|
Loading…
Reference in New Issue