swoole_buffer提供的append操作用于将一个字符串数据追加到缓存区末尾。
int swoole_buffer->append(string $data);
- $data是要写入的数据,支持二进制内容
- 执行成功后,会返回新的长度
下面我们分析下其流程。
static PHP_METHOD(swoole_buffer, append)
{
swString str;//定义swString变量
bzero(&str, sizeof(str));//变量内存空间初始化
//解析输入参数,这里的参数包括要追加字符串和字符串长度信息
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str.str, &str.length) == FAILURE)
{
RETURN_FALSE;
}
if (str.length < 1)//参数有效性检查,输入数据异常
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "string empty.");
RETURN_FALSE;
}
swString *buffer = swoole_get_object(getThis());//获取swoole内部封装对象buffer
//判断buffer目前已有的空间是否能容纳新追加的字符串,这里buffer空间有最大值限制
if ((str.length + buffer->length) > buffer->size && (str.length + buffer->length) > SW_STRING_BUFFER_MAXLEN)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "buffer size can't exceed %d", SW_STRING_BUFFER_MAXLEN);
RETURN_FALSE;
}
size_t size_old = buffer->size;
if (swString_append(buffer, &str) == SW_OK)//执行追加的操作,这里可能会扩容
{
if (buffer->size > size_old)//目前buffer的size比追加之前大,也就是发生了扩容
{
zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("capacity"), buffer->size TSRMLS_CC);//更新swoole_buffer的capacity的属性
}
zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("length"),
buffer->length - buffer->offset TSRMLS_CC);//更新swoole_buffer的length属性
RETURN_LONG(buffer->length - buffer->offset);
}
else
{
RETURN_FALSE;
}
}
int swString_append(swString *str, swString *append_str)
{
int new_size = str->length + append_str->length;//新的size大小
if (new_size > str->size)//新的size大于目前buffer的size,则执行扩容
{
//执行扩容,关于扩容我们后续文章讨论
if (swString_extend(str, swoole_size_align(new_size * 2, sysconf(_SC_PAGESIZE))) < 0)
{
return SW_ERR;
}
}
memcpy(str->str + str->length, append_str->str, append_str->length);//进行内存空间拷贝
str->length += append_str->length;//更新buffer的length大小
return SW_OK;
}