swoole_buffer提供的write操作用于向缓存区的任意内存位置写数据。read/write函数可以直接读写内存。所以使用务必要谨慎,否则可能会破坏现有数据。
swoole_buffer->write(int $offset, string $data)
- $offset 偏移量
- $data 写入的数据
现在我们看下其处理流程。
static PHP_METHOD(swoole_buffer, write)
{
long offset;
swString str;
bzero(&str, sizeof(str));
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &offset, &str.str, &str.length) == FAILURE)
{
RETURN_FALSE;
}
if (str.length < 1)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "string to write is empty.");
RETURN_FALSE;
}
swString *buffer = swoole_get_object(getThis());
if (offset < 0)
{
offset = buffer->length - buffer->offset + offset;
}
if (offset < 0)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset(%ld) is out of bounds.", offset);
RETURN_FALSE;
}
offset += buffer->offset;
if ((str.length + offset) > buffer->size && (str.length + offset) > 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_write(buffer, offset, &str) == SW_OK)
{
if (buffer->size > size_old)
{
zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("capacity"), buffer->size TSRMLS_CC);
}
zend_update_property_long(swoole_buffer_class_entry_ptr, getThis(), ZEND_STRL("length"),
buffer->length - buffer->offset TSRMLS_CC);
RETURN_LONG(buffer->length - buffer->offset);
}
else
{
RETURN_FALSE;
}
}
int swString_write(swString *str, off_t offset, swString *write_str)
{
int new_length = offset + write_str->length;
if (new_length > str->size)
{
if (swString_extend(str, swoole_size_align(new_length * 2, sysconf(_SC_PAGESIZE))) < 0)
{
return SW_ERR;
}
}
memcpy(str->str + offset, write_str->str, write_str->length);
if (new_length > str->length)
{
str->length = new_length;
}
return SW_OK;
}