1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2017 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 #ifndef LIBPSPP_FBUF_H
18 #define LIBPSPP_FBUF_H 1
22 #include <sys/types.h>
25 /* Data structure for buffered file I/O.
27 fbuf is much like stdio and serves the same purpose. The main difference is
28 that it is defined entirely in PSPP and thus it is possible to extend it in
29 a portable way, in particular to have a portable way to read and write a
30 memory buffer instead of a file descriptor, since GNU and BSD libc provide
31 ways to do that, but other libcs don't. */
35 struct fbuf *fbuf_open_fd (int fd);
36 int fbuf_open_file (const char *filename, int flags, mode_t mode,
37 struct fbuf **) WARN_UNUSED_RESULT;
38 struct fbuf *fbuf_open_memory (void *, size_t);
40 int fbuf_close (struct fbuf *);
42 int fbuf_get_status (const struct fbuf *);
43 void fbuf_clear_status (struct fbuf *);
45 int fbuf_is_seekable (const struct fbuf *);
46 off_t fbuf_get_size (const struct fbuf *);
48 int fbuf_flush (struct fbuf *);
50 off_t fbuf_tell (const struct fbuf *);
51 int fbuf_seek (struct fbuf *, off_t);
53 static inline int fbuf_putc (struct fbuf *, uint8_t);
54 ssize_t fbuf_write (struct fbuf *, const void *, size_t);
56 static inline int fbuf_getc (struct fbuf *);
57 ssize_t fbuf_read (struct fbuf *, void *, size_t);
59 /* Implementation details. */
63 const struct fbuf_class *class;
66 /* Offset in the underlying file descriptor:
68 - In read mode, this is the offset of 'read_head'.
70 - In write mode, this is the offset of 'write_tail'.
72 Starts out at TYPE_MINIMUM (off_t), which indicates that the underlying
73 descriptor offset is not known. Negative errno values indicate
78 In read mode, buffered data is read into the start of 'buffer'.
79 Initially 'read_tail' points to 'buffer' and 'read_head' just past the
80 last byte of buffered data. As the client reads data, 'read_tail'
81 advances until it reaches 'read_head', then the buffer is re-filled and
87 +----------+------------------------+
88 | | ...data to be read... |
89 +-----------------------------------+
92 buffer read_tail read_head
94 In write mode, read_tail and read_head are both NULL. */
95 uint8_t *read_tail, *read_head;
98 In write mode, write_tail and write_head initially point to 'buffer' and
99 'write_end' to 'buffer + FBUF_SIZE'. As the client writes, its data is
100 copied to and advances 'write_head', limited by 'write_end'. As the
101 fbuf flushes data to the fd, 'write_tail' advances, and when
102 'write_tail' catches 'write_head', both reset to 'buffer'.
107 +----------+------------------------+-------------------+
108 | |...data to be flushed...| |
109 +-----------------------------------+-------------------+
112 buffer write_tail write_head write_end
114 In read mode, write_tail, write_head, and write_end are all NULL. */
115 uint8_t *write_tail, *write_head, *write_end;
120 fbuf_putc (struct fbuf *fbuf, uint8_t byte)
122 if (fbuf->write_head < fbuf->write_end)
124 *fbuf->write_head++ = byte;
128 return fbuf_write (fbuf, &byte, 1);
131 int fbuf_getc__ (struct fbuf *);
133 fbuf_getc (struct fbuf *fbuf)
135 return (fbuf->read_tail < fbuf->read_head
137 : fbuf_getc__ (fbuf));
140 #endif /* libpspp/fbuf.h */