Cでイテレータパターン

シリーズもの今回はイテレータ構造体。まずはイテレータインターフェイスに当たるヘッダファイルIterator.h

#ifndef ITERATOR_HEADER_FILE_INCLUDED__
#define ITERATOR_HEADER_FILE_INCLUDED__

/*! Iterator構造体 */
typedef struct Iterator_tag Iterator;

/*!
	@brief	次の要素があるかどうかの判定
	@param	p:イテレータインスタンスを指すポインタ
	@retval	0: 次の要素無し
	@retval	!0: 次の要素あり	
	@attention	!0の場合、nextが正常に実行できる
	@attention	実際の処理はコンクリートクラスにて実装のこと
 */
int hasNext(Iterator *p);

/*!
	@brief	要素を取得し、次の要素を指すようにする
	@param	p:イテレータインスタンスを指すポインタ
	@retval	取得した要素を指すポインタ	
	@attention	戻り値の型はvoid *なので適切なポインタで受けること
	@attention	実際の処理はコンクリートクラスにて実装のこと
 */
void *next(Iterator *p);

#endif	/* End of ITERATOR_HEADER_FILE_INCLUDED__ */

んでこれを実装するBookShelfIteratorのヘッダファイルBookShelfIterator.h

#ifndef BOOK_SHELF_ITERATOR_HEADER_FILE_INCLUDED__
#define BOOK_SHELF_ITERATOR_HEADER_FILE_INCLUDED__

#include "Iterator.h"
#include "BookShelf.h"

/*!
	@brief	BookShelfIteratorコンストラクタ
	@param	p:BookShelfのインスタンスを指すポインタ
	@retval	生成したIteratorのインスタンスを指すポインタ
	@attention	戻り値のインスタンスはDisposeBookShelfで破棄すること
 */
Iterator *CreateBookShelfIterator(BookShelf *p);

/*!
	@brief	BookShelfIteratorのデストラクタ
	@param	p: BookShelfIteratorインスタンスを指すポインタ
 */
void DisposeBookShelfIterator(Iterator *p);

#endif


そんでもって、コンクリートイテレータであるBookShelfIterator.c。 BookShelfはBookを動的配列として保持していて、これをインデックス順に舐めるようなイテレータ実装とする。

#include "BookShelfIterator.h"
#include "BookShelf.h"
#include "Book.h"
#include <stdlib.h>

struct Iterator_tag{
	BookShelf *pBookShelf;
	int index;
};

int hasNext(Iterator *p)
{
	if (p->index < GetLength(p->pBookShelf)) {
		return 1;
	} else {
		return 0;
	}
}
void *next(Iterator *p)
{
	Book *pBook = GetBookAt(p->pBookShelf, p->index);
	p->index++;
	
	return pBook;
}

Iterator *CreateBookShelfIterator(BookShelf *pBookShelf)
{
	Iterator *self = NULL;

	self = malloc(sizeof(Iterator));
	if (self == NULL) {
		return NULL;
	}

	self->pBookShelf = pBookShelf;
	self->index = 0;

	return self;
}

void DisposeBookShelfIterator(Iterator *p)
{
	free(p);
}