#ifndef BPT_KEY2INDEX_HPP #define BPT_KEY2INDEX_HPP #include #include #include #include #include "drivearray.hpp" class String2Index { private: static const int kBucketSize = 262142; static const int kPageSize = 4096; struct Node { char str[66]; int val; Node() = default; Node(const std::string &_str, int _val) : val(_val) { assert(_str.length() <= 64); strcpy(str, _str.c_str()); } }; static const int kNodesPerBlock = (kPageSize - 3 * sizeof(int)) / sizeof(Node); struct Block { int tot, nxt_idx; Node data[kNodesPerBlock]; char padding[kPageSize - 3 * sizeof(int) - sizeof(Node) * (kNodesPerBlock)]; Block() : tot(0), nxt_idx(0) {} Block(int _tot, int _nxt_idx) : tot(_tot), nxt_idx(_nxt_idx) {} }; static_assert(kNodesPerBlock >= 1, "kNodesPerBlock error"); static_assert(sizeof(Block) == kPageSize - 4, "Block Size error"); DriveArray mem; int *hash_table = nullptr; std::string file_name; inline size_t Hash(std::string str) noexcept { const static std::string salt1 = "mL;]-=eT"; const static std::string salt2 = "9B= 1); } mem.read(*blk_ptr, idx); if (blk_ptr->tot == kNodesPerBlock) { Block __New_Head_Block(0, idx); idx = mem.write(__New_Head_Block); hash_table[hash_val % kBucketSize] = idx; mem.read(*blk_ptr, idx); } blk_ptr->data[blk_ptr->tot++] = Node(str, val); mem.update(*blk_ptr, idx); delete blk_ptr; } void Delete(const std::string &str, int val) noexcept { size_t hash_val = Hash(str); int idx = hash_table[hash_val % kBucketSize]; Block *blk_ptr = new Block; while (idx != 0) { mem.read(*blk_ptr, idx); for (int i = 0; i < blk_ptr->tot; ++i) { if (blk_ptr->data[i].str == str && blk_ptr->data[i].val == val) { int headidx = hash_table[hash_val % kBucketSize]; if (headidx == idx) { blk_ptr->data[i] = blk_ptr->data[--blk_ptr->tot]; mem.update(*blk_ptr, idx); } else { Block *head_blk_ptr = new Block; mem.read(*head_blk_ptr, headidx); blk_ptr->data[i] = head_blk_ptr->data[--head_blk_ptr->tot]; if (head_blk_ptr->tot == 0) { hash_table[hash_val % kBucketSize] = head_blk_ptr->nxt_idx; mem.Delete(headidx); } else mem.update(*head_blk_ptr, headidx); mem.update(*blk_ptr, idx); delete head_blk_ptr; } delete blk_ptr; return; } } idx = blk_ptr->nxt_idx; } delete blk_ptr; } std::vector Find(const std::string &str) noexcept { std::vector ret; size_t hash_val = Hash(str); int idx = hash_table[hash_val % kBucketSize]; Block *blk_ptr = new Block; while (idx != 0) { mem.read(*blk_ptr, idx); for (int i = 0; i < blk_ptr->tot; ++i) { if (blk_ptr->data[i].str == str) { ret.push_back(blk_ptr->data[i].val); } } idx = blk_ptr->nxt_idx; } delete blk_ptr; return std::move(ret); } }; #endif // BPT_KEY2INDEX_HPP