* 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:
@@ -17,11 +17,17 @@ struct ring_buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// flags for create_ring_buffer_etc()
|
||||||
|
#define RING_BUFFER_INIT_FROM_BUFFER 0x01
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ring_buffer *create_ring_buffer(size_t size);
|
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 delete_ring_buffer(struct ring_buffer *buffer);
|
||||||
|
|
||||||
void ring_buffer_clear(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);
|
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_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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* RING_BUFFER_H */
|
#endif /* RING_BUFFER_H */
|
||||||
|
|||||||
@@ -122,16 +122,39 @@ write_to_buffer(struct ring_buffer *buffer, const uint8 *data, ssize_t length,
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
struct ring_buffer *
|
struct ring_buffer*
|
||||||
create_ring_buffer(size_t size)
|
create_ring_buffer(size_t size)
|
||||||
{
|
{
|
||||||
struct ring_buffer *buffer = (ring_buffer *)malloc(sizeof(ring_buffer) + size);
|
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)
|
if (buffer == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buffer->size = size;
|
buffer->size = size;
|
||||||
ring_buffer_clear(buffer);
|
ring_buffer_clear(buffer);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size -= sizeof(ring_buffer);
|
||||||
|
ring_buffer* buffer = (ring_buffer*)memory;
|
||||||
|
|
||||||
|
buffer->size = size;
|
||||||
|
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;
|
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
|
#if 0
|
||||||
/** Sends the contents of the ring buffer to a port.
|
/** Sends the contents of the ring buffer to a port.
|
||||||
* The buffer will be empty afterwards only if sending the data actually works.
|
* The buffer will be empty afterwards only if sending the data actually works.
|
||||||
|
|||||||
Reference in New Issue
Block a user