707 lines
19 KiB
C
707 lines
19 KiB
C
|
#pragma once
|
||
|
#pragma once
|
||
|
|
||
|
#include <cstring>
|
||
|
#include <stdexcept>
|
||
|
#include <typeinfo>
|
||
|
|
||
|
namespace yazi {
|
||
|
namespace stl {
|
||
|
|
||
|
template <typename T>
|
||
|
class Vector
|
||
|
{
|
||
|
public:
|
||
|
Vector();
|
||
|
~Vector();
|
||
|
|
||
|
void push_back(const T& value);
|
||
|
void pop_back();
|
||
|
int size() const;
|
||
|
int capacity() const;
|
||
|
void reserve(int size);
|
||
|
void resize(int size);
|
||
|
void show() const;
|
||
|
T& at(int index);
|
||
|
T& front();
|
||
|
T& back();
|
||
|
bool empty() const;
|
||
|
void clear();
|
||
|
T& operator [] (int index);
|
||
|
Vector<T>& operator = (const Vector<T>& other);
|
||
|
T* data();
|
||
|
void swap(Vector<T>& other);
|
||
|
|
||
|
class iterator
|
||
|
{
|
||
|
public:
|
||
|
iterator() : m_pointer(nullptr) {}
|
||
|
iterator(T* pointer) : m_pointer(pointer) {}
|
||
|
~iterator() {}
|
||
|
|
||
|
bool operator == (const iterator& other)
|
||
|
{
|
||
|
return m_pointer == other.m_pointer;
|
||
|
}
|
||
|
|
||
|
bool operator != (const iterator& other)
|
||
|
{
|
||
|
return m_pointer != other.m_pointer;
|
||
|
}
|
||
|
|
||
|
iterator& operator = (const iterator& other)
|
||
|
{
|
||
|
m_pointer = other.m_pointer;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
iterator& operator ++ ()
|
||
|
{
|
||
|
m_pointer += 1;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
iterator operator ++ (int)
|
||
|
{
|
||
|
iterator it = *this;
|
||
|
++(*this);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
iterator operator + (int i)
|
||
|
{
|
||
|
iterator it = *this;
|
||
|
it.m_pointer += i;
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
iterator& operator += (int i)
|
||
|
{
|
||
|
m_pointer += i;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
iterator operator - (int i)
|
||
|
{
|
||
|
iterator it = *this;
|
||
|
it.m_pointer -= i;
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
iterator& operator -= (int i)
|
||
|
{
|
||
|
m_pointer -= i;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
int operator - (const iterator& other) const
|
||
|
{
|
||
|
return m_pointer - other.m_pointer;
|
||
|
}
|
||
|
|
||
|
T& operator * ()
|
||
|
{
|
||
|
return *m_pointer;
|
||
|
}
|
||
|
|
||
|
T* operator -> ()
|
||
|
{
|
||
|
return m_pointer;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
T* m_pointer;
|
||
|
};
|
||
|
|
||
|
iterator begin();
|
||
|
iterator end();
|
||
|
|
||
|
class reverse_iterator
|
||
|
{
|
||
|
public:
|
||
|
reverse_iterator() : m_pointer(nullptr) {}
|
||
|
reverse_iterator(T* pointer) : m_pointer(pointer) {}
|
||
|
~reverse_iterator() {}
|
||
|
|
||
|
bool operator == (const reverse_iterator& other)
|
||
|
{
|
||
|
return m_pointer == other.m_pointer;
|
||
|
}
|
||
|
|
||
|
bool operator != (const reverse_iterator& other)
|
||
|
{
|
||
|
return m_pointer != other.m_pointer;
|
||
|
}
|
||
|
|
||
|
reverse_iterator& operator = (const reverse_iterator& other)
|
||
|
{
|
||
|
m_pointer = other.m_pointer;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
reverse_iterator& operator ++ ()
|
||
|
{
|
||
|
m_pointer -= 1;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
reverse_iterator operator ++ (int)
|
||
|
{
|
||
|
reverse_iterator it = *this;
|
||
|
++(*this);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
reverse_iterator operator + (int i)
|
||
|
{
|
||
|
reverse_iterator it = *this;
|
||
|
it.m_pointer -= i;
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
reverse_iterator& operator += (int i)
|
||
|
{
|
||
|
m_pointer -= i;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
reverse_iterator operator - (int i)
|
||
|
{
|
||
|
reverse_iterator it = *this;
|
||
|
it.m_pointer += i;
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
reverse_iterator& operator -= (int i)
|
||
|
{
|
||
|
m_pointer += i;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
T& operator * ()
|
||
|
{
|
||
|
return *m_pointer;
|
||
|
}
|
||
|
|
||
|
T* operator -> ()
|
||
|
{
|
||
|
return m_pointer;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
T* m_pointer;
|
||
|
};
|
||
|
|
||
|
reverse_iterator rbegin();
|
||
|
reverse_iterator rend();
|
||
|
|
||
|
iterator find(const T& value);
|
||
|
iterator rfind(const T& value);
|
||
|
|
||
|
iterator insert(iterator pos, const T& value);
|
||
|
iterator insert(iterator pos, int n, const T& value);
|
||
|
|
||
|
iterator erase(iterator pos);
|
||
|
iterator erase(iterator first, iterator last);
|
||
|
|
||
|
private:
|
||
|
bool is_basic_type();
|
||
|
|
||
|
protected:
|
||
|
T* m_data;
|
||
|
int m_size;
|
||
|
int m_capacity;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
Vector<T>::Vector() : m_data(nullptr), m_size(0), m_capacity(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
Vector<T>::~Vector()
|
||
|
{
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
}
|
||
|
m_size = 0;
|
||
|
m_capacity = 0;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::push_back(const T& value)
|
||
|
{
|
||
|
if (m_size < m_capacity)
|
||
|
{
|
||
|
m_data[m_size] = value;
|
||
|
m_size++;
|
||
|
return;
|
||
|
}
|
||
|
if (m_capacity == 0)
|
||
|
{
|
||
|
m_capacity = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_capacity *= 2;
|
||
|
}
|
||
|
T* data = new T[m_capacity];
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(data, m_data, m_size * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < m_size; i++)
|
||
|
{
|
||
|
data[i] = m_data[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
}
|
||
|
m_data = data;
|
||
|
m_data[m_size] = value;
|
||
|
m_size++;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::pop_back()
|
||
|
{
|
||
|
if (m_size > 0)
|
||
|
{
|
||
|
m_size--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
int Vector<T>::size() const
|
||
|
{
|
||
|
return m_size;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
int Vector<T>::capacity() const
|
||
|
{
|
||
|
return m_capacity;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::reserve(int size)
|
||
|
{
|
||
|
if (m_capacity >= size)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
while (m_capacity < size)
|
||
|
{
|
||
|
if (m_capacity == 0)
|
||
|
{
|
||
|
m_capacity = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_capacity *= 2;
|
||
|
}
|
||
|
}
|
||
|
T* data = new T[m_capacity];
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(data, m_data, m_size * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < m_size; i++)
|
||
|
{
|
||
|
data[i] = m_data[i];
|
||
|
}
|
||
|
}
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
}
|
||
|
m_data = data;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::resize(int size)
|
||
|
{
|
||
|
if (m_size >= size)
|
||
|
{
|
||
|
m_size = size;
|
||
|
return;
|
||
|
}
|
||
|
if (size <= m_capacity)
|
||
|
{
|
||
|
for (int i = m_size; i < size; i++)
|
||
|
{
|
||
|
m_data[i] = T();
|
||
|
}
|
||
|
m_size = size;
|
||
|
return;
|
||
|
}
|
||
|
while (m_capacity < size)
|
||
|
{
|
||
|
if (m_capacity == 0)
|
||
|
{
|
||
|
m_capacity = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_capacity *= 2;
|
||
|
}
|
||
|
}
|
||
|
T* data = new T[m_capacity];
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(data, m_data, m_size * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < m_size; i++)
|
||
|
{
|
||
|
data[i] = m_data[i];
|
||
|
}
|
||
|
}
|
||
|
for (int i = m_size; i < size; i++)
|
||
|
{
|
||
|
data[i] = T();
|
||
|
}
|
||
|
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
}
|
||
|
m_data = data;
|
||
|
m_size = size;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::show() const
|
||
|
{
|
||
|
std::cout << "size=" << size() << ", capacity=" << capacity() << std::endl;
|
||
|
for (int i = 0; i < m_size; i++)
|
||
|
{
|
||
|
std::cout << m_data[i] << ",";
|
||
|
}
|
||
|
std::cout << std::endl;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T& Vector<T>::at(int index)
|
||
|
{
|
||
|
if (index < 0 || index >= m_size)
|
||
|
{
|
||
|
throw std::logic_error("out of range");
|
||
|
}
|
||
|
return m_data[index];
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T& Vector<T>::front()
|
||
|
{
|
||
|
if (m_size <= 0)
|
||
|
{
|
||
|
throw std::logic_error("vector is empty");
|
||
|
}
|
||
|
return m_data[0];
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T& Vector<T>::back()
|
||
|
{
|
||
|
if (m_size <= 0)
|
||
|
{
|
||
|
throw std::logic_error("vector is empty");
|
||
|
}
|
||
|
return m_data[m_size - 1];
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
bool Vector<T>::empty() const
|
||
|
{
|
||
|
return m_size == 0;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::clear()
|
||
|
{
|
||
|
m_size = 0;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T& Vector<T>::operator [] (int index)
|
||
|
{
|
||
|
return at(index);
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
Vector<T>& Vector<T>::operator = (const Vector<T>& other)
|
||
|
{
|
||
|
if (m_capacity < other.m_size)
|
||
|
{
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
m_size = 0;
|
||
|
m_capacity = 0;
|
||
|
}
|
||
|
while (m_capacity < other.m_size)
|
||
|
{
|
||
|
if (m_capacity == 0)
|
||
|
{
|
||
|
m_capacity = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_capacity *= 2;
|
||
|
}
|
||
|
}
|
||
|
m_data = new T[m_capacity];
|
||
|
}
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(m_data, other.m_data, m_size * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < other.m_size; i++)
|
||
|
{
|
||
|
m_data[i] = other.m_data[i];
|
||
|
}
|
||
|
}
|
||
|
m_size = other.m_size;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
T* Vector<T>::data()
|
||
|
{
|
||
|
return m_data;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void Vector<T>::swap(Vector<T>& other)
|
||
|
{
|
||
|
T* data = other.m_data;
|
||
|
int size = other.m_size;
|
||
|
int capacity = other.m_capacity;
|
||
|
|
||
|
other.m_data = m_data;
|
||
|
other.m_size = m_size;
|
||
|
other.m_capacity = m_capacity;
|
||
|
|
||
|
m_data = data;
|
||
|
m_size = size;
|
||
|
m_capacity = capacity;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::begin()
|
||
|
{
|
||
|
Vector<T>::iterator it(m_data);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::end()
|
||
|
{
|
||
|
Vector<T>::iterator it(m_data + m_size);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::reverse_iterator Vector<T>::rbegin()
|
||
|
{
|
||
|
Vector<T>::reverse_iterator it(m_data + m_size - 1);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::reverse_iterator Vector<T>::rend()
|
||
|
{
|
||
|
Vector<T>::reverse_iterator it(m_data - 1);
|
||
|
return it;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::find(const T& value)
|
||
|
{
|
||
|
for (Vector<T>::iterator it = begin(); it != end(); it++)
|
||
|
{
|
||
|
if (*it == value)
|
||
|
{
|
||
|
return it;
|
||
|
}
|
||
|
}
|
||
|
return end();
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::rfind(const T& value)
|
||
|
{
|
||
|
for (Vector<T>::reverse_iterator it = rbegin(); it != rend(); it++)
|
||
|
{
|
||
|
if (*it == value)
|
||
|
{
|
||
|
return Vector<T>::iterator(it.operator->());
|
||
|
}
|
||
|
}
|
||
|
return end();
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::insert(Vector<T>::iterator pos, const T& value)
|
||
|
{
|
||
|
return insert(pos, 1, value);
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::insert(Vector<T>::iterator pos, int n, const T& value)
|
||
|
{
|
||
|
int size = pos - begin();
|
||
|
if (m_size + n <= m_capacity)
|
||
|
{
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memmove(m_data + size + n, m_data + size, (m_size - size) * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = m_size; i > size; i--)
|
||
|
{
|
||
|
m_data[i + n - 1] = m_data[i - 1];
|
||
|
}
|
||
|
}
|
||
|
for (int i = 0; i < n; i++)
|
||
|
{
|
||
|
m_data[size + i] = value;
|
||
|
}
|
||
|
m_size += n;
|
||
|
return Vector<T>::iterator(m_data + size);
|
||
|
}
|
||
|
while (m_size + n > m_capacity)
|
||
|
{
|
||
|
if (m_capacity == 0)
|
||
|
{
|
||
|
m_capacity = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_capacity *= 2;
|
||
|
}
|
||
|
}
|
||
|
T* data = new T[m_capacity];
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(data, m_data, size * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < size; i++)
|
||
|
{
|
||
|
data[i] = m_data[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < n; i++)
|
||
|
{
|
||
|
data[size + i] = value;
|
||
|
}
|
||
|
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memcpy(data + size + n, m_data + size, (m_size - size) * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = size; i < m_size; i++)
|
||
|
{
|
||
|
data[i + n] = m_data[i];
|
||
|
}
|
||
|
}
|
||
|
if (m_data != nullptr)
|
||
|
{
|
||
|
delete[] m_data;
|
||
|
m_data = nullptr;
|
||
|
}
|
||
|
m_data = data;
|
||
|
m_size += n;
|
||
|
return Vector<T>::iterator(m_data + size);
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::erase(Vector<T>::iterator pos)
|
||
|
{
|
||
|
if (end() - pos == 1)
|
||
|
{
|
||
|
m_size -= 1;
|
||
|
return end();
|
||
|
}
|
||
|
int size = pos - begin();
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memmove(m_data + size, m_data + size + 1, (m_size - size - 1) * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = size; i < m_size - 1; i++)
|
||
|
{
|
||
|
m_data[i] = m_data[i + 1];
|
||
|
}
|
||
|
}
|
||
|
m_size -= 1;
|
||
|
return pos;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
typename Vector<T>::iterator Vector<T>::erase(Vector<T>::iterator first, Vector<T>::iterator last)
|
||
|
{
|
||
|
int f = first - begin();
|
||
|
int l = last - begin();
|
||
|
int n = last - first;
|
||
|
if (is_basic_type())
|
||
|
{
|
||
|
std::memmove(m_data + f, m_data + l, (m_size - l) * sizeof(T));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < m_size - l; i++)
|
||
|
{
|
||
|
m_data[f] = m_data[l];
|
||
|
}
|
||
|
}
|
||
|
m_size -= n;
|
||
|
return first;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
bool Vector<T>::is_basic_type()
|
||
|
{
|
||
|
if (std::is_pointer<T>::value)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
return (typeid(T) == typeid(bool)) ||
|
||
|
(typeid(T) == typeid(char)) ||
|
||
|
(typeid(T) == typeid(unsigned char)) ||
|
||
|
(typeid(T) == typeid(short)) ||
|
||
|
(typeid(T) == typeid(unsigned short)) ||
|
||
|
(typeid(T) == typeid(int)) ||
|
||
|
(typeid(T) == typeid(unsigned int)) ||
|
||
|
(typeid(T) == typeid(long)) ||
|
||
|
(typeid(T) == typeid(unsigned long)) ||
|
||
|
(typeid(T) == typeid(float)) ||
|
||
|
(typeid(T) == typeid(double));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|