5. I/O interface
A callback driven I/O interface is used to read/write serial data in different configurations.
5.1. Struct
The IO interface is a struct that consists of 3 things: a write callback, a read callback, and some user data. The user data is tacked on the end of the read/write callbacks.
typedef struct txtvm_io txtvm_io;
struct txtvm_io {
int (*read)(int,char*,void*);
int (*write)(int,char*,void*);
void *ud;
};
The read
callback requests to read a number bytes into
a supplied buffer. It returns the number of bytes actually
read. A negative value is an error.
The write
callback requests to write a number of bytes
in a supplied buffer. It returns the number of bytes
actually written. A negative value is an error.
5.2. Initialize
Initialize the IO with txtvm_io_init
. This will make it do
nothing.
void txtvm_io_init(txtvm_io *io);
void txtvm_io_init(txtvm_io *io)
{
io->read = NULL;
io->write = NULL;
io->ud = NULL;
}
5.3. Calling Read/Write callbacks
Call the read callback with txtvm_io_read
. Will return -1
if there is no read callback.
int txtvm_io_read(txtvm_io *io, int sz, char *buf);
int txtvm_io_read(txtvm_io *io, int sz, char *buf)
{
if (io->read == NULL) return -1;
return io->read(sz, buf, io->ud);
}
Writing is done in a similar way with txtvm_io_write
. It
will also return -1 if no write callback is to be found.
int txtvm_io_write(txtvm_io *io, int sz, char *buf);
int txtvm_io_write(txtvm_io *io, int sz, char *buf)
{
if (io->write == NULL) return -1;
return io->write(sz, buf, io->ud);
}
5.4. Read-Only Memory Buffer Setup
This setup configures things to read bytes from a memory buffer. Writing is disabled.
void txtvm_io_readbuf(txtvm_io *io,
txtvm_io_readbuf_data *data);
<<readbuf>>
void txtvm_io_readbuf(txtvm_io *io,
txtvm_io_readbuf_data *data)
{
io->read = readbuf;
io->write = NULL;
io->ud = data;
}
The reader callback struct is embedded inside of a struct for the serial parser. This new struct is initialized with both the memory buffer to read from, as well as the size.
typedef struct {
unsigned long pos;
unsigned long sz;
const char *buf;
} txtvm_io_readbuf_data;
Internally, the struct keeps track of the buffer offset position.
Reading from the buffer is a matter of making sure the requested block size is in bounds, adjusting if needed, copying the chunk, then updating the offset position.
static int readbuf(int sz, char *buf, void *ud)
{
txtvm_io_readbuf_data *r;
int i;
r = ud;
if (r->pos >= r->sz) return 0;
if ((r->pos + sz) >= r->sz) {
sz = r->sz - r->pos;
}
for (i = 0; i < sz; i++) {
buf[i] = r->buf[r->pos + i];
}
r->pos += sz;
return sz;
}
5.5. Write-Only Memory Buffer Setup
Sets up the I/O interface to write content to a buffer with a maximum capacity. If it reaches that point, it returns an error.
void txtvm_io_writebuf(txtvm_io *io,
txtvm_io_writebuf_data *data);
<<writebuf>>
void txtvm_io_writebuf(txtvm_io *io,
txtvm_io_writebuf_data *data)
{
io->read = NULL;
io->write = writebuf;
io->ud = data;
}
typedef struct {
unsigned long pos;
unsigned long sz;
char *buf;
} txtvm_io_writebuf_data;
static int writebuf(int sz, char *buf, void *ud)
{
txtvm_io_writebuf_data *w;
int i;
w = ud;
if (w->pos >= w->sz) return 0;
if ((w->pos + sz) >= w->sz) {
sz = w->sz - w->pos;
}
for (i = 0; i < sz; i++) {
w->buf[w->pos + i] = buf[i];
}
w->pos += sz;
return sz;
}
5.6. I/O Errors
5.6.1. Incomplete Write
ERRORCODE(TXTVM_INCOMPLETE_WRITE, "Incomplete write.")
5.6.2. Incomplete Read
ERRORCODE(TXTVM_INCOMPLETE_READ, "Incomplete read.")
prev | home | next