Formatting code
This commit is contained in:
parent
6dc64ce76b
commit
13a8f07e32
37 changed files with 2242 additions and 2281 deletions
|
|
@ -11,12 +11,7 @@ namespace tp {
|
|||
return hash(key);
|
||||
}
|
||||
|
||||
template<
|
||||
typename tKey, typename tVal,
|
||||
class tAllocator = DefaultAllocator,
|
||||
ualni(*tHashFunc)(SelCopyArg<tKey>) = DefaultHashFunc<tKey>,
|
||||
int tTableInitialSize = 4
|
||||
>
|
||||
template<typename tKey, typename tVal, class tAllocator = DefaultAllocator, ualni(*tHashFunc)(SelCopyArg<tKey>) = DefaultHashFunc<tKey>, int tTableInitialSize = 4>
|
||||
class Map {
|
||||
|
||||
enum {
|
||||
|
|
@ -25,23 +20,23 @@ namespace tp {
|
|||
MAP_MAX_LOAD_PERCENTAGE = 66,
|
||||
};
|
||||
|
||||
typedef SelCopyArg<tKey> KeyArg;
|
||||
typedef SelCopyArg<tVal> ValArg;
|
||||
typedef SelCopyArg<tKey> KeyArg;
|
||||
typedef SelCopyArg<tVal> ValArg;
|
||||
|
||||
public:
|
||||
|
||||
class Node {
|
||||
friend Map;
|
||||
Node(KeyArg aKey, ValArg aVal) : key(aKey), val(aVal) {}
|
||||
public:
|
||||
friend Map;
|
||||
Node(KeyArg aKey, ValArg aVal) : key(aKey), val(aVal) {}
|
||||
public:
|
||||
tKey key;
|
||||
tVal val;
|
||||
};
|
||||
|
||||
struct Idx {
|
||||
alni idx = -1;
|
||||
operator bool() { return idx != -1; }
|
||||
};
|
||||
struct Idx {
|
||||
alni idx = -1;
|
||||
operator bool() { return idx != -1; }
|
||||
};
|
||||
|
||||
private:
|
||||
tAllocator mAlloc;
|
||||
|
|
@ -49,160 +44,160 @@ namespace tp {
|
|||
ualni mNSlots = 0;
|
||||
ualni mNEntries = 0;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
constexpr halnf maxLoadFactor() { return halnf(MAP_MAX_LOAD_PERCENTAGE) / 100.f; }
|
||||
|
||||
inline Node** newTable(const ualni len) {
|
||||
return new(mAlloc.allocate(sizeof(Node*) * len)) Node*[len]();
|
||||
}
|
||||
inline Node** newTable(const ualni len) {
|
||||
return new(mAlloc.allocate(sizeof(Node*) * len)) Node*[len]();
|
||||
}
|
||||
|
||||
inline Node* newNode(KeyArg key, ValArg val) {
|
||||
return new(mAlloc.allocate(sizeof(Node))) Node(key, val);
|
||||
}
|
||||
inline Node* newNode(KeyArg key, ValArg val) {
|
||||
return new(mAlloc.allocate(sizeof(Node))) Node(key, val);
|
||||
}
|
||||
|
||||
inline Node* newNodeNotConstructed() {
|
||||
return (Node*) mAlloc.allocate(sizeof(Node));
|
||||
}
|
||||
inline Node* newNodeNotConstructed() {
|
||||
return (Node*) mAlloc.allocate(sizeof(Node));
|
||||
}
|
||||
|
||||
inline void deleteTable(Node** table) {
|
||||
mAlloc.deallocate(table);
|
||||
}
|
||||
inline void deleteTable(Node** table) {
|
||||
mAlloc.deallocate(table);
|
||||
}
|
||||
|
||||
inline void deleteNode(Node* p) {
|
||||
p->~Node();
|
||||
mAlloc.deallocate(p);
|
||||
}
|
||||
inline void deleteNode(Node* p) {
|
||||
p->~Node();
|
||||
mAlloc.deallocate(p);
|
||||
}
|
||||
|
||||
void markDeletedSlot(ualni idx) const {
|
||||
mTable[idx] = (Node*)-1;
|
||||
}
|
||||
void markDeletedSlot(ualni idx) const {
|
||||
mTable[idx] = (Node*)-1;
|
||||
}
|
||||
|
||||
static bool isDeletedNode(Node* node) {
|
||||
return node == (Node*)-1;
|
||||
}
|
||||
static bool isDeletedNode(Node* node) {
|
||||
return node == (Node*)-1;
|
||||
}
|
||||
|
||||
void rehash() {
|
||||
alni nSlotsOld = mNSlots;
|
||||
Node** tableOld = mTable;
|
||||
void rehash() {
|
||||
alni nSlotsOld = mNSlots;
|
||||
Node** tableOld = mTable;
|
||||
|
||||
mNSlots = next2pow((uhalni)((1.f / (maxLoadFactor())) * mNEntries + 1));
|
||||
mTable = newTable(mNSlots);
|
||||
mNEntries = 0;
|
||||
mNSlots = next2pow((uhalni)((1.f / (maxLoadFactor())) * mNEntries + 1));
|
||||
mTable = newTable(mNSlots);
|
||||
mNEntries = 0;
|
||||
|
||||
for (alni i = 0; i < nSlotsOld; i++) {
|
||||
if (!tableOld[i] || isDeletedNode(tableOld[i])) {
|
||||
continue;
|
||||
}
|
||||
for (alni i = 0; i < nSlotsOld; i++) {
|
||||
if (!tableOld[i] || isDeletedNode(tableOld[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
alni idx = findSlotWrite(tableOld[i]->key);
|
||||
mTable[idx] = tableOld[i];
|
||||
mNEntries++;
|
||||
}
|
||||
alni idx = findSlotWrite(tableOld[i]->key);
|
||||
mTable[idx] = tableOld[i];
|
||||
mNEntries++;
|
||||
}
|
||||
|
||||
deleteTable(tableOld);
|
||||
}
|
||||
deleteTable(tableOld);
|
||||
}
|
||||
|
||||
alni findSlotRead(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
alni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx])) {
|
||||
goto SKIP;
|
||||
}
|
||||
if (!mTable[idx]) {
|
||||
return -1;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
SKIP:
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
alni findSlotRead(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
alni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx])) {
|
||||
goto SKIP;
|
||||
}
|
||||
if (!mTable[idx]) {
|
||||
return -1;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
SKIP:
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
|
||||
// compares keys only when collisions occur
|
||||
alni findSlotReadExisting(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
alni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx])) {
|
||||
goto SKIP;
|
||||
}
|
||||
if (!mTable[idx]) {
|
||||
return -1;
|
||||
}
|
||||
if (mTable[((5 * idx) + 1 + shift) & mask] == nullptr) {
|
||||
return idx;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
SKIP:
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
// compares keys only when collisions occur
|
||||
alni findSlotReadExisting(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
alni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx])) {
|
||||
goto SKIP;
|
||||
}
|
||||
if (!mTable[idx]) {
|
||||
return -1;
|
||||
}
|
||||
if (mTable[((5 * idx) + 1 + shift) & mask] == nullptr) {
|
||||
return idx;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
SKIP:
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
|
||||
ualni findSlotWrite(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
ualni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx]) || !mTable[idx]) {
|
||||
return idx;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
ualni findSlotWrite(KeyArg key) const {
|
||||
ualni const hashed_key = tHashFunc(key);
|
||||
ualni const mask = mNSlots - 1;
|
||||
ualni const shift = (hashed_key >> MAP_PERTURB_SHIFT) & ~1;
|
||||
ualni idx = hashed_key & mask;
|
||||
NEXT:
|
||||
if (isDeletedNode(mTable[idx]) || !mTable[idx]) {
|
||||
return idx;
|
||||
}
|
||||
if (mTable[idx]->key == key) {
|
||||
return idx;
|
||||
}
|
||||
idx = ((5 * idx) + 1 + shift) & mask;
|
||||
goto NEXT;
|
||||
}
|
||||
|
||||
void put(Node* node) {
|
||||
const ualni idx = findSlotWrite(node->key);
|
||||
void put(Node* node) {
|
||||
const ualni idx = findSlotWrite(node->key);
|
||||
|
||||
if (!mTable[idx] || isDeletedNode(mTable[idx])) {
|
||||
mNEntries++;
|
||||
}
|
||||
if (!mTable[idx] || isDeletedNode(mTable[idx])) {
|
||||
mNEntries++;
|
||||
}
|
||||
|
||||
mTable[idx] = node;
|
||||
mTable[idx] = node;
|
||||
|
||||
if ((halnf)mNEntries / mNSlots > maxLoadFactor()) {
|
||||
rehash();
|
||||
}
|
||||
}
|
||||
if ((halnf)mNEntries / mNSlots > maxLoadFactor()) {
|
||||
rehash();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Map() {
|
||||
MODULE_SANITY_CHECK(gModuleContainers)
|
||||
mNSlots = next2pow(uhalni(tTableInitialSize - 1));
|
||||
mTable = newTable(mNSlots);
|
||||
}
|
||||
Map() {
|
||||
MODULE_SANITY_CHECK(gModuleContainers)
|
||||
mNSlots = next2pow(uhalni(tTableInitialSize - 1));
|
||||
mTable = newTable(mNSlots);
|
||||
}
|
||||
|
||||
Node** buff() const {
|
||||
return mTable;
|
||||
}
|
||||
Node** buff() const {
|
||||
return mTable;
|
||||
}
|
||||
|
||||
[[nodiscard]] ualni size() const {
|
||||
return mNEntries;
|
||||
}
|
||||
[[nodiscard]] ualni size() const {
|
||||
return mNEntries;
|
||||
}
|
||||
|
||||
[[nodiscard]] ualni slotsSize() const {
|
||||
return mNEntries;
|
||||
}
|
||||
[[nodiscard]] ualni slotsSize() const {
|
||||
return mNEntries;
|
||||
}
|
||||
|
||||
[[nodiscard]] const tAllocator& getAllocator() const {
|
||||
return mAlloc;
|
||||
}
|
||||
[[nodiscard]] const tAllocator& getAllocator() const {
|
||||
return mAlloc;
|
||||
}
|
||||
|
||||
void put(KeyArg key, ValArg val) {
|
||||
const ualni idx = findSlotWrite(key);
|
||||
const ualni idx = findSlotWrite(key);
|
||||
if (!mTable[idx] || isDeletedNode(mTable[idx])) {
|
||||
mTable[idx] = newNode(key, val);
|
||||
mNEntries++;
|
||||
|
|
@ -215,22 +210,22 @@ namespace tp {
|
|||
|
||||
// undefined behavior if item is not presents
|
||||
tVal& get(KeyArg key) {
|
||||
DEBUG_ASSERT(findSlotRead(key) != -1 && "Key Error")
|
||||
DEBUG_ASSERT(findSlotRead(key) != -1 && "Key Error")
|
||||
return mTable[findSlotReadExisting(key)]->val;
|
||||
}
|
||||
|
||||
const tVal& get(KeyArg key) const {
|
||||
DEBUG_ASSERT(findSlotRead(key) != -1 && "Key Error")
|
||||
return mTable[findSlotReadExisting(key)]->val;
|
||||
return mTable[findSlotReadExisting(key)]->val;
|
||||
}
|
||||
|
||||
[[nodiscard]] Idx presents(KeyArg key) const { return { findSlotRead(key) }; }
|
||||
[[nodiscard]] Idx presents(KeyArg key) const { return { findSlotRead(key) }; }
|
||||
|
||||
void remove(KeyArg key) {
|
||||
DEBUG_ASSERT(findSlotRead(key) != -1 && "Key Error")
|
||||
auto idx = findSlotReadExisting(key);
|
||||
DEBUG_ASSERT(findSlotRead(key) != -1 && "Key Error")
|
||||
auto idx = findSlotReadExisting(key);
|
||||
|
||||
deleteNode(mTable[idx]);
|
||||
deleteNode(mTable[idx]);
|
||||
|
||||
markDeletedSlot(idx);
|
||||
|
||||
|
|
@ -241,30 +236,30 @@ namespace tp {
|
|||
}
|
||||
|
||||
const tVal& getSlotVal(ualni slot) const {
|
||||
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
}
|
||||
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
}
|
||||
|
||||
tVal& getSlotVal(ualni slot) {
|
||||
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
}
|
||||
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
}
|
||||
|
||||
const tVal& getSlotVal(Idx slot) const {
|
||||
DEBUG_ASSERT(slot.idx < mNSlots && (mTable[slot.idx] && !isDeletedNode(mTable[slot.idx])) && "Key Error")
|
||||
DEBUG_ASSERT(slot.idx < mNSlots && (mTable[slot.idx] && !isDeletedNode(mTable[slot.idx])) && "Key Error")
|
||||
return mTable[slot]->val;
|
||||
}
|
||||
|
||||
tVal& getSlotVal(Idx slot) {
|
||||
DEBUG_ASSERT(slot.idx < mNSlots && (mTable[slot.idx] && !isDeletedNode(mTable[slot.idx])) && "Key Error")
|
||||
DEBUG_ASSERT(slot.idx < mNSlots && (mTable[slot.idx] && !isDeletedNode(mTable[slot.idx])) && "Key Error")
|
||||
return mTable[slot.idx]->val;
|
||||
}
|
||||
|
||||
Map& operator=(const Map& in) {
|
||||
if (this == &in) {
|
||||
return *this;
|
||||
}
|
||||
removeAll();
|
||||
if (this == &in) {
|
||||
return *this;
|
||||
}
|
||||
removeAll();
|
||||
mNSlots = in.mNSlots;
|
||||
mTable = newTable(mNSlots);
|
||||
for (alni i = 0; i < mNSlots; i++) {
|
||||
|
|
@ -272,31 +267,31 @@ namespace tp {
|
|||
put(in.mTable[i]->key, in.mTable[i]->val);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator==(const Map& in) const {
|
||||
if (this == &in) {
|
||||
return true;
|
||||
}
|
||||
if (in.mNEntries != mNEntries) {
|
||||
return false;
|
||||
}
|
||||
for (auto i : in) {
|
||||
if (!presents(i->key) || get(i->key) != i->val) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
[[nodiscard]] bool operator==(const Map& in) const {
|
||||
if (this == &in) {
|
||||
return true;
|
||||
}
|
||||
if (in.mNEntries != mNEntries) {
|
||||
return false;
|
||||
}
|
||||
for (auto i : in) {
|
||||
if (!presents(i->key) || get(i->key) != i->val) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeAll() {
|
||||
for (ualni i = 0; i < mNSlots; i++) {
|
||||
if (mTable[i] && !isDeletedNode(mTable[i])) {
|
||||
deleteNode(mTable[i]);
|
||||
deleteNode(mTable[i]);
|
||||
}
|
||||
}
|
||||
deleteTable(mTable);
|
||||
deleteTable(mTable);
|
||||
mTable = newTable(tTableInitialSize);
|
||||
mNSlots = tTableInitialSize;
|
||||
mNEntries = 0;
|
||||
|
|
@ -323,74 +318,74 @@ namespace tp {
|
|||
|
||||
const Node* GetEntry(ualni idx) const {
|
||||
auto slot = slotIdx(idx);
|
||||
DEBUG_ASSERT(slot != -1 && "Key error")
|
||||
DEBUG_ASSERT(slot != -1 && "Key error")
|
||||
return mTable[slot];
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
class Iterator {
|
||||
const Map* map;
|
||||
Node* mIter;
|
||||
alni mSlot;
|
||||
alni mEntry;
|
||||
class Iterator {
|
||||
const Map* map;
|
||||
Node* mIter;
|
||||
alni mSlot;
|
||||
alni mEntry;
|
||||
|
||||
friend Map;
|
||||
explicit Iterator(const Map* _map) {
|
||||
mSlot = -1;
|
||||
mEntry = -1;
|
||||
map = _map;
|
||||
this->operator++();
|
||||
}
|
||||
friend Map;
|
||||
explicit Iterator(const Map* _map) {
|
||||
mSlot = -1;
|
||||
mEntry = -1;
|
||||
map = _map;
|
||||
this->operator++();
|
||||
}
|
||||
|
||||
public:
|
||||
Node* operator->() { return mIter; }
|
||||
const Node* operator->() const { return mIter; }
|
||||
const Iterator& operator*() const { return *this; }
|
||||
public:
|
||||
Node* operator->() { return mIter; }
|
||||
const Node* operator->() const { return mIter; }
|
||||
const Iterator& operator*() const { return *this; }
|
||||
|
||||
bool operator!=(ualni idx) const { return mSlot != idx; }
|
||||
bool operator!=(ualni idx) const { return mSlot != idx; }
|
||||
|
||||
void operator++() {
|
||||
mSlot++;
|
||||
while ((map->isDeletedNode(map->mTable[mSlot]) || !map->mTable[mSlot]) && (mSlot != map->mNSlots)) {
|
||||
mSlot++;
|
||||
}
|
||||
if (mSlot != map->mNSlots) {
|
||||
mIter = map->mTable[mSlot];
|
||||
mEntry++;
|
||||
}
|
||||
}
|
||||
};
|
||||
void operator++() {
|
||||
mSlot++;
|
||||
while ((map->isDeletedNode(map->mTable[mSlot]) || !map->mTable[mSlot]) && (mSlot != map->mNSlots)) {
|
||||
mSlot++;
|
||||
}
|
||||
if (mSlot != map->mNSlots) {
|
||||
mIter = map->mTable[mSlot];
|
||||
mEntry++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] Iterator begin() const {
|
||||
return Iterator(this);
|
||||
}
|
||||
[[nodiscard]] Iterator begin() const {
|
||||
return Iterator(this);
|
||||
}
|
||||
|
||||
[[nodiscard]] ualni end() const {
|
||||
return mNSlots;
|
||||
}
|
||||
return mNSlots;
|
||||
}
|
||||
|
||||
template<class Saver>
|
||||
void write(Saver& file) {
|
||||
file.write(mNEntries);
|
||||
for (auto item : *this) {
|
||||
file.write(item->val);
|
||||
file.write(item->key);
|
||||
}
|
||||
}
|
||||
template<class Saver>
|
||||
void write(Saver& file) {
|
||||
file.write(mNEntries);
|
||||
for (auto item : *this) {
|
||||
file.write(item->val);
|
||||
file.write(item->key);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Loader>
|
||||
void read(Loader& file) {
|
||||
removeAll();
|
||||
ualni len;
|
||||
file.read(len);
|
||||
for (auto i = len; i; i--) {
|
||||
auto node = newNodeNotConstructed();
|
||||
file.read(node->val);
|
||||
file.read(node->key);
|
||||
put(node);
|
||||
}
|
||||
}
|
||||
template<class Loader>
|
||||
void read(Loader& file) {
|
||||
removeAll();
|
||||
ualni len;
|
||||
file.read(len);
|
||||
for (auto i = len; i; i--) {
|
||||
auto node = newNodeNotConstructed();
|
||||
file.read(node->val);
|
||||
file.read(node->key);
|
||||
put(node);
|
||||
}
|
||||
}
|
||||
|
||||
~Map() { removeAll(); }
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue