Agar


Note: The Agar manual pages follow certain conventions, notably concerning function return values. Please read AG_Intro(3) first.


SYNOPSIS

#include <agar/core.h>

DESCRIPTION

The AG_DataSource structure provides a generic interface to different data sources. Built-in sources include AG_FileSource for files, AG_CoreSource for fixed-size memory, AG_AutoCoreSource for automatically-allocated memory and AG_ConstCoreSource for read-only memory.

New data sources can be implemented by overloading the AG_DataSource structure.

INTERFACE


AG_DataSource * AG_OpenFile (const char *path, const char *mode)

AG_DataSource * AG_OpenFileHandle (FILE *f)

AG_DataSource * AG_OpenCore (void *p, size_t size)

AG_DataSource * AG_OpenConstCore (const void *p, size_t size)

AG_DataSource * AG_OpenAutoCore (void)

void AG_CloseFile (AG_DataSource *ds)

void AG_CloseFileHandle (AG_DataSource *ds)

void AG_CloseCore (AG_DataSource *ds)

void AG_CloseConstCore (AG_DataSource *ds)

void AG_CloseAutoCore (AG_DataSource *ds)

void AG_CloseDataSource (AG_DataSource *ds)

AG_IOStatus AG_Read (AG_DataSource *ds, void *buf, size_t size, size_t nmemb)

AG_IOStatus AG_ReadAt (AG_DataSource *ds, void *buf, size_t size, size_t nmemb, off_t pos)

AG_IOStatus AG_Write (AG_DataSource *ds, const void *buf, size_t size, size_t nmemb)

AG_IOStatus AG_WriteAt (AG_DataSource *ds, const void *buf, size_t size, size_t nmemb, off_t pos)

off_t AG_Tell (AG_DataSource *ds)

int AG_Seek (AG_DataSource *ds, off_t offs, enum ag_seek_mode mode)

void AG_LockDataSource (AG_DataSource *ds)

void AG_UnlockDataSource (AG_DataSource *ds)

void AG_SetByteOrder (AG_DataSource *ds, enum ag_byte_order order)

void AG_SetSourceDebug (AG_DataSource *ds, int enable)

void AG_DataSourceInit (AG_DataSource *ds)

void AG_DataSourceDestroy (AG_DataSource *ds)

void AG_DataSourceSetErrorFn (AG_DataSource *ds, void (*fn)(AG_Event *), const char *fmt, ...)

void AG_DataSourceError (AG_DataSource *ds, const char *fmt, ...)


The AG_OpenFile() function opens the file at path, where mode is a fopen3 style mode string. AG_OpenFileHandle() creates a new data source for a previously opened file.

The AG_OpenCore() and AG_OpenConstCore() functions create new data sources for the region of memory p of size bytes.

AG_OpenAutoCore() creates a new data source using dynamically-allocated memory (accessible as the data member of the structure).

AG_CloseFile(), AG_CloseFileHandle(), AG_CloseCore(), AG_CloseConstCore() and AG_CloseAutoCore() close a data source of the given type. Alternatively, AG_CloseDataSource() can be used to close any type of source.

AG_Read() reads nmemb items of size bytes from the data source into buf. The AG_ReadAt() variant reads from the given position pos.

AG_Write() writes nmemb items of size bytes buf into the data source. The AG_WriteAt() variant writes to the given position pos.

Note that AG_Read(), AG_ReadAt(), AG_Write() and AG_WriteAt() all return an enum of type AG_IOStatus relating the success of the operation. AG_IOStatus is defined as:
typedef enum ag_io_status {
	AG_IO_SUCCESS = 0,
	AG_IO_EOF = 1,
	AG_IO_ERROR = 2,
	AG_IO_UNAVAIL = 3
} AG_IOStatus;

AG_Tell() returns the current position in the data source. If the underlying data source does not support this operation, a value of 0 is returned.

AG_Seek() seeks to the given position in the data source. Acceptable values for mode include AG_SEEK_SET (relative to data start), AG_SEEK_CUR (relative to current position), AG_SEEK_END (relative to data end).

The AG_LockDataSource() and AG_UnlockDataSource() functions acquire and release the exclusive lock protecting this data source, and are no-ops if thread support is disabled.

AG_SetByteOrder() configures the byte order to be used by integer read/write operations. Accepted parameters are AG_BYTEORDER_BE for big-endian and AG_BYTEORDER_LE for little-endian. To determine the byte order of the current architecture, you can use the standard AG_BYTEORDER define (which evaluates to AG_BIG_ENDIAN or AG_LITTLE_ENDIAN).

AG_SetSourceDebug() enables or disables the inclusion of debugging information in the archive. Debugging information allows type-safety checking at the primitive data level, at the cost of an increased archive size due to the additional metadata that must be encoded.

The AG_DataSourceInit() and AG_DataSourceDestroy() functions are used when implementing new data source types. They are used internally by the AG_Open*() and AG_Close*() functions.

AG_DataSourceSetErrorFn() configures an alternate handler routine for data source exceptions (which can occur when using routines such as AG_ReadUint32(), for example on I/O error). From the handler routine, a pointer to the AG_DataSource can be retrieved using AG_SELF, and the error message is retrieved using AG_STRING(1). The default exception handler simply calls AG_FatalError(3).

The AG_DataSourceError() function raises a data source error, with the optional error message string. It is intended for use in custom I/O routines which do not return an error status. If fmt is NULL, the error is obtained from AG_GetError(3).

IMPLEMENTING NEW SOURCES

Implementing a new data source is simply a matter of inheriting from the AG_DataSource structure and configuring a number of low-level I/O functions (any of which can be set to NULL if not applicable to the data source).

Public members of the AG_DataSource structure include:
typedef struct ag_data_source {
	AG_Mutex lock;			/* Lock on all operations */
	enum ag_byte_order byte_order;	/* Byte order of source */
	size_t wrLast;			/* Last write count (bytes) */
	size_t rdLast;			/* Last read count (bytes) */
	size_t wrTotal;			/* Total write count (bytes) */
	size_t rdTotal;			/* Total read count (bytes) */
	AG_IOStatus (*read)(struct ag_data_source *, void *buf,
	                    size_t size, size_t nmemb, size_t *rv);
	AG_IOStatus (*read_at)(struct ag_data_source *, void *buf,
	                       size_t size, size_t nmemb, off_t pos,
	                       size_t *rv);
	AG_IOStatus (*write)(struct ag_data_source *, const void *buf,
	                     size_t size, size_t nmemb, size_t *rv);
	AG_IOStatus (*write_at)(struct ag_data_source *, const void *buf,
	                        size_t size, size_t nmemb, off_t pos,
	                        size_t *rv);
	off_t       (*tell)(struct ag_data_source *);
	int         (*seek)(struct ag_data_source *, off_t offs,
	                    enum ag_seek_mode mode);
	void        (*close)(struct ag_data_source *);
} AG_DataSource;

The byte_order setting affects integer read operations.

The wrLast, rdLast, wrTotal and rdTotal fields keep count of the read/written bytes, and are automatically incremented by the generic AG_DataSource calls.

The read operation reads nmemb items of size bytes from the data source and into buf, returning the total number of bytes read into rv. The read_at variant reads data at a specified offset.

The write operation writes nmemb items of size bytes from buf to the data source, returning the total number of bytes written into rv. The write_at variant writes the data at a specified offset.

tell returns the current offset.

seek moves to the specified offset and returns 0 on success and -1 on failure.

close closes the data source.

INTEGER OPERATIONS

The following functions read and write integer values using the byte order specified for the data source.


Uint8 AG_ReadUint8 (AG_DataSource *ds)

int AG_ReadUint8v (AG_DataSource *ds, Uint8 *v)

Sint8 AG_ReadSint8 (AG_DataSource *ds)

int AG_ReadSint8v (AG_DataSource *ds, Sint8 *v)

Uint16 AG_ReadUint16 (AG_DataSource *ds)

int AG_ReadUint16v (AG_DataSource *ds, Uint16 *v)

Sint16 AG_ReadSint16 (AG_DataSource *ds)

int AG_ReadSint16v (AG_DataSource *ds, Sint16 *v)

Uint32 AG_ReadUint32 (AG_DataSource *ds)

int AG_ReadUint32v (AG_DataSource *ds, Uint32 *v)

Sint32 AG_ReadSint32 (AG_DataSource *ds)

int AG_ReadSint32 (AG_DataSource *ds, Sint32 *v)

Uint64 AG_ReadUint64 (AG_DataSource *ds)

int AG_ReadUint64v (AG_DataSource *ds, Uint64 *v)

Sint64 AG_ReadSint64 (AG_DataSource *ds)

int AG_ReadSint64v (AG_DataSource *ds, Sint64 *v)

void AG_WriteUint8 (AG_DataSource *ds, Uint8 value)

int AG_WriteUint8v (AG_DataSource *ds, const Uint8 *value)

void AG_WriteSint8 (AG_DataSource *ds, Sint8 value)

int AG_WriteSint8v (AG_DataSource *ds, const Sint8 *value)

void AG_WriteUint16 (AG_DataSource *ds, Uint16 value)

int AG_WriteUint16v (AG_DataSource *ds, const Uint16 *value)

void AG_WriteSint16 (AG_DataSource *ds, Sint16 value)

int AG_WriteSint16v (AG_DataSource *ds, const Sint16 *value)

void AG_WriteUint32 (AG_DataSource *ds, Uint32 value)

int AG_WriteUint32v (AG_DataSource *ds, const Uint32 *value)

void AG_WriteSint32 (AG_DataSource *ds, Sint32 value)

int AG_WriteSint32v (AG_DataSource *ds, const Sint32 *value)

void AG_WriteUint64 (AG_DataSource *ds, Uint64 value)

int AG_WriteUint64v (AG_DataSource *ds, const Uint64 *value)

void AG_WriteSint64 (AG_DataSource *ds, Sint64 value)

int AG_WriteSint64v (AG_DataSource *ds, const Sint64 *value)

void AG_WriteUint8At (AG_DataSource *ds, Uint8 value, off_t offs)

void AG_WriteSint8At (AG_DataSource *ds, Sint8 value, off_t offs)

void AG_WriteUint16At (AG_DataSource *ds, Uint16 value, off_t offs)

void AG_WriteSint16At (AG_DataSource *ds, Sint16 value, off_t offs)

void AG_WriteUint32At (AG_DataSource *ds, Uint32 value, off_t offs)

void AG_WriteSint32At (AG_DataSource *ds, Sint32 value, off_t offs)

void AG_WriteUint64At (AG_DataSource *ds, Uint64 value, off_t offs)

void AG_WriteSint64At (AG_DataSource *ds, Sint64 value, off_t offs)




The AG_Read[SU]intN() functions read and return an integer value of N bits from the data source. The AG_Read[SU]intNv() variants write the value to the specified pointer.

The AG_Write[SU]intN() functions write an integer value of N bits to the data source. The AG_Write[SU]intNv() variants accept a pointer argument.

The AG_Write[SU]intNAt() variants write the integer to the specified position in the data source.

All AG_Read*v() functions return 0 on success and -1 on failure, without raising any exceptions. The other functions will raise a data source exception if an failuer (e.g., an I/O error) occured.

The 64-bit types are only available if HAVE_64BIT is defined.

FLOATING POINT OPERATIONS

The following routines read and write floating-point numbers in IEEE.754 representation.


float AG_ReadFloat (AG_DataSource *ds)

int AG_ReadFloatv (AG_DataSource *ds, float *f)

double AG_ReadDouble (AG_DataSource *ds)

int AG_ReadDoublev (AG_DataSource *ds, double *f)

long double AG_ReadLongDouble (AG_DataSource *ds)

int AG_ReadLongDouble (AG_DataSource *ds, long double *f)

void AG_WriteFloat (AG_DataSource *ds, float f)

int AG_WriteFloatv (AG_DataSource *ds, float *f)

void AG_WriteFloatAt (AG_DataSource *ds, float f, off_t pos)

void AG_WriteDouble (AG_DataSource *ds, double f)

int AG_WriteDoublev (AG_DataSource *ds, double *f)

void AG_WriteDoubleAt (AG_DataSource *ds, double f, off_t pos)

void AG_WriteLongDouble (AG_DataSource *ds, long double f)

int AG_WriteLongDoublev (AG_DataSource *ds, long double *f)

void AG_WriteLongDoubleAt (AG_DataSource *ds, long double f, off_t pos)


AG_ReadFloat(), AG_ReadDouble() and AG_ReadLongDouble() read a floating-point value from the data source.

AG_WriteFloat(), AG_WriteDouble() and AG_WriteLongDouble() write a floating-point value to the data source. The AG_Write*At() variants write the value at a given position.

All AG_Read*v() functions return 0 on success and -1 on failure, without raising any exceptions. The other functions will raise a data source exception if an failuer (e.g., an I/O error) occured.

The "long double" functions are available only if HAVE_LONG_DOUBLE is defined.

STRING OPERATIONS

The following functions read and write arbitrary strings, and are commonly used for text. The encoding of the strings is simply an unsigned 32-bit integer byte count, followed by the string. The encoding may or may not include a terminating NUL.


char * AG_ReadStringLen (AG_DataSource *ds, size_t maxsize)

int AG_ReadStringLenv (AG_DataSource *ds, size_t maxsize, char **s)

char * AG_ReadString (AG_DataSource *ds)

int AG_ReadStringv (AG_DataSource *ds, char **s)

char * AG_ReadNulStringLen (AG_DataSource *ds, size_t maxsize)

char * AG_ReadNulString (AG_DataSource *ds)

size_t AG_CopyString (char *buf, AG_DataSource *ds, size buf_size)

size_t AG_CopyNulString (char *buf, AG_DataSource *ds, size buf_size)

void AG_SkipString (AG_DataSource *ds)

void AG_WriteString (AG_DataSource *ds, const char *s)

int AG_WriteStringv (AG_DataSource *ds, const char *s)




The AG_ReadStringLen() function reads a string of up to maxsize bytes and returns a dynamically allocated, NUL-terminated copy of the string. AG_ReadString() implicitely limits the string to AG_LOAD_STRING_MAX bytes. Both functions will raise a data source exception on error.

The AG_ReadStringLenv() and AG_ReadStringv() variants accept a pointer s to an existing, valid string buffer which will be reallocated to fit the new string. Both functions will return -1 (without raising a data source exception) on failure. If a low-level I/O error occurs after the buffer is reallocated, the string at s will be truncated to zero-length.

AG_CopyString() copies the string directly into a fixed-size buffer buf of buf_size bytes and NUL-terminates it. AG_CopyString() returns the number of bytes that would have been copied were buf_size unlimited. If an error occurs, a data source exception is raised.

The AG_ReadNulString(), AG_ReadNulStringLen() and AG_CopyNulString() variants handle strings where the encoding includes the NUL-termination. These functions do not perform type checking are mostly useful when reading non-Agar generated data files.

The AG_SkipString() routine skips over the string at the current position in the buffer.

The AG_WriteString() function writes a string to a data source, where the encoding is not NUL-terminated. If an error occurs, a data source exception is raised. The AG_WriteStringv() variant returns 0 on success and -1 on failure, without raising exceptions.

SEE ALSO

AG_Intro(3), AG_Version(3), AG_ByteSwap(3)

HISTORY

A similar interface called AG_Netbuf first appeared in Agar 1.0. The current AG_DataSource interface appeared in Agar 1.3. Exception handling and error-checking variants of the primitive I/O routines appeared in Agar 1.3.3.