/*
 *  slist.c
 *  Chatter
 *
 *  Created by Curtis Jones on 2009.10.09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "slist.h"
#include "logger.h"

/**
 *
 *
 */
int
slist_init (slist_t *slist, opool_t *pool)
{
	if (unlikely(slist == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(pool == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null opool_t\n", __PRETTY_FUNCTION__);
	
	slist->head = NULL;
	slist->count = 0;
	slist->pool = opool_retain(pool);
	
	return 0;
}

/**
 *
 *
 */
int
slist_destroy (slist_t *slist)
{
	cobject_t *object = NULL;
	
	if (unlikely(slist == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_t\n", __PRETTY_FUNCTION__);
	
	while (0 == slist_pop(slist, &object) && object != NULL) {
		cobject_release(object);
	}
	
	opool_release(slist->pool);
	slist->pool = NULL;
	
	return 0;
}

/**
 *
 *
 */
inline int
slist_push (slist_t *slist, cobject_t *object)
{
	int error;
	slist_item_t *item;
	
	if (unlikely(slist == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(object == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null data\n", __PRETTY_FUNCTION__);
	
	if (unlikely(0 != (error = opool_pop(slist->pool, (void**)&item))))
		LOG_ERROR_AND_RETURN(-101, "%s.. failed to opool_pop, 0x%08X [%d]\n", __PRETTY_FUNCTION__, error, error);
	
	item->data = cobject_retain(object);
	item->next = slist->head;
	
	slist->head = item;
	slist->count++;
	
	return 0;
}

/**
 * Don't forget: it is up to the caller of slist_pop() to release the memory.
 *
 */
inline int
slist_pop (slist_t *slist, cobject_t **object)
{
	slist_item_t *item;
	
	if (unlikely(slist == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(object == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null cobject_t\n", __PRETTY_FUNCTION__);
	
	if (slist->head != NULL) {
		item = slist->head;
		*object = item->data;
		slist->head = item->next;
		slist->count--;
		opool_push(slist->pool, item);
	}
	else
		*object = NULL;
	
	return 0;
}

/**
 *
 *
 */
inline int
slist_iter_init (slist_t *slist, slist_iter_t *iter)
{
	if (unlikely(slist == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(iter == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null slist_iter_t\n", __PRETTY_FUNCTION__);
	
	iter->item = slist->head;
	
	return 0;
}

/**
 *
 *
 */
inline int
slist_iter_next (slist_iter_t *iter, cobject_t **object)
{
	if (unlikely(iter == NULL))
		LOG_ERROR_AND_RETURN(-1, "%s.. null slist_iter_t\n", __PRETTY_FUNCTION__);
	
	if (unlikely(object == NULL))
		LOG_ERROR_AND_RETURN(-2, "%s.. null cobject_t\n", __PRETTY_FUNCTION__);
	
	if (iter->item == NULL)
		*object = NULL;
	else {
		*object = iter->item->data;
		iter->item = iter->item->next;
	}
	
	return 0;
}
