如何解决从内部函数不是文件创建一个`FILE`?
POSIX/C 定义了许多很好的函数来处理文件对象,例如 fputs
和 fprintf
。
/*
`FILE*` rather than `SomeType*` wanted?
*/
void f(const char *text) {
SomeType* printer_object = \
allocate_printer_if_not_defined_statically_else_return_that();
printer_object.error_out(text); /* equiv. semantics to stderr */
// printer_object.info_out(text); /* equiv. semantics to stdout */
cleanup_printer_object(&printer_object);
}
如何启用随机函数(如上面的 f
)以符合 fopen
、fclose
等?
部分解决方案(感谢 Freenode 的 ##C 上的 atk):
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#define container_of(ptr,type,member) ((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type,member)))
struct io_ops;
typedef size_t io_ops_read_func(struct io_ops **ops,void *buf,size_t size);
typedef size_t io_ops_write_func(struct io_ops **ops,const void *buf,size_t size);
typedef void io_ops_close_func(struct io_ops **ops);
struct io_ops {
io_ops_read_func *read;
io_ops_write_func *write;
io_ops_close_func *close;
/* You also probably want seek */
};
size_t io_read(struct io_ops **ops,size_t size)
{
if (!ops || !*ops) {
errno = EINVAL;
return 0;
}
if (!(*ops)->read) {
errno = ENOSYS;
return 0;
}
return (*ops)->read(ops,buf,size);
}
size_t io_write(struct io_ops **ops,size_t size)
{
if (!ops || !*ops) {
errno = EINVAL;
return 0;
}
if (!(*ops)->write) {
errno = ENOSYS;
return 0;
}
return (*ops)->write(ops,size);
}
void io_close(struct io_ops **ops)
{
if (!ops || !*ops) {
errno = EINVAL;
return;
}
if (!(*ops)->close) {
errno = ENOSYS;
return;
}
(*ops)->close(ops);
}
struct buffer_io {
void *buffer;
size_t size;
size_t pos;
struct io_ops *ops;
};
size_t buffer_io_ops_read(struct io_ops **ops,size_t size)
{
struct buffer_io *bio = container_of(ops,struct buffer_io,ops);
assert(bio->pos <= bio->size);
if (size > bio->size - bio->pos)
size = bio->size - bio->pos;
memcpy(buf,(unsigned char *)bio->buffer + bio->pos,size);
bio->pos += size;
return size;
}
size_t buffer_io_ops_write(struct io_ops **ops,ops);
assert(bio->pos <= bio->size);
if (size > bio->size - bio->pos)
size = bio->size - bio->pos;
memcpy((unsigned char *)bio->buffer + bio->pos,size);
bio->pos += size;
return size;
}
void buffer_io_ops_close(struct io_ops **ops)
{
struct buffer_io *bio = container_of(ops,ops);
free(bio);
}
struct io_ops buffer_io_ops = {
.read = buffer_io_ops_read,.write = buffer_io_ops_write,.close = buffer_io_ops_close,};
struct io_ops **new_buffer_io(void *buf,size_t size)
{
struct buffer_io *bio;
bio = malloc(sizeof *bio);
if (bio == NULL)
return NULL;
bio->buffer = buf;
bio->size = size;
bio->pos = 0;
bio->ops = &buffer_io_ops;
return &bio->ops;
}
int main(void)
{
char buf[1024],*test = "foo bar baz",readbuf[1024];
struct io_ops **bio = new_buffer_io(buf,sizeof buf);
io_write(bio,test,sizeof *test);
io_close(bio);
bio = new_buffer_io(buf,sizeof buf);
io_read(bio,readbuf,sizeof *test);
assert(memcmp(test,sizeof *test) == 0);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。