diff options
author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-11-24 18:18:16 -0700 |
---|---|---|
committer | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-11-24 18:18:16 -0700 |
commit | c6176c05918f65b48148380f7eb41ac3f5c09d81 (patch) | |
tree | e0dfd471c678e52b4b35e91b4795a470d2c461a4 | |
parent | 205bddb307a1148828ae1cdbc56e960a401834a3 (diff) | |
download | gbarubik-c6176c05918f65b48148380f7eb41ac3f5c09d81.tar.gz gbarubik-c6176c05918f65b48148380f7eb41ac3f5c09d81.zip |
add dynamically sized vector from usu c++ assignment.
-rw-r--r-- | inc/vector.hpp | 311 | ||||
-rw-r--r-- | src/vector.cpp | 171 |
2 files changed, 482 insertions, 0 deletions
diff --git a/inc/vector.hpp b/inc/vector.hpp new file mode 100644 index 0000000..5de1fa0 --- /dev/null +++ b/inc/vector.hpp @@ -0,0 +1,311 @@ + +#ifndef USU_VECTOR_HPP +#define USU_VECTOR_HPP + +#include <algorithm> +#include <cmath> +#include <cstddef> +#include <cstdint> +#include <functional> +#include <iostream> +#include <memory> +#include <stdexcept> +#include <tuple> + +namespace usu { +template <typename T> class vector { +public: + using size_type = std::size_t; + using reference = T &; + using pointer = std::shared_ptr<T[]>; + using value_type = T; + using resize_type = std::function<size_type(size_type)>; + + static resize_type DEFAULT_RESIZER; + static size_type DEFAULT_CAPACITY; + + vector(); + vector(size_type size); + vector(resize_type resize); + vector(std::initializer_list<T> list); + vector(size_type size, resize_type resize); + vector(std::initializer_list<T> list, resize_type resize); + + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + iterator(); + iterator(pointer data); + iterator(size_type pos, pointer data); + iterator(const iterator &obj); + iterator(iterator &&obj) noexcept; + + iterator &operator=(const iterator &rhs); + iterator &operator=(iterator &&rhs); + bool operator==(const iterator &rhs) const; + bool operator!=(const iterator &rhs) const; + iterator operator++(); + iterator operator--(); + iterator operator++(int); + iterator operator--(int); + value_type operator*(); + std::shared_ptr<T> operator->(); + + private: + pointer m_data; + size_type m_pos; + }; + + reference operator[](size_type index); + void add(T value); + void insert(size_type index, T value); + void remove(size_type index); + void clear(); + size_type size(); + size_type capacity(); + iterator begin(); + iterator end(); + +protected: + pointer m_data; + size_type m_capacity; + size_type m_size; + resize_type m_resize; + + void maybe_resize(); +}; + +template <> class vector<bool> : public vector<std::uint8_t> { +public: + using size_type = std::size_t; + using pointer = std::shared_ptr<std::uint8_t[]>; + using resize_type = std::function<size_type(size_type)>; + + vector(); + vector(size_type size); + vector(resize_type resize); + vector(std::initializer_list<bool> list); + vector(size_type size, resize_type resize); + vector(std::initializer_list<bool> list, resize_type resize); + + class reference { + public: + reference(); + reference(size_type pos, pointer data); + reference &operator=(bool value); + operator bool(); + bool operator==(const reference &rhs) const; + bool operator!=(const reference &rhs) const; + + bool get() const; + void add(); + void sub(); + + private: + size_type m_pos; + pointer m_data; + }; + + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + iterator(); + iterator(pointer data); + iterator(size_type pos, pointer data); + iterator(const iterator &obj); + iterator(iterator &&obj) noexcept; + + iterator &operator=(const iterator &rhs); + iterator &operator=(iterator &&rhs); + bool operator==(const iterator &rhs) const; + bool operator!=(const iterator &rhs) const; + iterator operator++(); + iterator operator--(); + iterator operator++(int); + iterator operator--(int); + reference operator*(); + + private: + reference m_ref; + }; + + reference operator[](size_type index); + + void add(bool value); + void insert(size_type index, bool value); + void remove(size_type index); + + iterator begin(); + iterator end(); + +private: + void maybe_resize(); +}; + +template <typename T> +vector<T>::iterator::iterator() : vector<T>::iterator::iterator(nullptr) {} + +template <typename T> +vector<T>::iterator::iterator(pointer data) : m_data(data), m_pos(0) {} + +template <typename T> +vector<T>::iterator::iterator(size_type pos, pointer data) + : m_data(data), m_pos(pos) {} + +template <typename T> vector<T>::iterator::iterator(const iterator &obj) { + m_pos = obj.m_pos; + m_data = obj.m_data; +} + +template <typename T> vector<T>::iterator::iterator(iterator &&obj) noexcept { + m_pos = obj.m_pos; + m_data = obj.m_data; + obj.m_pos = 0; + obj.m_data = nullptr; +} + +template <typename T> +bool vector<T>::iterator::operator!=(const iterator &rhs) const { + return m_pos != rhs.m_pos; +} + +template <typename T> +bool vector<T>::iterator::operator==(const iterator &rhs) const { + return m_pos == rhs.m_pos; +} + +template <typename T> +typename vector<T>::iterator vector<T>::iterator::operator++() { + m_pos++; + return *this; +} + +template <typename T> +typename vector<T>::iterator vector<T>::iterator::operator--() { + m_pos--; + return *this; +} + +template <typename T> +typename vector<T>::iterator vector<T>::iterator::operator++(int) { + iterator it = *this; + m_pos++; + return it; +} + +template <typename T> +typename vector<T>::iterator vector<T>::iterator::operator--(int) { + iterator it = *this; + m_pos--; + return it; +} + +template <typename T> +typename vector<T>::value_type vector<T>::iterator::operator*() { + return m_data[m_pos]; +} + +template <typename T> std::shared_ptr<T> vector<T>::iterator::operator->() { + return std::make_shared<T>(m_data[m_pos]); +} + +template <typename T> +typename vector<T>::resize_type vector<T>::DEFAULT_RESIZER = + [](size_type currentCapacity) -> size_type { return currentCapacity * 2; }; + +template <typename T> +typename vector<T>::size_type vector<T>::DEFAULT_CAPACITY = 10; + +template <typename T> +vector<T>::vector() : usu::vector<T>(0, DEFAULT_RESIZER) {} + +template <typename T> +usu::vector<T>::vector(size_type size) + : usu::vector<T>(size, DEFAULT_RESIZER) {} + +template <typename T> +vector<T>::vector(resize_type resize) : usu::vector<T>(0, resize) {} + +template <typename T> +vector<T>::vector(std::initializer_list<T> list) + : usu::vector<T>(list, DEFAULT_RESIZER) {} + +template <typename T> +vector<T>::vector(std::initializer_list<T> list, resize_type resize) + : usu::vector<T>(0, resize) { + for (auto i = list.begin(); i < list.end(); ++i) + add(*i); +} + +template <typename T> +vector<T>::vector(size_type size, resize_type resize) + : m_data(nullptr), + m_capacity(DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY + : DEFAULT_RESIZER(size)), + m_size(size), m_resize(resize) { + maybe_resize(); +} + +template <typename T> void vector<T>::maybe_resize() { + if (m_data == nullptr) + m_data = std::make_shared<T[]>(m_capacity); + if (m_size >= m_capacity) { + m_capacity = std::max(m_capacity == 0 ? 1 : m_resize(m_capacity), m_size); + + pointer newData = std::make_shared<T[]>(m_capacity); + for (size_type i = 0; i < m_size; ++i) + newData[i] = m_data[i]; + + m_data = newData; + } +} + +template <typename T> void vector<T>::add(T value) { + maybe_resize(); + m_data[m_size++] = value; +} + +template <typename T> +typename vector<T>::reference vector<T>::operator[](size_type index) { + return m_data[index]; +} + +template <typename T> void vector<T>::insert(size_type index, T value) { + maybe_resize(); + + for (size_type i = m_size; i > index; --i) + m_data[i] = m_data[i - 1]; + m_data[index] = value; + + m_size++; +} + +template <typename T> void vector<T>::remove(size_type index) { + for (size_type i = index; i < m_size; ++i) + m_data[i] = m_data[i + 1]; + m_size--; +} + +template <typename T> typename vector<T>::iterator vector<T>::begin() { + vector<T>::iterator begin(m_data); + return begin; +} + +template <typename T> typename vector<T>::iterator vector<T>::end() { + vector<T>::iterator end(m_size, m_data); + return end; +} + +template <typename T> void vector<T>::clear() { m_size = 0; } + +template <typename T> typename vector<T>::size_type vector<T>::size() { + return m_size; +} + +template <typename T> typename vector<T>::size_type vector<T>::capacity() { + return m_capacity; +} + +} // namespace usu + +#endif diff --git a/src/vector.cpp b/src/vector.cpp new file mode 100644 index 0000000..eb2158b --- /dev/null +++ b/src/vector.cpp @@ -0,0 +1,171 @@ +#include "vector.hpp" + +usu::vector<bool>::reference::reference() + : usu::vector<bool>::reference(0, nullptr) {} + +usu::vector<bool>::reference::reference(size_type pos, pointer data) + : m_pos(pos), m_data(data) {} + +typename usu::vector<bool>::reference & +usu::vector<bool>::reference::operator=(bool value) { + std::uint8_t mask = 1 << (7 - (m_pos % 8)); + if (value) + m_data[m_pos / 8] |= mask; + else + m_data[m_pos / 8] &= (~mask); + return *this; +} + +typename usu::vector<bool>::reference +usu::vector<bool>::operator[](size_type index) { + reference r(index, m_data); + return r; +} + +void usu::vector<bool>::reference::add() { m_pos++; } + +void usu::vector<bool>::reference::sub() { m_pos--; } + +bool usu::vector<bool>::reference::get() const { + return ((m_data[m_pos / 8] >> (7 - (m_pos % 8))) & 1) == 1; +} + +usu::vector<bool>::reference::operator bool() { return get(); } + +bool usu::vector<bool>::reference::operator==(const reference &rhs) const { + return m_data == rhs.m_data && m_pos == rhs.m_pos; +} + +bool usu::vector<bool>::reference::operator!=(const reference &rhs) const { + return m_data != rhs.m_data || m_pos != rhs.m_pos; +} + +usu::vector<bool>::iterator::iterator() + : usu::vector<bool>::iterator(nullptr) {} + +usu::vector<bool>::iterator::iterator(pointer data) + : usu::vector<bool>::iterator(0, data) {} + +usu::vector<bool>::iterator::iterator(size_type pos, pointer data) { + m_ref = reference(pos, data); +} + +usu::vector<bool>::iterator::iterator(const iterator &obj) { + m_ref = obj.m_ref; +} + +usu::vector<bool>::iterator::iterator(iterator &&obj) noexcept { + m_ref = obj.m_ref; + obj.m_ref = reference(0, nullptr); +} + +typename usu::vector<bool>::iterator usu::vector<bool>::iterator::operator++() { + m_ref.add(); + return *this; +} + +typename usu::vector<bool>::iterator usu::vector<bool>::iterator::operator--() { + m_ref.sub(); + return *this; +} + +typename usu::vector<bool>::iterator +usu::vector<bool>::iterator::operator++(int) { + iterator it = *this; + m_ref.add(); + return it; +} + +typename usu::vector<bool>::iterator +usu::vector<bool>::iterator::operator--(int) { + iterator it = *this; + m_ref.sub(); + return it; +} + +typename usu::vector<bool>::reference usu::vector<bool>::iterator::operator*() { + return m_ref; +} + +bool usu::vector<bool>::iterator::operator!=(const iterator &rhs) const { + return m_ref != rhs.m_ref; +} + +bool usu::vector<bool>::iterator::operator==(const iterator &rhs) const { + return m_ref == rhs.m_ref; +} + +usu::vector<bool>::vector() : usu::vector<bool>(0, DEFAULT_RESIZER){}; + +usu::vector<bool>::vector(size_type size) + : usu::vector<bool>(size, DEFAULT_RESIZER){}; + +usu::vector<bool>::vector(resize_type resize) : usu::vector<bool>(0, resize){}; + +usu::vector<bool>::vector(size_type size, resize_type resize) { + m_resize = resize; + m_size = size; + m_capacity = DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY : resize(size); + maybe_resize(); +}; + +usu::vector<bool>::vector(std::initializer_list<bool> list) + : usu::vector<bool>(list, DEFAULT_RESIZER){}; + +usu::vector<bool>::vector(std::initializer_list<bool> list, resize_type resize) + : usu::vector<std::uint8_t>(0, resize) { + for (auto i = list.begin(); i != list.end(); ++i) + add(*i); +}; + +void usu::vector<bool>::add(bool value) { + maybe_resize(); + reference r(m_size++, m_data); + r = value; +} + +void usu::vector<bool>::insert(size_type index, bool value) { + maybe_resize(); + + reference r1(m_size, m_data); + reference r2(m_size == 0 ? 0 : m_size - 1, m_data); + + for (size_type i = m_size; i > index; --i, r1.sub(), r2.sub()) + r1 = r2.get(); + r1 = value; + m_size++; +} + +void usu::vector<bool>::remove(size_type index) { + reference r1(index, m_data); + reference r2(index + 1 >= m_size ? index : index + 1, m_data); + + for (size_type i = index; i < m_size; ++i, r1.add(), r2.add()) + r1 = r2.get(); + r1 = false; + m_size--; +} + +void usu::vector<bool>::maybe_resize() { + if (m_data == nullptr) + m_data = std::make_shared<std::uint8_t[]>(m_capacity / 8); + if (m_size >= m_capacity) { + m_capacity = std::max(m_capacity == 0 ? 1 : m_resize(m_capacity), m_size); + + pointer newData = std::make_shared<std::uint8_t[]>(m_capacity / 8); + for (size_type i = 0; i <= m_size / 8; ++i) + newData[i] = m_data[i]; + + m_data = newData; + } +} + +typename usu::vector<bool>::iterator usu::vector<bool>::begin() { + vector<bool>::iterator begin(m_data); + return begin; +} + +typename usu::vector<bool>::iterator usu::vector<bool>::end() { + vector<bool>::iterator end(m_size, m_data); + return end; +} |