2025-02-02 21:40:31 +03:00
|
|
|
#include <BH/IO.h>
|
2025-01-18 17:24:36 +03:00
|
|
|
#include <malloc.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER_SIZE (sizeof(char *))
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
struct BH_IO
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
2025-01-30 13:53:26 +03:00
|
|
|
BH_IOCallback cb;
|
2025-01-18 17:24:36 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
BH_IO *BH_IONew(BH_IOCallback cb,
|
|
|
|
|
void *data)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
size_t requested;
|
2025-01-30 13:53:26 +03:00
|
|
|
BH_IO *io;
|
2025-01-18 17:24:36 +03:00
|
|
|
|
|
|
|
|
/* Get information about IO device size */
|
2025-01-30 13:53:26 +03:00
|
|
|
if (cb(NULL, BH_IO_INFO_CB, &requested, NULL))
|
2025-01-18 17:24:36 +03:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Allocate space for the IO device */
|
|
|
|
|
io = malloc(sizeof(*io) + requested);
|
|
|
|
|
if (!io)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Initialize IO device */
|
2025-01-30 13:53:26 +03:00
|
|
|
io->cb = cb;
|
|
|
|
|
if (cb(io + 1, BH_IO_INIT_CB, data, NULL))
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
free(io);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return io;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
void BH_IOFree(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device destruction handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
io->cb(io + 1, BH_IO_DESTROY_CB, NULL, NULL);
|
2025-01-29 09:19:34 +03:00
|
|
|
|
|
|
|
|
/* Deallocate object */
|
|
|
|
|
free(io);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
const char *BH_IOClassname(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
if (!io)
|
|
|
|
|
goto error;
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
if (io->cb(io + 1, BH_IO_INFO_CB, NULL, &name) != BH_OK)
|
2025-01-18 17:24:36 +03:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOOpen(BH_IO *io,
|
|
|
|
|
int mode)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device open handler with specified mode */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_OPEN_CB, &mode, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOClose(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device close handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_CLOSE_CB, NULL, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IORead(BH_IO *io,
|
|
|
|
|
char *buffer,
|
|
|
|
|
size_t size,
|
|
|
|
|
size_t *actual)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
int code;
|
|
|
|
|
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device read handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
code = io->cb(io + 1, BH_IO_READ_CB, buffer, &size);
|
2025-01-18 17:24:36 +03:00
|
|
|
|
|
|
|
|
/* If caller wants to know actual read size - report it back */
|
|
|
|
|
if (actual)
|
|
|
|
|
*actual = size;
|
|
|
|
|
|
|
|
|
|
return code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOWrite(BH_IO *io,
|
|
|
|
|
const char *buffer,
|
|
|
|
|
size_t size,
|
|
|
|
|
size_t *actual)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
int code;
|
|
|
|
|
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device write handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
code = io->cb(io + 1, BH_IO_WRITE_CB, (void *)buffer, &size);
|
2025-01-18 17:24:36 +03:00
|
|
|
|
|
|
|
|
/* If caller wants to know actual written size - report it back */
|
|
|
|
|
if (actual)
|
|
|
|
|
*actual = size;
|
|
|
|
|
|
|
|
|
|
return code;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOPeek(BH_IO *io,
|
|
|
|
|
char *buffer,
|
|
|
|
|
size_t size,
|
|
|
|
|
size_t *actual)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
int code;
|
|
|
|
|
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device peek handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
code = io->cb(io + 1, BH_IO_PEEK_CB, (void *)buffer, &size);
|
2025-01-18 17:24:36 +03:00
|
|
|
|
|
|
|
|
/* If caller wants to know actual written size - report it back */
|
|
|
|
|
if (actual)
|
|
|
|
|
*actual = size;
|
|
|
|
|
|
|
|
|
|
return code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOTell(BH_IO *io,
|
|
|
|
|
int64_t *position)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device tell handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_TELL_CB, position, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOSeek(BH_IO *io,
|
|
|
|
|
int64_t position,
|
|
|
|
|
int direction)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device seek handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_SEEK_CB, &position, &direction);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOFlush(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device flush handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_FLUSH_CB, NULL, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOSize(BH_IO *io,
|
|
|
|
|
int64_t *size)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device size handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_SIZE_CB, size, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOFlags(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_IO_FLAG_ERROR;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device flags handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_FLAGS_CB, NULL, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-01-30 13:53:26 +03:00
|
|
|
int BH_IOClear(BH_IO *io)
|
2025-01-18 17:24:36 +03:00
|
|
|
{
|
|
|
|
|
/* Prevent working with NULL io */
|
|
|
|
|
if (!io)
|
|
|
|
|
return BH_OK;
|
|
|
|
|
|
|
|
|
|
/* Call the IO device clear error handler */
|
2025-01-30 13:53:26 +03:00
|
|
|
return io->cb(io + 1, BH_IO_CLEAR_CB, NULL, NULL);
|
2025-01-18 17:24:36 +03:00
|
|
|
}
|
2025-02-03 15:18:57 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BH_IO *BH_BufferNew(BH_IO *io)
|
|
|
|
|
{
|
|
|
|
|
(void)io;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|