2017-10-21 06:11:49 +01:00
|
|
|
#include "isobufferbuffer.h"
|
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
/* isoBufferBuffer is implemented as two consecutive, duplicate,
|
|
|
|
* ring buffers. the effect of this is that we are able to hand
|
|
|
|
* out pointers to pieces of contiguous memory representing the
|
|
|
|
* last N inserted elements (for some N <= capacity()) even
|
|
|
|
* when we looped back to the begining of the ring buffer less
|
|
|
|
* than N insertions ago
|
|
|
|
*
|
|
|
|
* There are some differences with the original implementation
|
|
|
|
* functionality-wise.
|
|
|
|
* Where the original implementation allowed queries half as
|
|
|
|
* long as the length passed in, and allocated a buffer 1.5 times
|
|
|
|
* the length passed in, this version allows queries of length up
|
|
|
|
* to the length passed into the constructor and allocates a
|
|
|
|
* buffer 2 times the length passed in.
|
|
|
|
* Overall, this means that in contrast to the original
|
|
|
|
* implementation which only allowed queries up to a third as
|
|
|
|
* long as the allocated buffer, we can now do queries as long as
|
|
|
|
* half of the allocated buffer, which is a notable improvement.
|
|
|
|
*/
|
|
|
|
|
2018-11-05 23:15:48 +00:00
|
|
|
isoBufferBuffer::isoBufferBuffer(uint32_t length)
|
2018-12-27 22:51:10 +00:00
|
|
|
: m_data(std::make_unique<char[]>(length*2))
|
|
|
|
, m_capacity(length)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adds a character to the end of the buffer
|
|
|
|
void isoBufferBuffer::insert(char c)
|
|
|
|
{
|
2019-03-09 22:13:46 +00:00
|
|
|
char* dataPtr = m_data.get();
|
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
// Add character to first half of the buffer
|
2019-03-09 22:13:46 +00:00
|
|
|
dataPtr[m_top] = c;
|
2018-12-27 22:51:10 +00:00
|
|
|
// Then to the second
|
2019-03-09 22:13:46 +00:00
|
|
|
dataPtr[m_top+m_capacity] = c;
|
2018-12-27 22:51:10 +00:00
|
|
|
|
|
|
|
// Loop the buffer index if necessary and update size accordingly
|
|
|
|
m_top = (m_top + 1) % m_capacity;
|
|
|
|
m_size = std::min(m_size + 1, m_capacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
void isoBufferBuffer::insert(char const * s)
|
|
|
|
{
|
|
|
|
while (*s != '\0')
|
|
|
|
insert(*s++);
|
|
|
|
}
|
|
|
|
|
|
|
|
void isoBufferBuffer::insert(std::string const & s)
|
|
|
|
{
|
|
|
|
for (char c : s)
|
|
|
|
insert(c);
|
|
|
|
}
|
|
|
|
|
2018-12-30 23:02:04 +00:00
|
|
|
void isoBufferBuffer::insert_hex(uint8_t x)
|
|
|
|
{
|
|
|
|
char str[5];
|
|
|
|
sprintf(str, "0x%02hhx", x);
|
|
|
|
insert((char const *)str);
|
|
|
|
}
|
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
char const* isoBufferBuffer::query(uint32_t count) const
|
2017-10-21 06:11:49 +01:00
|
|
|
{
|
2018-12-27 22:51:10 +00:00
|
|
|
if (count > m_capacity)
|
|
|
|
qFatal("isoBufferBuffer::query : you may not request more items than the capacity of the buffer");
|
|
|
|
|
|
|
|
if (count > m_size)
|
|
|
|
qFatal("isoBufferBuffer::query : you may not request more items than inserted");
|
|
|
|
|
|
|
|
return end() - count;
|
2017-10-21 06:11:49 +01:00
|
|
|
}
|
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
void isoBufferBuffer::clear()
|
2018-11-05 23:15:48 +00:00
|
|
|
{
|
2018-12-27 22:51:10 +00:00
|
|
|
m_top = 0;
|
|
|
|
m_size = 0;
|
2018-11-05 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
char const * isoBufferBuffer::begin() const
|
|
|
|
{
|
|
|
|
return m_data.get() + m_top - m_size + m_capacity;
|
|
|
|
}
|
2018-11-05 23:15:48 +00:00
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
char const * isoBufferBuffer::end() const
|
|
|
|
{
|
|
|
|
return m_data.get() + m_top + m_capacity;
|
|
|
|
}
|
2018-11-05 23:15:48 +00:00
|
|
|
|
2018-12-27 22:51:10 +00:00
|
|
|
uint32_t isoBufferBuffer::size() const
|
|
|
|
{
|
|
|
|
return m_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t isoBufferBuffer::capacity() const
|
|
|
|
{
|
|
|
|
return m_capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|