1.evbuffer以队列的形式管理字节,从尾部添加,从头部取出(FIFO)
2.evbuffer内部存储形式是多个独立的连续内存
 
 
 
接口
//创建和删除
struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *buf);
 
//加锁解锁
//默认情况下是没有加锁的,多线程并发访问不安全
//第二个参数lock为空,则自动分配一个锁( 使用evthread_set_lock_creation_callback()设置的锁创建函数)
int evbuffer_enable_locking(struct evbuffer *buf, void *lock);
//没有必要为单独的操作加锁,因为单独的操作已经是原子级别的了
void evbuffer_lock(struct evbuffer *buf);
void evbuffer_unlock(struct evbuffer *buf);
 
 
//获取evbuffer包含的字节数
size_t evbuffer_get_length(const struct evbuffer *buf);
 
//获取队列首部的连续空间长度
size_t evbuffer_get_contiguous_space(const struct evbuffer *buf);
 
//基础的读写数据接口
//将数据添加到尾部
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
//格式化的添加数据到尾部
int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);
 
//修改最后一块连续内存,或者添加一块连续内存
int evbuffer_expand(struct evbuffer *buf, size_t datlen);
 
//从evbuffer移动数据到另一个evbuffer
int evbuffer_add_buffer(struct evbuffer *dst, struct evbuffer *src);
int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
    size_t datlen);
 
//在首部添加数据
//这些函数不应该用于和bufferevent关联的evbuffer
int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
 
//查看首部N字节的连续空间(首先必须确定这N字节空间是连续的,使用evbuffer_get_contiguous_space ()
//size参数为负数,则拷贝首部连续空间的所有数据
//如果size很大,该接口效率低
unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size);
 
//从evbuffer删除数据
//evbuffer_drain不拷贝数据,evbuffer_remove要拷贝数据
int evbuffer_drain(struct evbuffer *buf, size_t len);
int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
 
//从首部拷贝而不删除数据
//如果效率不好可以使用 evbuffer_peek()
ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data, size_t datlen);
ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf,
     const struct evbuffer_ptr *pos,
     void *data_out, size_t datlen);
 
//按行进行读写
enum evbuffer_eol_style {
        EVBUFFER_EOL_ANY,     //已任何序列为换行符
        EVBUFFER_EOL_CRLF,   //回车换行的组合为换行标示 (\r\n或者\n)
        EVBUFFER_EOL_CRLF_STRICT,  //严格的\r\n
        EVBUFFER_EOL_LF,  //以\n为换行标示
        EVBUFFER_EOL_NUL //以NULL为换行标示
};
 
//返回的指针在堆上分配,n_read_out参数也是返回参数
char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
    enum evbuffer_eol_style eol_style);
 
//在evbuffer中搜索
//表示位置的结构(pos是相对于开始位置的偏移值)
struct evbuffer_ptr {
        ev_ssize_t pos;
        struct {
                /* internal fields */
        } _internal;
};
struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer,
    const char *what, size_t len, const struct evbuffer_ptr *start);
struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer,
    const char *what, size_t len, const struct evbuffer_ptr *start,
    const struct evbuffer_ptr *end);
struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
    struct evbuffer_ptr *start, size_t *eol_len_out,
    enum evbuffer_eol_style eol_style);
 
 
//偏移位置计算标示
//EVBUFFER_PTR_SET,将位置作为绝对位置来设置
//EVBUFFER_PTR_ADD,在当前位置加上参数指定的位置
enum evbuffer_ptr_how {
        EVBUFFER_PTR_SET,
        EVBUFFER_PTR_ADD
};
int evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *pos,
    size_t position, enum evbuffer_ptr_how how);
 
 
//搜索所有的字符串
#include <event2/buffer.h>
#include <string.h>

/* Count the total occurrences of 'str' in 'buf'. */int count_instances(struct evbuffer *buf, const char *str)
{
    size_t len = strlen(str);
    int total = 0;
    struct evbuffer_ptr p;

    if (!len)
        /* Don't try to count the occurrences of a 0-length string. */
        return -1;

    evbuffer_ptr_set(buf, &p, 0, EVBUFFER_PTR_SET);

    while (1) {
         p = evbuffer_search(buf, str, len, &p);
         if (p.pos < 0)
             break;
         total++;
         evbuffer_ptr_set(buf, &p, 1, EVBUFFER_PTR_ADD);
    }

    return total;
}
 
 
//在不使用拷贝的情况下,直接查看evbuffer的数据
struct evbuffer_iovec {
        void *iov_base;
        size_t iov_len;
};
 
//修改被evbuffer_iovec指向的数据,将导致未定义行为
//任何修改evbuffer的函数被调用,将导致evbuffer_peek设置的指针失效
int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
    struct evbuffer_ptr *start_at,
    struct evbuffer_iovec *vec_out, int n_vec);
 
 
//直接向evbuffer写入数据,不存在数据拷贝
//获取evbuffer的内部指针,如果目前的空间不够,将会进行自动扩展
//目前的实现将不会使用多于两个的evbuffer_iovec
//如果提供一个evbuffer_iovec则会进行空间连续校验,以及导致evbuffer调整内部存储,所以最好提供大于1个的evbuffer_iovec
int evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
    struct evbuffer_iovec *vec, int n_vecs);
 
//如果获取到指针后,有修改evbuffer数据的行为,将导致指针失效
//或者的指针的值不能被修改
//如果evbuffer以及有数据则,这些数据将加到已有数据的后面
 
//将数据提交的evbuffer
int evbuffer_commit_space(struct evbuffer *buf,
    struct evbuffer_iovec *vec, int n_vecs);
 
网络IO
 
//howmuch参数为负 对于读表示读多少由libevent自行判断,对于写表示写整个buffer的内容
//读到结尾返回值为0,返回负数表示失败,失败的原因应进一步确认,是非阻塞IO不能立即完成
//还是其他真实错误
 
//如果使用bufferevent则这些调用都由bufferevent完成,不需要用户调用
 
 
int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
        ev_ssize_t howmuch);
int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
 
 
Evbuffer and callback
//当数据增加或删除时的回调函数
struct evbuffer_cb_info {
        size_t orig_size;//变化前的长度
        size_t n_added;   //添加的长度
        size_t n_deleted;  //删除的长度
};

typedef void (*evbuffer_cb_func)(struct evbuffer *buffer,
    const struct evbuffer_cb_info *info, void *arg);
 
//设置回调函数
struct evbuffer_cb_entry;
struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer,
    evbuffer_cb_func cb, void *cbarg);
 
//失效或删除回调函数
int evbuffer_remove_cb_entry(struct evbuffer *buffer,
    struct evbuffer_cb_entry *ent);
int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb,
    void *cbarg);
//使用 EVBUFFER_CB_ENABLED失效
#define EVBUFFER_CB_ENABLED 1
int evbuffer_cb_set_flags(struct evbuffer *buffer,
                          struct evbuffer_cb_entry *cb,
                          ev_uint32_t flags);
int evbuffer_cb_clear_flags(struct evbuffer *buffer,
                          struct evbuffer_cb_entry *cb,
                          ev_uint32_t flags);
 
 
//延迟回调函数的调用
int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
 
 
//避免数据拷贝的 基本的ebuffer-IO
 
typedef void (*evbuffer_ref_cleanup_cb)(const void *data,
    size_t datalen, void *extra);

int evbuffer_add_reference(struct evbuffer *outbuf,
    const void *data, size_t datlen,
    evbuffer_ref_cleanup_cb cleanupfn, void *extra);
 
 
//直接发送文件相关接口,由于支持的版本很新,目前未测试
 
int evbuffer_add_file(struct evbuffer *output, int fd, ev_off_t offset,
    size_t length);
 
struct evbuffer_file_segment;

struct evbuffer_file_segment *evbuffer_file_segment_new(
        int fd, ev_off_t offset, ev_off_t length, unsigned flags);
void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
int evbuffer_add_file_segment(struct evbuffer *buf,
    struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length);
 
 
typedef void (*evbuffer_file_segment_cleanup_cb)(
    struct evbuffer_file_segment const *seg, int flags, void *arg);

void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
        evbuffer_file_segment_cleanup_cb cb, void *arg);
 
 
int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
    struct evbuffer *inbuf);
 
 
int evbuffer_freeze(struct evbuffer *buf, int at_front);
int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
 
 
//过时的接口
char *evbuffer_readline(struct evbuffer *buffer);
unsigned char *evbuffer_find(struct evbuffer *buffer,
    const unsigned char *what, size_t len);
 
typedef void (*evbuffer_cb)(struct evbuffer *buffer,
    size_t old_len, size_t new_len, void *arg);
void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);