* Added create_ring_buffer_etc() which allows to re-create a ring buffer from

a given flat buffer.
* Added ring_buffer_peek() for random position reading from the ring buffer
  without changing its state.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35813 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-03-11 17:12:21 +00:00
parent dd5f340aea
commit 546f4e5e05
2 changed files with 76 additions and 5 deletions

View File

@ -17,11 +17,17 @@ struct ring_buffer {
};
// flags for create_ring_buffer_etc()
#define RING_BUFFER_INIT_FROM_BUFFER 0x01
#ifdef __cplusplus
extern "C" {
#endif
struct ring_buffer *create_ring_buffer(size_t size);
struct ring_buffer *create_ring_buffer_etc(void *memory, size_t size,
uint32 flags);
void delete_ring_buffer(struct ring_buffer *buffer);
void ring_buffer_clear(struct ring_buffer *buffer);
@ -32,9 +38,12 @@ size_t ring_buffer_read(struct ring_buffer *buffer, uint8 *data, ssize_t length)
size_t ring_buffer_write(struct ring_buffer *buffer, const uint8 *data, ssize_t length);
ssize_t ring_buffer_user_read(struct ring_buffer *buffer, uint8 *data, ssize_t length);
ssize_t ring_buffer_user_write(struct ring_buffer *buffer, const uint8 *data, ssize_t length);
size_t ring_buffer_peek(struct ring_buffer *buffer, size_t offset, void *data,
size_t length);
#ifdef __cplusplus
}
#endif
#endif /* RING_BUFFER_H */

View File

@ -122,15 +122,38 @@ write_to_buffer(struct ring_buffer *buffer, const uint8 *data, ssize_t length,
// #pragma mark -
struct ring_buffer *
struct ring_buffer*
create_ring_buffer(size_t size)
{
struct ring_buffer *buffer = (ring_buffer *)malloc(sizeof(ring_buffer) + size);
if (buffer == NULL)
return NULL;
return create_ring_buffer_etc(NULL, size, 0);
}
struct ring_buffer*
create_ring_buffer_etc(void* memory, size_t size, uint32 flags)
{
if (memory == NULL) {
ring_buffer* buffer = (ring_buffer*)malloc(sizeof(ring_buffer) + size);
if (buffer == NULL)
return NULL;
buffer->size = size;
ring_buffer_clear(buffer);
return buffer;
}
size -= sizeof(ring_buffer);
ring_buffer* buffer = (ring_buffer*)memory;
buffer->size = size;
ring_buffer_clear(buffer);
if ((flags & RING_BUFFER_INIT_FROM_BUFFER) != 0
&& (size_t)buffer->size == size
&& buffer->in >= 0 && (size_t)buffer->in <= size
&& buffer->first >= 0 && (size_t)buffer->first < size) {
// structure looks valid
} else
ring_buffer_clear(buffer);
return buffer;
}
@ -205,6 +228,45 @@ ring_buffer_user_write(struct ring_buffer *buffer, const uint8 *data, ssize_t le
}
/*! Reads data from the ring buffer, but doesn't remove the data from it.
\param buffer The ring buffer.
\param offset The offset relative to the beginning of the data in the ring
buffer at which to start reading.
\param data The buffer to which to copy the data.
\param length The number of bytes to read at maximum.
\return The number of bytes actually read from the buffer.
*/
size_t
ring_buffer_peek(struct ring_buffer* buffer, size_t offset, void* data,
size_t length)
{
size_t available = buffer->in;
if (offset >= available || length == 0)
return 0;
if (offset + length > available)
length = available - offset;
if ((offset += buffer->first) >= (size_t)buffer->size)
offset -= buffer->size;
if (offset + length <= (size_t)buffer->size) {
// simple copy
memcpy(data, buffer->buffer + offset, length);
} else {
// need to copy both ends
size_t upper = buffer->size - offset;
size_t lower = length - upper;
memcpy(data, buffer->buffer + offset, upper);
memcpy((uint8*)data + upper, buffer->buffer, lower);
}
return length;
}
#if 0
/** Sends the contents of the ring buffer to a port.
* The buffer will be empty afterwards only if sending the data actually works.