/* emio.h */ /* Copyright 1997-2000 by Eberhard Mattes Donated to the public domain. No warranty. 1997-07-19 Initial version 1999-03-17 struct emi_file (for copy_bidir_emi() in libemfw.h) 2000-05-01 Add emi_fill() 2000-05-28 Add emo_set_read(), emo_read(), and emo_shutdown() */ /* Fast stream I/O with some additional bells and whistles. Features: - Fast. As we use different implementations for read-only and write-only streams, emi_getc() and emo_putc() are very simple and fast. - Simple to use. Simpler to use than Unix file descriptors and C streams. For instance, emo_write() tries to write all the data. - Safe. The code contains lots of assertions (except for the functions implemented as macros) and does not use function pointers. Source included :-) - Built-in support for time out. A time out can be defined which will be applied to the underlying functions read() and write(), but not close(). - Built-in support for artificially restricting the length of a read-only file. This is quite useful for implementing "Content-Length". - If an operation fails due to an error reported by an underlying function such as write(), errno is set and all future I/O requests will fail, reporting the original errno. That is, we can delay error checking in inner loops to the end of the loop without risking to loose errno. As we cannot look into the future, write operations which go to the buffer cannot report an error immediately and we cannot tell how much data has been actually written. Drawbacks: - There are no read/write streams. - Opening a write-only file always truncates an existing file or creates a new file. - emo_printf() uses a fixed-length buffer. Output might be truncated. If HAVE_VSNPRINTF is not defined, you have to be very careful to avoid buffer overflow. (emo_printf() terminates the process on buffer overflow.) Notes: - If NDEBUG is not defined, emi_getc() and emo_putc() will be slow. */ #ifndef EMIO_INCLUDED #define EMIO_INCLUDED #include /* va_list */ #include "libemcommon.h" /* ------------------------------ EMI_FILE ------------------------------ */ typedef struct emi_file { int fd; /* File descriptor */ unsigned flags; /* Flag bits (EMI_FLAG_xxx) */ size_t bufsize; /* Buffer size */ int timeout; /* Timeout or 0 */ int error; /* Saved errno from last error */ long limit; /* Artificial file length limit or -1 */ const char *ptr; /* Pointer to next character in buffer */ const char *end; /* Pointer to end of buffer */ char *buf; /* Buffer */ unsigned long amount; /* Total number of bytes read */ } EMI_FILE; #define EMI_EOF (-1) /* Returned by emi_getc() on EOF or error */ #define EMI_FLAG_ERROR 0x0001 /* read() failed, no input possible */ #define EMI_FLAG_EOF 0x0002 /* EOF reached */ EMI_FILE *emi_open (const char *, size_t); EMI_FILE *emi_fdopen (int, size_t); int emi_close (EMI_FILE *); int emi_read (EMI_FILE *, void *, int); int emi_fill (EMI_FILE *, int); int emi_limit (EMI_FILE *, long); int emi_timeout (EMI_FILE *, int); unsigned long emi_amount (EMI_FILE *, int); int emi_peek (EMI_FILE *, void *, int); int emi_getc1 (EMI_FILE *); void emi_getc_assert (EMI_FILE *); #define emi_error(f) ((f)->flags & EMI_FLAG_ERROR) #define emi_getc(f) ( EMI_GETC_ASSERT (f), \ ((f)->ptr != (f)->end ? (unsigned char)*(f)->ptr++ : emi_getc1 (f))) #ifdef NDEBUG #define EMI_GETC_ASSERT(f) ((void)0) #else #define EMI_GETC_ASSERT(f) emi_getc_assert(f) #endif /* ------------------------------ EMO_FILE ------------------------------ */ typedef struct { int fd; /* File descriptor */ unsigned flags; /* Flag bits (EMO_FLAG_xxx) */ size_t bufsize; /* Buffer size */ int timeout; /* Timeout or 0 */ int error; /* Saved errno from last error */ char *ptr; /* Pointer to next character in buffer */ char *end; /* Pointer to end of buffer */ char *buf; /* Buffer */ unsigned long amount; /* Total number of bytes written */ } EMO_FILE; #define EMO_EOF (-1) /* Return by emo_putc() on error */ #define EMO_FLAG_ERROR 0x0001 /* An error has occurred */ #define EMO_FLAG_READ 0x0002 /* Read while writing to avoid dead lock */ EMO_FILE *emo_open (const char *, size_t); EMO_FILE *emo_fdopen (int, size_t); int emo_close (EMO_FILE *); int emo_flush (EMO_FILE *); int emo_write (EMO_FILE *, const void *, int); int emo_puts (EMO_FILE *, const char *); int emo_printf (EMO_FILE *, const char *, ...) ATTR_PRINTF (2, 3); int emo_vprintf (EMO_FILE *, const char *, va_list); int emo_timeout (EMO_FILE *, int); unsigned long emo_amount (EMO_FILE *, int); int emo_set_read (EMO_FILE *); int emo_read (EMO_FILE *, int); int emo_shutdown (EMO_FILE *); int emo_putc1 (EMO_FILE *, int); void emo_putc_assert (EMO_FILE *); #define emo_error(f) ((f)->flags & EMO_FLAG_ERROR) #define emo_putc(f,c) ( EMO_PUTC_ASSERT (f), \ ((f)->ptr != (f)->end ? (unsigned char)(*(f)->ptr++ = (c)) \ : emo_putc1 (f, c))) #ifdef NDEBUG #define EMO_PUTC_ASSERT(f) ((void)0) #else #define EMO_PUTC_ASSERT(f) emo_putc_assert(f) #endif #endif