Cube-World-Commands-Mod/cwmods/msvc/vector.h

210 lines
4.8 KiB
C++

// based on https://github.com/Andoryuuta/cwsdk/blob/master/cwsdk/msvc_bincompat/vector.h
#ifndef MSVC_VECTOR_H
#define MSVC_VECTOR_H
#include <iostream>
#include <stdexcept>
#include <cstdint>
#include <windows.h>
#include "allocator.h"
namespace msvc {
template <typename T>
struct vector {
private:
T* _start;
T* _end;
T* _cap;
public:
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
typedef T* pointer;
// forward iterator
class iterator {
public:
typedef iterator self_type;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
iterator() {}
iterator(pointer ptr) : _ptr(ptr) { }
self_type operator=(const self_type& other) { _ptr = other._ptr; return *this; }
self_type operator++() { _ptr++; return *this; } // ++i
self_type operator++(int junk) { self_type i = *this; _ptr++; return i; } // i++
self_type operator--() { _ptr--; return *this; }
self_type operator--(int junk) { self_type i = *this; _ptr--; return i; }
reference operator*() { return *_ptr; }
pointer operator->() { return _ptr; }
bool operator==(const self_type& rhs) const { return _ptr == rhs._ptr; }
bool operator!=(const self_type& rhs) const { return _ptr != rhs._ptr; }
private:
pointer _ptr;
};
// const forward iterator
class const_iterator {
public:
typedef const_iterator self_type;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
const_iterator() {}
const_iterator(pointer ptr) : _ptr(ptr) { }
self_type operator++() { _ptr++; return *this; }
self_type operator++(int junk) { self_type i = *this; _ptr++; return i; }
self_type operator--() { _ptr--; return *this; }
self_type operator--(int junk) { self_type i = *this; _ptr--; return i; }
const value_type& operator*() { return *_ptr; }
const value_type* operator->() { return _ptr; }
bool operator==(const self_type& rhs) const { return _ptr == rhs._ptr; }
bool operator!=(const self_type& rhs) const { return _ptr != rhs._ptr; }
private:
pointer _ptr;
};
/* Constructors & Destructors start*/
vector() {
auto mem = (pointer)operator new(0);
_start = mem;
_end = mem;
_cap = mem;
reserve(1);
}
~vector() {
if (_start != nullptr) {
operator delete(_start);
}
}
/* Constructors & Destructors end*/
/* Element access methods start*/
reference at(size_type pos) {
if (pos > size()) {
throw std::out_of_range("index out of bounds");
}
return operator[](pos);
}
reference operator [](size_type pos) {
return _start[pos];
}
reference front() {
return *begin();
}
reference back() {
auto tmp = end();
tmp--;
return *tmp;
}
/* Element access methods end*/
/* Iterators methods start*/
iterator begin() {
return iterator(_start);
}
iterator end() {
return iterator(_end);
}
const_iterator begin() const {
return const_iterator(_start);
}
const_iterator end() const {
return const_iterator(_end);
}
/* Iterators methods end*/
/* Capacity methods start*/
bool empty() const {
return begin() == end();
}
size_type size() const {
return _end - _start;
}
size_type max_size() const {
// Silly, theoretical max container size.
return UINTPTR_MAX / sizeof(T);
}
void reserve(size_type new_cap) {
msvc::allocator<T> thisAllocator;
size_type old_capacity = capacity();
// No need to reserve more if we need less space than we have
if (new_cap <= old_capacity) {
return;
}
if (new_cap > max_size()) {
throw std::length_error("new_cap > max_size()");
}
// Create new backing array
pointer new_backing = thisAllocator.allocate(new_cap);
// Copy old contents to new array
size_type old_size = size();
memcpy((void*)new_backing, (void*)_start, old_size * sizeof(T));
// Remember old array
pointer old_backing = _start;
// Update the vector
_start = new_backing;
_end = new_backing + old_size;
_cap = new_backing + new_cap;
// Deallocate old array
thisAllocator.deallocate(old_backing, old_capacity);
}
size_type capacity() const {
return _cap - _start;
}
/* Capacity methods end*/
/* Modifer methods start*/
void push_back(const T& value) {
if (capacity() == 0) {
reserve(1);
}
else if (size() == capacity()) {
reserve(capacity() * 2);
}
_start[size()] = value;
_end++;
}
void pop_back() {
if (size() > 0) {
back().~T();
_end--;
}
}
void clear() noexcept {
_end = _start;
}
/* Modifer methods end*/
};
}
#endif // MSVC_VECTOR_H