#ifndef ACL_SCAN_DIR_INCLUDE_H
#define ACL_SCAN_DIR_INCLUDE_H

#include <sys/stat.h>

#ifdef  __cplusplus
extern "C" {
#endif

#include "acl_define.h"
/**
 * Ŀ¼ɨͶ
 */
typedef struct ACL_SCAN_DIR ACL_SCAN_DIR;

/**
 * Ŀ¼ɨûõĻصͶ
 * @param scan {ACL_SCAN_DIR*} Ŀ¼ɨָ
 * @param ctx {void*} ûָ
 */
typedef int (*ACL_SCAN_DIR_FN)(ACL_SCAN_DIR *scan, void *ctx);

/**
 * Ŀ¼ɨУĿ¼ûԶɾĿ¼ǣص˷
 * ֪ͨûɾָĿĿ¼
 * @param scan {ACL_SCAN_DIR*} Ŀ¼ɨָ
 * @param ctx {void*} ûָ
 */
typedef int (*ACL_SCAN_RMDIR_FN)(ACL_SCAN_DIR *scan, const char *path, void *ctx);

/**
 * ɨ·, Ϊ acl_scan_dir ĳʼ
 * @param path {const char*} Ҫ򿪵·
 * @param recursive {int} ǷҪݹɨĿ¼
 * @return {ACL_SCAN_DIR*} NULL: Err; != NULL, OK
 */
ACL_API ACL_SCAN_DIR *acl_scan_dir_open(const char *path, int recursive);

/**
 * ɨ·, Ϊ acl_scan_dir ĳʼ
 * @param path {const char*} Ҫ򿪵·
 * @param flags {unsigned} ־λ,  ACL_SCAN_FLAG_XXX
 * @return {ACL_SCAN_DIR*} NULL: Err; != NULL, OK
 */
ACL_API ACL_SCAN_DIR *acl_scan_dir_open2(const char *path, unsigned flags);
#define ACL_SCAN_FLAG_RECURSIVE	(1 << 0)	/* Ƿݹɨ */
#define ACL_SCAN_FLAG_RMDIR	(1 << 1)	/* ǷԶɾĿ¼ */

/**
 * رɨ
 * @param scan {ACL_SCAN_DIR*} ָ
 */
ACL_API void acl_scan_dir_close(ACL_SCAN_DIR *scan);

/**
 * Ŀ¼ɨͳϢصı0
 * @param scan {ACL_SCAN_DIR*} ָ
 */
ACL_API void acl_scan_dir_reset(ACL_SCAN_DIR *scan);

/**
 * ͨ˽ӿɨĻصȣһƱ־
 * Ϊ ACL_SCAN_CTL_END ʱʾƲб
 * @param scan {ACL_SCAN_DIR*} ָ
 * @param name {int} һ ACL_SCAN_CTL_XXX
 */
ACL_API void acl_scan_dir_ctl(ACL_SCAN_DIR *scan, int name, ...);
#define ACL_SCAN_CTL_END	0  /**< ƽ־ */
#define ACL_SCAN_CTL_FN		1  /**<  ACL_SCAN_DIR_FN ־ */
#define ACL_SCAN_CTL_CTX	2  /**< û */
#define ACL_SCAN_CTL_RMDIR_FN	3  /**< ɾĿ¼ص */

/**
 * õǰ״̬µ·(ڳ acl_scan_dir_open
 * ʱĳ·)
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {const char*} ·, == NULL: err; != NULL, OK
 */
ACL_API const char *acl_scan_dir_path(ACL_SCAN_DIR *scan);

/**
 * ǰɨļɨĶļ򷵻 "\0"
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {const char*} ļ
 */
ACL_API const char *acl_scan_dir_file(ACL_SCAN_DIR *scan);

/**
 * ǰѾɨĿ¼ܸ
 * @param scan {ACL_SCAN_DIR*}
 * @return {unsigned} Ŀ¼ܸ
 */
ACL_API unsigned acl_scan_dir_ndirs(ACL_SCAN_DIR *scan);

/**
 * ǰѾɨļܸ
 * @param scan {ACL_SCAN_DIR*}
 * @return {unsigned} ļܸ
 */
ACL_API unsigned acl_scan_dir_nfiles(ACL_SCAN_DIR *scan);

/**
 * ǰѾɨļСܺ
 * @param scan {ACL_SCAN_DIR*}
 * @return {acl_int64} -1: Error; >= 0: Ok
 */
ACL_API acl_int64 acl_scan_dir_nsize(ACL_SCAN_DIR *scan);

/**
 * ȡõǰɨ赽ļĿ¼Ϣڱ׼ stat() 
 * @param scan {ACL_SCAN_DIR*} ָ
 * @param sbuf {struct acl_stat*} ָ
 * @return {int} 0: Ok, -1: Error
 */
ACL_API int acl_scan_stat(ACL_SCAN_DIR *scan, struct acl_stat *sbuf);

/**
 * ȡõǰɨĿ¼ڵϢ API ͬ acl_scan_stat
 * @param scan {ACL_SCAN_DIR*} ָ
 * @param sbuf {struct acl_stat*} ָ
 * @return {int} 0: Ok, -1: Error
 */
ACL_API int acl_scan_dir_stat(ACL_SCAN_DIR *scan, struct acl_stat *sbuf);

/**
 * Ŀ¼Ƿɨ
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {int} 0: ʾδɨϣ !=0: ʾɨ
 */
ACL_API int acl_scan_dir_end(ACL_SCAN_DIR *scan);

/**
 * Ҫɨ·ѹջ
 * @param scan {ACL_SCAN_DIR*} ָ
 * @param path {const char*} Ҫѹջ·
 * @return {int} 0: OK; -1: Err
 */
ACL_API int acl_scan_dir_push(ACL_SCAN_DIR *scan, const char *path);

/**
 * һ·
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {ACL_SCAN_DIR*} ضջеһ, == NULL: ; != NULL, OK
 */
ACL_API ACL_SCAN_DIR *acl_scan_dir_pop(ACL_SCAN_DIR *scan);

/**
 *  scan ǰ·һ·ļ, ע⣬úڲݹɨ,
 *  acl_scan_dir_open еĲ recursive ԸúЧ
 *  1 ".."  "." 
 *  2 , ·, · acl_scan_dir_path 
 * @param scan {ACL_SCAN_DIR*} ַָ
 * @return {const char*} ΪĿ¼ƻļ, != NULL: OK; == NULL, ɨ
 */
ACL_API const char *acl_scan_dir_next(ACL_SCAN_DIR *scan);

/**
 * һļ(·, ·ͨ acl_scan_dir_path ),
 * úڲֵ֧ݹɨĿ¼, acl_scan_dir_open еĲ recursive ԸúЧ
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {const char*} һɨļ: !NULL, OK; NULL ɨϣӦɨ
 */
ACL_API const char *acl_scan_dir_next_file(ACL_SCAN_DIR *scan);

/**
 * һĿ¼(·, ·ͨ acl_scan_dir_path ),
 * úڲֵ֧ݹɨĿ¼, acl_scan_dir_open еĲ recursive ԸúЧ
 * @param scan {ACL_SCAN_DIR*} ָ
 * @return {const char*} һɨĿ¼: !NULL, OK; NULL ɨ, Ӧɨ
 */
ACL_API const char *acl_scan_dir_next_dir(ACL_SCAN_DIR *scan);

/**
 * һĿ¼ļ(·, ·ͨ acl_scan_dir_path ),
 * úڲֵ֧ݹɨĿ¼, acl_scan_dir_open еĲ recursive ԸúЧ
 * @param scan {ACL_SCAN_DIR*} ָ
 * @param is_file {int*} ؽǿʱõַ洢ֵʾɨ赽Ƿ
 *  ļΪ true ΪļΪĿ¼
 * @return {const char*} һɨĿ¼ļ: !NULL, OK; NULL ɨ,
 *  Ӧɨ
 */
ACL_API const char *acl_scan_dir_next_name(ACL_SCAN_DIR *scan, int *is_file);

/**
 * ȡõǰĿ¼ռ̿ռС(ֽڼ)
 * úڲֵ֧ݹɨĿ¼, acl_scan_dir_open еĲ recursive ԸúЧ
 * @param scan {ACL_SCAN_DIR*} Ŀ¼ʱɨ
 * @param nfile {int*} ɨ¼ɨļ
 * @param ndir {int*} ɨ¼ɨĿ¼
 * @return {acl_int64} -1: Error; >= 0: Ok
 */
ACL_API acl_int64 acl_scan_dir_size2(ACL_SCAN_DIR *scan, int *nfile, int *ndir);

/**
 * ȡõǰĿ¼ռ̿ռС(ֽڼ)
 * @param pathname {const char*} Ŀ¼·
 * @param recursive {int} ǷҪݹɨĿ¼µĿ¼
 * @param nfile {int*} ɨ¼ɨļ
 * @param ndir {int*} ɨ¼ɨĿ¼
 * @return {acl_int64} -1: Error, >= 0: Ok
 */
ACL_API acl_int64 acl_scan_dir_size(const char *pathname, int recursive,
		int *nfile, int *ndir);

/**
 * ɾ·еļĿ¼
 * @param nfile {int*} ɨ¼ɨļ
 * @param ndir {int*} ɨ¼ɨĿ¼
 * úڲֵ֧ݹɨĿ¼, acl_scan_dir_open еĲ recursive ԸúЧ
 * @param scan {ACL_SCAN_DIR*} Ŀ¼ʱɨ
 * @return {acl_int64} >= 0: ʵɾļĿ¼ĳߴС֮(ֽ); < 0: .
 */
ACL_API acl_int64 acl_scan_dir_rm2(ACL_SCAN_DIR *scan, int *nfile, int *ndir);

/**
 * ɾ·еļĿ¼
 * @param pathname {const char*} ·
 * @param recursive {int} ǷݹɾĿ¼Ŀ¼µļ
 * @param ndir {int*} òǿգ̽ *ndir ܹɾĿ¼Ŀ
 * @param nfile {int*} òǿգ̽ *nfile ܹɾļĿ
 * @return {acl_int64} >= 0: ʵɾļĿ¼ĳߴС֮(ֽ); < 0: .
 */
ACL_API acl_int64 acl_scan_dir_rm(const char *pathname, int recursive,
		int *ndir, int *nfile);

#ifdef  __cplusplus
}
#endif

#endif


