#ifndef	__ARRAY_INCLUDE_H__
#define	__ARRAY_INCLUDE_H__

#ifdef  __cplusplus
extern "C" {
#endif

#include "iterator.h"

/**
 * ̬Ͷ
 */
typedef	struct ARRAY ARRAY;
struct ARRAY{
	int     capacity;	/**< items ռС */
	int     count;		/**< items кԪصĸ */
	void  **items;		/**< ̬ */
	unsigned flags;
#define	ARRAY_F_UNORDER		(1 << 0)	/* Ƿ˳ */

	/* Ӽ */

	/* βӶ̬ */
	void  (*push_back)(struct ARRAY*, void*);
	/* ͷӶ̬ */
	void  (*push_front)(struct ARRAY*, void*);
	/* β̬ */
	void *(*pop_back)(struct ARRAY*);
	/* ͷ̬ */
	void *(*pop_front)(struct ARRAY*);

	/* for iterator */

	/* ȡͷ */
	void *(*iter_head)(ITER*, struct ARRAY*);
	/* ȡһ */
	void *(*iter_next)(ITER*, struct ARRAY*);
	/* ȡβ */
	void *(*iter_tail)(ITER*, struct ARRAY*);
	/* ȡһ */
	void *(*iter_prev)(ITER*, struct ARRAY*);
};

/**
 * һ̬
 * @param init_size {int} ̬ĳʼС
 * @param flags {unsigned} ̬Ա־
 * @return {ARRAY*} ָ̬
 */
ARRAY *array_create(int init_size, unsigned flags);

/**
 * ͷŵ̬ڵĳԱͷŶ̬
 * @param a {ARRAY*} ָ̬
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ
 */
void array_clean(ARRAY *a, void (*free_fn)(void *));

/**
 * ͷŵ̬ڵĳԱͷŶ̬󣬵󴴽 dbuf 
 * ʱͷŽͷ dbuf ʱͷ
 * @param a {ARRAY*} ָ̬
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ
 */
void array_free(ARRAY *a, void (*free_fn)(void *));
#define array_destroy array_free

/**
 * ̬βӶ̬Ա
 * @param a {ARRAY*} ָ̬
 * @param obj {void*} ̬Ա
 * @return {int} >=0: ɹ, ֵΪԪе±λã-1: ʧ
 */
int array_append(ARRAY *a, void *obj);

/**
 * ̬ͷӶ̬Ա
 * @param a {ARRAY*} ָ̬
 * @param obj {void*} ̬Ա
 * @return {int} >=0: ɹ, ֵΪԪе±λã-1: ʧ
 */
int array_prepend(ARRAY *a, void *obj);

/**
 * ָ̬λǰӶ̬Ա(ý㼰Ժн㶼һλ)
 * @param a {ARRAY*} ָ̬
 * @param position {int} ĳλãԽ
 * @param obj {void*} ̬Ա
 * @return {int} 0: ɹ-1: ʧ
 */
int array_pred_insert(ARRAY *a, int position, void *obj);

/**
 * ָ̬λúӶ̬Ա(ýԺн㶼һλ)
 * @param a {ARRAY*} ָ̬
 * @param position {int} ĳλãԽ
 * @param obj {void*} ̬Ա
 * @return {int} 0: ɹ-1: ʧ
 */
int array_succ_insert(ARRAY *a, int position, void *obj);
#define array_insert array_succ_insert

/**
 * Ӷ̬еָλɾĳɾԪصȺ˳пܷ˸ı,
 * ΪɾԶԪλô
 * @param a {ARRAY*} ָ̬
 * @param pos {int} ĳλãԽ
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ룬
 *  ָΪգͷţô˺ͷŶ̬
 * @return {int} 0: ɹ-1: ʧ
 */
int array_delete(ARRAY *a, int pos, void (*free_fn)(void*));

/**
 * Ӷ̬ɾַָָĶ̬, ɾԪصȺ˳򱣳ֲ
 * ɾλмĳλãΪ˱֤Ԫص˳ڲɾԪغԪ
 * ǰһλ
 * @param a {ARRAY*} ָ̬
 * @param obj {void*} ַָ̬
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ룬
 *  ָΪգͷţô˺ͷŶ̬
 * @return {int} 0: ɹ-1: ʧ
 */
int array_delete_obj(ARRAY *a, void *obj, void (*free_fn)(void *));

/**
 * Ӷ̬ɾĳ±귶ΧĶ̬
 * @param a {ARRAY*} ָ̬
 * @param ibegin {int} ʼ±λ
 * @param iend {int} ±λ
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ룬
 *  ָΪգͷţô˺ͷŶ̬
 * @return {int} 0: ɹ-1: ʧ
 */
int array_delete_range(ARRAY *a, int ibegin, int iend, void (*free_fn)(void*));

/**
 * ƶ̬еĶ
 * @param a {ARRAY*} ָ̬
 * @param ito {int} ƶĿ±λ
 * @param ifrom {int} Ӵ±λÿʼƶ
 * @param free_fn {void (*)(void*)} ͷŶ̬ڳԱͷźָ룬
 *  ָΪգͷţô˺ͷŶ̬ͷŵĶ̬Ϊ
 *  [idx_obj_begin, idx_src_begin), Ϊһ뿪
 * @return {int} 0: ɹ-1: ʧ
 */
int array_mv_idx(ARRAY *a, int ito, int ifrom, void (*free_fn)(void *) );

/**
 * Ԥȱ֤̬Ŀռ䳤
 * @param a {ARRAY*} ָ̬
 * @param app_count {int} Ҫ̬ app_count λ
 */
void array_pre_append(ARRAY *a, int app_count);

/**
 * Ӷ̬еĳ±λȡ̬
 * @param a {ARRAY*} ָ̬
 * @param idx {int} ±λãԽ磬򷵻-1
 * @return {void*} != NULL: ɹ== NULL: ڻʧ
 */
void *array_index(const ARRAY *a, int idx);

/**
 * õǰ̬ж̬ĸ
 * @param a {ARRAY*} ָ̬
 * @return {int} ̬ж̬ĸ
 */
int array_size(const ARRAY *a);

void *array_head(ARRAY *a);
void *array_tail(ARRAY *a);
void array_push_back(struct ARRAY *a, void *obj);
void array_push_front(struct ARRAY *a, void *obj);
void *array_pop_back(struct ARRAY *a);
void *array_pop_front(struct ARRAY *a);

#ifdef  __cplusplus
}
#endif

#endif

