This repository has been archived on 2025-02-26. You can view files and clone it, but cannot push or open issues or pull requests.
hilbert-os/kernel/include/hilbert/kernel/utility.hpp
2024-07-31 13:36:53 -04:00

426 lines
9.6 KiB
C++

#pragma once
#include <stddef.h>
#include <stdint.h>
void *operator new(size_t, void *ptr);
void operator delete(void *, void *);
namespace hilbert::kernel::utility {
template <class t>
struct no_ref;
template <class t>
struct no_ref<t &&> {
typedef t _t;
};
template <class t>
struct no_ref<t &> {
typedef t _t;
};
template <class t>
struct no_ref {
typedef t _t;
};
template <class t>
constexpr typename no_ref<t>::_t &&move(t &&v) {
return static_cast<typename no_ref<t>::_t &&>(v);
}
template <class t>
static inline t min(t a, t b) {
return a < b ? a : b;
}
//includes start_i, does not include end_i
void mark_bitmap_region_zero(
uint64_t *bitmap, uint64_t start_i, uint64_t end_i);
//includes start_i, does not include end_i
void mark_bitmap_region_one(
uint64_t *bitmap, uint64_t start_i, uint64_t end_i);
struct uuid {
uint8_t bytes[16];
};
//if c appears in str, this returns the index of the first time it appears.
//otherwise, this returns len.
static inline unsigned find(const char *str, unsigned len, char c) {
for (unsigned i = 0; i < len; ++i)
if (str[i] == c)
return i;
return len;
}
//if c appears in str, this returns the index of the last time it appears.
//otherwise, this returns len.
static inline unsigned find_last(const char *str, unsigned len, char c) {
for (unsigned i = len; i > 0; --i)
if (str[i - 1] == c)
return i - 1;
return len;
}
//str1 starts with str2
static inline bool starts_with(
const char *str1, unsigned str1_len, const char *str2, unsigned str2_len
) {
if (str1_len < str2_len)
return false;
for (unsigned i = 0; i < str2_len; ++i)
if (str1[i] != str2[i])
return false;
return true;
}
template <class value_t>
struct list {
struct node {
value_t value;
node *next;
node *prev;
};
node *first;
node *last;
list() : first(0), last(0) {}
list(const list &other) = delete;
list(list &&other) = delete;
~list() {
if (first) {
for (node *n = first->next; n; n = n->next)
delete n->prev;
delete last;
}
}
list &operator =(const list &other) = delete;
list &operator =(list &&other) = delete;
void insert_end(const value_t &value) {
node *n = new node {};
n->value = value;
n->next = 0;
n->prev = last;
if (last)
last->next = n;
else
first = n;
last = n;
}
void insert_end(value_t &&value) {
node *n = new node {};
n->value = value;
n->next = 0;
n->prev = last;
if (last)
last->next = n;
else
first = n;
last = n;
}
//if other == 0, then insert at the end
void insert_before(value_t &&value, node *other) {
node *n = new node {};
n->value = value;
n->next = other;
if (other) {
n->prev = other->prev;
other->prev = n;
}
else {
n->prev = last;
last = n;
}
if (n->prev)
n->prev->next = n;
else
first = n;
}
void clear() {
if (first) {
for (node *n = first->next; n; n = n->next)
delete n->prev;
delete last;
}
first = 0;
last = 0;
}
//assumes there is a last.
void remove_last() {
node *new_last = last->prev;
if (new_last)
new_last->next = 0;
else
first = 0;
delete last;
last = new_last;
}
void remove(node *n) {
if (n->prev)
n->prev->next = n->next;
else
first = n->next;
if (n->next)
n->next->prev = n->prev;
else
last = n->prev;
delete n;
}
void remove_first_of(const value_t &value) {
for (node *n = first; n; n = n->next)
if (n->value == value) {
remove(n);
return;
}
}
};
template <class value_t>
struct vector {
value_t *buffer;
unsigned buffer_len;
unsigned count;
vector(unsigned buffer_len = 16)
: buffer(new value_t[buffer_len]), buffer_len(buffer_len), count(0) {}
vector(const value_t *copy_from, unsigned len)
: buffer(new value_t[len]), buffer_len(len), count(len) {
for (unsigned i = 0; i < len; ++i)
buffer[i] = copy_from[i];
}
vector(const vector &other)
: buffer(new value_t[other.buffer_len]),
buffer_len(other.buffer_len), count(other.count)
{
for (unsigned i = 0; i < count; ++i)
buffer[i] = other.buffer[i];
}
vector(vector &&other) = delete;
~vector() {
if (buffer)
delete[] buffer;
}
vector &operator =(const vector &other) {
if (buffer)
delete[] buffer;
buffer = new value_t[other.buffer_len];
buffer_len = other.buffer_len;
count = other.count;
for (unsigned i = 0; i < other.count; ++i)
buffer[i] = other.buffer[i];
return *this;
}
vector &operator =(vector &&other) {
if (buffer)
delete[] buffer;
buffer = other.buffer;
buffer_len = other.buffer_len;
count = other.count;
other.buffer = 0;
return *this;
}
bool operator ==(const vector &other) {
if (other.count != count)
return false;
for (unsigned i = 0; i < count; ++i)
if (other.buffer[i] != buffer[i])
return false;
return true;
}
void verify_buffer_len(unsigned target_len) {
if (buffer_len >= target_len)
return;
unsigned new_buffer_len = buffer_len;
do
new_buffer_len *= 2;
while (new_buffer_len < target_len);
value_t *new_buffer = new value_t[new_buffer_len];
for (unsigned i = 0; i < count; ++i)
new_buffer[i] = move(buffer[i]);
delete[] buffer;
buffer = new_buffer;
buffer_len = new_buffer_len;
}
void add_end(value_t &&v) {
verify_buffer_len(count + 1);
buffer[count] = move(v);
++count;
}
void add_end(const value_t &v) {
verify_buffer_len(count + 1);
buffer[count] = v;
++count;
}
bool starts_with(const vector &other) {
if (count < other.count)
return false;
for (unsigned i = 0; i < other.count; ++i)
if (buffer[i] != other.buffer[i])
return false;
return true;
}
};
typedef vector<char> string;
template <class value_t>
struct id_allocator {
vector<value_t *> the_vector;
public:
id_allocator() : the_vector() {}
id_allocator(const id_allocator &other) = delete;
id_allocator(id_allocator &&other) = delete;
id_allocator &operator =(const id_allocator &other) = delete;
id_allocator &operator =(id_allocator &&other) = delete;
//returns id; pointer becomes owned by id_allocator
unsigned add(value_t *v) {
for (unsigned i = 0; i < the_vector.count; ++i)
if (the_vector.buffer[i] == 0) {
the_vector.buffer[i] = v;
return i;
}
the_vector.add_end(v);
return the_vector.count - 1;
}
//returns id
unsigned add_new(value_t &&v) {
return add(new value_t(move(v)));
}
//pionter becomes owned by id_allocator
void add_id(value_t *v, unsigned i) {
the_vector.verify_buffer_len(i + 1);
the_vector.buffer[i] = v;
}
bool has_id(unsigned i) {
return i < the_vector.count && the_vector.buffer[i] != 0;
}
value_t &get(unsigned i) {
return *the_vector.buffer[i];
}
value_t *take(unsigned i) {
value_t *v = the_vector.buffer[i];
the_vector.buffer[i] = 0;
return v;
}
void remove_id(unsigned i) {
delete the_vector.buffer[i];
the_vector.buffer[i] = 0;
}
};
template <class value_t>
struct queue {
value_t *buffer;
unsigned buffer_len;
unsigned count;
unsigned next_read_index;
queue(unsigned initial_len = 1024) : buffer(new value_t[initial_len]),
buffer_len(initial_len), count(0), next_read_index(0) { }
~queue() {
delete[] buffer;
}
void insert(const value_t &v) {
if (count == buffer_len) {
value_t *new_buffer = new value_t[buffer_len * 2];
for (unsigned i = 0; i < buffer_len - next_read_index; ++i)
new_buffer[i] = move(buffer[i + next_read_index]);
for (unsigned i = buffer_len - next_read_index; i < buffer_len; ++i)
new_buffer[i] = move(buffer[i + next_read_index - buffer_len]);
delete[] buffer;
buffer = new_buffer;
buffer_len *= 2;
next_read_index = 0;
}
buffer[(count + next_read_index) % buffer_len] = v;
++count;
}
//assumes not empty
const value_t &peek() const {
return buffer[next_read_index];
}
//assumes not empty
value_t &&take() {
value_t &&ret = move(buffer[next_read_index]);
if (++next_read_index == buffer_len)
next_read_index = 0;
--count;
return move(ret);
}
//assumes not empty
value_t &last_inserted() const {
return buffer[(count - 1 + next_read_index) % buffer_len];
}
void remove(const value_t &v) {
unsigned written = 0;
for (unsigned i = 0; i < count; ++i) {
unsigned read_idx = (next_read_index + i) % buffer_len;
unsigned write_idx = (next_read_index + written) % buffer_len;
if (buffer[read_idx] != v) {
if (read_idx != write_idx)
buffer[write_idx] = utility::move(buffer[read_idx]);
++written;
}
}
count = written;
}
void clear() {
count = 0;
}
};
template <class t>
struct maybe {
bool has_value;
t value;
};
}