DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit a05231b01dd2376f9cf80019e4e6c00e716647e1
parent fac31729ed450a7c530e83e0feecf46d6562b5fd
Author: falkTX <falktx@falktx.com>
Date:   Fri,  3 May 2024 21:37:13 +0200

Add a few ringbuffer peek methods

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Mdistrho/extra/RingBuffer.hpp | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/distrho/extra/RingBuffer.hpp b/distrho/extra/RingBuffer.hpp @@ -405,6 +405,36 @@ public: } // ------------------------------------------------------------------- + // 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); }