/*
 * Copyright 2001, 2002, 2003, 2013 Adam Sampson <ats@offog.org>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Adam's IO library. */

#ifndef _IOLIB_H
#define _IOLIB_H 1

/* We need NULL, size_t, ssize_t. */
#include <stddef.h>
#include <unistd.h>

/* Default file descriptors. */
extern int fd_in, fd_out, fd_err;

/* A variable-length buffer for arbitrary data (i.e. nulls within it
   don't matter unless you're using bstr). To declare a buffer, say
   "buffer b = BUFFER;". */
typedef struct {
	/* The data. */
	char *s;
	/* The length of the data. */
	size_t len;
	/* The size of the area that's actually allocated. */
	size_t size;
} buffer;
#define BUFFER {NULL, 0, 0}

/* Adjust the length of a buffer, keeping the existing contents. */
void bsetlength(buffer *b, size_t len);
/* Destroy a buffer. */
void bfree(buffer *b);
/* Set a buffer to a C string. */
void bmake(buffer *b, const char *s);
/* Append a block of memory to a buffer. */
void bappendm(buffer *dest, const char *src, size_t len);
/* Append a C string to a buffer. */
void bappends(buffer *dest, const char *s);
/* Append a byte to a buffer. */
void bappendc(buffer *dest, char c);
/* Append a buffer to another buffer. */
void bappend(buffer *dest, const buffer *src);
/* Get the length of a buffer. */
size_t blength(const buffer *b);
/* Get a buffer as a C string. */
const char *bstr(const buffer *b);
/* Find the first occurrence of byte c in the buffer.
   Returns the position, or -1 if not found. */
ssize_t bindex(const buffer *b, char c);
/* Replace character from with character to throughout buffer. */
void breplacec(buffer *b, char from, char to);
/* Remove n bytes from the start of b; if saveto != NULL, append the
   removed bytes to saveto. */
void bpopl(buffer *b, size_t n, buffer *saveto);

/* Write all n bytes from s to fd, ignoring EINTR. Return 0 on success, -1 on
   error. */
int writea(int fd, const char *s, size_t n);
/* Write some of a buffer to an fd.
   Returns number of bytes written on success, -1 on error. */
ssize_t writeb(int fd, const buffer *b);
/* Write all of a buffer to an fd, ignoring EINTR.
   Returns 0 on success, -1 on error. */
int writeba(int fd, const buffer *b);
/* Read at most n bytes from an fd into b.
   Returns number of bytes read on success, 0 on EOF, -1 on error. */
ssize_t readb(int fd, buffer *b, size_t n);
/* Read from an fd into b until EOF.
   Returns 0 on success, -1 on error. */
int readba(int fd, buffer *b);
/* Read at most max bytes from overflow, then fd into b until term is hit. Put
   any extra characters read after term into overflow.
   Return 1 on success, 0 on EOF, -1 on error. */
int readuntilb(int fd, buffer *b, size_t max, char term, buffer *overflow);
/* Read at most max bytes from overflow, then fd into b until \n is hit. Put
   any extra characters read after \n into overflow.
   Return 1 on success, 0 on EOF, -1 on error. */
int readlineb(int fd, buffer *b, size_t max, buffer *overflow);

/* Format the optional arguments onto fd. Usage is something like:
   format(some_fd, format, ...);
   format string can contain:
     '@b' for buf *
     '@c' for char *
     '@i' for int (decimal)
     '@I' for unsigned int (decimal)
     '@x' for int (hex)
     '@X' for unsigned int (hex)
     '@l' for long (decimal)
     '@L' for unsigned long (decimal)
     '@a' for an IPv4 address in network byte order as an unsigned long
     '@@' for a literal @
   Returns 0 on success, -1 on error. */
int format(int fd, const char *format, ...);
/* Like iformat, but appends formatted data to a buffer. */
void bformat(buffer *b, const char *format, ...);

#endif

