1 /*
2 ** Copyright (C) 2006-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 #ifndef _SKIOBUF_H
9 #define _SKIOBUF_H
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include <silk/silk.h>
15 
16 RCSIDENTVAR(rcsID_SKIOBUF_H, "$SiLK: skiobuf.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
17 
18 /*
19 **  skiobuf.h
20 **
21 **  Routines for buffered file io.
22 **
23 */
24 
25 #if SK_ENABLE_ZLIB
26 #include <zlib.h>
27 #endif
28 
29 
30 /**
31  *    The default uncompressed block size.
32  */
33 #define SKIOBUF_DEFAULT_BLOCKSIZE SKSTREAM_DEFAULT_BLOCKSIZE
34 
35 
36 /**
37  *    The maximum compressed or uncompressed block size.
38  */
39 #define SKIOBUF_MAX_BLOCKSIZE 0x100000 /* One megabyte */
40 
41 
42 /**
43  *    The default record size.  A single record is guaranteed not to
44  *    span multiple blocks.
45  */
46 #define SKIOBUF_DEFAULT_RECORDSIZE 1
47 
48 
49 /**
50  *    The type of IO buffer objects
51  */
52 typedef struct sk_iobuf_st sk_iobuf_t;
53 
54 
55 /*
56  *    skIOBuf can wrap an abstract file descriptor 'fd' if it
57  *    implements some of the following functions.  A reading skIOBuf
58  *    requires the skio_read_fn_t; a writing skIOBuf requires the
59  *    skio_write_fn_t.
60  */
61 
62 /**
63  *    Implements a read(2)-like call: skIOBuf is requesting that the
64  *    'fd' add 'count' bytes of data into 'dest' for input, returning
65  *    the number of bytes actually added.  Should return a number less
66  *    than count for a short read, -1 for an error.
67  */
68 typedef ssize_t
69 (*skio_read_fn_t)(
70     void           *fd,
71     void           *dest,
72     size_t          count);
73 
74 /**
75  *    Implements a write(2)-like call: skIOBuf is requesting that the
76  *    'fd' accept 'count' bytes of data from 'src' for output,
77  *    returning the number of bytes actually accepted.  Should return
78  *    a number less than count for a short write (is this even
79  *    meaningful?), -1 for an error.
80  */
81 typedef ssize_t
82 (*skio_write_fn_t)(
83     void           *fd,
84     const void     *src,
85     size_t          count);
86 
87 /**
88  *    Implements an lseek(2)-like call: skIOBuf is requesting that the
89  *    read pointer be positioned relative to 'whence' by 'offset'
90  *    bytes, returning the new offset of the read pointer.  'whence'
91  *    can be SEEK_SET, SEEK_CUR, or SEEK_END.  Returns (off_t)(-1) on
92  *    error.  If seek cannot work on a particular fd because it is not
93  *    a seekable file, set errno to ESPIPE.
94  */
95 typedef off_t
96 (*skio_seek_fn_t)(
97     void           *fd,
98     off_t           offset,
99     int             whence);
100 
101 /**
102  *    Implements an fflush(3)-like call: skIOBuf is requesting that
103  *    the 'fd' syncronize its output buffers with the physical media.
104  *    Returns 0 on success, or -1 on error.  This function may be
105  *    NULL.
106  */
107 typedef int (*skio_flush_fn_t)(
108     void           *fd);
109 
110 /**
111  *    Implements a strerror(3)-like call: skIOBuf is requesting a
112  *    human-readable error message given the error code 'fd_errno'.
113  */
114 typedef const char *
115 (*skio_strerror_fn_t)(
116     void           *fd,
117     int             fd_errno);
118 
119 /**
120  *    skIOBuf is requesting that the 'fd' deallocate itself.
121  */
122 typedef void
123 (*skio_free_fn_t)(
124     void           *fd);
125 
126 
127 /**
128  *    All supported operations on an abstract file descriptor.  Either
129  *    'read' or 'write' must be specified.
130  */
131 typedef struct skio_abstract_st {
132     skio_read_fn_t      read;
133     skio_write_fn_t     write;
134     skio_seek_fn_t      seek;
135     skio_flush_fn_t     flush;
136     skio_free_fn_t      free_fd;
137     skio_strerror_fn_t  strerror;
138 } skio_abstract_t;
139 
140 
141 /**
142  *    Creates a new IO buffer for either reading or writing according
143  *    to 'mode'.  A 'mode' of SK_IO_APPEND creates a writing IO
144  *    buffer.
145  *
146  *    Returns the new IO buffer or NULL on allocation error.
147  */
148 sk_iobuf_t *
149 skIOBufCreate(
150     skstream_mode_t     mode);
151 
152 
153 /**
154  *    Destroys the IO buffer 'iobuf'.  If the IO buffer is a writer,
155  *    the buffer will be flushed before destruction.  Does nothing
156  *    when 'iobuf' is NULL.
157  */
158 void
159 skIOBufDestroy(
160     sk_iobuf_t         *iobuf);
161 
162 
163 /**
164  *    Binds the file descriptor 'fd' to the IO buffer 'iobuf'.
165  *
166  *    If the IO buffer is a reader, any data read from the stream and
167  *    held in the IO buffer is lost.
168  *
169  *    If the IO buffer is a writer and is already associated with a
170  *    file descriptor, the buffer will be flushed before binding.
171  *
172  *    Binding a file descriptor resets the write/read count of the IO
173  *    buffer.  'compmethod' is a valid compression method from
174  *    silk_files.h.
175  *
176  *    Returns 0 on success, -1 on failure.
177  */
178 int
179 skIOBufBind(
180     sk_iobuf_t         *iobuf,
181     int                 fd,
182     sk_compmethod_t     compmethod);
183 
184 
185 /**
186  *    Binds the abstract file descriptor 'fd' to the IO buffer 'iobuf'.
187  *
188  *    If the IO buffer is a reader, any data read from the stream and
189  *    held in the IO buffer is lost.
190  *
191  *    If the IO buffer is a writer and is already associated with a
192  *    file descriptor, the buffer will be flushed before binding.
193  *
194  *    Binding a file descriptor resets the write/read count of the IO
195  *    buffer.  'compmethod' is a valid compression method from
196  *    silk_files.h.  'fd_ops' is a pointer to a struct of file
197  *    operations on the abstract file descriptor 'fd'.
198  */
199 int
200 skIOBufBindAbstract(
201     sk_iobuf_t         *iobuf,
202     void               *fd,
203     sk_compmethod_t     compmethod,
204     skio_abstract_t    *fd_ops);
205 
206 
207 /**
208  *    Reads 'count' uncompressed bytes into 'data' from the IO buffer
209  *    'iobuf'.  When 'data' is NULL, moves the read location 'count'
210  *    bytes forward in the stream and that data is lost.
211  *
212  *    Returns the number of uncompressed bytes read/skipped on
213  *    success.  The return value is always 'count' if the stream
214  *    contained at least that number of bytes.  If the return value is
215  *    a positive number less than 'count', the IO buffer was only able
216  *    to read that number of bytes before reaching the end of the
217  *    stream.  Returns 0 when there is no more data in the stream.
218  *    Returns -1 on failure.
219  */
220 ssize_t
221 skIOBufRead(
222     sk_iobuf_t         *iobuf,
223     void               *data,
224     size_t              count);
225 
226 
227 /**
228  *    Copies 'count' bytes from 'data' back into the read buffer of
229  *    the IO buffer 'iobuf' so those bytes will be returned by the
230  *    next call to skIOBufRead().
231  *
232  *    Adjusts the IO buffer's total read byte count by 'adjust_total'
233  *    bytes.  'adjust_total' should 0 when returning bytes from a
234  *    previous skIOBufRead().
235  *
236  *    Returns 'count' if the call was successful.  Returns -1 if
237  *    'iobuf' has not been bound, if 'iobuf' is not a reader, if the
238  *    'data' parameter is NULL, or on allocation failure.
239  *
240  *    Any other return value indicates the 'iobuf' does not have space
241  *    for 'count' bytes and that 'iobuf' is unchanged.  The return
242  *    value is the number of bytes 'iobuf' has available for unget.
243  */
244 ssize_t
245 skIOBufUnget(
246     sk_iobuf_t         *iobuf,
247     const void         *data,
248     size_t              count,
249     off_t               adjust_total);
250 
251 
252 /**
253  *    Reads no more than 'count' uncompressed bytes into 'data' from
254  *    the IO buffer 'iobuf', stopping at the first occurrence of the
255  *    character 'c' in the stream and including that character in
256  *    'data'.  The 'data' parameter may be NULL.
257  *
258  *    Return values are identical to those for skIOBufRead().
259  */
260 ssize_t
261 skIOBufReadToChar(
262     sk_iobuf_t         *iobuf,
263     void               *data,
264     size_t              count,
265     int                 c);
266 
267 
268 /**
269  *    Writes 'count' uncompressed bytes from 'data' into the IO buffer
270  *    'iobuf'.
271  *
272  *    Returns the number of uncompressed bytes written on success, -1
273  *    on failure.  This function will never return a number of bytes
274  *    less than 'count'.
275  */
276 ssize_t
277 skIOBufWrite(
278     sk_iobuf_t         *iobuf,
279     const void         *data,
280     size_t              count);
281 
282 
283 /**
284  *    Flushes the IO buffer writer 'iobuf'.  This does not close the
285  *    buffer or the underlying file descriptor.
286  *
287  *    Returns the number of compressed bytes written to the underlying
288  *    file descriptor since it was bound to the IO buffer on success.
289  *
290  *    Returns -1 on failure on when invoked on a IO buffer created for
291  *    reading.
292  */
293 off_t
294 skIOBufFlush(
295     sk_iobuf_t         *iobuf);
296 
297 
298 /**
299  *    Returns the compressed number of bytes that have been actually
300  *    been read/written from/to the underlying file descriptor.
301  *    Returns -1 on error.
302  */
303 off_t
304 skIOBufTotal(
305     sk_iobuf_t         *iobuf);
306 
307 
308 /**
309  *    Returns an upper bound on the number of compressed bytes that
310  *    would be written to the underlying file descriptor since the
311  *    binding of the buffer if the buffer were flushed.  Returns -1 on
312  *    error.
313  */
314 off_t
315 skIOBufTotalUpperBound(
316     sk_iobuf_t         *iobuf);
317 
318 
319 /**
320  *     Sets the block size for the IO buffer.  This function can only
321  *     be called immediately after creation or binding of the IO
322  *     buffer.  Returns 0 on success, -1 on error.
323  */
324 int
325 skIOBufSetBlockSize(
326     sk_iobuf_t         *iobuf,
327     uint32_t            size);
328 
329 
330 /**
331  *     Returns the maximum possible compressed block size.
332  */
333 uint32_t
334 skIOBufUpperCompBlockSize(
335     sk_iobuf_t         *iobuf);
336 
337 
338 /**
339  *     Sets the record size for the IO buffer.  This function can only
340  *     be called immediately after creation or binding of the IO
341  *     buffer.  Returns 0 on success, -1 on error.
342  */
343 int
344 skIOBufSetRecordSize(
345     sk_iobuf_t         *iobuf,
346     uint32_t            size);
347 
348 
349 /**
350  *    Returns a string representing the error state of the IO buffer
351  *    'buf'.  This is a static string similar to that used by
352  *    strerror.  This function also resets the error state of the IO
353  *    buffer.
354  */
355 const char *
356 skIOBufStrError(
357     sk_iobuf_t         *iobuf);
358 
359 #ifdef __cplusplus
360 }
361 #endif
362 #endif /* _SKIOBUF_H */
363 
364 /*
365 ** Local Variables:
366 ** mode:c
367 ** indent-tabs-mode:nil
368 ** c-basic-offset:4
369 ** End:
370 */
371