% File I/O

# File I/O

## API: ALLEGRO_FILE

An opaque object representing an open file.  This could be a
real file on disk or a virtual file.

## API: ALLEGRO_FILE_INTERFACE

A structure containing function pointers to handle a type of "file",
real or virtual.  See the full discussion in [al_set_new_file_interface].

## API: ALLEGRO_SEEK

* ALLEGRO_SEEK_SET - Seek to pos from beginning of file
* ALLEGRO_SEEK_CUR - Seek to pos from curent position
* ALLEGRO_SEEK_END - Seek to pos from end of file

## API: al_fopen

Creates and opens a file (real or virtual) given the path and mode.
The current file interface is used to open the file.

'path' - the path to open

'mode' - mode to open the entry in ("r", "w", etc.)

Depending on the stream type and the mode string, files may be opened in
"text" mode.  The handling of newlines is particularly important.  For example,
using the default stdio-based streams on DOS and Windows platforms, where the
native end-of-line terminators are CR+LF sequences, a call to [al_fgetc] may
return just one character ('\n') where there were two bytes (CR+LF) in the
file.  When writing out '\n', two bytes would be written instead.
(As an aside, '\n' is not defined to be equal to LF either.)

Newline translations can be useful for text files but is disastrous for binary
files.  To avoid this behaviour you need to open file streams in binary mode
by using a mode argument containing a "b", e.g. "rb", "wb".

See also: [al_set_new_file_interface].

## API: al_fclose

Close the given file.

## API: al_fread

Read 'size' bytes into 'ptr' from entry 'fp'

Return number of bytes actually read.

## API: al_fwrite

Write 'size' bytes from 'ptr' into file 'fp'

Return number of bytes actually written or 0 on error.

Does not distinguish between EOF and other errors.
Use [al_feof] and [al_ferror]
to tell them apart.

## API: al_fflush

Flush any pending writes to 'fp' to disk.

Returns true on success, false otherwise, and errno is set to indicate the error.

See also: [al_get_errno]

## API: al_ftell

Returns the current position in file, or -1 on error.
errno is set to indicate the error.

On some platforms this function may not support large files.

See also: [al_get_errno]

## API: al_fseek

Seek to 'offset' in file based on 'whence'.

'whence' can be:

* ALLEGRO_SEEK_SET - Seek from beggining of file
* ALLEGRO_SEEK_CUR - Seek from current position
* ALLEGRO_SEEK_END - Seek from end of file

Returns true on success, false on failure and errno is set to indicate the error.

On some platforms this function may not support large files.

See also: [al_get_errno]

## API: al_feof

Returns true if the end-of-file indicator has been set on the file,
i.e. we have attempted to read *past* the end of the file.

This does *not* return true if we simply are at the end of the file.
The following code correctly reads two bytes, even when the file
contains exactly two bytes:

    int b1 = al_fgetc(f);
    int b2 = al_fgetc(f);
    if (al_feof(f)) {
       /* At least one byte was unsuccessfully read. */
       report_error();
    }

## API: al_ferror

Returns true if there was some sort of previous error.

## API: al_fungetc

Ungets a single byte from a file. Does not write to file, it only places the
char back into the entry's buffer.

See also [al_get_errno]

## API: al_fsize

Return the size of the file, if it can be determined, or -1 otherwise.

## API: al_fgetc

Read and return next byte in entry 'f'.
Returns EOF on end of file or if an error occurred.

## API: al_fputc

Write a single byte to entry.

Parameters:

* c - byte value to write
* f - entry to write to

Returns:
EOF on error

## API: al_fread16le

Reads a 16-bit word in little-endian format (LSB first).

Returns:
The read 16-bit word or EOF on error

## API: al_fread16be

Reads a 16-bit word in big-endian format (MSB first).

Returns:
The read 16-bit word or EOF on error.

## API: al_fwrite16le

Writes a 16-bit word in little-endian format (LSB first).

Returns the number of bytes written: 2 on success, less than 2 on an error.

## API: al_fwrite16be

Writes a 16-bit word in big-endian format (MSB first).

Returns the number of bytes written: 2 on success, less than 2 on an error.

## API: al_fread32le

Reads a 32-bit word in little-endian format (LSB first).
If 'ret_success' is not NULL, it will be set to true on success
or false on failure.

Returns the read 32-bit word.  'ret_success' indicates if a full 32-bit word
was read before reaching the EOF or an error.

## API: al_fread32be

Read a 32-bit word in big-endian format (MSB first).
If 'ret_success' is not NULL, it will be set to true on success
or false on failure.

Returns:
The read 32-bit word.  'ret_success' indicates if a full 32-bit word
was read before reaching the EOF or an error.

## API: al_fwrite32le

Writes a 32-bit word in little-endian format (LSB first).

Returns the number of bytes written: 4 on success, less than 4 on an error.

## API: al_fwrite32be

Writes a 32-bit word in big-endian format (MSB first).

Returns the number of bytes written: 4 on success, less than 4 on an error.

## API: al_fgets

Read a string of bytes terminated with a newline or end-of-file
into the buffer given.  The line terminator(s), if any, are included in the
returned string.  A maximum of max-1 bytes are read, with one byte being
reserved for a NUL terminator.

Parameters:

* f - file to read from
* buf - buffer to fill
* max - maximum size of buffer

Returns the pointer to buf on success.  Returns NULL if an error occurred or
if the end of file was reached without reading any bytes.

See [al_fopen] about translations of end-of-line characters.

## API: al_fget_ustr

Read a string of bytes terminated with a newline or end-of-file.
The line terminator(s), if any, are included in the returned string.

On success returns a pointer to a new ALLEGRO_USTR structure.
This must be freed eventually with [al_ustr_free].
Returns NULL if an error occurred or if the end of file was reached without
reading any bytes.

See [al_fopen] about translations of end-of-line characters.

## API: al_fputs

Writes a string to file.  Apart from the return value,
this is equivalent to:

    al_fwrite(f, p, strlen(p));

Parameters:

* f - file handle to write to
* p - string to write

Returns a non-negative integer on success, EOF on error.

Note: depending on the stream type and the mode passed to [al_fopen], newline
characters in the string may or may not be automatically translated to
native end-of-line sequences, e.g. CR/LF instead of LF.

# Standard I/O specific routines

## API: al_fopen_fd

Create an ALLEGRO_FILE object that operates on an open file descriptor using
stdio routines.  See the documentation of fdopen() for a description of the
'mode' argument.

Returns an ALLEGRO_FILE object on success or NULL on an error.
On an error, the Allegro errno will be set and the file descriptor will
not be closed.

The file descriptor will be closed by [al_fclose] so you should not
call close() on it.

## API: al_make_temp_file

Make a temporary randomly named file given a filename 'template'.

'template' is a string giving the format of the generated filename and
should include one or more capital Xs.  The Xs are replaced with random
alphanumeric characters.  There should be no path separators.

If 'ret_path' is not NULL, the address it points to will be set
to point to a new path structure with the name of the temporary file.

Returns the opened ALLEGRO_FILE on success, NULL on failure.

# Alternative file streams

By default, the Allegro file I/O routines use the C library I/O routines,
hence work with files on the local filesystem, but can be overridden so that
you can read and write to other streams.  For example, you can work with block
of memory or sub-files inside .zip files.

There are two ways to get an ALLEGRO_FILE that doesn't use stdio.
An addon library may provide a function that returns a new ALLEGRO_FILE
directly, after which, all al_f* calls on that object will use
overridden functions for that type of stream.
Alternatively, [al_set_new_file_interface] changes which function will handle
the following [al_fopen] calls for the current thread.

## API: al_set_new_file_interface

Set the ALLEGRO_FILE_INTERFACE table for the calling thread.
This will change the handler for later calls to [al_fopen].

See also: [al_store_state], [al_restore_state].

## API: al_get_new_file_interface

Return a pointer to the ALLEGRO_FILE_INTERFACE table in effect
for the calling thread.

See also: [al_store_state], [al_restore_state].

