2023-10-09 17:24:40 +00:00
|
|
|
//
|
|
|
|
// Created by kyle on 2023-10-09.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstring>
|
2023-10-10 02:59:21 +00:00
|
|
|
#include <ios>
|
2023-10-09 20:16:05 +00:00
|
|
|
#include <iostream>
|
2023-10-10 02:59:21 +00:00
|
|
|
#include <iomanip>
|
|
|
|
|
|
|
|
#include "Buffer.h"
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
namespace klib {
|
|
|
|
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
constexpr size_t defaultCapacity = 32;
|
|
|
|
constexpr size_t maxReasonableLine = 8192;
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
nearestPower(size_t x)
|
|
|
|
{
|
|
|
|
if (x == 0) {
|
|
|
|
return 0;
|
2023-10-09 22:23:23 +00:00
|
|
|
}
|
2023-10-09 20:16:05 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
std::cout << "x -> ";
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
x--;
|
|
|
|
|
|
|
|
x |= x >> 1;
|
|
|
|
x |= x >> 2;
|
|
|
|
x |= x >> 4;
|
|
|
|
x |= x >> 8;
|
|
|
|
x |= x >> 16;
|
|
|
|
x |= x >> 32;
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
std::cout << x + 1 << std::endl;
|
2023-10-09 20:16:05 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
return x + 1;
|
2023-10-09 17:24:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer::Buffer()
|
|
|
|
: contents(nullptr), length(0), capacity(0)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
this->Resize(defaultCapacity);
|
2023-10-09 17:24:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer::Buffer(size_t initialCapacity)
|
|
|
|
: contents(nullptr), length(0), capacity(0)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
this->Resize(initialCapacity);
|
2023-10-09 17:24:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Buffer::Buffer(const char *data)
|
|
|
|
: contents(nullptr), length(0), capacity(0)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
size_t datalen = strnlen(data, maxReasonableLine);
|
2023-10-09 17:24:40 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
this->Append((uint8_t *) data, datalen);
|
2023-10-09 17:24:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 19:45:19 +00:00
|
|
|
bool
|
|
|
|
Buffer::Append(const char *s)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
size_t slen = strnlen(s, maxReasonableLine);
|
2023-10-09 19:45:19 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
return this->Append((uint8_t *) s, slen);
|
2023-10-09 19:45:19 +00:00
|
|
|
}
|
|
|
|
|
2023-10-09 17:24:40 +00:00
|
|
|
bool
|
|
|
|
Buffer::Append(uint8_t *data, size_t datalen)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
auto resized = false;
|
|
|
|
auto newCap = this->mustGrow(datalen);
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
if (newCap > 0) {
|
|
|
|
this->Resize(newCap);
|
|
|
|
resized = true;
|
|
|
|
}
|
|
|
|
|
2023-10-09 22:23:23 +00:00
|
|
|
assert(this->contents != nullptr);
|
2023-10-09 17:24:40 +00:00
|
|
|
memcpy(this->contents + this->length, data, datalen);
|
|
|
|
this->length += datalen;
|
|
|
|
return resized;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Buffer::Append(uint8_t c)
|
|
|
|
{
|
|
|
|
return this->Append(&c, 1);
|
|
|
|
}
|
|
|
|
|
2023-10-09 19:45:19 +00:00
|
|
|
|
|
|
|
bool
|
|
|
|
Buffer::Insert(size_t index, const char *s)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
size_t slen = strnlen(s, maxReasonableLine);
|
2023-10-09 19:45:19 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
return this->Insert(index, (uint8_t *) (s), slen);
|
2023-10-09 19:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 17:24:40 +00:00
|
|
|
bool
|
|
|
|
Buffer::Insert(size_t index, uint8_t *data, size_t datalen)
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
auto resized = this->shiftRight(index, datalen);
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
memcpy(this->contents + index, data, datalen);
|
2023-10-09 19:45:19 +00:00
|
|
|
this->length += datalen;
|
2023-10-09 17:24:40 +00:00
|
|
|
return resized;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Buffer::Insert(size_t index, uint8_t c)
|
|
|
|
{
|
|
|
|
return this->Insert(index, &c, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 19:45:19 +00:00
|
|
|
bool
|
|
|
|
Buffer::Remove(size_t index, size_t count)
|
|
|
|
{
|
|
|
|
auto resized = this->shiftLeft(index, count);
|
|
|
|
|
|
|
|
this->length -= count;
|
|
|
|
return resized;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
Buffer::Remove(size_t index)
|
|
|
|
{
|
|
|
|
return this->Remove(index, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 17:24:40 +00:00
|
|
|
void
|
|
|
|
Buffer::Resize(size_t newCapacity)
|
|
|
|
{
|
|
|
|
if (newCapacity < this->length) {
|
2023-10-10 02:59:21 +00:00
|
|
|
newCapacity = nearestPower(this->length + newCapacity);
|
2023-10-09 17:24:40 +00:00
|
|
|
}
|
|
|
|
|
2023-10-09 22:23:23 +00:00
|
|
|
auto newContents = new uint8_t[newCapacity];
|
2023-10-09 17:24:40 +00:00
|
|
|
|
2023-10-09 19:45:19 +00:00
|
|
|
memset(newContents, 0, newCapacity);
|
2023-10-09 17:24:40 +00:00
|
|
|
if (this->length > 0) {
|
|
|
|
memcpy(newContents, this->contents, this->length);
|
|
|
|
}
|
|
|
|
|
2023-10-09 22:23:23 +00:00
|
|
|
delete this->contents;
|
2023-10-10 02:59:21 +00:00
|
|
|
this->contents = nullptr;
|
2023-10-09 17:24:40 +00:00
|
|
|
this->contents = newContents;
|
|
|
|
this->capacity = newCapacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
Buffer::Trim()
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
size_t projectedCapacity = nearestPower(this->length);
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
assert(projectedCapacity >= length);
|
|
|
|
|
|
|
|
if (projectedCapacity < this->capacity) {
|
|
|
|
this->Resize(projectedCapacity);
|
|
|
|
return this->Capacity();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Buffer::Clear()
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
if (this->length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2023-10-09 17:24:40 +00:00
|
|
|
memset(this->contents, 0, this->length);
|
|
|
|
this->length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Buffer::Reclaim()
|
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
std::cout << "clear" << std::endl;
|
2023-10-09 19:45:19 +00:00
|
|
|
this->Clear();
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
std::cout << "nullptr check" << std::endl;
|
|
|
|
if (this->contents == nullptr) {
|
|
|
|
std::cout << "assert checks" << std::endl;
|
|
|
|
assert(this->length == 0);
|
|
|
|
assert(this->capacity == 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "delete " << this->Capacity() << "B" << std::endl;
|
|
|
|
this->HexDump(std::cout);
|
2023-10-09 17:24:40 +00:00
|
|
|
delete this->contents;
|
2023-10-10 02:59:21 +00:00
|
|
|
std::cout << "reset contents" << std::endl;
|
|
|
|
this->contents = nullptr;
|
|
|
|
std::cout << "reset capacity" << std::endl;
|
2023-10-09 17:24:40 +00:00
|
|
|
this->capacity = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
2023-10-09 22:23:23 +00:00
|
|
|
Buffer::mustGrow(size_t delta) const
|
2023-10-09 17:24:40 +00:00
|
|
|
{
|
|
|
|
if ((delta + this->length) < this->capacity) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto newCapacity = delta + this->length;
|
|
|
|
return nearestPower(newCapacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
void
|
|
|
|
Buffer::HexDump(std::ostream &os)
|
|
|
|
{
|
|
|
|
#ifndef NDEBUG
|
|
|
|
size_t index = 0;
|
|
|
|
|
|
|
|
os << std::hex;
|
|
|
|
os << std::setfill('0');
|
|
|
|
|
|
|
|
for (index = 0; index < this->length; index++) {
|
|
|
|
bool eol = (index % 16) == 0;
|
|
|
|
if (eol && (index > 0)) {
|
|
|
|
os << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eol) {
|
|
|
|
os << std::setw(8);
|
|
|
|
os << index << " ";
|
|
|
|
os << std::setw(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
os << (unsigned short)this->contents[index];
|
|
|
|
|
|
|
|
if ((index % 15) != 0 || (index == 0)) {
|
|
|
|
os << " ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((index % 16) != 0) {
|
|
|
|
os << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
os << std::setw(0) << std::dec;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-10-09 17:24:40 +00:00
|
|
|
bool
|
2023-10-09 19:45:19 +00:00
|
|
|
Buffer::shiftRight(size_t offset, size_t delta)
|
2023-10-09 17:24:40 +00:00
|
|
|
{
|
2023-10-10 02:59:21 +00:00
|
|
|
auto resized = false;
|
|
|
|
auto newCap = this->mustGrow(delta);
|
2023-10-09 17:24:40 +00:00
|
|
|
|
|
|
|
if (newCap > 0) {
|
|
|
|
this->Resize(newCap);
|
|
|
|
resized = true;
|
|
|
|
}
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
if (this->length == 0) return 0;
|
2023-10-09 17:24:40 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
memmove(this->contents + (offset + delta), this->contents + offset, this->length);
|
2023-10-09 17:24:40 +00:00
|
|
|
return resized;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 19:45:19 +00:00
|
|
|
bool
|
|
|
|
Buffer::shiftLeft(size_t offset, size_t delta)
|
|
|
|
{
|
2023-10-09 20:16:05 +00:00
|
|
|
// for (size_t i = offset; i < this->length; i++) {
|
|
|
|
// this->contents[i] = this->contents[i+delta];
|
|
|
|
// }
|
2023-10-09 19:45:19 +00:00
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
memmove(this->contents + offset, this->contents + (offset + delta), this->length);
|
2023-10-09 19:45:19 +00:00
|
|
|
|
|
|
|
return this->Trim() != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-10 02:59:21 +00:00
|
|
|
uint8_t &
|
2023-10-09 19:45:19 +00:00
|
|
|
Buffer::operator[](size_t index)
|
|
|
|
{
|
|
|
|
return this->contents[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-10-09 17:24:40 +00:00
|
|
|
} // namespace klib
|