227 lines
5.6 KiB
Markdown
227 lines
5.6 KiB
Markdown
|
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.
|