I wanted a buffer like std::vector<uint8_t> which is very fast at resizing, and it does not require byte initialization (it resizes to 16K, then to 2-4 bytes, then goes back to 16K, and repeat, a lot. std::vector zeroes all the bytes every time it grows back to 16K, I thought I could avoid the zeroing-overhead with a custom implementation)
I came up with this:
// buffer which should be faster than std::vector<uint8_t> when resizing a lot because it does not do byte initialization when resizing 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_size_real) { this->internal_reserve(reserve_size); } } // this function is supposed to be very fast when newlen is smaller than the biggest it has ever been before. void resize(const size_t newlen) { if(__builtin_expect(newlen > this->buf_size_real,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=this->size()+len; this->resize(new_pos); memcpy(&this->buf[pos],data,len); } void reset(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_size_real=reserve_size; this->buf=newbuf; } size_t buf_size=0; size_t buf_size_real=0; uint8_t *buf=nullptr; };