/*****************************************************************************
 *  cbuf.h
 *****************************************************************************
 *  Copyright (C) 2002-2005 The Regents of the University of California.
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 *  Written by Chris Dunlap <cdunlap@llnl.gov>.
 *
 *  This file is from LSD-Tools, the LLNL Software Development Toolbox.
 *
 *  LSD-Tools is free software; you can redistribute it and/or modify it under
 *  the terms of the GNU General Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or (at your option)
 *  any later version.
 *
 *  In addition, as a special exception, the copyright holders give permission
 *  to link the code of portions of this program with the OpenSSL library under
 *  certain conditions as described in each individual source file, and
 *  distribute linked combinations including the two. You must obey the GNU
 *  General Public License in all respects for all of the code used other than
 *  OpenSSL. If you modify file(s) with this exception, you may extend this
 *  exception to your version of the file(s), but you are not obligated to do
 *  so. If you do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source files in
 *  the program, then also delete it here.
 *
 *  LSD-Tools is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 *  more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with LSD-Tools; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 *****************************************************************************/

#ifndef LSD_CBUF_H
#define LSD_CBUF_H

#include <stdbool.h>

/*
 *  Cbuf is a circular-buffer capable of dynamically resizing itself.
 *  Unread data in the buffer will be overwritten once the cbuf has
 *  reached its maximum size or is unable to allocate additional memory.
 *
 *  The CBUF_OPT_OVERWRITE option specifies how unread cbuf data will
 *  be overwritten.  If set to CBUF_NO_DROP, unread data will never be
 *  overwritten; writes into the cbuf will return -1 with ENOSPC.  If set
 *  to CBUF_WRAP_ONCE, a single write operation will wrap-around the buffer
 *  at most once, and up to cbuf_used() bytes of data may be overwritten.
 *  If set to CBUF_WRAP_MANY, a single write operation will wrap-around the
 *  buffer as many times as needed in order to write all of the data.
 *
 *  These routines are thread-safe.
 */

/****************
 *  Data Types  *
 ****************/

typedef struct cbuf cbuf_t;		/* circular-buffer opaque data type  */

/***************
 *  Functions  *
 ***************/

/*
 *  Creates and returns a new circular buffer.
 *  The default overwrite option behavior is CBUF_WRAP_MANY.
 *  Abandoning a cbuf without calling cbuf_destroy() will cause a memory leak.
 */
extern cbuf_t *cbuf_create(int size, bool overwrite);

/*
 *  Destroys the circular buffer [cb].
 */
extern void cbuf_destroy(cbuf_t *cb);

/*
 *  Returns the number of bytes in [cb] available for writing before unread
 *    data is overwritten (assuming the cbuf can resize itself if needed).
 */
extern int cbuf_free(cbuf_t *cb);

/*
 *  Returns the number of bytes in [cb] available for reading.
 */
extern int cbuf_used(cbuf_t *cb);

/*
 *  Reads up to [len] bytes of data from the [src] cbuf into [dstbuf].
 *  Returns the number of bytes read, or -1 on error (with errno set).
 */
extern int cbuf_read(cbuf_t *src, void *dstbuf, int len);

/*
 *  Writes up to [len] bytes of data from [srcbuf] into the [dst] cbuf
 *    according to dst's CBUF_OPT_OVERWRITE behavior.
 *  Returns the number of bytes written, or -1 on error (with errno set).
 *    Sets [ndropped] (if not NULL) to the number of bytes overwritten.
 */
extern int cbuf_write(cbuf_t *dst, void *srcbuf, int len, int *ndropped);

/*
 *  Reads the specified [lines] of data from the [src] cbuf into [dstbuf],
 *    but does not consume the data read from the cbuf.  If [lines] is -1,
 *    reads the maximum number of lines that [dstbuf] can hold.  The buffer
 *    will be NUL-terminated and contain at most ([len] - 1) characters.
 *  The "peek" can be committed to the cbuf via a call to cbuf_drop(),
 *    but the peek+drop combination is not atomic.
 *  Returns strlen of the line(s) on success; truncation occurred if >= [len].
 *    Returns 0 if the number of lines is not available (ie, all or none).
 *    Returns -1 on error (with errno set).
 */
extern int cbuf_peek_line(cbuf_t *src, char *dstbuf, int len, int lines);

/*
 *  Reads the specified [lines] of data from the [src] cbuf into [dstbuf].
 *    If [lines] is -1, reads the maximum number of lines that [dstbuf]
 *    can hold.  The buffer will be NUL-terminated and contain at most
 *    ([len] - 1) characters.
 *  Returns strlen of the line(s) on success; truncation occurred if >= [len],
 *    in which case excess line data is discarded.  Returns 0 if the number
 *    of lines is not available (ie, all or none), in which case no data is
 *    consumed.  Returns -1 on error (with errno set).
 */
extern int cbuf_read_line(cbuf_t *src, char *dstbuf, int len, int lines);

/*
 *  Reads up to [len] bytes of data from the [src] cbuf into the file
 *    referenced by the [dstfd] file descriptor.  If [len] is -1, it will
 *    be set to the number of [src] bytes available for reading.
 *  Returns the number of bytes read, or -1 on error (with errno set).
 */
extern int cbuf_read_to_fd(cbuf_t *src, int dstfd, int len);

/*
 *  Writes up to [len] bytes of data from the file referenced by the
 *    [srcfd] file descriptor into the [dst] cbuf according to dst's
 *    CBUF_OPT_OVERWRITE behavior.  If [len] is -1, it will be set to
 *    an appropriate chunk size.
 *  Returns the number of bytes written, 0 on EOF, or -1 on error (with errno).
 *    Sets [ndropped] (if not NULL) to the number of bytes overwritten.
 */
extern int cbuf_write_from_fd(cbuf_t *dst, int srcfd, int len, int *ndropped);

#endif
