/* /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$$$ /$$ /$$ /$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$$ |_ $$_/| $$$ /$$$| $$__ $$| $$_____/| $$$ | $$ |__ $$|_ $$_/ | $$$ | $$| $$_____/|__ $$__/ | $$ | $$$$ /$$$$| $$ \ $$| $$ | $$$$| $$ | $$ | $$ | $$$$| $$| $$ | $$ | $$ | $$ $$/$$ $$| $$$$$$$ | $$$$$ | $$ $$ $$ | $$ | $$ | $$ $$ $$| $$$$$ | $$ | $$ | $$ $$$| $$| $$__ $$| $$__/ | $$ $$$$ /$$ | $$ | $$ | $$ $$$$| $$__/ | $$ | $$ | $$\ $ | $$| $$ \ $$| $$ | $$\ $$$| $$ | $$ | $$ | $$\ $$$| $$ | $$ /$$$$$$| $$ \/ | $$| $$$$$$$/| $$$$$$$$| $$ \ $$| $$$$$$/ /$$$$$$ /$$| $$ \ $$| $$$$$$$$ | $$ |______/|__/ |__/|_______/ |________/|__/ \__/ \______/ |______/|__/|__/ \__/|________/ |__/ � 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 #include #include #include #include #include #include #include #include #include namespace bt { // Forward declarations class BinaryTable; class BT_Reference; template 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 constexpr BT_Type getTypeFromValue() { if constexpr (std::is_same_v || std::is_same_v) { return BT_Type::INTEGER; } else if constexpr (std::is_same_v) { return BT_Type::FLOAT; } else if constexpr (std::is_same_v) { return BT_Type::STRING; } else if constexpr (std::is_same_v> || std::is_same_v>) { return BT_Type::INTEGER_ARRAY; } else if constexpr (std::is_same_v>) { 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 encodeValue(const int32_t& value); std::vector encodeValue(const float& value); std::vector encodeValue(const std::string& value); std::vector encodeValue(const std::vector& value); std::vector encodeValue(const std::vector& value); // Template wrapper for encoding template std::vector 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 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 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& values); std::vector 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 freeListCache_; // Internal methods std::unordered_map getAddressTable(); void setAddressTable(const std::unordered_map& table); std::vector getFreeList(); void setFreeList(const std::vector& 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 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& data); public: explicit BinaryTable(const std::string& path); ~BinaryTable(); void initialize(); // Memory management void liftFreeList(); void dropFreeList(); void antiFreeListScope(std::function fn); void free(BT_Pointer pointer, int32_t size); BT_Pointer alloc(int32_t size); // Data operations template void set(const std::string& key, const T& value); template T get(const std::string& key); BT_Reference getReference(const std::string& key); template BT_UniformArray 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 friend class BT_UniformArray; int64_t getFileLength(); void setFilePosition(int64_t position); }; // Template specializations for decodeValue template<> int32_t BT_Reference::decodeValue(); template<> float BT_Reference::decodeValue(); template<> std::string BT_Reference::decodeValue(); template<> std::vector BT_Reference::decodeValue>(); template<> std::vector BT_Reference::decodeValue>(); template<> BT_UniformArray BT_Reference::decodeValue>(); template<> BT_UniformArray BT_Reference::decodeValue>(); // Template method implementations for BinaryTable template 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(valueBuffer.size())); writeBytes(valueAddress.address(), valueBuffer); addressTable[keyHash] = valueAddress; setAddressTable(addressTable); }); } template 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(); } template BT_UniformArray 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(this, it->second); } } // namespace bt