/** bufio - buffered read/write I/O interface */

#include "socket.h"		/* they will re-include us */

#ifndef LIBAIO__BUFIO_H
#define	LIBAIO__BUFIO_H

#include "util.h"


/*** SYNOPSIS */
/*| bufio_init(sock); */
/*| bufio_read(sock, 16, read_hook, NULL); */
/*| bufio_write(sock, 3, "hi!", NULL, NULL); */
/*| bufio_done(sock, libaio_dummy, NULL); */


/** Per-socket buffers */

typedef struct {
	/* User socket handlers (we have own handlers attached to the socket
	 * itself). Note that the user handler_e is still stored in sock_t. */
	void (*handler_r)(sock_t *sock, int len, char *buf, void *data);
	void (*handler_w)(sock_t *sock, void *data);

	/* !(NULL) == destruction scheduled */
	void (*handler_d)(sock_t *sock, void *data);

	void *handler_r_data;
	void *handler_w_data;
	void *handler_d_data;

	int winlen;			/* wanted length */
	int inblen, outblen;		/* actual length */
	char *inbuf, *outbuf;		/* buffers itselves */
} buf_t;


/*+ Buffered I/O routines */

/* Note that these are somewhat different from the sock_t handlers. You won't
 * normally touch anything in the structure above directly but just tell bufio
 * what to do for you, and it will do it on its own and give you the requested
 * data when all of them arrived. */

/* This function sets up a buf_t structure. You probably will not use this
 * directly. */
/* Returns pointer to the allocated structure or NULL on failure. */
buf_t *bufio_get();

/* This function sets up buffer I/O on specified socket. */
/* Returns 1 if ok, 0 otherwise */
int bufio_init(sock_t *sock);

/* This function lets you shedule read of a specified amount of data and pass
 * it to a specified function. Note that your handler may be called immediately
 * if enough data is already buffered. You cannot directly queue more reads;
 * if a read is already sheduled, it is cancelled and the handler is replaced.
 * (Cancelling does not involve touching the buffered data in any way,
 * of course.) */
/* Returns 1 if ok, 0 otherwise */
int bufio_read(sock_t *sock, int len, void (*handler)(sock_t *sock, int len, char *buf, void *data), void *data);

/* This function lets you shedule write of a specified amount of data and then
 * notify you back by a specified function. You can queue multiple writes, but
 * only the last handler will be called at the completion. You may specify
 * a NULL handler. */
/* Returns 1 if ok, 0 otherwise */
int bufio_write(sock_t *sock, int len, char *buf, void (*handler)(sock_t *sock, void *data), void *data);

/* This function lets you schedule the buffers destruction. It will wait until
 * the current read and write is finished (no more reads and writes are
 * permitted) and then it will release the buffer structures and call your
 * function to notify you. You may NOT specify NULL handler here - use 'libaio_dummy'
 * instead). */
/* Returns 1 if ok, 0 otherwise */
int bufio_done(sock_t *sock, void (*handler)(sock_t *sock, void *data), void *data);

/* This function will immediately release all buffer structures. */
/* Always returns NULL. */
buf_t *bufio_del(buf_t *buf);

#endif
