harfbuzz/src/graphite2/src/inc/vector.hpp

193 lines
7.2 KiB
C++

// SPDX-License-Identifier: MIT
// Copyright 2010, SIL International, All rights reserved.
// designed to have a limited subset of the std::vector api
#pragma once
#include <cstddef>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <iterator>
#include <new>
#include "Main.h"
namespace graphite2 {
// template <typename T>
// inline
// ptrdiff_t distance(T* first, T* last) { return last-first; }
template <typename T>
class vector
{
T * m_first, *m_last, *m_end;
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = T&;
using const_reference = T const &;
using pointer = T*;
using const_pointer = T const *;
using iterator = T*;
using const_iterator = T const *;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
constexpr vector() : m_first{nullptr}, m_last{nullptr}, m_end{nullptr} {}
vector(size_type n, const value_type& value) : vector<T>() { insert(begin(), n, value); }
explicit vector(size_type n) : vector<T>(n, T()) {}
template<class It>
vector(It first, const It last) : vector<T>() { insert(begin(), first, last); }
vector(const vector<T> &rhs) : vector<T>(rhs.begin(), rhs.end()) { }
vector(vector<T> &&rhs) : m_first{rhs.m_first}, m_last{rhs.m_last}, m_end{rhs.m_end} { rhs.m_first = rhs.m_last = nullptr; }
vector(std::initializer_list<T> ilist) : vector{ilist.begin(), ilist.end()} {}
~vector() { clear(); free(m_first); }
iterator begin() { return m_first; }
const_iterator cbegin() const { return m_first; }
const_iterator begin() const { return m_first; }
iterator end() { return m_last; }
const_iterator cend() const { return m_last; }
const_iterator end() const { return m_last; }
bool empty() const { return m_first == m_last; }
size_type size() const { return m_last - m_first; }
size_type capacity() const{ return m_end - m_first; }
void reserve(size_type n);
void resize(size_type n, value_type const & v = value_type());
reference front() { assert(size() > 0); return *begin(); }
const_reference front() const { assert(size() > 0); return *begin(); }
reference back() { assert(size() > 0); return *(end()-1); }
const_reference back() const { assert(size() > 0); return *(end()-1); }
vector<T> & operator = (const vector<T> & rhs) { if (&rhs != this) assign(rhs.begin(), rhs.end()); return *this; }
vector<T> & operator = (vector<T> && rhs);
reference operator [] (size_type n) { assert(size() > n); return m_first[n]; }
const_reference operator [] (size_type n) const { assert(size() > n); return m_first[n]; }
void assign(size_type n, const value_type& u) { clear(); insert(begin(), n, u); }
template<class It>
void assign(It first, It last) { clear(); insert(begin(), first, last); }
void assign(std::initializer_list<T> ilist) { assign(ilist.begin(), ilist.end()); }
iterator insert(const_iterator p, const value_type & x) { auto n = _insert_default(p, 1); new (n) value_type(x); return n; }
iterator insert(const_iterator p, value_type && x) { auto n = _insert_default(p, 1); new (n) value_type(std::move(x)); return n; }
iterator insert(const_iterator p, size_type n, const T & x);
template<class It>
iterator insert(const_iterator p, It first, It last);
void pop_back() { assert(size() > 0); --m_last; }
void push_back(const value_type &v) { if (m_last == m_end) reserve(size()+1); new (m_last++) value_type(v); }
void push_back(value_type && v) { if (m_last == m_end) reserve(size()+1); new (m_last++) value_type(std::move(v)); }
template<typename... Args>
iterator emplace(const_iterator p, Args &&... args) { auto n = _insert_default(p, 1); new (n) value_type(std::forward<Args>(args)...); return n; }
template<typename... Args>
reference emplace_back(Args &&... args) { if (m_last == m_end) reserve(size()+1); return *new (m_last++) value_type(std::forward<Args>(args)...); }
void clear() { erase(begin(), end()); }
iterator erase(const_iterator p) { return erase(p, std::next(p)); }
iterator erase(const_iterator first, const_iterator last);
private:
iterator _insert_default(const_iterator p, size_type n);
};
template <typename T>
inline
void vector<T>::reserve(size_type n)
{
if (n > capacity())
{
const ptrdiff_t sz = size();
size_t requested;
if (checked_mul(n, sizeof(value_type), requested)) std::abort();
m_first = static_cast<value_type*>(realloc(m_first, requested));
if (!m_first) std::abort();
m_last = m_first + sz;
m_end = m_first + n;
}
}
template <typename T>
inline
void vector<T>::resize(size_type n, const value_type & v) {
const ptrdiff_t d = n-size();
if (d < 0) erase(end()+d, end());
else if (d > 0) insert(end(), d, v);
}
template<typename T>
inline
vector<T> & vector<T>::operator = (vector<T> && rhs) {
if (&rhs != this) {
clear();
m_first = rhs.m_first;
m_last = rhs.m_last;
m_end = rhs.m_end;
rhs.m_first = rhs.m_last = nullptr;
}
return *this;
}
template<typename T>
inline
auto vector<T>::_insert_default(const_iterator p, size_type n) -> iterator
{
assert(begin() <= p && p <= end());
const ptrdiff_t d = p - begin();
reserve(((size() + n + 7) >> 3) << 3);
auto i = begin() + d;
// Move tail if there is one
if (i != end()) memmove(i + n, i, std::distance(i, end())*sizeof(value_type));
m_last += n;
return i;
}
template<typename T>
inline
auto vector<T>::insert(const_iterator p, size_type n, const T & x) -> iterator
{
auto const i = _insert_default(p, n);
// Copy in elements
for (auto u = i; n; --n, ++u) { new (u) value_type(x); }
return i;
}
template<typename T>
template<class It>
inline
auto vector<T>::insert(const_iterator p, It first, It last) -> iterator
{
auto const i = _insert_default(p, std::distance(first, last));
// Copy in elements
for (auto u = i;first != last; ++first, ++u) { new (u) value_type(*first); }
return i;
}
template<typename T>
inline
auto vector<T>::erase(const_iterator first, const_iterator last) -> iterator
{
if (first != last)
{
for (iterator e = const_cast<iterator>(first); e != last; ++e)
e->~value_type();
auto const sz = std::distance(first, last);
if (m_last != last) memmove(const_cast<iterator>(first),
last,
std::distance(last, cend())*sizeof(value_type));
m_last -= sz;
}
return const_cast<iterator>(first);
}
} // namespace graphite2