* Applied a patch by Lukasz that already collected dust on my HD - sorry
Lukasz! * It makes split_buffer() more efficient by avoiding making a copy of the original buffer. * Minor cleanup, and coding style changes by myself. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31007 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -956,6 +956,51 @@ get_node_at_offset(net_buffer_private *buffer, size_t offset)
|
||||
}
|
||||
|
||||
|
||||
/*! Appends up to \a size bytes from the data of the \a from net_buffer to the
|
||||
\a to net_buffer. The source buffer will remain unchanged.
|
||||
*/
|
||||
static status_t
|
||||
append_data_from_buffer(net_buffer *to, const net_buffer *from, size_t size)
|
||||
{
|
||||
net_buffer_private *source = (net_buffer_private *)from;
|
||||
net_buffer_private *dest = (net_buffer_private *)to;
|
||||
|
||||
if (size > from->size)
|
||||
return B_BAD_VALUE;
|
||||
if (size == 0)
|
||||
return B_OK;
|
||||
|
||||
data_node *nodeTo = get_node_at_offset(source, size);
|
||||
if (nodeTo == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
data_node *node = (data_node *)list_get_first_item(&source->buffers);
|
||||
if (node == NULL) {
|
||||
CHECK_BUFFER(source);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
while (node != nodeTo) {
|
||||
if (append_data(dest, node->start, node->used) < B_OK) {
|
||||
CHECK_BUFFER(dest);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
node = (data_node *)list_get_next_item(&source->buffers, node);
|
||||
}
|
||||
|
||||
int32 diff = node->offset + node->used - size;
|
||||
if (append_data(dest, node->start, node->used - diff) < B_OK) {
|
||||
CHECK_BUFFER(dest);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
CHECK_BUFFER(dest);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
copy_metadata(net_buffer *destination, const net_buffer *source)
|
||||
{
|
||||
@@ -1213,27 +1258,23 @@ clone_buffer(net_buffer *_buffer, bool shareFreeSpace)
|
||||
/*!
|
||||
Split the buffer at offset, the header data
|
||||
is returned as new buffer.
|
||||
TODO: optimize and avoid making a copy.
|
||||
*/
|
||||
static net_buffer *
|
||||
split_buffer(net_buffer *from, uint32 offset)
|
||||
{
|
||||
// TODO: Copying the whole buffer becomes less and less efficient with
|
||||
// greater size - offset differences. What we actually want is a method
|
||||
// to copy data from one buffer to another. Then the following should be:
|
||||
// create buffer, resize, copy data. An additional append_data_from_buffer()
|
||||
// method would be even better.
|
||||
net_buffer *buffer = duplicate_buffer(from);
|
||||
net_buffer *buffer = create_buffer(DATA_NODE_SIZE);
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
copy_metadata(buffer, from);
|
||||
|
||||
ParanoiaChecker _(from);
|
||||
ParanoiaChecker _2(buffer);
|
||||
|
||||
TRACE(("%ld: split_buffer(buffer %p -> %p, offset %ld)\n",
|
||||
find_thread(NULL), from, buffer, offset));
|
||||
|
||||
if (trim_data(buffer, offset) == B_OK) {
|
||||
if (append_data_from_buffer(buffer, from, offset) == B_OK) {
|
||||
if (remove_header(from, offset) == B_OK) {
|
||||
CHECK_BUFFER(from);
|
||||
CHECK_BUFFER(buffer);
|
||||
|
||||
Reference in New Issue
Block a user