Skip to content

Commit

Permalink
Initial structure for replacable allocator work.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Sep 23, 2004
1 parent d9675ed commit c0acfc0
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 2 deletions.
46 changes: 44 additions & 2 deletions archivers/zip.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
39 changes: 39 additions & 0 deletions physfs.c
Expand Up @@ -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 ... */

Expand Down Expand Up @@ -752,11 +756,17 @@ static int initializeMutexes(void)
} /* 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);
Expand Down Expand Up @@ -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 changes: 86 additions & 0 deletions physfs.h
Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions physfs_internal.h
Expand Up @@ -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);


/*--------------------------------------------------------------------------*/
Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions platform/posix.c
Expand Up @@ -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 ... */
Expand Down

0 comments on commit c0acfc0

Please sign in to comment.