Skip to content

Commit

Permalink
Add a few ringbuffer peek methods
Browse files Browse the repository at this point in the history
Signed-off-by: falkTX <[email protected]>
  • Loading branch information
falkTX committed May 3, 2024
1 parent fac3172 commit a05231b
Showing 1 changed file with 89 additions and 2 deletions.
91 changes: 89 additions & 2 deletions distrho/extra/RingBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,36 @@ class RingBufferControl
return false;
}

// -------------------------------------------------------------------
// peek operations (returns a value without advancing read position)

/*
* Peek for an unsigned 32-bit integer.
* Returns 0 if reading fails.
*/
uint32_t peekUInt() const noexcept
{
uint32_t ui = 0;
return tryPeek(&ui, sizeof(int32_t)) ? ui : 0;
}

/*!
* Peek for a custom data type specified by the template typename used,
* with size being automatically deduced by the compiler (through the use of sizeof).
*
* Returns true if peeking succeeds.
* In case of failure, @a type value is automatically cleared by its deduced size.
*/
template <typename T>
bool peekCustomType(T& type) const noexcept
{
if (tryPeek(&type, sizeof(T)))
return true;

std::memset(&type, 0, sizeof(T));
return false;
}

// -------------------------------------------------------------------
// write operations

Expand Down Expand Up @@ -601,7 +631,7 @@ class RingBufferControl
}
else
{
const uint32_t firstpart(buffer->size - tail);
const uint32_t firstpart = buffer->size - tail;
std::memcpy(bytebuf, buffer->buf + tail, firstpart);
std::memcpy(bytebuf + firstpart, buffer->buf, readto);
}
Expand All @@ -619,6 +649,63 @@ class RingBufferControl
return true;
}

/** @internal try reading from the buffer, can fail. */
bool tryPeek(void* const buf, const uint32_t size) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(buffer != nullptr, false);
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#endif
DISTRHO_SAFE_ASSERT_RETURN(buffer->buf != nullptr, false);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
DISTRHO_SAFE_ASSERT_RETURN(buf != nullptr, false);
DISTRHO_SAFE_ASSERT_RETURN(size > 0, false);
DISTRHO_SAFE_ASSERT_RETURN(size < buffer->size, false);

// empty
if (buffer->head == buffer->tail)
return false;

uint8_t* const bytebuf = static_cast<uint8_t*>(buf);

const uint32_t head = buffer->head;
const uint32_t tail = buffer->tail;
const uint32_t wrap = head > tail ? 0 : buffer->size;

if (size > wrap + head - tail)
return false;

uint32_t readto = tail + size;

if (readto > buffer->size)
{
readto -= buffer->size;

if (size == 1)
{
std::memcpy(bytebuf, buffer->buf + tail, 1);
}
else
{
const uint32_t firstpart = buffer->size - tail;
std::memcpy(bytebuf, buffer->buf + tail, firstpart);
std::memcpy(bytebuf + firstpart, buffer->buf, readto);
}
}
else
{
std::memcpy(bytebuf, buffer->buf + tail, size);

if (readto == buffer->size)
readto = 0;
}

return true;
}

/** @internal try writing to the buffer, can fail. */
bool tryWrite(const void* const buf, const uint32_t size) noexcept
{
Expand Down Expand Up @@ -656,7 +743,7 @@ class RingBufferControl
}
else
{
const uint32_t firstpart(buffer->size - wrtn);
const uint32_t firstpart = buffer->size - wrtn;
std::memcpy(buffer->buf + wrtn, bytebuf, firstpart);
std::memcpy(buffer->buf, bytebuf + firstpart, writeto);
}
Expand Down

0 comments on commit a05231b

Please sign in to comment.