- A lotta cleanup - BEd command parser rewrite - Vase class removed - Proper IO system. - A lot more.
73 lines
2.0 KiB
C++
73 lines
2.0 KiB
C++
#include "internal/vase/vase.h"
|
|
|
|
namespace bed::internal::vase {
|
|
AppendStorage::AppendStorage(std::filesystem::path base_dir) {
|
|
base_dir /= "tapp.XXXXXX";
|
|
char *s = strdup(base_dir.c_str());
|
|
fd = mkstemp(s);
|
|
if (fd == -1)
|
|
throw std::runtime_error("mkstemp failed");
|
|
unlink(s);
|
|
free(s);
|
|
allocated_capacity = 1ull << 30;
|
|
if (ftruncate(fd, allocated_capacity) == -1)
|
|
throw std::runtime_error("ftruncate failed");
|
|
buf = (char *)mmap(nullptr, allocated_capacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
if (buf == MAP_FAILED)
|
|
throw std::runtime_error("mmap failed");
|
|
}
|
|
|
|
AppendStorage::~AppendStorage() {
|
|
if (buf && buf != MAP_FAILED)
|
|
munmap(buf, allocated_capacity);
|
|
if (fd != -1)
|
|
close(fd);
|
|
}
|
|
|
|
void AppendStorage::grow(uint64_t len) {
|
|
if (current_size + len > allocated_capacity) {
|
|
uint64_t new_capacity = allocated_capacity * 2;
|
|
if (new_capacity < current_size + len)
|
|
new_capacity = current_size + len + (1ull << 30);
|
|
if (ftruncate(fd, new_capacity) == -1)
|
|
throw std::runtime_error("ftruncate failed");
|
|
#if defined(__linux__)
|
|
void *new_buf = mremap(buf, allocated_capacity, new_capacity, MREMAP_MAYMOVE);
|
|
if (new_buf == MAP_FAILED)
|
|
throw std::runtime_error("mremap failed");
|
|
#else
|
|
munmap(buf, allocated_capacity);
|
|
void *new_buf = mmap(nullptr, new_capacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
if (new_buf == MAP_FAILED)
|
|
throw std::runtime_error("mmap failed");
|
|
#endif
|
|
allocated_capacity = new_capacity;
|
|
buf = (char *)new_buf;
|
|
}
|
|
}
|
|
|
|
uint64_t AppendStorage::append(const char c) {
|
|
grow(1);
|
|
buf[current_size++] = c;
|
|
return current_size - 1;
|
|
}
|
|
|
|
uint64_t AppendStorage::append(const char *text, uint64_t len) {
|
|
grow(len);
|
|
memcpy(buf + current_size, text, len);
|
|
uint64_t old_pos = current_size;
|
|
current_size += len;
|
|
return old_pos;
|
|
}
|
|
|
|
const char *AppendStorage::read(uint64_t pos) {
|
|
if (pos >= current_size)
|
|
return nullptr;
|
|
return buf + pos;
|
|
}
|
|
|
|
uint64_t AppendStorage::length() {
|
|
return current_size;
|
|
}
|
|
} // namespace bed::internal::vase
|