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
|
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
FLOATING POINT OPERATIONS
The following routines read and write floating-point numbers in IEEE.754
representation.
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.
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. |
