Files
SweepStore/cpp/binary_table.h

292 lines
9.0 KiB
C++
Raw Blame History

/*
/$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$$$ /$$ /$$ /$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$$
|_ $$_/| $$$ /$$$| $$__ $$| $$_____/| $$$ | $$ |__ $$|_ $$_/ | $$$ | $$| $$_____/|__ $$__/
| $$ | $$$$ /$$$$| $$ \ $$| $$ | $$$$| $$ | $$ | $$ | $$$$| $$| $$ | $$
| $$ | $$ $$/$$ $$| $$$$$$$ | $$$$$ | $$ $$ $$ | $$ | $$ | $$ $$ $$| $$$$$ | $$
| $$ | $$ $$$| $$| $$__ $$| $$__/ | $$ $$$$ /$$ | $$ | $$ | $$ $$$$| $$__/ | $$
| $$ | $$\ $ | $$| $$ \ $$| $$ | $$\ $$$| $$ | $$ | $$ | $$\ $$$| $$ | $$
/$$$$$$| $$ \/ | $$| $$$$$$$/| $$$$$$$$| $$ \ $$| $$$$$$/ /$$$$$$ /$$| $$ \ $$| $$$$$$$$ | $$
|______/|__/ |__/|_______/ |________/|__/ \__/ \______/ |______/|__/|__/ \__/|________/ |__/
<EFBFBD> 2025-26 by Benjamin Watt of IMBENJI.NET LIMITED - All rights reserved.
Use of this source code is governed by a MIT license that can be found in the LICENSE file.
This file is part of the SweepStore (formerly Binary Table) package for C++.
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <variant>
#include <memory>
#include <stdexcept>
#include <type_traits>
#include <functional>
namespace bt {
// Forward declarations
class BinaryTable;
class BT_Reference;
template<typename T> class BT_UniformArray;
// Type enumeration matching Dart version
enum class BT_Type : uint8_t {
POINTER = 0,
ADDRESS_TABLE = 1,
INTEGER = 2,
FLOAT = 3,
STRING = 4,
INTEGER_ARRAY = 5,
FLOAT_ARRAY = 6
};
// Size mapping for types
constexpr int getTypeSize(BT_Type type) {
switch (type) {
case BT_Type::POINTER: return 8;
case BT_Type::ADDRESS_TABLE: return -1;
case BT_Type::INTEGER: return 4;
case BT_Type::FLOAT: return 4;
case BT_Type::STRING: return -1;
case BT_Type::INTEGER_ARRAY: return -1;
case BT_Type::FLOAT_ARRAY: return -1;
}
return -1;
}
// Check if type is array type
constexpr bool isArrayType(BT_Type type) {
return type == BT_Type::INTEGER_ARRAY || type == BT_Type::FLOAT_ARRAY;
}
// Type deduction helpers
template<typename T>
constexpr BT_Type getTypeFromValue() {
if constexpr (std::is_same_v<T, int32_t> || std::is_same_v<T, int>) {
return BT_Type::INTEGER;
} else if constexpr (std::is_same_v<T, float>) {
return BT_Type::FLOAT;
} else if constexpr (std::is_same_v<T, std::string>) {
return BT_Type::STRING;
} else if constexpr (std::is_same_v<T, std::vector<int32_t>> || std::is_same_v<T, std::vector<int>>) {
return BT_Type::INTEGER_ARRAY;
} else if constexpr (std::is_same_v<T, std::vector<float>>) {
return BT_Type::FLOAT_ARRAY;
} else {
static_assert(sizeof(T) == 0, "Unsupported type");
}
}
// Pointer class
class BT_Pointer {
private:
int64_t address_;
public:
explicit BT_Pointer(int64_t address = -1) : address_(address) {}
bool isNull() const { return address_ == -1; }
int64_t address() const { return address_; }
bool operator==(const BT_Pointer& other) const {
return address_ == other.address_;
}
bool operator!=(const BT_Pointer& other) const {
return !(*this == other);
}
};
// Null pointer constant
const BT_Pointer BT_Null{-1};
// Free list entry
struct BT_FreeListEntry {
BT_Pointer pointer;
int32_t size;
BT_FreeListEntry(BT_Pointer ptr, int32_t sz) : pointer(ptr), size(sz) {}
};
// Value encoding functions
std::vector<uint8_t> encodeValue(const int32_t& value);
std::vector<uint8_t> encodeValue(const float& value);
std::vector<uint8_t> encodeValue(const std::string& value);
std::vector<uint8_t> encodeValue(const std::vector<int32_t>& value);
std::vector<uint8_t> encodeValue(const std::vector<float>& value);
// Template wrapper for encoding
template<typename T>
std::vector<uint8_t> encodeValue(const T& value) {
return encodeValue(value);
}
// Reference class for handling stored values
class BT_Reference {
protected:
BinaryTable* table_;
BT_Pointer pointer_;
public:
BT_Reference(BinaryTable* table, BT_Pointer pointer);
template<typename T>
T decodeValue();
int32_t size() const;
BT_Type getType() const;
bool isNull() const { return pointer_.isNull(); }
BT_Pointer getPointer() const { return pointer_; }
};
// Uniform array class template
template<typename T>
class BT_UniformArray : public BT_Reference {
public:
BT_UniformArray(BinaryTable* table, BT_Pointer pointer) : BT_Reference(table, pointer) {}
int32_t length() const;
T operator[](int32_t index) const;
void set(int32_t index, const T& value);
void add(const T& value);
void addAll(const std::vector<T>& values);
std::vector<T> fetchSublist(int32_t start = 0, int32_t end = -1);
};
// Main BinaryTable class
class BinaryTable {
private:
std::fstream file_;
std::string filePath_;
// Free list management
bool freeListLifted_;
std::vector<BT_FreeListEntry> freeListCache_;
// Internal methods
std::unordered_map<int64_t, BT_Pointer> getAddressTable();
void setAddressTable(const std::unordered_map<int64_t, BT_Pointer>& table);
std::vector<BT_FreeListEntry> getFreeList();
void setFreeList(const std::vector<BT_FreeListEntry>& list);
int64_t hashString(const std::string& str) const;
void truncateFile(int64_t newSize);
// File I/O helpers
int32_t readInt32(int64_t position);
float readFloat32(int64_t position);
int64_t readInt64(int64_t position);
uint8_t readByte(int64_t position);
std::vector<uint8_t> readBytes(int64_t position, int32_t count);
void writeInt32(int64_t position, int32_t value);
void writeFloat32(int64_t position, float value);
void writeInt64(int64_t position, int64_t value);
void writeByte(int64_t position, uint8_t value);
void writeBytes(int64_t position, const std::vector<uint8_t>& data);
public:
explicit BinaryTable(const std::string& path);
~BinaryTable();
void initialize();
// Memory management
void liftFreeList();
void dropFreeList();
void antiFreeListScope(std::function<void()> fn);
void free(BT_Pointer pointer, int32_t size);
BT_Pointer alloc(int32_t size);
// Data operations
template<typename T>
void set(const std::string& key, const T& value);
template<typename T>
T get(const std::string& key);
BT_Reference getReference(const std::string& key);
template<typename T>
BT_UniformArray<T> getArray(const std::string& key);
void remove(const std::string& key);
void truncate();
// Debug methods
void debugAddressTable(const std::string& context = "");
// File access for reference classes
friend class BT_Reference;
template<typename T> friend class BT_UniformArray;
int64_t getFileLength();
void setFilePosition(int64_t position);
};
// Template specializations for decodeValue
template<> int32_t BT_Reference::decodeValue<int32_t>();
template<> float BT_Reference::decodeValue<float>();
template<> std::string BT_Reference::decodeValue<std::string>();
template<> std::vector<int32_t> BT_Reference::decodeValue<std::vector<int32_t>>();
template<> std::vector<float> BT_Reference::decodeValue<std::vector<float>>();
template<> BT_UniformArray<int32_t> BT_Reference::decodeValue<BT_UniformArray<int32_t>>();
template<> BT_UniformArray<float> BT_Reference::decodeValue<BT_UniformArray<float>>();
// Template method implementations for BinaryTable
template<typename T>
void BinaryTable::set(const std::string& key, const T& value) {
antiFreeListScope([&]() {
auto addressTable = getAddressTable();
int64_t keyHash = hashString(key);
if (addressTable.find(keyHash) != addressTable.end()) {
throw std::runtime_error("Key already exists");
}
auto valueBuffer = encodeValue(value);
BT_Pointer valueAddress = alloc(static_cast<int32_t>(valueBuffer.size()));
writeBytes(valueAddress.address(), valueBuffer);
addressTable[keyHash] = valueAddress;
setAddressTable(addressTable);
});
}
template<typename T>
T BinaryTable::get(const std::string& key) {
auto addressTable = getAddressTable();
int64_t keyHash = hashString(key);
auto it = addressTable.find(keyHash);
if (it == addressTable.end()) {
throw std::runtime_error("Key does not exist");
}
BT_Reference valueRef(this, it->second);
return valueRef.decodeValue<T>();
}
template<typename T>
BT_UniformArray<T> BinaryTable::getArray(const std::string& key) {
auto addressTable = getAddressTable();
int64_t keyHash = hashString(key);
auto it = addressTable.find(keyHash);
if (it == addressTable.end()) {
throw std::runtime_error("Key does not exist");
}
return BT_UniformArray<T>(this, it->second);
}
} // namespace bt