Navigation C API Pages Python bindings Applications

IO Interface

GFXprim implements an I/O interface which is used by all image loaders.

The purpose of the interface is:

  • Make it easy to load and save images from/into memory buffers

  • Fast and clean containers (ZIP for example) implementation (zlib deflate could feed data directly into a memory based IO stream)

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.

Note 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:

  • The parent I/O is seekable

  • The the combination of off and whence fits inside the sub I/O

Warning 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.