#include <stdlib.h>
#include "c-stack.h"

struct stack_node {
	void * value;
	struct stack_node * next;
};

void clear_stack( struct stack * s, void (*free_el)( void * ) ) {
	for ( struct stack_node * next = s->head; next; ) {
		struct stack_node * crnt = next;
		next = crnt->next;
		free_el( crnt->value );
		free( crnt );
	}
	s->head = NULL;
}

struct stack new_stack() { return (struct stack){ NULL }; /***/ }

void copy_stack( struct stack * s, const struct stack * t, void * (*copy)( const void * ) ) {
	struct stack_node ** crnt = &s->head;
	for ( struct stack_node * next = t->head; next; next = next->next ) {
		*crnt = malloc( sizeof(struct stack_node) ); /***/
		(*crnt)->value = copy( next->value );
		crnt = &(*crnt)->next;
	}
	*crnt = NULL;
}
struct stack * assign_stack( struct stack * s, const struct stack * t, 
		void * (*copy_el)( const void * ), void (*free_el)( void * ) ) {
	if ( s->head == t->head ) return s;
	clear_stack( s, free_el ); /***/
	copy_stack( s, t, copy_el ); /***/
	return s;
}

_Bool stack_empty( const struct stack * s ) { return s->head == NULL; }

void push_stack( struct stack * s, void * v ) {
	struct stack_node * n = malloc( sizeof(struct stack_node) ); /***/
	*n = (struct stack_node){ v, s->head }; /***/
	s->head = n;
}

void * pop_stack( struct stack * s ) {
	struct stack_node * n = s->head;
	s->head = n->next;
	void * v = n->value;
	free( n );
	return v;
}
