cs440-assignment2/Map.hpp

287 lines
8.1 KiB
C++

// commenting everything out when I commit so all commits my code technically
// compiles
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <optional>
#include <stdexcept>
#include <utility>
#include <vector>
namespace cs440 {
template <typename Key_T, typename Mapped_T> class Map {
private:
using ValueType = std::pair<const Key_T, Mapped_T>;
// idx 0 = root
// left = parent * 2 + 1
// right = parent * 2 + 2
std::vector<std::optional<ValueType>> store;
public:
class Iterator;
class ConstIterator;
class ReverseIterator;
// TODO: Iterator functionality
class Iterator {
public:
using underlying = typename std::vector<std::optional<ValueType>>::iterator;
private:
underlying store_iter;
public:
Iterator() = delete;
Iterator(underlying iter) : store_iter{iter} {}
ConstIterator to_const() const { return ConstIterator(this); }
Iterator &operator++() { return *this; }
Iterator operator++(int) {
Iterator tmp = *this;
++(*this);
return tmp;
}
Iterator &operator--() {}
Iterator operator--(int) {
Iterator tmp = *this;
--(*this);
return tmp;
}
ValueType &operator*() const { return this->store_iter->value(); }
ValueType *operator->() const { return &this->store_iter->value(); }
friend bool operator==(Iterator const &lhs, Iterator const &rhs) {
return lhs.store_iter == rhs.store_iter;
}
friend bool operator!=(Iterator const &lhs, Iterator const &rhs) {
return lhs.store_iter != rhs.store_iter;
}
friend bool operator==(ConstIterator const &lhs, Iterator const &rhs) {
return lhs == rhs.to_const();
}
friend bool operator!=(ConstIterator const &lhs, Iterator const &rhs) {
return lhs != rhs.to_const();
}
friend bool operator==(Iterator const &lhs, ConstIterator const &rhs) {
return lhs.to_const() == rhs;
}
friend bool operator!=(Iterator const &lhs, ConstIterator const &rhs) {
return lhs.to_const() != rhs;
}
};
class ConstIterator {
public:
using underlying = Iterator;
private:
underlying store_iter;
public:
ConstIterator() = delete;
ConstIterator(underlying iter) : store_iter{iter} {}
friend bool operator==(ConstIterator const &lhs, ConstIterator const &rhs) {
return lhs.store_iter == rhs.store_iter;
}
ConstIterator &operator++() {
++this->store_iter;
return *this;
}
ConstIterator operator++(int) {
ConstIterator tmp = *this;
this->store_iter++;
return tmp;
}
ConstIterator &operator--() {
--this->store_iter;
return *this;
}
ConstIterator operator--(int) {
ConstIterator tmp = *this;
this->store_iter--;
return tmp;
}
const ValueType &operator*() const { return *this->store_iter; }
const ValueType *operator->() const {
// I find this rather funny
return this->store_iter.operator->();
}
friend bool operator!=(ConstIterator const &lhs, ConstIterator const &rhs) {
return lhs.store_iter != rhs.store_iter;
}
};
class ReverseIterator {
public:
using underlying = typename std::vector<std::optional<ValueType>>::iterator;
private:
underlying store_iter;
public:
ReverseIterator() = delete;
ReverseIterator(underlying store_iter) : store_iter{store_iter} {}
ReverseIterator &operator++() {}
ReverseIterator operator++(int) {}
ReverseIterator &operator--() {}
ReverseIterator operator--(int) {}
ValueType &operator*() const {}
ValueType *operator->() const {}
friend bool operator==(ReverseIterator const &lhs,
ReverseIterator const &rhs) {
return lhs.store_iter == rhs.store_iter;
}
friend bool operator!=(ConstIterator const &lhs, ConstIterator const &rhs) {
return lhs.store_iter != rhs.store_iter;
}
};
Map() : store{} {}
Map(const Map &rhs) : store{rhs.store} {}
Map &operator=(const Map &rhs) { this->store = rhs.store; }
Map(std::initializer_list<ValueType> elems) : store{} {
this->insert(elems.begin(), elems.end());
}
// who cares we're using vector
~Map() {}
size_t size() const {
std::size_t count = 0;
for (auto &m_pair : this->store) {
count += m_pair.has_value() ? 1 : 0;
}
return count;
}
bool empty() const { return this->store.empty(); }
Iterator begin() {
std::size_t start = 0;
while (2 * (start - store.begin()) + 1 < store.size()) {
store = 2 * store + 2;
}
return Iterator(store.cbegin() + start);
}
Iterator end() { return Iterator(store.end()); }
ConstIterator begin() const {
std::size_t start = 0;
while (2 * (start - store.begin()) + 1 < store.size()) {
store = 2 * store + 2;
}
return ConstIterator(store.cbegin() + start);
}
ConstIterator end() const { return ConstIterator(store.cend()); }
ConstIterator cbegin() const { return this->begin(); }
ConstIterator cend() const { return this->end(); }
ReverseIterator rbegin() {
std::size_t start = 0;
while (2 * (start - store.begin()) + 1 < store.size()) {
store = 2 * store + 2;
}
return ReverseIterator(store.begin() + start);
}
ReverseIterator rend() { return ReverseIterator(store.end()); }
Iterator find(const Key_T &key) {
std::size_t idx = 0;
while (store[idx].first != key) {
if (idx >= store.size()) {
return this->end();
}
if (store[idx].first < key) {
idx = idx * 2 + 1;
} else {
idx = idx * 2 + 2;
}
}
}
ConstIterator find(const Key_T &key) const {
std::size_t idx = 0;
while (store[idx].first != key) {
if (idx >= store.size()) {
return this->end();
}
if (store[idx].first < key) {
idx = idx * 2 + 1;
} else {
idx = idx * 2 + 2;
}
}
}
Mapped_T &at(const Key_T &key) {
std::size_t i = 0;
while (this->store.at(i).has_value()) {
switch (true) {
case this->store.at(i).first == key:
return this->store.at(i).second;
case this->store.at(i).first < key:
i = 2 * i + 1;
break;
case this->store.at(i).first > key:
i = 2 * i + 2;
break;
}
}
throw std::out_of_range{""};
}
const Mapped_T &at(const Key_T &key) const { return this->at(key); }
Mapped_T &operator[](const Key_T &key) { return this->at(key); }
// TODO: single insert
std ::pair<Iterator, bool> insert(const ValueType &) {}
template <typename IT_T> void insert(IT_T range_beg, IT_T range_end) {
std::for_each(range_beg, range_end,
[&](ValueType &val) { this->insert(val); });
}
// TODO: erase via iterator
void erase(Iterator pos) {}
void erase(const Key_T &key) { this->erase(this->find(key)); }
void clear() { this->store = {}; }
friend bool operator==(const Map &lhs, const Map &rhs) {
if (lhs.store.size() != rhs.store.size()) {
return false;
}
auto liter = lhs.cbegin();
auto riter = rhs.cbegin();
// both must be the same length so this is fine
while (liter != lhs.cend()) {
if (*liter != *riter) {
return false;
}
liter++;
riter++;
}
return true;
}
friend bool operator!=(const Map &lhs, const Map &rhs) {
return !(lhs == rhs);
}
friend bool operator<(const Map &lhs, const Map &rhs) {
std::size_t lhs_i = 0;
std::size_t rhs_i = 0;
for (; lhs_i < lhs.store.size() && rhs_i < rhs.store.size();
lhs_i++, rhs_i++) {
bool lhs_exhaust = false;
while (!lhs.store[lhs_i].has_value()) {
lhs_i++;
if (lhs.store.size() >= lhs_i) {
lhs_exhaust = true;
break;
}
}
bool rhs_exhaust = false;
while (!rhs.store[rhs_i].has_value()) {
rhs_i++;
if (rhs.store.size() >= rhs_i) {
rhs_exhaust = true;
break;
}
}
if (lhs_exhaust && !rhs_exhaust) {
return true;
}
if (lhs_exhaust || rhs_exhaust) {
break;
}
if (lhs.store[lhs_i] != rhs.store[rhs_i]) {
return lhs.store[lhs_i] < rhs.store[rhs_i];
}
}
return false;
}
};
} // namespace cs440