lighttpd-1.4.39 : buffer

参考: http://www.cnblogs.com/kernel_hcy/archive/2009/11/04/1594134.html

字符串

lighttpd需要对字符串进行处理,源文件是buffer.c buffer.h
buffer的定义如下所示,注释写的很清晰。

/* generic string + binary data container; contains a terminating 0 in both
 * cases
 *
 * used == 0 indicates a special "empty" state (unset config values); ptr
 * might be NULL too then. otherwise an empty string has used == 1 (and ptr[0]
 * == 0);
 *
 * copy/append functions will ensure used >= 1 (i.e. never leave it in the
 * special empty state); only buffer_copy_buffer will copy the special empty
 * state.
 */
typedef struct {
    char *ptr;

    /* "used" includes a terminating 0 */
    size_t used;
    /* size of allocated buffer at *ptr */
    size_t size;
} buffer;

相关函数

  • buffer_reset
/* truncates to used == 0; frees large buffers, might keep smaller ones for reuse */
void buffer_reset(buffer *b); /* b can be NULL */

void buffer_reset(buffer *b) {
    if (NULL == b) return;

    /* limit don't reuse buffer larger than ... bytes */
    if (b->size > BUFFER_MAX_REUSE_SIZE) {
        free(b->ptr);
        b->ptr = NULL;
        b->size = 0;
    } else if (b->size > 0) {
        b->ptr[0] = '\0';
    }

    b->used = 0;
}

其中FFER_MAX_REUSE_SIZE的定义在settings.h中:

/**
 * max size of a buffer which will just be reset
 * to ->used = 0 instead of really freeing the buffer
 *
 * 64kB (no real reason, just a guess)
 */
#define BUFFER_MAX_REUSE_SIZE  (4 * 1024)

也就是说,如果buffer的大小不超过4K,那么不会释放该空间,而是重新使用。

  • buffer_move
/* reset b. if NULL != b && NULL != src, move src content to b. reset src. */
void buffer_move(buffer *b, buffer *src);

如果b和src均不为NULL时,将src的内容“剪切”到b中。(注意不是复制)
如果b为NULL,那么对src执行buffer_reset操作。
如果b不为空,那么先将b“清空”(buffer_reset(b), b的大小小于4K时,不回被free,记得吗),然后将b和src进行swap。源码如下所示:

void buffer_move(buffer *b, buffer *src) {
    buffer tmp;

    if (NULL == b) {
        buffer_reset(src);
        return;
    }
    buffer_reset(b);
    if (NULL == src) return;

    tmp = *src; *src = *b; *b = tmp;
}
  • buffer_align_size
#define BUFFER_PIECE_SIZE 64
static size_t buffer_align_size(size_t size) {
    size_t align = BUFFER_PIECE_SIZE - (size % BUFFER_PIECE_SIZE);
    /* overflow on unsinged size_t is defined to wrap around */
    if (size + align < size) return size;
    return size + align;
}

保证buffer的大小是按照 BUFFER_PIECE_SIZE 对齐的
注意if判断,它处理了size+align有可能会溢出(overflow)的情况。这点以后要注意!

  • buffer_alloc , buffer_realloc
/* make sure buffer is at least "size" big. discard old data */
static void buffer_alloc(buffer *b, size_t size) {
    force_assert(NULL != b);
    if (0 == size) size = 1;

    if (size <= b->size) return;

    if (NULL != b->ptr) free(b->ptr);

    b->used = 0;
    b->size = buffer_align_size(size);
    b->ptr = malloc(b->size);

    force_assert(NULL != b->ptr);
}

/* make sure buffer is at least "size" big. keep old data */
static void buffer_realloc(buffer *b, size_t size) {
    force_assert(NULL != b);
    if (0 == size) size = 1;

    if (size <= b->size) return;

    b->size = buffer_align_size(size);
    b->ptr = realloc(b->ptr, b->size);

    force_assert(NULL != b->ptr);
}

涉及到对空间的分配,逻辑很清晰。

  • li_tohex
static const char hex_chars[] = "0123456789abcdef";

void li_tohex(char *buf, const char *s, size_t s_len) {
    size_t i;

    for (i = 0; i < s_len; i++) {
        buf[2*i] = hex_chars[(s[i] >> 4) & 0x0F];
        buf[2*i+1] = hex_chars[s[i] & 0x0F];
    }
    buf[2*s_len] = '\0';
}

该函数将字符串s中的字符转换为16进制,保存在buff中。例如字符‘A’将转换为 “41”。因此转换后长度翻倍。
我想到的一种转换方法是使用sprintf。
但是这里的方法更好。hex_chars相当于一个字典。s[i]>>4 & 0x0F 是求16进制的高位数字,s[i] & 0x0F 是求16进制的地位数字,然后再hex_chars中查找对应的字符。

  • buffer_copy_string
void buffer_copy_string(buffer *b, const char *s) {
    buffer_copy_string_len(b, s, NULL != s ? strlen(s) : 0);
}

这里对三目运算符的使用很优雅。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值