Commit 0ca511a4 authored by Christopher Friedt's avatar Christopher Friedt
Browse files

sys: ring_buffer: ring_buf_peek() and ring_buf_size_get()



Add ring_buf_size_get() to get the number of bytes currently available
in the ring buffer.

Add ring_buf_peek() to read data from the head of a ring buffer without
removal.

Fixes #37145

Signed-off-by: default avatarChristopher Friedt <chrisfriedt@gmail.com>
parent 97adf875
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -215,6 +215,18 @@ static inline uint32_t ring_buf_capacity_get(struct ring_buf *buf)
	return buf->size;
}

/**
 * @brief Determine used space in a ring buffer.
 *
 * @param buf Address of ring buffer.
 *
 * @return Ring buffer space used (in 32-bit words or bytes).
 */
static inline uint32_t ring_buf_size_get(struct ring_buf *buf)
{
	return buf->tail - buf->head;
}

/**
 * @brief Write a data item to a ring buffer.
 *
@@ -406,6 +418,34 @@ int ring_buf_get_finish(struct ring_buf *buf, uint32_t size);
 */
uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size);

/**
 * @brief Peek at data from a ring buffer.
 *
 * This routine reads data from a ring buffer @a buf without removal.
 *
 * @warning
 * Use cases involving multiple reads of the ring buffer must prevent
 * concurrent read operations, either by preventing all readers from
 * being preempted or by using a mutex to govern reads to the ring buffer.
 *
 * @warning
 * Ring buffer instance should not mix byte access and  item mode
 * (calls prefixed with ring_buf_item_).
 *
 * @warning
 * Multiple calls to peek will result in the same data being 'peeked'
 * multiple times. To remove data, use either @ref ring_buf_get or
 * @ref ring_buf_get_claim followed by @ref ring_buf_get_finish with a
 * non-zero `size`.
 *
 * @param buf  Address of ring buffer.
 * @param data Address of the output buffer. Cannot be NULL.
 * @param size Data size (in bytes).
 *
 * @retval Number of bytes written to the output buffer.
 */
uint32_t ring_buf_peek(struct ring_buf *buf, uint8_t *data, uint32_t size);

/**
 * @}
 */
+25 −0
Original line number Diff line number Diff line
@@ -284,3 +284,28 @@ uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size)

	return total_size;
}

uint32_t ring_buf_peek(struct ring_buf *buf, uint8_t *data, uint32_t size)
{
	uint8_t *src;
	uint32_t partial_size;
	uint32_t total_size = 0U;
	int err;

	size = MIN(size, ring_buf_size_get(buf));

	do {
		partial_size = ring_buf_get_claim(buf, &src, size);
		__ASSERT_NO_MSG(data != NULL);
		memcpy(data, src, partial_size);
		data += partial_size;
		total_size += partial_size;
		size -= partial_size;
	} while (size && partial_size);

	/* effectively unclaim total_size bytes */
	err = ring_buf_get_finish(buf, 0);
	__ASSERT_NO_MSG(err == 0);

	return total_size;
}