cog/Frameworks/Dumb/dumb/DUMBFILE_SYSTEM.md

5.6 KiB

Specification of DUMBFILE_SYSTEM

DUMB is designed filesystem-agnostic, even though the C standard library already defines an abstraction over files on a disk. This is useful because Allegro 4 and 5 define their own abstractions.

To register your own filesystem abstraction with DUMB, you must create an instance of struct DUMBFILE_SYSTEM, fill in your own function pointers according to the specification below, and call register_dumbfile_system on your instance.

The header dumb.h defines DUMBFILE_SYSTEM as a struct of function pointers:

typedef struct DUMBFILE_SYSTEM
{
    void *(*open)(const char *filename);
    int (*skip)(void *f, dumb_off_t n);
    int (*getc)(void *f);
    dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
    void (*close)(void *f);
    int (*seek)(void *f, dumb_off_t n);
    dumb_off_t (*get_size)(void *f);
}
DUMBFILE_SYSTEM;

Here, dumb_off_t is a signed integer at least 64 bits wide, it is intended to measure file offsets. The return type dumb_ssize_t is a signed integer exactly as wide as size_t, it is intended to store either a size_t or a negative error code. Both dumb_*_t are defined in dumb.h.

The function pointers skip and getnc are optional, i.e., you may set some of these to NULL in your struct instance. DUMB will then try to mimick the missing functions' behavior by calling your getc several times. If DUMB is built with debugging flags, it will assert that all other functions are not NULL. In release mode, DUMB will silently fail.

Your non-NULL function pointers must conform to the following specification.

open

void *(*open)(const char *filename);

Open a file for reading.

Arguments:

  • const char *filename: A normal filename as understood by the operating system. Will be opened for reading.

Returns as void *:

  • the address of a file handle on successfully opening the file. DUMB will pass this file handle as argument to other functions of the DUMBFILE_SYSTEM.

  • NULL on error during opening the file.

Each file has a position internally managed by DUMB. A newly opened file has a position of 0. Other functions from the DUMBFILE_SYSTEM can move this position around.

DUMB allocates memory for the successfully opened file, and will store opaque information in that memory, e.g., the DUMB-internal file position. This memory be freed when DUMB calls close on the file's handle. The memory is separate from your own filesystem implementation: You are responsible for supplying the data, and DUMB is responsible for storing anything about interpreting that data.

skip

int (*skip)(void *f, dumb_off_t n);

Advance the position in the file.

Arguments:

  • void *f: A file handle that open returned. Guaranteed non-NULL.

  • dumb_off_t n: Number of bytes to advance in the file. DUMB will only call this with n >= 0. For n < 0, the behavior of skip is undefined.

Returns as int:

  • 0 on successfully skipping ahead by n bytes.

  • -1 on error.

It is legal to set skip = NULL in a DUMBFILE_SYSTEM. DUMB will then call getc a total of n times to skip ahead in a file. For speed, it is advisable to supply a proper skip implementation.

getc

int (*getc)(void *f);

Read a byte from the file.

Arguments:

  • void *f: A file handle that open returned. Guaranteed non-NULL.

Returns as int:

  • the value of the byte read, on successfully reading one byte.

  • -1 on error.

After a succesful read, DUMB will treat the file as advanced by one byte.

getnc

dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);

Read up to the given number of bytes from the file into a given buffer.

  • char *ptr: The start of a buffer provided by DUMB.

  • size_t n: The length of the number of bytes to be read.

  • void *f: A file handle that open returned. Guaranteed non-NULL.

Returns as dumb_ssize_t:

  • the number of bytes successfully read, if it was possible to read at least one byte.

  • -1 on error.

This function shall bytes from the file f and store them in sequence in the buffer beginning at ptr. It shall read fewer than n bytes if end of file is encountered before n bytes could have been read, otherwise it should read n bytes.

It is legal to set skip = NULL in a DUMBFILE_SYSTEM. DUMB will then call getc a total of n times and store the results in its buffer.

close

void (*close)(void *f);

Closes a file that has been opened before with open.

Arguments:

  • void *f: A file handle that open returned. Guaranteed non-NULL.

DUMB will deallocate the memory that it used to interpret the file. You are free to treat your resource however you would like: You may deallocate it, or keep it around for other things. For example, Allegro 5's implementation of close takes a void pointer and does nothing with it at all.

seek

int (*seek)(void *f, dumb_off_t n);

Jump to an arbitrary position in the file.

Arguments:

  • void *f: A file handle that open returned. Guaranteed non-NULL.

  • dumb_off_t n: The position in the file, relative to the beginning. There is no guarantee whether n >= 0.

Returns as int:

  • 0 on successfully seeking in the file.

  • -1 on error.

DUMB will modify its internal position of the file accordingly.

A value of n < 0 shall set the file into an erroneous state from which no bytes can be read.

get_size

dumb_off_t (*get_size)(void *f);

Get the length in bytes, i.e., the position after the final byte, of a file.

Arguments:

  • void *f: A file handle that open returned. Guaranteed non-NULL.

Returns as dumb_off_t:

  • the length of the file in bytes.