swoole源码分析之Buffer的substr操作

版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/82953986

swoole_buffer提供的substr操作用于从缓冲区中取出内容。

string swoole_buffer->substr(int $offset, int $length = -1, bool $remove = false);
  • $offset 表示偏移量,如果为负数,表示倒数计算偏移量
  • $length 表示读取数据的长度,默认为从 $offset 到整个缓存区末尾
  • $remove 表示从缓冲区的头部将此数据移除。只有 $offset = 0 时此参数才有效

下面我们分析下其流程。

static PHP_METHOD(swoole_buffer, substr)
{
    long offset;
    long length = -1;
    zend_bool remove = 0;
    
    //解析输入参数信息,这里输入参数有三个,分别用offset,length,remove表示,具体参数解释可参考上述接口描述
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|lb", &offset, &length, &remove) == FAILURE)
    {
        RETURN_FALSE;
    }

    swString *buffer = swoole_get_object(getThis());//获取swoole内部封装对象buffer

    if (remove && !(offset == 0 && length <= buffer->length))//参数有效性检查,remove只在offset为0时才有效
    {
        remove = 0;
    }

    if (offset < 0)//处理offset为负数的情况,offset为负数表示从buffer的尾部往前读
    {
        offset = buffer->length + offset;
    }

    offset += buffer->offset;
    if (length < 0)//处理length为负数的情况,length取目前数据的总的长度,从offset开始算起。
    {
        length = buffer->length - offset;
    }

    if (offset + length > buffer->length)//参数有效性检查,即offset开始,length个空间是否超过Buffer数据的总长度信息
    {
        swoole_php_error(E_WARNING, "offset(%ld, %ld) is out of bounds.", offset, length);
        RETURN_FALSE;
    }

    if (remove)//remove为真,表示读取数据后删除这部分数据
    {
        buffer->offset += length;//更新buffer的offset信息
        zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("length"), buffer->length - buffer->offset TSRMLS_CC);//更新swoole_buffer的length属性信息

        if (buffer->offset > SW_STRING_BUFFER_GARBAGE_MIN && buffer->offset * SW_STRING_BUFFER_GARBAGE_RATIO > buffer->size)//判断是否需要回收buffer不用的空间,这里判断条件为不用空间大小大于64K且不用空间已经占用了整个buffer的1/4的空间部分
        {
            swoole_buffer_recycle(buffer);//执行回收,回收逻辑后续介绍
        }
    }
    SW_RETURN_STRINGL(buffer->str + offset, length, 1);//按字符串返回
}

猜你喜欢

转载自blog.csdn.net/u013702678/article/details/82953986