/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 :
 * =====================================================================
 *  sc_iterator.c
 *  Copyright (c)  2003 - 2011  sys0tem
 *  LICENSE :
 *	LGPL (GNU Lesser General Public License - Version 3,29 June 2007)
 *	http://www.gnu.org/copyleft/lesser.html
 *	or
 *	EPL (Eclipse Public License - v1.0)
 *	http://www.eclipse.org/legal/epl-v10.html
 * =====================================================================
 */
#include <string.h>
#include <sc_os.h>
#include <sc_error.h>
#include <sc_env.h>
#include <sc_mmgr.h>
#include <sc_iterator.h>


/* ---------------------------------------------------------------------
 *  プロトタイプ宣言
 * ---------------------------------------------------------------------
 */
static bool        SC_Iterator_hasNext(SC_Iterator* ite);
static const void* SC_Iterator_next(SC_Iterator* ite, size_t* size);
static const char* SC_Iterator_nextStr(SC_Iterator* ite);

/**
 * SC_Iterator を生成します。
 * メモリ確保に失敗した場合、NULL を返します。
 *
 * @param head Iteratorのエントリの先頭
 * @return SC_Iterator
 */
SC_Iterator* SC_Iterator_new(SC_Iterator_Entry* head)
{
	SC_Iterator* ite = (SC_Iterator*) malloc(sizeof(SC_Iterator));
	if (ite == NULL)
	{	/* メモリ確保失敗	*/
		return NULL;
	}
	ite->_head = head;
	ite->_now  = head;

	ite->hasNext      = SC_Iterator_hasNext;
	ite->next         = SC_Iterator_next;
	ite->nextStr      = SC_Iterator_nextStr;
	return ite;
}


/**
 * SC_Iterator を破棄します。
 * ここで破棄されるデータは、SC_Iterator のみであり、
 * new された際の引数に渡されたデータについては破棄しません。
 * new の際渡された各データが malloc 等で確保されている場合、
 * 以下のようなコードで破棄する必要があります。
 *
 * <pre>
 * SC_Iterator_Entry* next;
 * SC_Iterator_Entry* entry;
 *
 * entry = ite->_head;
 * while (entry != NULL)
 * {
 *     next = entry->next;
 *     free(entry);
 *     entry = next;
 * }
 * </pre>
 *
 * @param ite Iterator
 */
void SC_Iterator_delete(SC_Iterator* ite)
{
	free (ite);
}


/* ---------------------------------------------------------------------
 *  以下、内部でのみ利用する関数
 * ---------------------------------------------------------------------
 */


/**
 * 次の要素が存在するかどうか返します。
 *
 * @param ite Iterator
 * @return true/false (存在する/しない)
 */
static
bool SC_Iterator_hasNext(SC_Iterator* ite)
{
	if (ite->_now == NULL)
	{
		return false;
	}
	return true;
}


/**
 * 次の要素を取得します。
 * 要素が存在しない場合 NULL が返されます。
 * size が NULL でない場合、要素のサイズが格納されます。
 *
 * @param ite Iterator
 * @param size サイズ
 * @return 値
 */
static
const void* SC_Iterator_next(SC_Iterator* ite, size_t* size)
{
	SC_Iterator_Entry* entry;
	if (ite->_now == NULL)
	{
		return NULL;
	}
	/* 読み出しポインタを進める	*/
	entry = ite->_now;
	ite->_now = ite->_now->next;
	if (size != NULL)
	{
		*size = entry->size;
	}
	return entry->value;
}


/**
 * 次の要素を文字列として取得します。
 * 要素が存在しない場合 NULL が返されます。
 *
 * @param ite Iterator
 * @return 値
 */
static
const char* SC_Iterator_nextStr(SC_Iterator* ite)
{
	return (const char*) SC_Iterator_next(ite, NULL);
}

