Skip to content

Instantly share code, notes, and snippets.

@divinity76
Last active January 26, 2021 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save divinity76/2138b2fc3319e84eb6819de0d4ade859 to your computer and use it in GitHub Desktop.
Save divinity76/2138b2fc3319e84eb6819de0d4ade859 to your computer and use it in GitHub Desktop.
fast uint8 buffer (faster than std::vector<uint8_t> )
#include <cstddef>
#include <cstring>
#include <new> // std::bad_alloc
#include <stdexcept> // std::out_of_range
// buffer which should be faster than std::vector<uint8_t> when resizing because
// it does not do byte initialization
class uint8_fast_buffer
{
public:
uint8_fast_buffer(const size_t initial_size)
{
if (initial_size == 0)
{
// .. i don't really like the idea of buf being nullptr, this avoids that issue.
this->internal_reserve(1);
}
else
{
this->internal_reserve(initial_size);
this->buf_size = initial_size;
}
}
~uint8_fast_buffer() noexcept
{
free(this->buf);
}
size_t size(void) noexcept
{
return this->buf_size;
}
void reserve(const size_t reserve_size)
{
if (reserve_size > this->buf_cap)
{
this->internal_reserve(reserve_size);
}
}
// this function is supposed to be very fast when newlen <= buf_cap
void resize(const size_t newlen)
{
if (__builtin_expect(newlen > this->buf_cap, 0))
{
this->internal_reserve(newlen);
}
this->buf_size = newlen;
}
void append(const uint8_t *data, const size_t len)
{
const size_t pos = this->size();
const size_t new_pos = pos + len;
this->resize(new_pos);
memcpy(&this->buf[pos], data, len);
}
// warning, slow operation...
void prepend_slow(const uint8_t *data, const size_t len)
{
const size_t original_size = this->size();
const size_t new_size = original_size + len;
this->resize(new_size);
memmove(&this->buf[len], this->buf, original_size);
memcpy(this->buf, data, len);
}
void clear(void) noexcept
{
this->buf_size = 0;
}
bool empty(void) noexcept
{
return (this->buf_size == 0);
}
uint8_t *data(void) noexcept
{
return this->buf;
}
uint8_t &at(const size_t pos)
{
if (__builtin_expect(pos >= this->size(), 0))
{
throw std::out_of_range(std::to_string(pos) + std::string(" >= ") + std::to_string(this->size()));
}
return this->buf[pos];
}
uint8_t &operator[](const size_t pos) noexcept
{
return this->buf[pos];
}
private:
void internal_reserve(const size_t reserve_size)
{
uint8_t *newbuf = (uint8_t *)realloc(this->buf, reserve_size);
if (__builtin_expect(newbuf == nullptr, 0))
{
throw std::bad_alloc();
}
this->buf_cap = reserve_size;
this->buf = newbuf;
}
size_t buf_size = 0;
size_t buf_cap = 0;
uint8_t *buf = nullptr;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment