GFXprim implements an I/O interface which is used by all image loaders.
The purpose of the interface is:
The I/O interface is defined by a structure with callbacks.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
/*
* Values are 1:1 with constants passed to lseek()
*/
enum GP_IOWhence {
GP_IO_SEEK_SET = 0,
GP_IO_SEEK_CUR = 1,
GP_IO_SEEK_END = 2,
};
typedef struct GP_IO {
ssize_t (*Read)(struct GP_IO *self, void *buf, size_t size);
ssize_t (*Write)(struct GP_IO *self, void *buf, size_t size);
off_t (*Seek)(struct GP_IO *self, off_t off, enum GP_IOWhence whence);
int (*Close)(struct GP_IO *self);
off_t mark;
char priv[];
} GP_IO;
The fields of the I/O stream structure are mostly self describing. The Seek
behaves exactly as lseek(2), the Read as read(2) and the Write as
write(2).
The mark and priv are private fields that shall not be touched by user.
An IO reader must implement at least Read, Seek (at least able to seek
forward to skip some data) and Close.
An IO writer must implement at least Write and Close.
Return value from the Seek is a value of current offset in the stream (after
the seek has been done) or in case of failure (off_t)-1.
Return value from Read or Write is a number of bytes read/written or in
case of failure a negative number (-1).
Return value from Close is zero on success and non-zero on IO failure.
|
Make sure errno is set if any of the operations has failed. |
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
ssize_t GP_IORead(GP_IO *io, void *buf, size_t size);
This is a wrapper to io→Read().
Reads at most size bytes from an IO stream and stores them into the
buffer. Returns number of bytes read.
On failure negative value is returned and errno is set.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
int GP_IOFill(GP_IO *io, void *buf, size_t size);
Similar to GP_IORead() but either reads the whole buffer or fails.
Returns zero on success and non-zero on failure.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
ssize_t GP_IOWrite(GP_IO *io, void *buf, size_t size);
This is a wrapper to io→Write().
Writes at most size bytes from an IO stream and stores them into the
buffer. Returns number of bytes read.
On failure negative value is returned and errno is set.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
int GP_IOFlush(GP_IO *io, void *buf, size_t size);
Similar to GP_IOWrite() but either writes the whole buffer or fails.
Returns zero on success and non-zero on failure.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
int GP_IOPrintF(GP_IO *io, const char *fmt, ...);
Printf-like function for an I/O stream.
Returns zero on success and non-zero on failure.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
int GP_IOClose(GP_IO *io);
This is a wrapper to io→Close().
Finalizes reading/writing, closes file descriptors (in case of file IO), frees
memory buffers.
Returns zero on success, non-zero on I/O failure and errno is set.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
enum GP_IOWhence {
GP_IO_SEEK_SET = 0,
GP_IO_SEEK_CUR = 1,
GP_IO_SEEK_END = 2,
};
off_t GP_IOSeek(GP_IO *io, off_t off, enum GP_IOWhence whence);
This is a wrapper to io→Seek().
Returns (off_t)-1 on failure and errno is set.
Generally not all read I/O streams are seekable back (zlib/rle decompression
streams, etc.) but all streams should be able to seek to the start of the
stream, to the end and forward.
Table 1. Most common errno values
EINVAL |
Invalid whence or off points outside the stream. |
ENOSYS |
Operation not supported, combination of whence and off points
inside the stream (is valid) but action cannot be done. |
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
off_t GP_IOTell(GP_IO *io);
Wrapper to GP_IOSeek(), returns current position in I/O stream.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
off_t GP_IORewind(GP_IO *io)
Wrapper to GP_IOSeek(), rewinds to the start of the I/O stream.
Returns zero on success, non-zero on failure and errno is set.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
GP_IO *GP_IOMem(void *buf, size_t size, void (*free)(void *));
Creates an read-only I/O from a memory buffer.
Returns initialized I/O or in case of failure NULL and errno is set.
The buf is pointer to the start of the buffer, the size is size in bytes.
The free() callback if not NULL is called with the start of the buffer as
an argument on IOClose().
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
enum GP_IOFileMode {
GP_IO_RDONLY = 0x00,
GP_IO_WRONLY = 0x01,
GP_IO_RDWR = 0x02,
};
GP_IO *GP_IOFile(const char *path, enum GP_IOFileMode mode);
Creates an IO stream from a file.
Returns a pointer to initialized I/O stream, or in case of failure NULL and
errno is set.
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
GP_IO *GP_IOSubIO(GP_IO *pio, size_t size);
Creates an readable I/O on the top of an existing readable I/O.
The stream position in the parent I/O is advanced when reading or seeking the
sub I/O.
The sub I/O is limited to an interval starting at current position and can
advance size bytes at max; then it behaves like the stream has ended i.e.
GP_IORead() returns zero.
You can seek in the resulting I/O if:
|
If you combine reading or seeking in the parent I/O and sub I/O the
result is undefined. |
#include <loaders/gp_io.h>
/* or */
#include <gfxprim.h>
GP_IO *GP_IOWBuffer(GP_IO *io, size_t bsize);
Creates write buffered I/O on the top of an existing I/O.
Generally you should create a buffered I/O if you are about to write data a
few bytes at the time.
If bsize is zero default size is choosen.