R)
continue;
return -1;
}
// EOF 直接返回
if (r->cnt == 0)
return 0;
// 重新设置 buffer ptr
r->ptr = r->buf;
}
// 尝试读取数据并返回
ssize_t cnt = r->cnt < n ? r->cnt : n;
memcpy(buf, r->ptr, cnt);
r->cnt -= cnt;
r->ptr += cnt;
return cnt;
}
//
// readn - 力求读取 n 个字节
// r : 缓冲读取对象
// buf : 缓冲区
// n : 读取长度
// return : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
ssize_t
rio_readn(struct rio * r, void * buf, size_t n) {
size_t div = n;
char * ptr = buf;
while (div > 0) {
ssize_t ret = rio_read(r, ptr, div);
if (ret < 0)
return -1;
if (ret == 0)
break;
ptr += ret;
div -= ret;
}
return n - div;
}
//
// rio_readline - 力求读取一行数据, 会吃掉最后一个 \n 字符
// r : 缓冲读取对象
// buf : 缓冲区
// n : 读取长度
// return : 返回读取的长度, -1 标识错误, < n 标识关闭, 默认 n
//
ssize_t
rio_readline(struct rio * r, void * buf, size_t n) {
size_t i;
char * ptr = buf, c;
for (i = 1; i < n; ++i) {
ssize_t ret = rio_read(r, &c, 1);
if (ret < 0)
return -1;
if (c == '\n' || ret == 0)
break;
*ptr++ = c;
}
*ptr = '\0';
return i - 1;
}
缓冲写实战包装要复杂一点. 和业务绑定重(或者实现多策略的). 例如缓冲区满了这时候的策略就由业务
决定, 是缓冲区扩容, 还是等待下次写事件触发. 等等, 真实战场的缓冲读写需要具体场景和机器打配合,
来构造满意的读写策略.
后记 - 让水倒流
|