/* 
 NAME
 	cobstack.m - source code for Obstack class
 VERSION
 	$Id$
 CHANGELOG
 	$Log$
 */

#include <coconut/cobstack.h>
#include <coconut/cmemalloc.h>
#include <coconut/csystem.h>
#include <coconut/dconfig.h>

#include <stdlib.h>
#include <string.h>
#include <strings.h>

static void * obstack_chunk_alloc(size_t s){
	return [CMemAlloc allocate: s] ;
}

static void obstack_chunk_free(void * p){
	free(p) ;
}

@implementation CObstack

- init
{
	obstack_init(&object_stack) ;
	return [super init] ;
}

- (void) dealloc
{
	[self clear] ;
	[super dealloc] ;
}

- (void *) allocate: (size_t) size
{
	return [CSystem checkPtr: obstack_alloc(&object_stack, size)] ;
}

- (void *) reallocate: (void *) ptr size: (size_t) size
{
	void * newptr ;
	newptr = obstack_alloc(&object_stack,size) ;
	[CSystem checkPtr: newptr] ; 
	memmove(newptr, ptr, size) ;
	return newptr ;
}

- free: (void *) ptr
{
	return nil ;
}

- (id <PAllocator>) duplicate
{
	id <PAllocator>	newstack ;
	newstack = [[CObstack alloc] init] ;
	[CSystem checkPtr: newstack] ;
	return newstack ;
}

- grow: (void *) src size:(size_t) size
{
	obstack_grow(&object_stack, src, size) ;
	return nil ;
}

- growChar: (utf8_char) c
{
	obstack_1grow(&object_stack, c) ;
	return nil ;
}

- growPtr: (const void *) p
{
	obstack_ptr_grow(&object_stack, (void *) p) ;
	return nil ;
}

- growInt: (int) i
{
	obstack_int_grow(&object_stack, i) ;
	return nil ;
}

- rewind: (const void *) ptr
{
	obstack_free(&object_stack, (void *) ptr) ;
	return nil ;
}

- (void *) finish
{
	return [CSystem checkPtr: obstack_finish(&object_stack)] ;
}

- clear
{
	struct _obstack_chunk * chunk = object_stack.chunk ;
	struct _obstack_chunk * prev ;

	while(chunk){
                prev = chunk->prev ;
		obstack_chunk_free(chunk) ;
		chunk = prev ;
	}
	obstack_init(&object_stack) ;
	return nil ;
}

@end

