mirror of
https://github.com/eversinc33/Banshee
synced 2026-06-08 14:08:04 +00:00
253 lines
5.7 KiB
C++
253 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include <ntifs.h>
|
|
#include <wdf.h>
|
|
|
|
#include "DriverMeta.hpp"
|
|
|
|
// https://github.com/gauraVsehgaL/cppkernel/blob/master/vector.hpp
|
|
// Placement new
|
|
inline PVOID operator new(SIZE_T, PVOID where)
|
|
{
|
|
return where;
|
|
}
|
|
|
|
// TEMPLATE CLASS remove_reference
|
|
template <class _Ty>
|
|
struct remove_reference
|
|
{ // remove reference
|
|
typedef _Ty type;
|
|
};
|
|
|
|
template <class _Ty>
|
|
struct remove_reference<_Ty&>
|
|
{ // remove reference
|
|
typedef _Ty type;
|
|
};
|
|
|
|
template <class _Ty>
|
|
struct remove_reference<_Ty&&>
|
|
{ // remove rvalue reference
|
|
typedef _Ty type;
|
|
};
|
|
|
|
template <typename T>
|
|
typename remove_reference<T>::type&& move(T&& arg)
|
|
{
|
|
return static_cast<typename remove_reference<T>::type&&>(arg);
|
|
}
|
|
|
|
// TEMPLATE FUNCTION forward
|
|
template <class _Ty>
|
|
inline constexpr _Ty&& forward(typename remove_reference<_Ty>::type& _Arg)
|
|
{ // forward an lvalue as either an lvalue or an rvalue
|
|
return (static_cast<_Ty&&>(_Arg));
|
|
}
|
|
|
|
template <class _Ty>
|
|
inline constexpr _Ty&& forward(typename remove_reference<_Ty>::type&& _Arg)
|
|
{ // forward an rvalue as an rvalue
|
|
return (static_cast<_Ty&&>(_Arg));
|
|
}
|
|
|
|
namespace ktd
|
|
{
|
|
template <typename T, POOL_TYPE PoolType>
|
|
class vector
|
|
{
|
|
public:
|
|
unsigned long Tag = DRIVER_TAG;
|
|
|
|
vector() : ptr(nullptr), Capacity(0), NumberOfElements(0)
|
|
{
|
|
}
|
|
|
|
vector(SIZE_T InitialNumberOfElements) : ptr(nullptr), Capacity(0), NumberOfElements(0)
|
|
{
|
|
reserve(InitialNumberOfElements);
|
|
NumberOfElements = InitialNumberOfElements;
|
|
for (auto i = 0UL; i < NumberOfElements; i++) new (ptr + i) T();
|
|
}
|
|
|
|
vector(SIZE_T InitialNumberOfElements, T val) : vector(InitialNumberOfElements)
|
|
{
|
|
reserve(InitialNumberOfElements);
|
|
NumberOfElements = InitialNumberOfElements;
|
|
for (auto i = 0UL; i < NumberOfElements; i++) new (ptr + i) T(val);
|
|
}
|
|
|
|
vector(const vector<T, PoolType>& other) : vector()
|
|
{
|
|
reserve(other.Capacity);
|
|
NumberOfElements = other.NumberOfElements;
|
|
for (auto i = 0UL; i < NumberOfElements; i++) new (ptr + i) T(other.ptr[i]);
|
|
}
|
|
|
|
vector(vector<T, PoolType>&& other) : Capacity(other.Capacity), NumberOfElements(other.NumberOfElements)
|
|
{
|
|
this->ptr = other.ptr;
|
|
other.ptr = nullptr;
|
|
}
|
|
|
|
vector<T, PoolType>& operator=(vector<T, PoolType>&& other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
this->Capacity = other.Capacity;
|
|
this->NumberOfElements = other.NumberOfElements;
|
|
this->ptr = other.ptr;
|
|
other.ptr = nullptr;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
vector<T, PoolType>& operator=(const vector<T, PoolType>& other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
if (this->Capacity < other.Capacity)
|
|
{
|
|
this->Capacity = other.Capacity;
|
|
auto OrigPtr = this->ptr;
|
|
this->ptr = allocate(Capacity);
|
|
destroy(OrigPtr, this->NumberOfElements);
|
|
deallocate(OrigPtr);
|
|
}
|
|
|
|
this->NumberOfElements = other.NumberOfElements;
|
|
|
|
for (auto i = 0UL; i < NumberOfElements; i++) ptr[i] = other.ptr[i];
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
~vector()
|
|
{
|
|
// explicitly call destructors if required.
|
|
if (!ptr)
|
|
return;
|
|
|
|
for (auto i = 0UL; i < NumberOfElements; i++) ptr[i].~T();
|
|
|
|
deallocate(ptr);
|
|
}
|
|
|
|
VOID reserve(SIZE_T NewCapacity)
|
|
{
|
|
if (NewCapacity <= Capacity || NewCapacity == 0)
|
|
return;
|
|
|
|
auto origptr = ptr;
|
|
ptr = allocate(NewCapacity);
|
|
|
|
for (auto i = 0UL; i < NumberOfElements; i++) new (ptr + i) T(origptr[i]);
|
|
|
|
Capacity = NewCapacity;
|
|
|
|
if (origptr)
|
|
{
|
|
for (auto i = 0UL; i < NumberOfElements; i++) origptr[i].~T();
|
|
|
|
deallocate(origptr);
|
|
}
|
|
}
|
|
|
|
VOID push_back(const T& val)
|
|
{
|
|
auto NewCapacity = Capacity;
|
|
if (NumberOfElements + 1 > Capacity)
|
|
{
|
|
// re allocate.
|
|
if (Capacity == 0)
|
|
NewCapacity = 1;
|
|
|
|
NewCapacity *= 2;
|
|
|
|
reserve(NewCapacity);
|
|
}
|
|
|
|
new (ptr + NumberOfElements) T(val);
|
|
NumberOfElements++;
|
|
}
|
|
|
|
VOID push_back(T&& val)
|
|
{
|
|
auto NewCapacity = Capacity;
|
|
if (NumberOfElements + 1 > Capacity)
|
|
{
|
|
// re allocate.
|
|
if (Capacity == 0)
|
|
NewCapacity = 1;
|
|
|
|
NewCapacity *= 2;
|
|
|
|
reserve(NewCapacity);
|
|
}
|
|
|
|
new (ptr + NumberOfElements) T(move(val));
|
|
NumberOfElements++;
|
|
}
|
|
|
|
template <class... Args>
|
|
T& emplace_back(Args&&... args)
|
|
{
|
|
auto NewCapacity = Capacity;
|
|
if (NumberOfElements + 1 > Capacity)
|
|
{
|
|
// re allocate.
|
|
if (Capacity == 0)
|
|
NewCapacity = 1;
|
|
|
|
NewCapacity *= 2;
|
|
|
|
reserve(NewCapacity);
|
|
}
|
|
|
|
new (ptr + NumberOfElements) T(forward<Args>(args)...);
|
|
|
|
return ptr[NumberOfElements++];
|
|
}
|
|
|
|
SIZE_T size()
|
|
{
|
|
return this->NumberOfElements;
|
|
}
|
|
|
|
T& operator[](SIZE_T index)
|
|
{
|
|
return ptr[index];
|
|
}
|
|
|
|
VOID Clear()
|
|
{
|
|
destroy(ptr, NumberOfElements);
|
|
NumberOfElements = 0;
|
|
}
|
|
|
|
private:
|
|
T* ptr;
|
|
SIZE_T Capacity;
|
|
SIZE_T NumberOfElements;
|
|
|
|
T* allocate(SIZE_T NewCapacity)
|
|
{
|
|
return static_cast<T*>(ExAllocatePoolWithTag(PoolType, sizeof(T) * NewCapacity, Tag));
|
|
}
|
|
|
|
VOID destroy(T* mem, SIZE_T NumElems)
|
|
{
|
|
if (!mem)
|
|
return;
|
|
|
|
for (auto i = 0UL; i < NumElems; i++) mem[i].~T();
|
|
}
|
|
|
|
VOID deallocate(T* mem)
|
|
{
|
|
if (mem)
|
|
ExFreePool(mem);
|
|
}
|
|
};
|
|
} // namespace ktd
|