/* This file is part of GNU Pies. Copyright (C) 2019-2023 Sergey Poznyakoff GNU Pies 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 3, or (at your option) any later version. GNU Pies 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 GNU Pies. If not, see . */ #define IO_BUF_SIZE 512 struct iobuf { char buf[IO_BUF_SIZE]; /* Initial line buffer */ size_t start; /* Start of data */ size_t avail; /* Start of available space */ }; static inline void iobuf_reset (struct iobuf *bp) { bp->start = bp->avail = 0; } /* Return the count of data bytes in the buffer */ static inline size_t iobuf_data_size (struct iobuf *bp) { return bp->avail - bp->start; } static inline char * iobuf_data_ptr (struct iobuf *bp) { return bp->buf + bp->start; } static inline void iobuf_data_advance (struct iobuf *bp, size_t n) { bp->start += n; if (bp->start == bp->avail) iobuf_reset (bp); } static inline int iobuf_putback (struct iobuf *bp) { return bp->buf[--bp->start-1]; } static inline int iobuf_getc (struct iobuf *bp) { int c = -1; if (iobuf_data_size (bp) > 0) { c = *iobuf_data_ptr (bp); iobuf_data_advance(bp, 1); } return c; } /* Return the count of available bytes in the buffer */ static inline size_t iobuf_avail_size (struct iobuf *bp) { return sizeof (bp->buf) - bp->avail; } static inline char * iobuf_avail_ptr (struct iobuf *bp) { return bp->buf + bp->avail; } static inline void iobuf_avail_advance (struct iobuf *bp, size_t n) { bp->avail += n; if (iobuf_avail_size (bp) == 0 && iobuf_data_size (bp) == 0) iobuf_reset (bp); } static inline int iobuf_putc (struct iobuf *bp, int c) { if (iobuf_avail_size (bp) > 0) { *iobuf_avail_ptr (bp) = c; iobuf_avail_advance (bp, 1); return c; } return -1; } static inline ssize_t iobuf_fill (struct iobuf *bp, int fd) { ssize_t n = read (fd, iobuf_avail_ptr (bp), iobuf_avail_size (bp)); if (n >= 0) iobuf_avail_advance (bp, n); return n; } static inline ssize_t iobuf_flush (struct iobuf *bp, int fd) { ssize_t n = write (fd, iobuf_data_ptr (bp), iobuf_data_size (bp)); if (n >= 0) iobuf_data_advance (bp, n); return n; } static inline ssize_t iobuf_copy (struct iobuf *dst, struct iobuf *src) { ssize_t n = iobuf_data_size (src); if (n > 0) { ssize_t avail = iobuf_avail_size (dst); if (avail < n) n = avail; if (n) { memcpy (iobuf_avail_ptr (dst), iobuf_data_ptr (src), n); iobuf_avail_advance (dst, n); iobuf_data_advance (src, n); } } return n; }