Last active
January 26, 2021 03:16
-
-
Save divinity76/2138b2fc3319e84eb6819de0d4ade859 to your computer and use it in GitHub Desktop.
fast uint8 buffer (faster than std::vector<uint8_t> )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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