#ifndef FILE_IO_H
#define FILE_IO_H

/* Header section */
#include <stdio.h>

/* Class structure */
struct file_io;

/* Class methods */
/****************************************/
/* Queries */
/****************************************/

/* Is there an error condition from last operation on object? */
int io_in_error (struct file_io *io);
/*   require (NULL != io); */
/* io_in_error (io) implies 0 != io_error_number (io) */
/* io_in_error (io) implies NULL != io_error_message (io) */

/* Is error that we are at the end of the stream? */
int io_at_eof(struct file_io *io);
/*   require (NULL != io); */
/*   require (io_in_error (io)); */

/* Is there a valid stream? */
int io_no_stream (struct file_io *io);
/*   require (NULL != io); */

/* Get error number */
int io_error_number (struct file_io *io);
/*   require (NULL != io); */
/* 0 != io_error_number (io) implies io_in_error (io) */
/* 0 != io_error_number (io) implies NULL != io_error_message (io) */

/* Get English string of the error message. */
const char* io_error_message (struct file_io *io);
/*   require (NULL != io); */
/* NULL != io_error_message (io) implies 0 != io_error_number (io) */
/* NULL != io_error_message (io) implies io_in_error (io) */

/****************************************/
/* Creation/destruction */

/* System features instantion is acquisition. If creation is
   successful then return value of io_new.. will not be NULL and
   io_in_error will be false. After io_delete is called any memory is
   freed and io == NULL. */

/****************************************/
/* Create object for regular file */
struct file_io* io_new_file(const char *path, const char *mode);
/*   require(path); */
/*   require(mode); */
/*   ensure((NULL == result) || !io_no_stream (result) || 0 != io_error_number (result)); */
/* NULL == result implies errno != 0 */

/* Create object for zlib compressed file */
struct file_io* io_new_zfile (const char *path, const char *mode);
/*   require(path); */
/*   require(mode); */
/*   ensure((NULL == result) || !io_no_stream (result) || 0 != io_error_number (result)); */
/* NULL == result implies errno != 0 */

/* Create object for bz2 compressed file */
struct file_io* io_new_bzfile (const char *path, const char *mode);
/*   require(path); */
/*   require(mode); */
/*   ensure((NULL == result) || !io_no_stream (result) || 0 != io_error_number (result)); */
/* NULL == result implies errno != 0 */

/* Close and destroy object */
void io_delete (struct file_io **io, char* err_msg, int err_msg_size);
/*   require (NULL != io); */
/*   require (NULL != *io); */
/*   require (0 == io_error_number(io)); */
/*   ensure (NULL == *io); */

/****************************************/
/* Manipulation procedures */
/****************************************/
/* These procedures will do nothing if io_in_error(..) is TRUE */

/* Read from file */
void io_read (struct file_io *io, void *ptr, size_t size, size_t amt);
/*   require (NULL != io); */
/*  require (!io_in_error(io)); status must be zero  */
/*  require (!io_no_stream (io));stream must exist  */

/* Write to file */
void io_write (struct file_io *io, void *ptr, size_t size, size_t amt);
/*   require (NULL != io); */
/*  require (!io_in_error(io)); status must be zero  */
/*  require (!io_no_stream (io));stream must exist  */

/* Reset any error condition */
void io_reset (struct file_io *io);
/*   require (io != NULL); */
/*   require (io_in_error(io)); */
/*   ensure (!io_in_error(io)); */
/*   ensure (NULL == io->error_message); */

#endif /* FILE_IO_H */
