=encoding UTF-8 =head1 NAME BH_IO - I/O subsystem =head1 SYNOPSIS #include BH_IO *io = BH_FileNew("input.txt", BH_FILE_WRITE | BH_FILE_TRUNCATE, NULL); BH_IOWrite(io, "Hello, world!", 13, NULL); BH_IOFree(io); cc prog.c -o prog -lbh =head1 DESCRIPTION BH_IO provides a subsystem that allows you to work with various objects (files, sockets, memory) via a single I/O interface. This allows you to write code that is not tied to a specific input/output system. It is guaranteed that any BH_IO object supports the following operations: L, L, L и L. Depending on the implementation of a particular BH_IO object, additional operations may be available: L, L, L, L, L, L, L and others. By default, the I/O subsystem allows you to work with files (L) or RAM (L), as well as buffer I/O (L). =head1 EXTENSIONS BH_IO provides the developer with the ability to create custom implementations of I/O devices. Example: typedef struct BH_MyIO { BH_IO parent; int flags; }; static int ioDestroy(BH_MyIO *io) { /* Ommitted for the example */ } static int ioRead(BH_MyIO *io, BH_IOReadInfo *info) { /* Ommitted for the example */ } static int ioWrite(BH_MyIO *io, BH_IOWriteInfo *info) { /* Ommited for the example */ } static int ioFlags(BH_MyIO *io, int *flags) { *flags = io->flags; return BH_OK; } static int ioCap(BH_MyIO *io, int *op) { BH_UNUSED(io); switch (*op) { case BH_IO_CTL_FLAGS: return BH_OK; default: return BH_NOIMPL; } } static int ioCtl(BH_MyIO *io, BH_IOCtlInfo *info) { switch (info->op) { case BH_IO_CTL_FLAGS: return ioFlags(io, (int *)info->arg); default: return BH_NOIMPL; } } static int ioCallback(BH_MyIO *io, int type, void *arg) { switch (type) { case BH_IO_OP_DESTROY: return ioDestroy(io); case BH_IO_OP_READ: return ioRead(io, (BH_IOReadInfo *)arg); case BH_IO_OP_WRITE: return ioWrite(io, (BH_IOWriteInfo *)arg); case BH_IO_OP_CTL: return ioCtl(io, (BH_IOCtlInfo *)arg); case BH_IO_OP_CAP: return ioCap(io, (int*)arg); default: return BH_NOIMPL; } } BH_IO *BH_MyIONew(int *result) { BH_MyIO *io; int code; code = BH_OOM; if ((io = malloc(sizeof(*io)))) { io->parent.callback = (BH_IOCallback)ioCallback; io->flags = 0; } if (result) *result = code; return (BH_IO*)io; } =head1 API CALLS =head2 BH_FileNew BH_IO *BH_FileNew(const char *path, int mode, int *result); Creates an I/O device for working with the file using the I. The I parameter can take a combination of the following values: =over =item B Opens the file for reading =item B Opens the file for writing =item B Opens the file in append mode =item B Truncates the file =item B The file must be created =item B The file must exist =back The optional parameter I returns 0 or an error code. This function returns a pointer to a new BH_IO object or NULL. =head2 BH_BufferNew BH_IO *BH_BufferNew(BH_IO *device, size_t size, int *result); Creates an I/O device to buffer data to another I. The I parameter is responsible for the size of the read and write buffers. The optional parameter I returns 0 or an error code. If successful, this function returns a pointer to the new BH_IO object or NULL in case of an error. =head2 BH_BytesNew BH_IO *BH_BytesNew(char *data, size_t size, int *result); Creates an I/O device for the memory region I with the size I. The optional parameter I returns 0 or an error code. If successful, this function returns a pointer to the new BH_IO object or NULL in case of an error. =head2 BH_IOFree void BH_IOFree(BH_IO *device); Destroys the I/O device. =head2 BH_IORead int BH_IORead(BH_IO *device, char *buffer, size_t size, size_t *actual); Reads up to I bytes from the I/O device and writes data to I. The optional parameter I returns the number of bytes that was read. If successful, this function returns 0 or an error code. =head2 BH_IOWrite int BH_IOWrite(BH_IO *io, const char *buffer, size_t size, size_t *actual); Writes up to I bytes to the I/O device from I. The optional parameter I returns the number of bytes that was written. If successful, this function returns 0 or an error code. =head2 BH_IOCtl int BH_IOCtl(BH_IO *device, int op, void *arg); Manipulates the parameters of the I/O device using the I command and the I argument. Possible values of I: =over =item B Argument: int * Return the I/O device flags. =item B Reset the I/O device errors. =item B Argument: L Reads data from an I/O device without extracting it. =item B Write buffered data to the I/O device. =item B Argument: int64_t * Get the size of the I/O device. =item B Argument: int64_t * Reads the current offset of the I/O device reader pointer. =item B Argument: L Changes the current position of the I/O reader pointer. =item B Argument: L|void * Gets the device I/O object used in the implementation. =item B Argument: L|void * Sets the device I/O object to be used in the implementation. =back If successful, this function returns 0 or an error code. =head2 BH_IOCap int BH_IOCap(BH_IO *device, int op); Checks whether the I command can be executed on the I/O device. If successful, this function returns 0 or an error code. =head2 BH_IOFlags int BH_IOFlags(BH_IO *device, int *flags); Returns the current I flags of the I/O device. Possible flags (and their combinations): =over =item B An error occurred during the execution. =item B The device has reached the end of the file. =back If successful, this function returns 0 or an error code. =head2 BH_IOClear int BH_IOClear(BH_IO *device); Cleans the I/O device from errors. If successful, this function returns 0 or an error code. =head2 BH_IOPeek int BH_IOPeek(BH_IO *device, char *buffer, size_t size, size_t *actual); Reads up to I bytes from the I/O device without extraction and writes the data to I. The optional parameter I returns the number of bytes that was actually read. If successful, this function returns 0 or an error code. =head2 BH_IOFlush int BH_IOFlush(BH_IO *device); Writes buffered values to the I/O device. If successful, this function returns 0 or an error code. =head2 BH_IOSize int BH_IOSize(BH_IO *device, int64_t *size); Reads the current size of the I/O device in bytes and writes the value to I. For different types of I/O devices, this value can mean different things (for example: the current file size, the size of the memory allocated for I/O, etc.). If successful, this function returns 0 or an error code. =head2 BH_IOTell int BH_IOTell(BH_IO *device, int64_t *offset); Reads the current offset of the I/O reader pointer relative to the start and writes the value to I. If successful, this function returns 0 or an error code. =head2 BH_IOSeek int BH_IOSeek(BH_IO *device, int64_t offset, int whence); Changes the current position of the I/O reader pointer, taking into account the offset I and the initial position I. Possible values of the initial position I: =over =item B Offset relative to the beginning of the device. =item B Offset relative to the current position of the device. =item B Offset relative to the end of the device. =back If successful, this function returns 0 or an error code. =head2 BH_IOError int BH_IOError(BH_IO *device); Checks whether the I/O device is in an error state. This function is equivalent to the following code: (BH_IOFlags(device) & BH_IO_FLAG_ERROR) =head2 BH_IOEndOfFile int BH_IOEndOfFile(BH_IO *device); Checks whether the I/O device has reached the end. This function is equivalent to the following code: (BH_IOFlags(device) & BH_IO_FLAG_EOF) =head1 STRUCTURES =head2 BH_IO typedef struct BH_IO { BH_IOCallback callback; } BH_IO; =head2 BH_IOReadInfo typedef struct BH_IOReadInfo { char *data; size_t size; size_t *actual; } BH_IOReadInfo; =head2 BH_IOWriteInfo typedef struct BH_IOWriteInfo { const char *data; size_t size; size_t *actual; } BH_IOWriteInfo; =head2 BH_IOCtlInfo typedef struct BH_IOCtlInfo { int op; void *arg; } BH_IOCtlInfo; =head2 BH_IOSeekInfo typedef struct BH_IOSeekInfo { int64_t offset; int whence; } BH_IOSeekInfo; =head1 SEE ALSO L