Browse Source

Add a few ringbuffer peek methods

Signed-off-by: falkTX <falktx@falktx.com>
pull/456/head
falkTX 1 year ago
parent
commit
a05231b01d
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
1 changed files with 89 additions and 2 deletions
  1. +89
    -2
      distrho/extra/RingBuffer.hpp

+ 89
- 2
distrho/extra/RingBuffer.hpp View File

@@ -404,6 +404,36 @@ public:
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

@@ -601,7 +631,7 @@ protected:
}
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);
}
@@ -619,6 +649,63 @@ protected:
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
{
@@ -656,7 +743,7 @@ protected:
}
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);
}


Loading…
Cancel
Save