/****************************************************************************
*
* Copyright (c) 2006 Novell, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail, you
* may find current contact information at www.novell.com.
*
****************************************************************************/
#include
static BongoMemChunk *
BongoMemChunkNew (size_t size)
{
BongoMemChunk *result;
result = MemMalloc(size + sizeof(struct _BongoMemChunk));
if (!result) {
return NULL;
}
result->curptr = &result->data[0];
result->endptr = result->curptr + size;
result->next = NULL;
return result;
}
static size_t
BongoMemChunkSize (BongoMemChunk *chunk)
{
return (unsigned long) chunk->endptr - (unsigned long) &chunk->data[0];
}
int
BongoMemStackInit (BongoMemStack *stack, size_t size)
{
stack->chunk = BongoMemChunkNew(size);
return stack->chunk ? 0 : -1;
}
void
BongoMemStackDestroy (BongoMemStack *stack)
{
BongoMemChunk *chunk;
BongoMemChunk *next;
for (chunk = stack->chunk; chunk; chunk = next) {
next = chunk->next;
MemFree(chunk);
}
stack->chunk = NULL;
}
BongoMemStack *
BongoMemStackNew(size_t size)
{
BongoMemStack *result;
result = MemMalloc(sizeof(BongoMemStack));
if (result) {
if (BongoMemStackInit(result, size)) {
MemFree(result);
}
}
return result;
}
void
BongoMemStackDelete(BongoMemStack *stack)
{
BongoMemStackDestroy(stack);
MemFree(stack);
}
void
BongoMemStackReset(BongoMemStack *stack)
{
BongoMemChunk *chunk;
BongoMemChunk *next;
for (chunk = stack->chunk; chunk; chunk = next) {
next = chunk->next;
if (next) {
MemFree(chunk);
} else {
chunk->curptr = &chunk->data[0];
chunk->next = NULL;
stack->chunk = chunk;
return;
}
}
}
void *
BongoMemStackAlloc(BongoMemStack *stack, size_t size)
{
void *result;
BongoMemChunk *chunk;
size_t newsize;
if (stack->chunk->curptr + size < stack->chunk->endptr) {
result = stack->chunk->curptr;
stack->chunk->curptr += size;
return result;
}
newsize = BongoMemChunkSize(stack->chunk);
if (newsize < size) {
newsize = size;
}
newsize *= 2;
chunk = BongoMemChunkNew(newsize);
if (!chunk) {
return NULL;
}
chunk->next = stack->chunk;
stack->chunk = chunk;
result = stack->chunk->curptr;
stack->chunk->curptr += size;
return result;
}
void
BongoMemStackPop(BongoMemStack *stack, void *obj)
{
BongoMemChunk *chunk;
BongoMemChunk *next;
for (chunk = stack->chunk; chunk; chunk = next) {
next = chunk->next;
if (obj > (void *) chunk && obj < (void *) chunk->endptr) {
chunk->curptr = obj;
stack->chunk = chunk;
return;
}
if (next) {
MemFree(chunk);
} else {
chunk->curptr = &chunk->data[0];
chunk->next = NULL;
stack->chunk = chunk;
return;
}
}
}
void *
BongoMemStackPush(BongoMemStack *stack, void *obj, size_t size)
{
void *ptr;
ptr = BONGO_MEMSTACK_ALLOC(stack, size);
if (ptr) {
memcpy(ptr, obj, size);
}
return ptr;
}
char *
BongoMemStackPushStr(BongoMemStack *stack, const char *str)
{
void *ptr;
size_t size;
size = strlen(str) + 1;
ptr = BONGO_MEMSTACK_ALLOC(stack, size);
if (ptr) {
memcpy(ptr, str, size);
}
return (char *) ptr;
}