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);//按字符串返回
}