liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

vector.hpp (2266B)


      1 #pragma once
      2 #include "linux.hpp"
      3 
      4 inline void* operator new(size_t, void* p) noexcept
      5 {
      6 	return p;
      7 }
      8 
      9 struct false_type { static constexpr bool value = false; };
     10 struct true_type { static constexpr bool value = true; };
     11 
     12 template<typename T, typename U> struct is_same : false_type {};
     13 template<typename T> struct is_same<T, T> : true_type {};
     14 template<typename T, typename U> constexpr bool is_same_v = is_same<T, U>::value;
     15 
     16 template <typename T>
     17 consteval unsigned bits()
     18 {
     19 	if constexpr (is_same_v<T, uint64_t>)
     20 		return 64;
     21 	if constexpr (is_same_v<T, int64_t>)
     22 		return 64;
     23 	if constexpr (is_same_v<T, uint32_t>)
     24 		return 32;
     25 	if constexpr (is_same_v<T, int32_t>)
     26 		return 32;
     27 }
     28 
     29 static_assert(bits<int64_t>() == 64);
     30 static_assert(bits<uint64_t>() == 64);
     31 static_assert(bits<int32_t>() == 32);
     32 static_assert(bits<uint32_t>() == 32);
     33 
     34 constexpr size_t next_power_of_two(size_t n)
     35 {
     36 	if (not n)
     37 		return n;
     38 	--n;
     39 	for (unsigned i = 1; i <= bits<size_t>(); i <<= 1)
     40 		n |= n >> i;
     41 	return ++n;
     42 }
     43 
     44 template <typename T>
     45 struct vector
     46 {
     47 	vector() = default;
     48 	~vector()
     49 	{
     50 		for (auto p = buf + used; p != buf; --p)
     51 			p->~T();
     52 		if (buf)
     53 			*munmap(buf, capacity);
     54 	}
     55 	vector(vector const& old)
     56 	{
     57 		reserve(old.size());
     58 		push_back(old);
     59 	}
     60 	vector& operator =(vector const&) = delete; // todo: clear, assign
     61 
     62 	void reserve(size_t min)
     63 	{
     64 		min *= sizeof(T);
     65 		if (min <= capacity)
     66 			return;
     67 		min = min <= 4096u ? 4096u : next_power_of_two(min);
     68 		auto new_buf = reinterpret_cast<T*>(*mmap(nullptr, min, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0));
     69 		for (size_t i = 0; i < used; ++i)
     70 		{
     71 			new (new_buf + i) T{buf[i]};
     72 			buf[i].~T();
     73 		}
     74 		if (buf)
     75 			*munmap(buf, capacity);
     76 		buf = new_buf;
     77 		capacity = min;
     78 	}
     79 	void push_back(T c)
     80 	{
     81 		reserve(used + 1);
     82 		new (buf + used++) T{c};
     83 	}
     84 	void push_back(span<T const> data)
     85 	{
     86 		reserve(size() + data.size());
     87 		T* p = buf + used;
     88 		for (auto const& x : data)
     89 			new (p++) T{x};
     90 		used += data.size();
     91 	}
     92 
     93 	T const* data() const { return buf; }
     94 	T* data() { return buf; }
     95 	size_t size() const { return used; }
     96 
     97   operator span<T>() const { return {buf, used}; }
     98   T* begin() { return buf; }
     99   T* end() { return buf + used; }
    100 
    101 private:
    102 	T* buf = nullptr;
    103 	size_t capacity = 0, used = 0;
    104 };