Move Buffer from kge.
This commit is contained in:
parent
36af6ac1f8
commit
1bc5bc0b10
|
@ -0,0 +1,180 @@
|
|||
//
|
||||
// Created by kyle on 2023-10-09.
|
||||
//
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "Buffer.h"
|
||||
|
||||
namespace klib {
|
||||
|
||||
|
||||
constexpr size_t defaultCapacity = 32;
|
||||
constexpr size_t maxReasonableLine = 8192;
|
||||
|
||||
|
||||
static size_t
|
||||
nearestPower(size_t x)
|
||||
{
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
x--;
|
||||
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x |= x >> 32;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
Buffer::Buffer()
|
||||
: contents(nullptr), length(0), capacity(0)
|
||||
{
|
||||
this->Resize(defaultCapacity);
|
||||
}
|
||||
|
||||
|
||||
Buffer::Buffer(size_t initialCapacity)
|
||||
: contents(nullptr), length(0), capacity(0)
|
||||
{
|
||||
this->Resize(initialCapacity);
|
||||
}
|
||||
|
||||
|
||||
Buffer::Buffer(const char *data)
|
||||
: contents(nullptr), length(0), capacity(0)
|
||||
{
|
||||
size_t datalen = strnlen(data, maxReasonableLine);
|
||||
|
||||
this->Append((uint8_t *)data, datalen);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Buffer::Append(uint8_t *data, size_t datalen)
|
||||
{
|
||||
auto resized = false;
|
||||
auto newCap = this->mustGrow(datalen);
|
||||
|
||||
if (newCap > 0) {
|
||||
this->Resize(newCap);
|
||||
resized = true;
|
||||
}
|
||||
|
||||
memcpy(this->contents + this->length, data, datalen);
|
||||
this->length += datalen;
|
||||
return resized;
|
||||
}
|
||||
|
||||
bool
|
||||
Buffer::Append(uint8_t c)
|
||||
{
|
||||
return this->Append(&c, 1);
|
||||
}
|
||||
|
||||
bool
|
||||
Buffer::Insert(size_t index, uint8_t *data, size_t datalen)
|
||||
{
|
||||
auto resized = this->shift(index, datalen);
|
||||
|
||||
memcpy(this->contents + index, data, datalen);
|
||||
return resized;
|
||||
}
|
||||
|
||||
bool
|
||||
Buffer::Insert(size_t index, uint8_t c)
|
||||
{
|
||||
return this->Insert(index, &c, 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Buffer::Resize(size_t newCapacity)
|
||||
{
|
||||
if (newCapacity < this->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *newContents = new uint8_t[newCapacity];
|
||||
|
||||
if (this->length > 0) {
|
||||
memcpy(newContents, this->contents, this->length);
|
||||
}
|
||||
|
||||
if (this->contents != nullptr) {
|
||||
delete this->contents;
|
||||
}
|
||||
|
||||
this->contents = newContents;
|
||||
this->capacity = newCapacity;
|
||||
}
|
||||
|
||||
size_t
|
||||
Buffer::Trim()
|
||||
{
|
||||
size_t projectedCapacity = nearestPower(this->length);
|
||||
|
||||
assert(projectedCapacity >= length);
|
||||
|
||||
if (projectedCapacity < this->capacity) {
|
||||
this->Resize(projectedCapacity);
|
||||
return this->Capacity();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::Clear()
|
||||
{
|
||||
memset(this->contents, 0, this->length);
|
||||
this->length = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::Reclaim()
|
||||
{
|
||||
delete this->contents;
|
||||
this->length = 0;
|
||||
this->capacity = 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
Buffer::mustGrow(size_t delta)
|
||||
{
|
||||
if ((delta + this->length) < this->capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto newCapacity = delta + this->length;
|
||||
return nearestPower(newCapacity);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Buffer::shift(size_t offset, size_t delta)
|
||||
{
|
||||
auto resized = false;
|
||||
auto newCap = this->mustGrow(delta);
|
||||
|
||||
if (newCap > 0) {
|
||||
this->Resize(newCap);
|
||||
resized = true;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = this->length; i >= offset; i++) {
|
||||
this->contents[i+delta] = this->contents[i];
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
|
||||
|
||||
} // namespace klib
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by kyle on 2023-10-09.
|
||||
//
|
||||
|
||||
#ifndef KGE_BUFFER_H
|
||||
#define KGE_BUFFER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace klib {
|
||||
|
||||
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer();
|
||||
Buffer(size_t);
|
||||
Buffer(const char *);
|
||||
|
||||
uint8_t *Contents() { return this->contents; }
|
||||
size_t Size() { return this->length; };
|
||||
size_t Capacity() { return this->capacity; }
|
||||
|
||||
bool Append(uint8_t *data, size_t datalen);
|
||||
bool Append(uint8_t c);
|
||||
bool Insert(size_t index, uint8_t *data, size_t datalen);
|
||||
bool Insert(size_t index, uint8_t c);
|
||||
|
||||
// bool Remove(size_t index, size_t length);
|
||||
|
||||
/* memory management */
|
||||
void Resize(size_t newCapacity);
|
||||
size_t Trim();
|
||||
void Clear();
|
||||
void Reclaim();
|
||||
|
||||
private:
|
||||
size_t mustGrow(size_t delta);
|
||||
bool shift(size_t offset, size_t delta);
|
||||
|
||||
uint8_t *contents;
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
} // namespace klib
|
||||
|
||||
#endif //KGE_BUFFER_H
|
|
@ -16,6 +16,7 @@ add_compile_options("-DDESKTOP_BUILD")
|
|||
|
||||
add_library(klib STATIC
|
||||
Arena.cc
|
||||
Buffer.cc
|
||||
TLV.cc
|
||||
Dictionary.cc)
|
||||
|
||||
|
@ -25,3 +26,6 @@ target_link_libraries(tlv_test klib)
|
|||
add_executable(dictionary_test dictionaryTest.cc)
|
||||
target_link_libraries(dictionary_test klib)
|
||||
|
||||
add_executable(buffer_test bufferTest.cc)
|
||||
target_link_libraries(buffer_test klib)
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "Buffer.h"
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
klib::Buffer buffer("hlo, world");
|
||||
|
||||
std::cout << buffer.Contents() << std::endl;
|
||||
|
||||
buffer.Insert(1, (uint8_t *)"el", 2);
|
||||
|
||||
std::cout << buffer.Contents() << std::endl;
|
||||
}
|
Loading…
Reference in New Issue