istream.h revision a0b6b441fc679e562e79be0fb2819ffc24ab5b74
70ee483d320a270993b56c713e350b736edd753fAki Tuomi#ifndef ISTREAM_H
70ee483d320a270993b56c713e350b736edd753fAki Tuomi#define ISTREAM_H
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Note that some systems (Solaris) may use a macro to redefine struct stat */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi#include <sys/stat.h>
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi uoff_t v_offset;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi int stream_errno;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int mmaped:1; /* be careful when copying data */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int blocking:1; /* read() shouldn't return 0 */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int closed:1;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int readable_fd:1; /* fd can be read directly if necessary
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (for sendfile()) */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int seekable:1; /* we can seek() backwards */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned int eof:1; /* read() has reached to end of file
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (but may still be data available in buffer) */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi struct istream_private *real_stream;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi};
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomitypedef void istream_callback_t(void *context);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_fd(int fd, size_t max_buffer_size,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi bool autoclose_fd);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Open the given path only when something is actually tried to be read from
70ee483d320a270993b56c713e350b736edd753fAki Tuomi the stream. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_file(const char *path, size_t max_buffer_size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_mmap(int fd, size_t block_size,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi uoff_t start_offset, uoff_t v_size,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi bool autoclose_fd);
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_from_data(const void *data, size_t size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_limit(struct istream *input, uoff_t v_size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_range(struct istream *input,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi uoff_t v_offset, uoff_t v_size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomistruct istream *i_stream_create_error(int stream_errno);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Set name (e.g. path) for input stream. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_set_name(struct istream *stream, const char *name);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Get input stream's name. If stream itself doesn't have a name,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi it looks up further into stream's parents until one of them has a name.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi Returns "" if stream has no name. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiconst char *i_stream_get_name(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* i_stream_close() + i_stream_unref() */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_destroy(struct istream **stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Reference counting. References start from 1, so calling i_stream_unref()
70ee483d320a270993b56c713e350b736edd753fAki Tuomi destroys the stream if i_stream_ref() is never used. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_ref(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Unreferences the stream and sets stream pointer to NULL. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_unref(struct istream **stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Call the given callback function when stream is destroyed. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_set_destroy_callback(struct istream *stream,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi istream_callback_t *callback, void *context)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi ATTR_NULL(3);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi#define i_stream_set_destroy_callback(stream, callback, context) \
70ee483d320a270993b56c713e350b736edd753fAki Tuomi i_stream_set_destroy_callback(stream + \
70ee483d320a270993b56c713e350b736edd753fAki Tuomi CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (istream_callback_t *)callback, context)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Remove the destroy callback. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_unset_destroy_callback(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Return file descriptor for stream, or -1 if none is available. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiint i_stream_get_fd(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Mark the stream closed. Any reads after this will return -1. The data
70ee483d320a270993b56c713e350b736edd753fAki Tuomi already read can still be used. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_close(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Sync the stream with the underlying backend, ie. if a file has been
70ee483d320a270993b56c713e350b736edd753fAki Tuomi modified, flush any cached data. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_sync(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Change the initial size for stream's input buffer. This basically just
70ee483d320a270993b56c713e350b736edd753fAki Tuomi grows the read buffer size from the default. This function has no effect
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unless it's called before reading anything. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_set_init_buffer_size(struct istream *stream, size_t size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Change the maximum size for stream's input buffer to grow. Useful only
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for buffered streams (currently only file). */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns the current max. buffer size. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomisize_t i_stream_get_max_buffer_size(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Enable/disable i_stream[_read]_next_line() returning the last line if it
70ee483d320a270993b56c713e350b736edd753fAki Tuomi doesn't end with LF. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_set_return_partial_line(struct istream *stream, bool set);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns number of bytes read if read was ok, -1 if EOF or error, -2 if the
70ee483d320a270993b56c713e350b736edd753fAki Tuomi input buffer is full. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomissize_t i_stream_read(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Skip forward a number of bytes. Never fails, the next read tells if it
70ee483d320a270993b56c713e350b736edd753fAki Tuomi was successful. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_skip(struct istream *stream, uoff_t count);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Seek to specified position from beginning of file. Never fails, the next
70ee483d320a270993b56c713e350b736edd753fAki Tuomi read tells if it was successful. This works only for files. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_seek(struct istream *stream, uoff_t v_offset);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Like i_stream_seek(), but also giving a hint that after reading some data
70ee483d320a270993b56c713e350b736edd753fAki Tuomi we could be seeking back to this mark or somewhere after it. If input
70ee483d320a270993b56c713e350b736edd753fAki Tuomi stream's implementation is slow in seeking backwards, it can use this hint
70ee483d320a270993b56c713e350b736edd753fAki Tuomi to cache some of the data in memory. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns 0 if ok, -1 if error. As the underlying stream may not be
70ee483d320a270993b56c713e350b736edd753fAki Tuomi a file, only some of the fields might be set, others would be zero.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi st_size is always set, and if it's not known, it's -1.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi If exact=FALSE, the stream may not return exactly correct values, but the
70ee483d320a270993b56c713e350b736edd753fAki Tuomi returned values can be compared to see if anything had changed (eg. in
70ee483d320a270993b56c713e350b736edd753fAki Tuomi compressed stream st_size could be compressed size) */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiint i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Similar to i_stream_stat() call. Returns 1 if size was successfully
70ee483d320a270993b56c713e350b736edd753fAki Tuomi set, 0 if size is unknown, -1 if error. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns TRUE if there are any bytes left to be read or in buffer. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomibool i_stream_have_bytes_left(const struct istream *stream) ATTR_PURE;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns TRUE if there are no bytes buffered and read() returns EOF. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomibool i_stream_is_eof(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns the absolute offset of the stream. This is the stream's current
70ee483d320a270993b56c713e350b736edd753fAki Tuomi v_offset + the parent's absolute offset when the stream was created. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiuoff_t i_stream_get_absolute_offset(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Gets the next line from stream and returns it, or NULL if more data is
70ee483d320a270993b56c713e350b736edd753fAki Tuomi needed to make a full line. i_stream_set_return_partial_line() specifies
70ee483d320a270993b56c713e350b736edd753fAki Tuomi if the last line should be returned if it doesn't end with LF. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomichar *i_stream_next_line(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Like i_stream_next_line(), but reads for more data if needed. Returns NULL
70ee483d320a270993b56c713e350b736edd753fAki Tuomi if more data is needed or error occurred. If the input buffer gets full,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi stream_errno is set to ENOBUFS. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomichar *i_stream_read_next_line(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns TRUE if the last line read with i_stream_next_line() ended with
70ee483d320a270993b56c713e350b736edd753fAki Tuomi CRLF (instead of LF). */
70ee483d320a270993b56c713e350b736edd753fAki Tuomibool i_stream_last_line_crlf(struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Returns pointer to beginning of read data, or NULL if there's no data
70ee483d320a270993b56c713e350b736edd753fAki Tuomi buffered. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiconst unsigned char *
70ee483d320a270993b56c713e350b736edd753fAki Tuomii_stream_get_data(const struct istream *stream, size_t *size_r);
70ee483d320a270993b56c713e350b736edd753fAki Tuomisize_t i_stream_get_data_size(const struct istream *stream);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Like i_stream_get_data(), but returns non-const data. This only works with
70ee483d320a270993b56c713e350b736edd753fAki Tuomi buffered streams (currently only file), others return NULL. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi size_t *size_r);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Like i_stream_get_data(), but read more when needed. Returns 1 if more
70ee483d320a270993b56c713e350b736edd753fAki Tuomi than threshold bytes are available, 0 if as much or less, -1 if error or
70ee483d320a270993b56c713e350b736edd753fAki Tuomi EOF with no bytes read that weren't already in buffer, or -2 if stream's
70ee483d320a270993b56c713e350b736edd753fAki Tuomi input buffer is full. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomiint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
a05819736f348d0c5ac8b4966ac6b04c21e1a391Timo Sirainen size_t *size_r, size_t threshold);
a05819736f348d0c5ac8b4966ac6b04c21e1a391Timo Sirainen
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* Append external data to input stream. Returns TRUE if successful, FALSE if
70ee483d320a270993b56c713e350b736edd753fAki Tuomi there is not enough space in the stream. */
a05819736f348d0c5ac8b4966ac6b04c21e1a391Timo Sirainenbool i_stream_add_data(struct istream *stream, const unsigned char *data,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi size_t size);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi
70ee483d320a270993b56c713e350b736edd753fAki Tuomi#endif
70ee483d320a270993b56c713e350b736edd753fAki Tuomi