#ifndef	ACL_SYS_PATCH_INCLUDE_H
#define	ACL_SYS_PATCH_INCLUDE_H

# ifdef	__cplusplus
extern "C" {
# endif

#include "acl_define.h"
#include "acl_vstream.h"

#if defined(_WIN32) || defined(_WIN64)
struct iovec {
	void *iov_base;   /**< Starting address */
	size_t iov_len;   /**< Number of bytes */
};

#ifdef	HAVE_NO_TIMEVAL
struct timeval {
	long tv_sec;      /**< seconds */
	long tv_usec;     /**< microseconds */
};
#endif

struct timezone {
	int tz_minuteswest; /**< minutes W of Greenwich */
	int tz_dsttime;     /**< type of dst correction */
};

/**
 * ˯߼
 * @param sec {int} ˯ߵ
 */
ACL_API void sleep(int sec);

/**
 * õǰʱ
 * @param tv {struct timeval*} 洢ǰʱ
 * @param tz {struct timezone*} ʱ
 */
ACL_API int gettimeofday(struct timeval *tv, struct timezone *tz);
ACL_API int gettimeofday1(struct timeval *tv, struct timezone *tz);
ACL_API int gettimeofday2(struct timeval *tv, struct timezone *tz);
ACL_API int gettimeofday3(struct timeval *tv, struct timezone *tz);
ACL_API int gettimeofday4(struct timeval *tv, struct timezone *tz);

#endif  /* _WIN32 */
#ifdef	ACL_UNIX
# include <sys/uio.h>
#endif

/**
 * ׽ֳʼ_WIN32ƽ̨ҪWSAStartupʼSOCKET
 * UNIXƽ̨Ҫͨ signal(SIGPIPE, SIG_IGN) ź
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_init(void);

/**
 * ˳ǰô˺ͷȫ׽Դ_WIN32Ч
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_end(void);

/**
 * ر׽
 * @param fd {ACL_SOCKET} ׽
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_close(ACL_SOCKET fd);

/**
 * ֹ׽ӿڵķ
 * @param fd {ACL_SOCKET} ׽
 * @param how {int}
 * @return {int}  0 ʾɹʾ
 */
#if defined(_WIN32) || defined(_WIN64)
# ifndef SHUT_RD
#  define SHUT_RD SD_RECEIVE
# endif
# ifndef SHUT_WR
#  define SHUT_WR SD_SEND
# endif
# ifndef SHUT_RDWR
#  define SHUT_RDWR SD_BOTH
# endif
#endif
ACL_API int acl_socket_shutdown(ACL_SOCKET fd, int how);

/**
 * ׽ֶ
 * @param fd {ACL_SOCKET} ׽
 * @param buf {void*} ڴ滺ַ
 * @param size {size_t} buf С
 * @param timeout {int} дʱʱ(ĬΪλ, ACL_VSTREAM_IS_MS() ʱ
 *  λΪ), ֵ >= 0 ʱ, öдʱ, < 0 򲻼.
 * @param fp {ACL_VSTREAM*} , Ϊ
 * @param arg {void*} ûѵĲڻصʽʱ
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_read(ACL_SOCKET fd, void *buf, size_t size,
	int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ׽д
 * @param fd {ACL_SOCKET} ׽
 * @param buf {void*} ݵַ
 * @param size {size_t} buf ݴС
 * @param timeout {int} дʱʱ(ĬΪλ, ACL_VSTREAM_IS_MS() ʱ
 *  λΪ), ֵ >= 0 ʱ, öдʱ, < 0 򲻼.
 * @param fp {ACL_VSTREAM*} , Ϊ
 * @param arg {void*} ûѵĲڻصʽʱ
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_write(ACL_SOCKET fd, const void *buf,
	size_t size, int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ׽д
 * @param fd {ACL_SOCKET} ׽
 * @param vec {const struct iovec*} ַ
 * @param count {int} vec 鳤
 * @param timeout {int} дʱʱ(ĬΪλ, ACL_VSTREAM_IS_MS() ʱ
 *  λΪ), ֵ >= 0 ʱ, öдʱ, < 0 򲻼.
 * @param fp {ACL_VSTREAM*} , Ϊ
 * @param arg {void*} ûѵĲڻصʽʱ
 * @return {int} 0: OK; -1: error
 */
ACL_API int acl_socket_writev(ACL_SOCKET fd, const struct iovec *vec,
	int count, int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ж׽Ƿ
 * @param fd {ACL_SOCKET}
 * @return {int} ֵ 1 ʾ 0 ʾ쳣
 */
ACL_API	int acl_socket_alive(ACL_SOCKET fd);
ACL_API	int acl_socket_alive2(ACL_SOCKET fd, double *tc1, double *tc2);

/**
 * ļ
 * @param filepath {cosnt char*} ļ·
 * @param flags {int} 򿪱־λ, O_RDONLY | O_WRONLY | O_RDWR, 
 *  O_CREAT | O_EXCL | O_TRUNC, O_APPEND(for UNIX)
 * @param mode {int} Ȩλ, UNIXЧ, 磺0700, 0755
 * @return {ACL_FILE_HANDLE} 򿪵ļ ACL_FILE_INVALID ʾʧ
 */
ACL_API ACL_FILE_HANDLE acl_file_open(const char *filepath, int flags, int mode);

/**
 * رմ򿪵ļ
 * @param fh {ACL_FILE_HANDLE} ļ
 * @return {int} 0: ok; -1: error
 */
ACL_API int acl_file_close(ACL_FILE_HANDLE fh);

/**
 * λļλ
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param offset {acl_off_t} ƫλ
 * @param whence {int} λñ־λSEEK_CUR, SEEK_SET, SEEK_END
 * @return {acl_off_t} ǰļƫλ
 */
ACL_API acl_off_t acl_lseek(ACL_FILE_HANDLE fh, acl_off_t offset, int whence);

/**
 * ļж
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param buf {void*} 洢
 * @param size {size_t} buf С
 * @param timeout {int} ò
 * @param fp {ACL_VSTREAM*} Ӧļ, Ϊ
 * @param arg {void*} ûݵĲ, Իصʽʹʱ˲Ч
 * @return {int} ʵ,  ACL_VSTREAM_EOF ʾ
 */
ACL_API int acl_file_read(ACL_FILE_HANDLE fh, void *buf, size_t size,
	int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ļд
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param buf {void*} ݴ洢
 * @param size {size_t} buf ݳȴС
 * @param timeout {int} ò
 * @param fp {ACL_VSTREAM*} Ӧļ, Ϊ
 * @param arg {void*} ûݵĲ, Իصʽʹʱ˲Ч
 * @return {int} ɹд,  ACL_VSTREAM_EOF ʾд
 */
ACL_API int acl_file_write(ACL_FILE_HANDLE fh, const void *buf, size_t size,
	int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ļдһ
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param vec {const struct iovec*} ݴ洢
 * @param count {int} vec Ԫظ
 * @param timeout {int} ò
 * @param fp {ACL_VSTREAM*} Ӧļ, Ϊ
 * @param arg {void*} ûݵĲ, Իصʽʹʱ˲Ч
 * @return {int} ɹд,  ACL_VSTREAM_EOF ʾд
 */
ACL_API int acl_file_writev(ACL_FILE_HANDLE fh, const struct iovec *vec,
	int count, int timeout, ACL_VSTREAM *fp, void *arg);

/**
 * ļеȫдӲ
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param fp {ACL_VSTREAM*} Ӧļ, Ϊ
 * @param arg {void*} ûݵĲ, Իصʽʹʱ˲Ч
 * @return {int} 0: ok; -1: error
 */
ACL_API int acl_file_fflush(ACL_FILE_HANDLE fh, ACL_VSTREAM *fp, void *arg);

/**
 * ļȡøļĴС
 * @param filename {const char*} ļ
 * @return {acl_int64} >= 0: ok;  -1: error
 */
ACL_API acl_int64 acl_file_size(const char *filename);

/**
 * ļȡøļĴС
 * @param fh {ACL_FILE_HANDLE} ļ
 * @param fp {ACL_VSTREAM*} Ӧļ, Ϊ
 * @param arg {void*} ûݵĲ, Իصʽʹʱ˲Ч
 * @return {acl_int64} >= 0: ok;  -1: error
 */
ACL_API acl_int64 acl_file_fsize(ACL_FILE_HANDLE fh, ACL_VSTREAM *fp, void *arg);

/**
 *  SOCKET 
 * @param domain {int}
 * @param type {int}
 * @param protocol {int}
 * @param result {ACL_SOCKET [2]} 洢
 * @return {int} ɹ 0ʧܷ -1
 */
ACL_API int acl_sane_socketpair(int domain, int type, int protocol,
		ACL_SOCKET result[2]);

/* in acl_sys_socket.c */

#if defined(_WIN32) || defined(_WIN64)
typedef int (WINAPI *acl_close_socket_fn)(ACL_SOCKET);
typedef int (WINAPI *acl_recv_fn)(ACL_SOCKET, char *, int, int);
typedef int (WINAPI *acl_send_fn)(ACL_SOCKET, const char *, int, int);
#else
typedef int (*acl_close_socket_fn)(ACL_SOCKET);
typedef ssize_t  (*acl_read_fn)(ACL_SOCKET, void *, size_t);
typedef ssize_t  (*acl_recv_fn)(ACL_SOCKET, void *, size_t, int);
typedef ssize_t  (*acl_write_fn)(ACL_SOCKET, const void *, size_t);
typedef ssize_t  (*acl_writev_fn)(ACL_SOCKET, const struct iovec *, int);
typedef ssize_t  (*acl_send_fn)(ACL_SOCKET, const void *, size_t, int);
#endif

#if !defined(_WIN32) && !defined(_WIN64)
ACL_API void acl_set_read(acl_read_fn fn);
ACL_API void acl_set_write(acl_write_fn fn);
ACL_API void acl_set_writev(acl_writev_fn fn);
#endif

ACL_API void acl_set_close_socket(acl_close_socket_fn fn);
ACL_API void acl_set_recv(acl_recv_fn fn);
ACL_API void acl_set_send(acl_send_fn fn);

# ifdef	__cplusplus
}
# endif

#endif

