forked from Bananymous/banan-os
All: rename every function from UpperCamelCase to snake_case
This was a mess since I didn't know which to use but now I decided to go with snake_case :)
This commit is contained in:
parent
4faa662a59
commit
9b8de5025a
|
@ -17,12 +17,12 @@ namespace BAN
|
||||||
|
|
||||||
String::String(const String& other)
|
String::String(const String& other)
|
||||||
{
|
{
|
||||||
MUST(copy_impl(other.SV()));
|
MUST(copy_impl(other.sv()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String::String(String&& other)
|
String::String(String&& other)
|
||||||
{
|
{
|
||||||
move_impl(Move(other));
|
move_impl(move(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
String::String(StringView other)
|
String::String(StringView other)
|
||||||
|
@ -37,14 +37,14 @@ namespace BAN
|
||||||
|
|
||||||
String& String::operator=(const String& other)
|
String& String::operator=(const String& other)
|
||||||
{
|
{
|
||||||
MUST(copy_impl(other.SV()));
|
MUST(copy_impl(other.sv()));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String& String::operator=(String&& other)
|
String& String::operator=(String&& other)
|
||||||
{
|
{
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
move_impl(Move(other));
|
move_impl(move(other));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,19 +54,19 @@ namespace BAN
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::PushBack(char ch)
|
ErrorOr<void> String::push_back(char ch)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(m_size + 2));
|
TRY(ensure_capacity(m_size + 2));
|
||||||
m_data[m_size] = ch;
|
m_data[m_size] = ch;
|
||||||
m_size++;
|
m_size++;
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Insert(char ch, size_type index)
|
ErrorOr<void> String::insert(char ch, size_type index)
|
||||||
{
|
{
|
||||||
ASSERT(index <= m_size);
|
ASSERT(index <= m_size);
|
||||||
TRY(EnsureCapasity(m_size + 1 + 1));
|
TRY(ensure_capacity(m_size + 1 + 1));
|
||||||
memmove(m_data + index + 1, m_data + index, m_size - index);
|
memmove(m_data + index + 1, m_data + index, m_size - index);
|
||||||
m_data[index] = ch;
|
m_data[index] = ch;
|
||||||
m_size += 1;
|
m_size += 1;
|
||||||
|
@ -74,45 +74,45 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Insert(StringView other, size_type index)
|
ErrorOr<void> String::insert(StringView other, size_type index)
|
||||||
{
|
{
|
||||||
ASSERT(index <= m_size);
|
ASSERT(index <= m_size);
|
||||||
TRY(EnsureCapasity(m_size + other.Size() + 1));
|
TRY(ensure_capacity(m_size + other.size() + 1));
|
||||||
memmove(m_data + index + other.Size(), m_data + index, m_size - index);
|
memmove(m_data + index + other.size(), m_data + index, m_size - index);
|
||||||
memcpy(m_data + index, other.Data(), other.Size());
|
memcpy(m_data + index, other.data(), other.size());
|
||||||
m_size += other.Size();
|
m_size += other.size();
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Append(StringView other)
|
ErrorOr<void> String::append(StringView other)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(m_size + other.Size() + 1));
|
TRY(ensure_capacity(m_size + other.size() + 1));
|
||||||
memcpy(m_data + m_size, other.Data(), other.Size());
|
memcpy(m_data + m_size, other.data(), other.size());
|
||||||
m_size += other.Size();
|
m_size += other.size();
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Append(const String& string)
|
ErrorOr<void> String::append(const String& string)
|
||||||
{
|
{
|
||||||
TRY(Append(string.SV()));
|
TRY(append(string.sv()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::PopBack()
|
void String::pop_back()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
m_size--;
|
m_size--;
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::Remove(size_type index)
|
void String::remove(size_type index)
|
||||||
{
|
{
|
||||||
Erase(index, 1);
|
erase(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::Erase(size_type index, size_type count)
|
void String::erase(size_type index, size_type count)
|
||||||
{
|
{
|
||||||
ASSERT(index + count <= m_size);
|
ASSERT(index + count <= m_size);
|
||||||
memmove(m_data + index, m_data + index + count, m_size - index - count);
|
memmove(m_data + index, m_data + index + count, m_size - index - count);
|
||||||
|
@ -120,7 +120,7 @@ namespace BAN
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::Clear()
|
void String::clear()
|
||||||
{
|
{
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
m_data[0] = '\0';
|
m_data[0] = '\0';
|
||||||
|
@ -147,9 +147,9 @@ namespace BAN
|
||||||
|
|
||||||
bool String::operator==(StringView other) const
|
bool String::operator==(StringView other) const
|
||||||
{
|
{
|
||||||
if (m_size != other.Size())
|
if (m_size != other.size())
|
||||||
return false;
|
return false;
|
||||||
return memcmp(m_data, other.Data(), m_size) == 0;
|
return memcmp(m_data, other.data(), m_size) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String::operator==(const char* other) const
|
bool String::operator==(const char* other) const
|
||||||
|
@ -160,7 +160,7 @@ namespace BAN
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Resize(size_type size, char ch)
|
ErrorOr<void> String::resize(size_type size, char ch)
|
||||||
{
|
{
|
||||||
if (size < m_size)
|
if (size < m_size)
|
||||||
{
|
{
|
||||||
|
@ -169,7 +169,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
else if (size > m_size)
|
else if (size > m_size)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(size + 1));
|
TRY(ensure_capacity(size + 1));
|
||||||
for (size_type i = m_size; i < size; i++)
|
for (size_type i = m_size; i < size; i++)
|
||||||
m_data[i] = ch;
|
m_data[i] = ch;
|
||||||
m_data[size] = '\0';
|
m_data[size] = '\0';
|
||||||
|
@ -179,58 +179,58 @@ namespace BAN
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::Reserve(size_type size)
|
ErrorOr<void> String::reserve(size_type size)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(size));
|
TRY(ensure_capacity(size));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView String::SV() const
|
StringView String::sv() const
|
||||||
{
|
{
|
||||||
return StringView(*this);
|
return StringView(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String::Empty() const
|
bool String::empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::size_type String::Size() const
|
String::size_type String::size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::size_type String::Capasity() const
|
String::size_type String::capacity() const
|
||||||
{
|
{
|
||||||
return m_capasity;
|
return m_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* String::Data() const
|
const char* String::data() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::EnsureCapasity(size_type size)
|
ErrorOr<void> String::ensure_capacity(size_type size)
|
||||||
{
|
{
|
||||||
if (m_capasity >= size)
|
if (m_capacity >= size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capasity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
||||||
void* new_data = BAN::allocator(new_cap);
|
void* new_data = BAN::allocator(new_cap);
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::FromString("String: Could not allocate memory");
|
return Error::from_string("String: Could not allocate memory");
|
||||||
if (m_data)
|
if (m_data)
|
||||||
memcpy(new_data, m_data, m_size + 1);
|
memcpy(new_data, m_data, m_size + 1);
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = (char*)new_data;
|
m_data = (char*)new_data;
|
||||||
m_capasity = new_cap;
|
m_capacity = new_cap;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> String::copy_impl(StringView other)
|
ErrorOr<void> String::copy_impl(StringView other)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(other.Size() + 1));
|
TRY(ensure_capacity(other.size() + 1));
|
||||||
memcpy(m_data, other.Data(), other.Size());
|
memcpy(m_data, other.data(), other.size());
|
||||||
m_size = other.Size();
|
m_size = other.size();
|
||||||
m_data[m_size] = '\0';
|
m_data[m_size] = '\0';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -239,11 +239,11 @@ namespace BAN
|
||||||
{
|
{
|
||||||
m_data = other.m_data;
|
m_data = other.m_data;
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
m_capasity = other.m_capasity;
|
m_capacity = other.m_capacity;
|
||||||
|
|
||||||
other.m_data = nullptr;
|
other.m_data = nullptr;
|
||||||
other.m_size = 0;
|
other.m_size = 0;
|
||||||
other.m_capasity = 0;
|
other.m_capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace BAN
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
StringView::StringView(const String& other)
|
StringView::StringView(const String& other)
|
||||||
: StringView(other.Data(), other.Size())
|
: StringView(other.data(), other.size())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
StringView::StringView(const char* string, size_type len)
|
StringView::StringView(const char* string, size_type len)
|
||||||
|
@ -30,9 +30,9 @@ namespace BAN
|
||||||
|
|
||||||
bool StringView::operator==(const String& other) const
|
bool StringView::operator==(const String& other) const
|
||||||
{
|
{
|
||||||
if (m_size != other.Size())
|
if (m_size != other.size())
|
||||||
return false;
|
return false;
|
||||||
return memcmp(m_data, other.Data(), m_size) == 0;
|
return memcmp(m_data, other.data(), m_size) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringView::operator==(StringView other) const
|
bool StringView::operator==(StringView other) const
|
||||||
|
@ -49,7 +49,7 @@ namespace BAN
|
||||||
return other[m_size] == '\0';
|
return other[m_size] == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView StringView::Substring(size_type index, size_type len) const
|
StringView StringView::substring(size_type index, size_type len) const
|
||||||
{
|
{
|
||||||
ASSERT(index <= m_size);
|
ASSERT(index <= m_size);
|
||||||
if (len == size_type(-1))
|
if (len == size_type(-1))
|
||||||
|
@ -61,14 +61,14 @@ namespace BAN
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Vector<StringView>> StringView::Split(char delim, bool allow_empties)
|
ErrorOr<Vector<StringView>> StringView::split(char delim, bool allow_empties)
|
||||||
{
|
{
|
||||||
// FIXME: Won't work while multithreading
|
// FIXME: Won't work while multithreading
|
||||||
static char s_delim = delim;
|
static char s_delim = delim;
|
||||||
return Split([](char c){ return c == s_delim; }, allow_empties);
|
return split([](char c){ return c == s_delim; }, allow_empties);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<Vector<StringView>> StringView::Split(bool(*comp)(char), bool allow_empties)
|
ErrorOr<Vector<StringView>> StringView::split(bool(*comp)(char), bool allow_empties)
|
||||||
{
|
{
|
||||||
size_type count = 0;
|
size_type count = 0;
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<StringView> result;
|
Vector<StringView> result;
|
||||||
TRY(result.Reserve(count));
|
TRY(result.reserve(count));
|
||||||
|
|
||||||
size_type start = 0;
|
size_type start = 0;
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
|
@ -95,28 +95,28 @@ namespace BAN
|
||||||
if (comp(m_data[i]))
|
if (comp(m_data[i]))
|
||||||
{
|
{
|
||||||
if (allow_empties || start != i)
|
if (allow_empties || start != i)
|
||||||
TRY(result.PushBack(this->Substring(start, i - start)));
|
TRY(result.push_back(this->substring(start, i - start)));
|
||||||
start = i + 1;
|
start = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (start != m_size)
|
if (start != m_size)
|
||||||
TRY(result.PushBack(this->Substring(start)));
|
TRY(result.push_back(this->substring(start)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char StringView::Back() const
|
char StringView::back() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return m_data[m_size - 1];
|
return m_data[m_size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
char StringView::Front() const
|
char StringView::front() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView::size_type StringView::Count(char ch) const
|
StringView::size_type StringView::count(char ch) const
|
||||||
{
|
{
|
||||||
size_type result = 0;
|
size_type result = 0;
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
|
@ -125,17 +125,17 @@ namespace BAN
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringView::Empty() const
|
bool StringView::empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView::size_type StringView::Size() const
|
StringView::size_type StringView::size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* StringView::Data() const
|
const char* StringView::data() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@ namespace BAN
|
||||||
const T& operator[](size_type) const;
|
const T& operator[](size_type) const;
|
||||||
T& operator[](size_type);
|
T& operator[](size_type);
|
||||||
|
|
||||||
const T& Back() const;
|
const T& back() const;
|
||||||
T& Back();
|
T& back();
|
||||||
const T& Front() const;
|
const T& front() const;
|
||||||
T& Front();
|
T& front();
|
||||||
|
|
||||||
constexpr size_type Size() const;
|
constexpr size_type size() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T m_data[S];
|
T m_data[S];
|
||||||
|
@ -61,35 +61,35 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
const T& Array<T, S>::Back() const
|
const T& Array<T, S>::back() const
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[S - 1];
|
return m_data[S - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
T& Array<T, S>::Back()
|
T& Array<T, S>::back()
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[S - 1];
|
return m_data[S - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
const T& Array<T, S>::Front() const
|
const T& Array<T, S>::front() const
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
T& Array<T, S>::Front()
|
T& Array<T, S>::front()
|
||||||
{
|
{
|
||||||
ASSERT(S != 0);
|
ASSERT(S != 0);
|
||||||
return m_data[0];
|
return m_data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, size_t S>
|
template<typename T, size_t S>
|
||||||
constexpr typename Array<T, S>::size_type Array<T, S>::Size() const
|
constexpr typename Array<T, S>::size_type Array<T, S>::size() const
|
||||||
{
|
{
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
#if defined(__is_kernel)
|
#if defined(__is_kernel)
|
||||||
#include <kernel/Panic.h>
|
#include <kernel/Panic.h>
|
||||||
#define MUST(error) ({ auto e = error; if (e.IsError()) Kernel::Panic("{}", e.GetError()); e.Value(); })
|
#define MUST(error) ({ auto e = error; if (e.is_error()) Kernel::panic("{}", e.get_error()); e.value(); })
|
||||||
#define ASSERT(cond) do { if (!(cond)) Kernel::Panic("ASSERT("#cond") failed"); } while(false)
|
#define ASSERT(cond) do { if (!(cond)) Kernel::panic("ASSERT("#cond") failed"); } while(false)
|
||||||
#else
|
#else
|
||||||
#error "NOT IMPLEMENTED"
|
#error "NOT IMPLEMENTED"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TRY(error) ({ auto e = error; if (e.IsError()) return e.GetError(); e.Value(); })
|
#define TRY(error) ({ auto e = error; if (e.is_error()) return e.get_error(); e.value(); })
|
||||||
|
|
||||||
namespace BAN
|
namespace BAN
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@ namespace BAN
|
||||||
class Error
|
class Error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Error FromString(const char* message)
|
static Error from_string(const char* message)
|
||||||
{
|
{
|
||||||
Error result;
|
Error result;
|
||||||
strncpy(result.m_message, message, sizeof(m_message));
|
strncpy(result.m_message, message, sizeof(m_message));
|
||||||
|
@ -29,8 +29,8 @@ namespace BAN
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GetErrorCode() const { return m_error_code; }
|
uint8_t get_error_code() const { return m_error_code; }
|
||||||
const char* GetMessage() const { return m_message; }
|
const char* get_message() const { return m_message; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char m_message[128];
|
char m_message[128];
|
||||||
|
@ -43,12 +43,12 @@ namespace BAN
|
||||||
public:
|
public:
|
||||||
ErrorOr(const T& value) : m_has_error(false) { m_data = (void*)new T(value); }
|
ErrorOr(const T& value) : m_has_error(false) { m_data = (void*)new T(value); }
|
||||||
ErrorOr(const Error& error) : m_has_error(true) { m_data = (void*)new Error(error); }
|
ErrorOr(const Error& error) : m_has_error(true) { m_data = (void*)new Error(error); }
|
||||||
template<typename S> ErrorOr(const ErrorOr<S>& other) : ErrorOr(other.GetError()) {}
|
template<typename S> ErrorOr(const ErrorOr<S>& other) : ErrorOr(other.get_error()) {}
|
||||||
~ErrorOr() { IsError() ? (delete reinterpret_cast<Error*>(m_data)) : (delete reinterpret_cast<T*>(m_data)); }
|
~ErrorOr() { is_error() ? (delete reinterpret_cast<Error*>(m_data)) : (delete reinterpret_cast<T*>(m_data)); }
|
||||||
|
|
||||||
bool IsError() const { return m_has_error; }
|
bool is_error() const { return m_has_error; }
|
||||||
const Error& GetError() const { return *reinterpret_cast<Error*>(m_data); }
|
const Error& get_error() const { return *reinterpret_cast<Error*>(m_data); }
|
||||||
T& Value() { return *reinterpret_cast<T*>(m_data); }
|
T& value() { return *reinterpret_cast<T*>(m_data); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_has_error = false;
|
bool m_has_error = false;
|
||||||
|
@ -63,9 +63,9 @@ namespace BAN
|
||||||
ErrorOr(const Error& error) : m_error(error) { }
|
ErrorOr(const Error& error) : m_error(error) { }
|
||||||
~ErrorOr() { }
|
~ErrorOr() { }
|
||||||
|
|
||||||
bool IsError() const { return m_has_error; }
|
bool is_error() const { return m_has_error; }
|
||||||
const Error& GetError() const { return m_error; }
|
const Error& get_error() const { return m_error; }
|
||||||
void Value() { }
|
void value() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error m_error;
|
Error m_error;
|
||||||
|
@ -79,9 +79,9 @@ namespace BAN::Formatter
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void print_argument_impl(F putc, const Error& error, const ValueFormat&)
|
void print_argument_impl(F putc, const Error& error, const ValueFormat&)
|
||||||
{
|
{
|
||||||
if (error.GetErrorCode() == 0xFF)
|
if (error.get_error_code() == 0xFF)
|
||||||
print(putc, error.GetMessage());
|
print(putc, error.get_message());
|
||||||
else
|
else
|
||||||
print(putc, "{} ({})", error.GetMessage(), error.GetErrorCode());
|
print(putc, "{} ({})", error.get_message(), error.get_error_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,6 @@ namespace BAN
|
||||||
class String;
|
class String;
|
||||||
class StringView;
|
class StringView;
|
||||||
template<typename> class Vector;
|
template<typename> class Vector;
|
||||||
|
template<typename> class LinkedList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace BAN
|
||||||
Ret operator()(Args... args)
|
Ret operator()(Args... args)
|
||||||
{
|
{
|
||||||
ASSERT(*this);
|
ASSERT(*this);
|
||||||
return reinterpret_cast<CallableBase*>(m_storage)->call(Forward<Args>(args)...);
|
return reinterpret_cast<CallableBase*>(m_storage)->call(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() const
|
operator bool() const
|
||||||
|
@ -67,7 +67,7 @@ namespace BAN
|
||||||
|
|
||||||
virtual Ret call(Args... args) override
|
virtual Ret call(Args... args) override
|
||||||
{
|
{
|
||||||
return m_function(Forward<Args>(args)...);
|
return m_function(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -84,7 +84,7 @@ namespace BAN
|
||||||
|
|
||||||
virtual Ret call(Args... args) override
|
virtual Ret call(Args... args) override
|
||||||
{
|
{
|
||||||
return (m_owner->*m_function)(Forward<Args>(args)...);
|
return (m_owner->*m_function)(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -102,7 +102,7 @@ namespace BAN
|
||||||
|
|
||||||
virtual Ret call(Args... args) override
|
virtual Ret call(Args... args) override
|
||||||
{
|
{
|
||||||
return (m_owner->*m_function)(Forward<Args>(args)...);
|
return (m_owner->*m_function)(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -119,7 +119,7 @@ namespace BAN
|
||||||
|
|
||||||
virtual Ret call(Args... args) override
|
virtual Ret call(Args... args) override
|
||||||
{
|
{
|
||||||
return m_lambda(Forward<Args>(args)...);
|
return m_lambda(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -28,31 +28,31 @@ namespace BAN
|
||||||
LinkedList() = default;
|
LinkedList() = default;
|
||||||
~LinkedList();
|
~LinkedList();
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> PushBack(const T&);
|
[[nodiscard]] ErrorOr<void> push_back(const T&);
|
||||||
[[nodiscard]] ErrorOr<void> PushBack(T&&);
|
[[nodiscard]] ErrorOr<void> push_back(T&&);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(const_iterator, const T&);
|
[[nodiscard]] ErrorOr<void> insert(const_iterator, const T&);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(const_iterator, T&&);
|
[[nodiscard]] ErrorOr<void> insert(const_iterator, T&&);
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard]] ErrorOr<void> EmplaceBack(Args...);
|
[[nodiscard]] ErrorOr<void> emplace_back(Args...);
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard]] ErrorOr<void> Emplace(const_iterator, Args...);
|
[[nodiscard]] ErrorOr<void> emplace(const_iterator, Args...);
|
||||||
|
|
||||||
void PopBack();
|
void pop_back();
|
||||||
void Remove(const_iterator);
|
void remove(const_iterator);
|
||||||
void Clear();
|
void clear();
|
||||||
|
|
||||||
iterator begin() { return iterator(m_data, false); }
|
iterator begin() { return iterator(m_data, false); }
|
||||||
const_iterator begin() const { return const_iterator(m_data, false); }
|
const_iterator begin() const { return const_iterator(m_data, false); }
|
||||||
iterator end() { return iterator(m_last, true); }
|
iterator end() { return iterator(m_last, true); }
|
||||||
const_iterator end() const { return const_iterator(m_last, true); }
|
const_iterator end() const { return const_iterator(m_last, true); }
|
||||||
|
|
||||||
const T& Back() const;
|
const T& back() const;
|
||||||
T& Back();
|
T& back();
|
||||||
const T& Front() const;
|
const T& front() const;
|
||||||
T& Front();
|
T& front();
|
||||||
|
|
||||||
size_type Size() const;
|
size_type size() const;
|
||||||
bool Empty() const;
|
bool empty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Node
|
struct Node
|
||||||
|
@ -166,34 +166,34 @@ namespace BAN
|
||||||
template<typename T>
|
template<typename T>
|
||||||
LinkedList<T>::~LinkedList()
|
LinkedList<T>::~LinkedList()
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> LinkedList<T>::PushBack(const T& value)
|
ErrorOr<void> LinkedList<T>::push_back(const T& value)
|
||||||
{
|
{
|
||||||
return PushBack(Move(T(value)));
|
return push_back(Move(T(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> LinkedList<T>::PushBack(T&& value)
|
ErrorOr<void> LinkedList<T>::push_back(T&& value)
|
||||||
{
|
{
|
||||||
return Insert(end(), Move(value));
|
return insert(end(), Move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> LinkedList<T>::Insert(const_iterator iter, const T& value)
|
ErrorOr<void> LinkedList<T>::insert(const_iterator iter, const T& value)
|
||||||
{
|
{
|
||||||
return Insert(iter, Move(T(value)));
|
return insert(iter, Move(T(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> LinkedList<T>::Insert(const_iterator iter, T&& value)
|
ErrorOr<void> LinkedList<T>::insert(const_iterator iter, T&& value)
|
||||||
{
|
{
|
||||||
Node* next = iter.m_past_end ? nullptr : iter.m_current;
|
Node* next = iter.m_past_end ? nullptr : iter.m_current;
|
||||||
Node* prev = next ? next->prev : m_last;
|
Node* prev = next ? next->prev : m_last;
|
||||||
Node* new_node = TRY(allocate_node());
|
Node* new_node = TRY(allocate_node());
|
||||||
new (&new_node->value) T(Move(value));
|
new (&new_node->value) T(move(value));
|
||||||
new_node->next = next;
|
new_node->next = next;
|
||||||
new_node->prev = prev;
|
new_node->prev = prev;
|
||||||
(prev ? prev->next : m_data) = new_node;
|
(prev ? prev->next : m_data) = new_node;
|
||||||
|
@ -204,19 +204,19 @@ namespace BAN
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> LinkedList<T>::EmplaceBack(Args... args)
|
ErrorOr<void> LinkedList<T>::emplace_back(Args... args)
|
||||||
{
|
{
|
||||||
return Emplace(end(), Forward<Args>(args)...);
|
return emplace(end(), forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> LinkedList<T>::Emplace(const_iterator iter, Args... args)
|
ErrorOr<void> LinkedList<T>::emplace(const_iterator iter, Args... args)
|
||||||
{
|
{
|
||||||
Node* next = iter.m_past_end ? nullptr : iter.m_current;
|
Node* next = iter.m_past_end ? nullptr : iter.m_current;
|
||||||
Node* prev = next ? next->prev : m_last;
|
Node* prev = next ? next->prev : m_last;
|
||||||
Node* new_node = TRY(allocate_node());
|
Node* new_node = TRY(allocate_node());
|
||||||
new (&new_node->value) T(Forward<Args>(args)...);
|
new (&new_node->value) T(forward<Args>(args)...);
|
||||||
new_node->next = next;
|
new_node->next = next;
|
||||||
new_node->prev = prev;
|
new_node->prev = prev;
|
||||||
(prev ? prev->next : m_data) = new_node;
|
(prev ? prev->next : m_data) = new_node;
|
||||||
|
@ -226,13 +226,13 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void LinkedList<T>::PopBack()
|
void LinkedList<T>::pop_back()
|
||||||
{
|
{
|
||||||
return Remove(m_last);
|
return remove(m_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void LinkedList<T>::Remove(const_iterator iter)
|
void LinkedList<T>::remove(const_iterator iter)
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
Node* node = iter.m_current;
|
Node* node = iter.m_current;
|
||||||
|
@ -246,7 +246,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void LinkedList<T>::Clear()
|
void LinkedList<T>::clear()
|
||||||
{
|
{
|
||||||
Node* ptr = m_data;
|
Node* ptr = m_data;
|
||||||
while (ptr)
|
while (ptr)
|
||||||
|
@ -262,41 +262,41 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& LinkedList<T>::Back() const
|
const T& LinkedList<T>::back() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *const_iterator(m_last);
|
return *const_iterator(m_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& LinkedList<T>::Back()
|
T& LinkedList<T>::back()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *iterator(m_last);
|
return *iterator(m_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& LinkedList<T>::Front() const
|
const T& LinkedList<T>::front() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *const_iterator(m_data);
|
return *const_iterator(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& LinkedList<T>::Front()
|
T& LinkedList<T>::front()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *iterator(m_data);
|
return *iterator(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename LinkedList<T>::size_type LinkedList<T>::Size() const
|
typename LinkedList<T>::size_type LinkedList<T>::size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool LinkedList<T>::Empty() const
|
bool LinkedList<T>::empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,7 @@ namespace BAN
|
||||||
{
|
{
|
||||||
Node* node = (Node*)BAN::allocator(sizeof(Node));
|
Node* node = (Node*)BAN::allocator(sizeof(Node));
|
||||||
if (node == nullptr)
|
if (node == nullptr)
|
||||||
return Error::FromString("LinkedList: Could not allocate memory");
|
return Error::from_string("LinkedList: Could not allocate memory");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,22 +70,22 @@ namespace BAN
|
||||||
}
|
}
|
||||||
RefCounted(RefCounted<T>&& other)
|
RefCounted(RefCounted<T>&& other)
|
||||||
{
|
{
|
||||||
*this = Move(other);
|
*this = move(other);
|
||||||
}
|
}
|
||||||
~RefCounted()
|
~RefCounted()
|
||||||
{
|
{
|
||||||
Reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static RefCounted<T> Create(Args... args)
|
static RefCounted<T> create(Args... args)
|
||||||
{
|
{
|
||||||
return RefCounted<T>(new T(Forward<Args>(args)...), new int32_t(1));
|
return RefCounted<T>(new T(forward<Args>(args)...), new int32_t(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
RefCounted<T>& operator=(const RefCounted<T>& other)
|
RefCounted<T>& operator=(const RefCounted<T>& other)
|
||||||
{
|
{
|
||||||
Reset();
|
reset();
|
||||||
if (other)
|
if (other)
|
||||||
{
|
{
|
||||||
m_pointer = other.m_pointer;
|
m_pointer = other.m_pointer;
|
||||||
|
@ -97,13 +97,13 @@ namespace BAN
|
||||||
|
|
||||||
RefCounted<T>& operator=(RefCounted<T>&& other)
|
RefCounted<T>& operator=(RefCounted<T>&& other)
|
||||||
{
|
{
|
||||||
Reset();
|
reset();
|
||||||
m_pointer = other.m_pointer;
|
m_pointer = other.m_pointer;
|
||||||
m_count = other.m_count;
|
m_count = other.m_count;
|
||||||
other.m_pointer = nullptr;
|
other.m_pointer = nullptr;
|
||||||
other.m_count = nullptr;
|
other.m_count = nullptr;
|
||||||
if (!(*this))
|
if (!(*this))
|
||||||
Reset();
|
reset();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ namespace BAN
|
||||||
T* operator->() { return m_pointer; }
|
T* operator->() { return m_pointer; }
|
||||||
const T* operator->() const { return m_pointer; }
|
const T* operator->() const { return m_pointer; }
|
||||||
|
|
||||||
void Reset()
|
void reset()
|
||||||
{
|
{
|
||||||
ASSERT(!m_count == !m_pointer);
|
ASSERT(!m_count == !m_pointer);
|
||||||
if (!m_count)
|
if (!m_count)
|
||||||
|
|
|
@ -6,19 +6,19 @@ namespace BAN
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr remove_reference_t<T>&& Move(T&& arg)
|
constexpr remove_reference_t<T>&& move(T&& arg)
|
||||||
{
|
{
|
||||||
return static_cast<remove_reference_t<T>&&>(arg);
|
return static_cast<remove_reference_t<T>&&>(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T&& Forward(remove_reference_t<T>& arg)
|
constexpr T&& forward(remove_reference_t<T>& arg)
|
||||||
{
|
{
|
||||||
return static_cast<T&&>(arg);
|
return static_cast<T&&>(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T&& Forward(remove_reference_t<T>&& arg)
|
constexpr T&& forward(remove_reference_t<T>&& arg)
|
||||||
{
|
{
|
||||||
static_assert(!is_lvalue_reference_v<T>);
|
static_assert(!is_lvalue_reference_v<T>);
|
||||||
return static_cast<T&&>(arg);
|
return static_cast<T&&>(arg);
|
||||||
|
|
|
@ -24,24 +24,24 @@ namespace BAN
|
||||||
Queue<T>& operator=(Queue<T>&&);
|
Queue<T>& operator=(Queue<T>&&);
|
||||||
Queue<T>& operator=(const Queue<T>&);
|
Queue<T>& operator=(const Queue<T>&);
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> Push(T&&);
|
[[nodiscard]] ErrorOr<void> push(T&&);
|
||||||
[[nodiscard]] ErrorOr<void> Push(const T&);
|
[[nodiscard]] ErrorOr<void> push(const T&);
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard]] ErrorOr<void> Emplace(Args...);
|
[[nodiscard]] ErrorOr<void> emplace(Args...);
|
||||||
|
|
||||||
void Pop();
|
void pop();
|
||||||
void Clear();
|
void clear();
|
||||||
|
|
||||||
bool Empty() const;
|
bool empty() const;
|
||||||
size_type Size() const;
|
size_type size() const;
|
||||||
|
|
||||||
const T& Front() const;
|
const T& front() const;
|
||||||
T& Front();
|
T& front();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] ErrorOr<void> EnsureCapacity(size_type size);
|
[[nodiscard]] ErrorOr<void> ensure_capacity(size_type size);
|
||||||
const T* AddressOf(size_type, void* = nullptr) const;
|
const T* address_of(size_type, void* = nullptr) const;
|
||||||
T* AddressOf(size_type, void* = nullptr);
|
T* address_of(size_type, void* = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t* m_data = nullptr;
|
uint8_t* m_data = nullptr;
|
||||||
|
@ -64,22 +64,22 @@ namespace BAN
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Queue<T>::Queue(const Queue<T>& other)
|
Queue<T>::Queue(const Queue<T>& other)
|
||||||
{
|
{
|
||||||
MUST(EnsureCapacity(other.Size()));
|
MUST(ensure_capacity(other.size()));
|
||||||
for (size_type i = 0; i < other.Size(); i++)
|
for (size_type i = 0; i < other.size(); i++)
|
||||||
new (AddressOf(i)) T(*AddressOf(i, other.m_data));
|
new (address_of(i)) T(*address_of(i, other.m_data));
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Queue<T>::~Queue()
|
Queue<T>::~Queue()
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Queue<T>& Queue<T>::operator=(Queue<T>&& other)
|
Queue<T>& Queue<T>::operator=(Queue<T>&& other)
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
|
|
||||||
m_data = other.m_data;
|
m_data = other.m_data;
|
||||||
m_capacity = other.m_capacity;
|
m_capacity = other.m_capacity;
|
||||||
|
@ -95,54 +95,54 @@ namespace BAN
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Queue<T>& Queue<T>::operator=(const Queue<T>& other)
|
Queue<T>& Queue<T>::operator=(const Queue<T>& other)
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
MUST(EnsureCapacity(other.Size()));
|
MUST(ensure_capacity(other.size()));
|
||||||
for (size_type i = 0; i < other.Size(); i++)
|
for (size_type i = 0; i < other.size(); i++)
|
||||||
new (AddressOf(i)) T(*AddressOf(i, other.m_data));
|
new (address_of(i)) T(*address_of(i, other.m_data));
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Queue<T>::Push(T&& value)
|
ErrorOr<void> Queue<T>::push(T&& value)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapacity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
new (AddressOf(m_size)) T(Move(value));
|
new (address_of(m_size)) T(move(value));
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Queue<T>::Push(const T& value)
|
ErrorOr<void> Queue<T>::push(const T& value)
|
||||||
{
|
{
|
||||||
return Push(Move(T(value)));
|
return push(move(T(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> Queue<T>::Emplace(Args... args)
|
ErrorOr<void> Queue<T>::emplace(Args... args)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapacity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
new (AddressOf(m_size)) T(Forward<Args>(args)...);
|
new (address_of(m_size)) T(forward<Args>(args)...);
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Queue<T>::Pop()
|
void Queue<T>::pop()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
for (size_type i = 0; i < m_size - 1; i++)
|
for (size_type i = 0; i < m_size - 1; i++)
|
||||||
*AddressOf(i) = Move(*AddressOf(i + 1));
|
*address_of(i) = move(*address_of(i + 1));
|
||||||
AddressOf(m_size - 1)->~T();
|
address_of(m_size - 1)->~T();
|
||||||
m_size--;
|
m_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Queue<T>::Clear()
|
void Queue<T>::clear()
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
AddressOf(i)->~T();
|
address_of(i)->~T();
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
m_capacity = 0;
|
m_capacity = 0;
|
||||||
|
@ -150,44 +150,44 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool Queue<T>::Empty() const
|
bool Queue<T>::empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Queue<T>::size_type Queue<T>::Size() const
|
typename Queue<T>::size_type Queue<T>::size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& Queue<T>::Front() const
|
const T& Queue<T>::front() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(0);
|
return *address_of(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& Queue<T>::Front()
|
T& Queue<T>::front()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(0);
|
return *address_of(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Queue<T>::EnsureCapacity(size_type size)
|
ErrorOr<void> Queue<T>::ensure_capacity(size_type size)
|
||||||
{
|
{
|
||||||
if (m_capacity > size)
|
if (m_capacity > size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
||||||
uint8_t* new_data = (uint8_t*)BAN::allocator(new_cap * sizeof(T));
|
uint8_t* new_data = (uint8_t*)BAN::allocator(new_cap * sizeof(T));
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::FromString("Queue: Could not allocate memory");
|
return Error::from_string("Queue: Could not allocate memory");
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
{
|
{
|
||||||
new (AddressOf(i, new_data)) T(Move(*AddressOf(i)));
|
new (address_of(i, new_data)) T(move(*address_of(i)));
|
||||||
AddressOf(i)->~T();
|
address_of(i)->~T();
|
||||||
}
|
}
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = new_data;
|
m_data = new_data;
|
||||||
|
@ -196,7 +196,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* Queue<T>::AddressOf(size_type index, void* base) const
|
const T* Queue<T>::address_of(size_type index, void* base) const
|
||||||
{
|
{
|
||||||
if (base == nullptr)
|
if (base == nullptr)
|
||||||
base = m_data;
|
base = m_data;
|
||||||
|
@ -204,7 +204,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Queue<T>::AddressOf(size_type index, void* base)
|
T* Queue<T>::address_of(size_type index, void* base)
|
||||||
{
|
{
|
||||||
if (base == nullptr)
|
if (base == nullptr)
|
||||||
base = m_data;
|
base = m_data;
|
||||||
|
|
|
@ -19,23 +19,23 @@ namespace BAN
|
||||||
~String();
|
~String();
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
static String Formatted(const char* format, const Args&... args);
|
static String formatted(const char* format, const Args&... args);
|
||||||
|
|
||||||
String& operator=(const String&);
|
String& operator=(const String&);
|
||||||
String& operator=(String&&);
|
String& operator=(String&&);
|
||||||
String& operator=(StringView);
|
String& operator=(StringView);
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> PushBack(char);
|
[[nodiscard]] ErrorOr<void> push_back(char);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(char, size_type);
|
[[nodiscard]] ErrorOr<void> insert(char, size_type);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(StringView, size_type);
|
[[nodiscard]] ErrorOr<void> insert(StringView, size_type);
|
||||||
[[nodiscard]] ErrorOr<void> Append(StringView);
|
[[nodiscard]] ErrorOr<void> append(StringView);
|
||||||
[[nodiscard]] ErrorOr<void> Append(const String&);
|
[[nodiscard]] ErrorOr<void> append(const String&);
|
||||||
|
|
||||||
void PopBack();
|
void pop_back();
|
||||||
void Remove(size_type);
|
void remove(size_type);
|
||||||
void Erase(size_type, size_type);
|
void erase(size_type, size_type);
|
||||||
|
|
||||||
void Clear();
|
void clear();
|
||||||
|
|
||||||
char operator[](size_type) const;
|
char operator[](size_type) const;
|
||||||
char& operator[](size_type);
|
char& operator[](size_type);
|
||||||
|
@ -44,34 +44,34 @@ namespace BAN
|
||||||
bool operator==(StringView) const;
|
bool operator==(StringView) const;
|
||||||
bool operator==(const char*) const;
|
bool operator==(const char*) const;
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> Resize(size_type, char = '\0');
|
[[nodiscard]] ErrorOr<void> resize(size_type, char = '\0');
|
||||||
[[nodiscard]] ErrorOr<void> Reserve(size_type);
|
[[nodiscard]] ErrorOr<void> reserve(size_type);
|
||||||
|
|
||||||
StringView SV() const;
|
StringView sv() const;
|
||||||
|
|
||||||
bool Empty() const;
|
bool empty() const;
|
||||||
size_type Size() const;
|
size_type size() const;
|
||||||
size_type Capasity() const;
|
size_type capacity() const;
|
||||||
|
|
||||||
const char* Data() const;
|
const char* data() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] ErrorOr<void> EnsureCapasity(size_type);
|
[[nodiscard]] ErrorOr<void> ensure_capacity(size_type);
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> copy_impl(StringView);
|
[[nodiscard]] ErrorOr<void> copy_impl(StringView);
|
||||||
void move_impl(String&&);
|
void move_impl(String&&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* m_data = nullptr;
|
char* m_data = nullptr;
|
||||||
size_type m_capasity = 0;
|
size_type m_capacity = 0;
|
||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
String String::Formatted(const char* format, const Args&... args)
|
String String::formatted(const char* format, const Args&... args)
|
||||||
{
|
{
|
||||||
String result;
|
String result;
|
||||||
BAN::Formatter::print([&](char c){ result.PushBack(c); }, format, args...);
|
BAN::Formatter::print([&](char c){ result.push_back(c); }, format, args...);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ namespace BAN::Formatter
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void print_argument_impl(F putc, const String& string, const ValueFormat&)
|
void print_argument_impl(F putc, const String& string, const ValueFormat&)
|
||||||
{
|
{
|
||||||
for (String::size_type i = 0; i < string.Size(); i++)
|
for (String::size_type i = 0; i < string.size(); i++)
|
||||||
putc(string[i]);
|
putc(string[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,20 +22,20 @@ namespace BAN
|
||||||
bool operator==(StringView) const;
|
bool operator==(StringView) const;
|
||||||
bool operator==(const char*) const;
|
bool operator==(const char*) const;
|
||||||
|
|
||||||
StringView Substring(size_type, size_type = -1) const;
|
StringView substring(size_type, size_type = -1) const;
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<Vector<StringView>> Split(char, bool = false);
|
[[nodiscard]] ErrorOr<Vector<StringView>> split(char, bool = false);
|
||||||
[[nodiscard]] ErrorOr<Vector<StringView>> Split(bool(*comp)(char), bool = false);
|
[[nodiscard]] ErrorOr<Vector<StringView>> split(bool(*comp)(char), bool = false);
|
||||||
|
|
||||||
char Back() const;
|
char back() const;
|
||||||
char Front() const;
|
char front() const;
|
||||||
|
|
||||||
size_type Count(char) const;
|
size_type count(char) const;
|
||||||
|
|
||||||
bool Empty() const;
|
bool empty() const;
|
||||||
size_type Size() const;
|
size_type size() const;
|
||||||
|
|
||||||
const char* Data() const;
|
const char* data() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* m_data = nullptr;
|
const char* m_data = nullptr;
|
||||||
|
@ -52,7 +52,7 @@ namespace BAN::Formatter
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void print_argument_impl(F putc, const StringView& sv, const ValueFormat&)
|
void print_argument_impl(F putc, const StringView& sv, const ValueFormat&)
|
||||||
{
|
{
|
||||||
for (StringView::size_type i = 0; i < sv.Size(); i++)
|
for (StringView::size_type i = 0; i < sv.size(); i++)
|
||||||
putc(sv[i]);
|
putc(sv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,45 +70,45 @@ namespace BAN
|
||||||
Vector<T>& operator=(Vector<T>&&);
|
Vector<T>& operator=(Vector<T>&&);
|
||||||
Vector<T>& operator=(const Vector<T>&);
|
Vector<T>& operator=(const Vector<T>&);
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> PushBack(T&&);
|
[[nodiscard]] ErrorOr<void> push_back(T&&);
|
||||||
[[nodiscard]] ErrorOr<void> PushBack(const T&);
|
[[nodiscard]] ErrorOr<void> push_back(const T&);
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard]] ErrorOr<void> EmplaceBack(Args...);
|
[[nodiscard]] ErrorOr<void> emplace_back(Args...);
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard]] ErrorOr<void> Emplace(size_type, Args...);
|
[[nodiscard]] ErrorOr<void> emplace(size_type, Args...);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(size_type, T&&);
|
[[nodiscard]] ErrorOr<void> insert(size_type, T&&);
|
||||||
[[nodiscard]] ErrorOr<void> Insert(size_type, const T&);
|
[[nodiscard]] ErrorOr<void> insert(size_type, const T&);
|
||||||
|
|
||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
const_iterator begin() const;
|
const_iterator begin() const;
|
||||||
const_iterator end() const;
|
const_iterator end() const;
|
||||||
|
|
||||||
void PopBack();
|
void pop_back();
|
||||||
void Remove(size_type);
|
void remove(size_type);
|
||||||
void Clear();
|
void clear();
|
||||||
|
|
||||||
bool Has(const T&) const;
|
bool has(const T&) const;
|
||||||
|
|
||||||
const T& operator[](size_type) const;
|
const T& operator[](size_type) const;
|
||||||
T& operator[](size_type);
|
T& operator[](size_type);
|
||||||
|
|
||||||
const T& Back() const;
|
const T& back() const;
|
||||||
T& Back();
|
T& back();
|
||||||
const T& Front() const;
|
const T& front() const;
|
||||||
T& Front();
|
T& front();
|
||||||
|
|
||||||
[[nodiscard]] ErrorOr<void> Resize(size_type);
|
[[nodiscard]] ErrorOr<void> resize(size_type);
|
||||||
[[nodiscard]] ErrorOr<void> Reserve(size_type);
|
[[nodiscard]] ErrorOr<void> reserve(size_type);
|
||||||
|
|
||||||
bool Empty() const;
|
bool empty() const;
|
||||||
size_type Size() const;
|
size_type size() const;
|
||||||
size_type Capacity() const;
|
size_type capacity() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] ErrorOr<void> EnsureCapasity(size_type);
|
[[nodiscard]] ErrorOr<void> ensure_capacity(size_type);
|
||||||
const T* AddressOf(size_type, void* = nullptr) const;
|
const T* address_of(size_type, void* = nullptr) const;
|
||||||
T* AddressOf(size_type, void* = nullptr);
|
T* address_of(size_type, void* = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t* m_data = nullptr;
|
uint8_t* m_data = nullptr;
|
||||||
|
@ -131,22 +131,22 @@ namespace BAN
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T>::Vector(const Vector<T>& other)
|
Vector<T>::Vector(const Vector<T>& other)
|
||||||
{
|
{
|
||||||
MUST(EnsureCapasity(other.m_size));
|
MUST(ensure_capacity(other.m_size));
|
||||||
for (size_type i = 0; i < other.m_size; i++)
|
for (size_type i = 0; i < other.m_size; i++)
|
||||||
new (AddressOf(i)) T(other[i]);
|
new (address_of(i)) T(other[i]);
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T>::~Vector()
|
Vector<T>::~Vector()
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T>& Vector<T>::operator=(Vector<T>&& other)
|
Vector<T>& Vector<T>::operator=(Vector<T>&& other)
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
|
|
||||||
m_data = other.m_data;
|
m_data = other.m_data;
|
||||||
m_capacity = other.m_capacity;
|
m_capacity = other.m_capacity;
|
||||||
|
@ -162,133 +162,133 @@ namespace BAN
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T>& Vector<T>::operator=(const Vector<T>& other)
|
Vector<T>& Vector<T>::operator=(const Vector<T>& other)
|
||||||
{
|
{
|
||||||
Clear();
|
clear();
|
||||||
MUST(EnsureCapasity(other.Size()));
|
MUST(ensure_capacity(other.size()));
|
||||||
for (size_type i = 0; i < other.Size(); i++)
|
for (size_type i = 0; i < other.size(); i++)
|
||||||
new (AddressOf(i)) T(other[i]);
|
new (address_of(i)) T(other[i]);
|
||||||
m_size = other.m_size;
|
m_size = other.m_size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::PushBack(T&& value)
|
ErrorOr<void> Vector<T>::push_back(T&& value)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
new (AddressOf(m_size)) T(Move(value));
|
new (address_of(m_size)) T(move(value));
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::PushBack(const T& value)
|
ErrorOr<void> Vector<T>::push_back(const T& value)
|
||||||
{
|
{
|
||||||
return PushBack(Move(T(value)));
|
return push_back(move(T(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> Vector<T>::EmplaceBack(Args... args)
|
ErrorOr<void> Vector<T>::emplace_back(Args... args)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
new (AddressOf(m_size)) T(Forward<Args>(args)...);
|
new (address_of(m_size)) T(forward<Args>(args)...);
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
ErrorOr<void> Vector<T>::Emplace(size_type index, Args... args)
|
ErrorOr<void> Vector<T>::emplace(size_type index, Args... args)
|
||||||
{
|
{
|
||||||
ASSERT(index <= m_size);
|
ASSERT(index <= m_size);
|
||||||
TRY(EnsureCapasity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
if (index < m_size)
|
if (index < m_size)
|
||||||
{
|
{
|
||||||
new (AddressOf(m_size)) T(Move(*AddressOf(m_size - 1)));
|
new (address_of(m_size)) T(move(*address_of(m_size - 1)));
|
||||||
for (size_type i = m_size - 1; i > index; i--)
|
for (size_type i = m_size - 1; i > index; i--)
|
||||||
*AddressOf(i) = Move(*AddressOf(i - 1));
|
*address_of(i) = move(*address_of(i - 1));
|
||||||
*AddressOf(index) = Move(T(Forward<Args>(args)...));
|
*address_of(index) = move(T(forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (AddressOf(m_size)) T(Forward<Args>(args)...);
|
new (address_of(m_size)) T(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::Insert(size_type index, T&& value)
|
ErrorOr<void> Vector<T>::insert(size_type index, T&& value)
|
||||||
{
|
{
|
||||||
ASSERT(index <= m_size);
|
ASSERT(index <= m_size);
|
||||||
TRY(EnsureCapasity(m_size + 1));
|
TRY(ensure_capacity(m_size + 1));
|
||||||
if (index < m_size)
|
if (index < m_size)
|
||||||
{
|
{
|
||||||
new (AddressOf(m_size)) T(Move(*AddressOf(m_size - 1)));
|
new (address_of(m_size)) T(move(*address_of(m_size - 1)));
|
||||||
for (size_type i = m_size - 1; i > index; i--)
|
for (size_type i = m_size - 1; i > index; i--)
|
||||||
*AddressOf(i) = Move(*AddressOf(i - 1));
|
*address_of(i) = move(*address_of(i - 1));
|
||||||
*AddressOf(index) = Move(value);
|
*address_of(index) = move(value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new (AddressOf(m_size)) T(Move(value));
|
new (address_of(m_size)) T(move(value));
|
||||||
}
|
}
|
||||||
m_size++;
|
m_size++;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::Insert(size_type index, const T& value)
|
ErrorOr<void> Vector<T>::insert(size_type index, const T& value)
|
||||||
{
|
{
|
||||||
return Insert(Move(T(value)), index);
|
return insert(move(T(value)), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::iterator Vector<T>::begin()
|
typename Vector<T>::iterator Vector<T>::begin()
|
||||||
{
|
{
|
||||||
return VectorIterator<T>(AddressOf(0));
|
return VectorIterator<T>(address_of(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::iterator Vector<T>::end()
|
typename Vector<T>::iterator Vector<T>::end()
|
||||||
{
|
{
|
||||||
return VectorIterator<T>(AddressOf(m_size));
|
return VectorIterator<T>(address_of(m_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::const_iterator Vector<T>::begin() const
|
typename Vector<T>::const_iterator Vector<T>::begin() const
|
||||||
{
|
{
|
||||||
return VectorConstIterator<T>(AddressOf(0));
|
return VectorConstIterator<T>(address_of(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::const_iterator Vector<T>::end() const
|
typename Vector<T>::const_iterator Vector<T>::end() const
|
||||||
{
|
{
|
||||||
return VectorConstIterator<T>(AddressOf(m_size));
|
return VectorConstIterator<T>(address_of(m_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Vector<T>::PopBack()
|
void Vector<T>::pop_back()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
AddressOf(m_size - 1)->~T();
|
address_of(m_size - 1)->~T();
|
||||||
m_size--;
|
m_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Vector<T>::Remove(size_type index)
|
void Vector<T>::remove(size_type index)
|
||||||
{
|
{
|
||||||
ASSERT(index < m_size);
|
ASSERT(index < m_size);
|
||||||
for (size_type i = index; i < m_size - 1; i++)
|
for (size_type i = index; i < m_size - 1; i++)
|
||||||
*AddressOf(i) = Move(*AddressOf(i + 1));
|
*address_of(i) = move(*address_of(i + 1));
|
||||||
AddressOf(m_size - 1)->~T();
|
address_of(m_size - 1)->~T();
|
||||||
m_size--;
|
m_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Vector<T>::Clear()
|
void Vector<T>::clear()
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
AddressOf(i)->~T();
|
address_of(i)->~T();
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
m_capacity = 0;
|
m_capacity = 0;
|
||||||
|
@ -296,10 +296,10 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool Vector<T>::Has(const T& other) const
|
bool Vector<T>::has(const T& other) const
|
||||||
{
|
{
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
if (*AddressOf(i) == other)
|
if (*address_of(i) == other)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -308,95 +308,95 @@ namespace BAN
|
||||||
const T& Vector<T>::operator[](size_type index) const
|
const T& Vector<T>::operator[](size_type index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < m_size);
|
ASSERT(index < m_size);
|
||||||
return *AddressOf(index);
|
return *address_of(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& Vector<T>::operator[](size_type index)
|
T& Vector<T>::operator[](size_type index)
|
||||||
{
|
{
|
||||||
ASSERT(index < m_size);
|
ASSERT(index < m_size);
|
||||||
return *AddressOf(index);
|
return *address_of(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& Vector<T>::Back() const
|
const T& Vector<T>::back() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(m_size - 1);
|
return *address_of(m_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& Vector<T>::Back()
|
T& Vector<T>::back()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(m_size - 1);
|
return *address_of(m_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T& Vector<T>::Front() const
|
const T& Vector<T>::front() const
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(0);
|
return *address_of(0);
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T& Vector<T>::Front()
|
T& Vector<T>::front()
|
||||||
{
|
{
|
||||||
ASSERT(m_size > 0);
|
ASSERT(m_size > 0);
|
||||||
return *AddressOf(0);
|
return *address_of(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::Resize(size_type size)
|
ErrorOr<void> Vector<T>::resize(size_type size)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(size));
|
TRY(ensure_capacity(size));
|
||||||
if (size < m_size)
|
if (size < m_size)
|
||||||
for (size_type i = size; i < m_size; i++)
|
for (size_type i = size; i < m_size; i++)
|
||||||
AddressOf(i)->~T();
|
address_of(i)->~T();
|
||||||
if (size > m_size)
|
if (size > m_size)
|
||||||
for (size_type i = m_size; i < size; i++)
|
for (size_type i = m_size; i < size; i++)
|
||||||
new (AddressOf(i)) T();
|
new (address_of(i)) T();
|
||||||
m_size = size;
|
m_size = size;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::Reserve(size_type size)
|
ErrorOr<void> Vector<T>::reserve(size_type size)
|
||||||
{
|
{
|
||||||
TRY(EnsureCapasity(size));
|
TRY(ensure_capacity(size));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool Vector<T>::Empty() const
|
bool Vector<T>::empty() const
|
||||||
{
|
{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::size_type Vector<T>::Size() const
|
typename Vector<T>::size_type Vector<T>::size() const
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename Vector<T>::size_type Vector<T>::Capacity() const
|
typename Vector<T>::size_type Vector<T>::capacity() const
|
||||||
{
|
{
|
||||||
return m_capacity;
|
return m_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ErrorOr<void> Vector<T>::EnsureCapasity(size_type size)
|
ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
|
||||||
{
|
{
|
||||||
if (m_capacity >= size)
|
if (m_capacity >= size)
|
||||||
return {};
|
return {};
|
||||||
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 3 / 2);
|
||||||
uint8_t* new_data = (uint8_t*)BAN::allocator(new_cap * sizeof(T));
|
uint8_t* new_data = (uint8_t*)BAN::allocator(new_cap * sizeof(T));
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Error::FromString("Vector: Could not allocate memory");
|
return Error::from_string("Vector: Could not allocate memory");
|
||||||
for (size_type i = 0; i < m_size; i++)
|
for (size_type i = 0; i < m_size; i++)
|
||||||
{
|
{
|
||||||
new (AddressOf(i, new_data)) T(Move(*AddressOf(i)));
|
new (address_of(i, new_data)) T(move(*address_of(i)));
|
||||||
AddressOf(i)->~T();
|
address_of(i)->~T();
|
||||||
}
|
}
|
||||||
BAN::deallocator(m_data);
|
BAN::deallocator(m_data);
|
||||||
m_data = new_data;
|
m_data = new_data;
|
||||||
|
@ -405,7 +405,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* Vector<T>::AddressOf(size_type index, void* base) const
|
const T* Vector<T>::address_of(size_type index, void* base) const
|
||||||
{
|
{
|
||||||
if (base == nullptr)
|
if (base == nullptr)
|
||||||
base = m_data;
|
base = m_data;
|
||||||
|
@ -413,7 +413,7 @@ namespace BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Vector<T>::AddressOf(size_type index, void* base)
|
T* Vector<T>::address_of(size_type index, void* base)
|
||||||
{
|
{
|
||||||
if (base == nullptr)
|
if (base == nullptr)
|
||||||
base = m_data;
|
base = m_data;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
asm volatile("movl %%cr2, %%eax":"=a"(cr2)); \
|
asm volatile("movl %%cr2, %%eax":"=a"(cr2)); \
|
||||||
asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \
|
asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \
|
||||||
asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \
|
asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \
|
||||||
Kernel::Panic(msg "\r\nRegister dump\r\n" \
|
Kernel::panic(msg "\r\nRegister dump\r\n" \
|
||||||
"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" \
|
"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" \
|
||||||
"esp=0x{8H}, ebp=0x{8H}\r\n" \
|
"esp=0x{8H}, ebp=0x{8H}\r\n" \
|
||||||
"CR0=0x{8H}, CR2=0x{8H}, CR3=0x{8H}, CR4=0x{8H}\r\n", \
|
"CR0=0x{8H}, CR2=0x{8H}, CR3=0x{8H}, CR4=0x{8H}\r\n", \
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \
|
asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \
|
||||||
asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \
|
asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \
|
||||||
asm volatile("popl %%eax":"=a"(error_code)); \
|
asm volatile("popl %%eax":"=a"(error_code)); \
|
||||||
Kernel::Panic(msg " (error code: 0x{8H})\r\n" \
|
Kernel::panic(msg " (error code: 0x{8H})\r\n" \
|
||||||
"Register dump\r\n" \
|
"Register dump\r\n" \
|
||||||
"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" \
|
"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n" \
|
||||||
"esp=0x{8H}, ebp=0x{8H}\r\n" \
|
"esp=0x{8H}, ebp=0x{8H}\r\n" \
|
||||||
|
@ -114,7 +114,7 @@ namespace IDT
|
||||||
uint8_t irq = 0;
|
uint8_t irq = 0;
|
||||||
for (uint32_t i = 0; i <= 0xFF; i++)
|
for (uint32_t i = 0; i <= 0xFF; i++)
|
||||||
{
|
{
|
||||||
if (InterruptController::Get().IsInService(i))
|
if (InterruptController::get().is_in_service(i))
|
||||||
{
|
{
|
||||||
irq = i;
|
irq = i;
|
||||||
break;
|
break;
|
||||||
|
@ -132,7 +132,7 @@ namespace IDT
|
||||||
else
|
else
|
||||||
dprintln("no handler for irq 0x{2H}\n", irq);
|
dprintln("no handler for irq 0x{2H}\n", irq);
|
||||||
|
|
||||||
InterruptController::Get().EOI(irq);
|
InterruptController::get().eoi(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void handle_irq_common();
|
extern "C" void handle_irq_common();
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
|
|
||||||
static MMU* s_instance = nullptr;
|
static MMU* s_instance = nullptr;
|
||||||
|
|
||||||
void MMU::Intialize()
|
void MMU::intialize()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
s_instance = new MMU();
|
s_instance = new MMU();
|
||||||
}
|
}
|
||||||
|
|
||||||
MMU& MMU::Get()
|
MMU& MMU::get()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
|
@ -70,7 +70,7 @@ MMU::MMU()
|
||||||
asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct));
|
asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::AllocatePage(uintptr_t address)
|
void MMU::allocate_page(uintptr_t address)
|
||||||
{
|
{
|
||||||
#if MMU_DEBUG_PRINT
|
#if MMU_DEBUG_PRINT
|
||||||
dprintln("AllocatePage(0x{8H})", address & PAGE_MASK);
|
dprintln("AllocatePage(0x{8H})", address & PAGE_MASK);
|
||||||
|
@ -93,15 +93,15 @@ void MMU::AllocatePage(uintptr_t address)
|
||||||
asm volatile("invlpg (%0)" :: "r"(address & PAGE_MASK) : "memory");
|
asm volatile("invlpg (%0)" :: "r"(address & PAGE_MASK) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::AllocateRange(uintptr_t address, ptrdiff_t size)
|
void MMU::allocate_range(uintptr_t address, ptrdiff_t size)
|
||||||
{
|
{
|
||||||
uintptr_t s_page = address & PAGE_MASK;
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
AllocatePage(page);
|
allocate_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::UnAllocatePage(uintptr_t address)
|
void MMU::unallocate_page(uintptr_t address)
|
||||||
{
|
{
|
||||||
#if MMU_DEBUG_PRINT
|
#if MMU_DEBUG_PRINT
|
||||||
dprintln("UnAllocatePage(0x{8H})", address & PAGE_MASK);
|
dprintln("UnAllocatePage(0x{8H})", address & PAGE_MASK);
|
||||||
|
@ -126,10 +126,10 @@ void MMU::UnAllocatePage(uintptr_t address)
|
||||||
asm volatile("invlpg (%0)" :: "r"(address & PAGE_MASK) : "memory");
|
asm volatile("invlpg (%0)" :: "r"(address & PAGE_MASK) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::UnAllocateRange(uintptr_t address, ptrdiff_t size)
|
void MMU::unallocate_range(uintptr_t address, ptrdiff_t size)
|
||||||
{
|
{
|
||||||
uintptr_t s_page = address & PAGE_MASK;
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
UnAllocatePage(page);
|
unallocate_page(page);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace IDT
|
||||||
|
|
||||||
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs)
|
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs)
|
||||||
{
|
{
|
||||||
Kernel::Panic(
|
Kernel::panic(
|
||||||
"{} (error code: 0x{16H})\r\n"
|
"{} (error code: 0x{16H})\r\n"
|
||||||
"Register dump\r\n"
|
"Register dump\r\n"
|
||||||
"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n"
|
"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n"
|
||||||
|
@ -118,7 +118,7 @@ namespace IDT
|
||||||
s_irq_handlers[irq]();
|
s_irq_handlers[irq]();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!InterruptController::Get().IsInService(irq))
|
if (!InterruptController::get().is_in_service(irq))
|
||||||
{
|
{
|
||||||
dprintln("spurious irq 0x{2H}", irq);
|
dprintln("spurious irq 0x{2H}", irq);
|
||||||
return;
|
return;
|
||||||
|
@ -126,7 +126,7 @@ namespace IDT
|
||||||
dprintln("no handler for irq 0x{2H}\n", irq);
|
dprintln("no handler for irq 0x{2H}\n", irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
InterruptController::Get().EOI(irq);
|
InterruptController::get().eoi(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flush_idt()
|
static void flush_idt()
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
|
|
||||||
static MMU* s_instance = nullptr;
|
static MMU* s_instance = nullptr;
|
||||||
|
|
||||||
void MMU::Intialize()
|
void MMU::intialize()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
s_instance = new MMU();
|
s_instance = new MMU();
|
||||||
}
|
}
|
||||||
|
|
||||||
MMU& MMU::Get()
|
MMU& MMU::get()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
|
@ -89,7 +89,7 @@ MMU::~MMU()
|
||||||
kfree(pml4);
|
kfree(pml4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::AllocatePage(uintptr_t address)
|
void MMU::allocate_page(uintptr_t address)
|
||||||
{
|
{
|
||||||
ASSERT((address >> 48) == 0);
|
ASSERT((address >> 48) == 0);
|
||||||
|
|
||||||
|
@ -129,15 +129,15 @@ void MMU::AllocatePage(uintptr_t address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::AllocateRange(uintptr_t address, ptrdiff_t size)
|
void MMU::allocate_range(uintptr_t address, ptrdiff_t size)
|
||||||
{
|
{
|
||||||
uintptr_t s_page = address & PAGE_MASK;
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
AllocatePage(page);
|
allocate_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::UnAllocatePage(uintptr_t address)
|
void MMU::unallocate_page(uintptr_t address)
|
||||||
{
|
{
|
||||||
ASSERT((address >> 48) == 0);
|
ASSERT((address >> 48) == 0);
|
||||||
|
|
||||||
|
@ -177,10 +177,10 @@ cleanup_done:
|
||||||
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::UnAllocateRange(uintptr_t address, ptrdiff_t size)
|
void MMU::unallocate_range(uintptr_t address, ptrdiff_t size)
|
||||||
{
|
{
|
||||||
uintptr_t s_page = address & PAGE_MASK;
|
uintptr_t s_page = address & PAGE_MASK;
|
||||||
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
uintptr_t e_page = (address + size - 1) & PAGE_MASK;
|
||||||
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
UnAllocatePage(page);
|
unallocate_page(page);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
class APIC final : public InterruptController
|
class APIC final : public InterruptController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void EOI(uint8_t) override;
|
virtual void eoi(uint8_t) override;
|
||||||
virtual void EnableIrq(uint8_t) override;
|
virtual void enable_irq(uint8_t) override;
|
||||||
virtual bool IsInService(uint8_t) override;
|
virtual bool is_in_service(uint8_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ReadFromLocalAPIC(ptrdiff_t);
|
uint32_t read_from_local_apic(ptrdiff_t);
|
||||||
void WriteToLocalAPIC(ptrdiff_t, uint32_t);
|
void write_to_local_apic(ptrdiff_t, uint32_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static APIC* Create();
|
static APIC* create();
|
||||||
friend class InterruptController;
|
friend class InterruptController;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -38,8 +38,8 @@ private:
|
||||||
uint32_t gsi_base;
|
uint32_t gsi_base;
|
||||||
uint8_t max_redirs;
|
uint8_t max_redirs;
|
||||||
|
|
||||||
uint32_t Read(uint8_t offset);
|
uint32_t read(uint8_t offset);
|
||||||
void Write(uint8_t offset, uint32_t data);
|
void write(uint8_t offset, uint32_t data);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -71,11 +71,11 @@ namespace CPUID
|
||||||
EDX_PBE = (uint32_t)1 << 31,
|
EDX_PBE = (uint32_t)1 << 31,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* FeatStringECX(uint32_t feat);
|
const char* feature_string_ecx(uint32_t feat);
|
||||||
const char* FeatStringEDX(uint32_t feat);
|
const char* feature_string_edx(uint32_t feat);
|
||||||
|
|
||||||
const char* GetVendor();
|
const char* get_vendor();
|
||||||
void GetFeatures(uint32_t& ecx, uint32_t& edx);
|
void get_features(uint32_t& ecx, uint32_t& edx);
|
||||||
bool Is64Bit();
|
bool is_64_bit();
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,6 +28,6 @@
|
||||||
|
|
||||||
namespace Debug
|
namespace Debug
|
||||||
{
|
{
|
||||||
void DumpStackTrace();
|
void dump_stack_trace();
|
||||||
void putchar(char);
|
void putchar(char);
|
||||||
}
|
}
|
|
@ -7,10 +7,10 @@ class InterruptController
|
||||||
public:
|
public:
|
||||||
virtual ~InterruptController() {}
|
virtual ~InterruptController() {}
|
||||||
|
|
||||||
virtual void EOI(uint8_t) = 0;
|
virtual void eoi(uint8_t) = 0;
|
||||||
virtual void EnableIrq(uint8_t) = 0;
|
virtual void enable_irq(uint8_t) = 0;
|
||||||
virtual bool IsInService(uint8_t) = 0;
|
virtual bool is_in_service(uint8_t) = 0;
|
||||||
|
|
||||||
static void Initialize(bool force_pic);
|
static void initialize(bool force_pic);
|
||||||
static InterruptController& Get();
|
static InterruptController& get();
|
||||||
};
|
};
|
|
@ -6,17 +6,17 @@
|
||||||
class MMU
|
class MMU
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void Intialize();
|
static void intialize();
|
||||||
static MMU& Get();
|
static MMU& get();
|
||||||
|
|
||||||
MMU();
|
MMU();
|
||||||
~MMU();
|
~MMU();
|
||||||
|
|
||||||
void AllocatePage(uintptr_t);
|
void allocate_page(uintptr_t);
|
||||||
void AllocateRange(uintptr_t, ptrdiff_t);
|
void allocate_range(uintptr_t, ptrdiff_t);
|
||||||
|
|
||||||
void UnAllocatePage(uintptr_t);
|
void unallocate_page(uintptr_t);
|
||||||
void UnAllocateRange(uintptr_t, ptrdiff_t);
|
void unallocate_range(uintptr_t, ptrdiff_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t* m_highest_paging_struct;
|
uint64_t* m_highest_paging_struct;
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
class PIC final : public InterruptController
|
class PIC final : public InterruptController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void EOI(uint8_t) override;
|
virtual void eoi(uint8_t) override;
|
||||||
virtual void EnableIrq(uint8_t) override;
|
virtual void enable_irq(uint8_t) override;
|
||||||
virtual bool IsInService(uint8_t) override;
|
virtual bool is_in_service(uint8_t) override;
|
||||||
|
|
||||||
static void Remap();
|
static void remap();
|
||||||
static void MaskAll();
|
static void mask_all();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PIC* Create();
|
static PIC* create();
|
||||||
friend class InterruptController;
|
friend class InterruptController;
|
||||||
};
|
};
|
|
@ -3,22 +3,25 @@
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
|
||||||
#define Panic(...) PanicImpl(__FILE__, __LINE__, __VA_ARGS__)
|
#define panic(...) detail::panic_impl(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename... Args>
|
namespace detail
|
||||||
__attribute__((__noreturn__))
|
|
||||||
static void PanicImpl(const char* file, int line, const char* message, Args... args)
|
|
||||||
{
|
{
|
||||||
derrorln("Kernel panic at {}:{}", file, line);
|
template<typename... Args>
|
||||||
derrorln(message, args...);
|
__attribute__((__noreturn__))
|
||||||
Debug::DumpStackTrace();
|
static void panic_impl(const char* file, int line, const char* message, Args... args)
|
||||||
asm volatile("cli");
|
{
|
||||||
for (;;)
|
derrorln("Kernel panic at {}:{}", file, line);
|
||||||
asm volatile("hlt");
|
derrorln(message, args...);
|
||||||
__builtin_unreachable();
|
Debug::dump_stack_trace();
|
||||||
|
asm volatile("cli");
|
||||||
|
for (;;)
|
||||||
|
asm volatile("hlt");
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
namespace RTC
|
namespace RTC
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::Time GetCurrentTime();
|
BAN::Time get_current_time();
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Function.h>
|
||||||
#include <BAN/LinkedList.h>
|
#include <BAN/LinkedList.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
namespace Serial
|
namespace Serial
|
||||||
{
|
{
|
||||||
|
|
||||||
void Initialize();
|
void initialize();
|
||||||
bool IsInitialized();
|
bool is_initialized();
|
||||||
|
|
||||||
void putchar(char);
|
void putchar(char);
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
Shell(TTY*);
|
Shell(TTY*);
|
||||||
Shell(const Shell&) = delete;
|
Shell(const Shell&) = delete;
|
||||||
void SetPrompt(BAN::StringView);
|
void set_prompt(BAN::StringView);
|
||||||
void Run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReRenderBuffer() const;
|
void rerender_buffer() const;
|
||||||
BAN::Vector<BAN::String> ParseArguments(BAN::StringView) const;
|
BAN::Vector<BAN::String> parse_arguments(BAN::StringView) const;
|
||||||
void ProcessCommand(const BAN::Vector<BAN::String>&);
|
void process_command(const BAN::Vector<BAN::String>&);
|
||||||
void KeyEventCallback(Input::KeyEvent);
|
void key_event_callback(Input::KeyEvent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TTY* m_tty;
|
TTY* m_tty;
|
||||||
|
|
|
@ -7,26 +7,26 @@ class TTY
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TTY(TerminalDriver*);
|
TTY(TerminalDriver*);
|
||||||
void Clear();
|
void clear();
|
||||||
void PutChar(char ch);
|
void putchar(char ch);
|
||||||
void Write(const char* data, size_t size);
|
void write(const char* data, size_t size);
|
||||||
void WriteString(const char* data);
|
void write_string(const char* data);
|
||||||
void SetCursorPosition(uint32_t x, uint32_t y);
|
void set_cursor_position(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
uint32_t Height() const { return m_height; }
|
uint32_t height() const { return m_height; }
|
||||||
uint32_t Width() const { return m_width; }
|
uint32_t width() const { return m_width; }
|
||||||
|
|
||||||
void RenderFromBuffer(uint32_t x, uint32_t y);
|
void render_from_buffer(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
// for kprint
|
// for kprint
|
||||||
static void PutCharCurrent(char ch);
|
static void putchar_current(char ch);
|
||||||
static bool IsInitialized();
|
static bool is_initialized();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResetAnsiEscape();
|
void reset_ansi_escape();
|
||||||
void HandleAnsiSGR();
|
void handle_ansi_sgr();
|
||||||
void HandleAnsiEscape(uint16_t ch);
|
void handle_ansi_escape(uint16_t ch);
|
||||||
void PutCharAt(uint16_t ch, uint32_t x, uint32_t y);
|
void putchar_at(uint16_t ch, uint32_t x, uint32_t y);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Cell
|
struct Cell
|
||||||
|
|
|
@ -22,13 +22,13 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual ~TerminalDriver() {}
|
virtual ~TerminalDriver() {}
|
||||||
|
|
||||||
virtual uint32_t Width() const = 0;
|
virtual uint32_t width() const = 0;
|
||||||
virtual uint32_t Height() const = 0;
|
virtual uint32_t height() const = 0;
|
||||||
|
|
||||||
virtual void PutCharAt(uint16_t, uint32_t, uint32_t, Color, Color) = 0;
|
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) = 0;
|
||||||
virtual void Clear(Color) = 0;
|
virtual void clear(Color) = 0;
|
||||||
|
|
||||||
virtual void SetCursorPosition(uint32_t, uint32_t) = 0;
|
virtual void set_cursor_position(uint32_t, uint32_t) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace TerminalColor
|
namespace TerminalColor
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
class VesaTerminalDriver final : public TerminalDriver
|
class VesaTerminalDriver final : public TerminalDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static VesaTerminalDriver* Create();
|
static VesaTerminalDriver* create();
|
||||||
~VesaTerminalDriver();
|
~VesaTerminalDriver();
|
||||||
|
|
||||||
virtual uint32_t Width() const override { return m_width / m_font.Width; }
|
virtual uint32_t width() const override { return m_width / m_font.Width; }
|
||||||
virtual uint32_t Height() const override { return m_height / m_font.Height; }
|
virtual uint32_t height() const override { return m_height / m_font.Height; }
|
||||||
|
|
||||||
virtual void PutCharAt(uint16_t, uint32_t, uint32_t, Color, Color) override;
|
virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override;
|
||||||
virtual void Clear(Color) override;
|
virtual void clear(Color) override;
|
||||||
|
|
||||||
virtual void SetCursorPosition(uint32_t, uint32_t) override;
|
virtual void set_cursor_position(uint32_t, uint32_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VesaTerminalDriver(uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp, uintptr_t address, bitmap_font font)
|
VesaTerminalDriver(uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp, uintptr_t address, bitmap_font font)
|
||||||
|
@ -27,7 +27,7 @@ private:
|
||||||
, m_font(font)
|
, m_font(font)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void SetPixel(uint32_t, Color);
|
void set_pixel(uint32_t, Color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_width = 0;
|
uint32_t m_width = 0;
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
#include <BAN/Formatter.h>
|
#include <BAN/Formatter.h>
|
||||||
#include <kernel/TTY.h>
|
#include <kernel/TTY.h>
|
||||||
|
|
||||||
#define kprint(...) BAN::Formatter::print(TTY::PutCharCurrent, __VA_ARGS__)
|
#define kprint(...) BAN::Formatter::print(TTY::putchar_current, __VA_ARGS__)
|
||||||
#define kprintln(...) BAN::Formatter::println(TTY::PutCharCurrent, __VA_ARGS__)
|
#define kprintln(...) BAN::Formatter::println(TTY::putchar_current, __VA_ARGS__)
|
||||||
|
|
|
@ -110,7 +110,7 @@ union RedirectionEntry
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool IsRSDP(uintptr_t rsdp_addr)
|
static bool is_rsdp(uintptr_t rsdp_addr)
|
||||||
{
|
{
|
||||||
const RSDP* rsdp = (const RSDP*)rsdp_addr;
|
const RSDP* rsdp = (const RSDP*)rsdp_addr;
|
||||||
|
|
||||||
|
@ -137,16 +137,16 @@ static bool IsRSDP(uintptr_t rsdp_addr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uintptr_t LocateRSDP()
|
static uintptr_t locate_rsdp()
|
||||||
{
|
{
|
||||||
// Look in main BIOS area below 1 MB
|
// Look in main BIOS area below 1 MB
|
||||||
for (uintptr_t addr = 0x000E0000; addr < 0x000FFFFF; addr += 16)
|
for (uintptr_t addr = 0x000E0000; addr < 0x000FFFFF; addr += 16)
|
||||||
if (IsRSDP(addr))
|
if (is_rsdp(addr))
|
||||||
return addr;
|
return addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsValidSDTHeader(const SDTHeader* header)
|
static bool is_valid_std_header(const SDTHeader* header)
|
||||||
{
|
{
|
||||||
uint8_t sum = 0;
|
uint8_t sum = 0;
|
||||||
for (uint32_t i = 0; i < header->length; i++)
|
for (uint32_t i = 0; i < header->length; i++)
|
||||||
|
@ -154,7 +154,7 @@ static bool IsValidSDTHeader(const SDTHeader* header)
|
||||||
return sum == 0;
|
return sum == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t LocateMADT(uintptr_t rsdp_addr)
|
uintptr_t locate_madt(uintptr_t rsdp_addr)
|
||||||
{
|
{
|
||||||
uintptr_t entry_address_base = 0;
|
uintptr_t entry_address_base = 0;
|
||||||
uintptr_t entry_address_mask = 0;
|
uintptr_t entry_address_mask = 0;
|
||||||
|
@ -165,70 +165,70 @@ uintptr_t LocateMADT(uintptr_t rsdp_addr)
|
||||||
if (rsdp->revision == 2)
|
if (rsdp->revision == 2)
|
||||||
{
|
{
|
||||||
uintptr_t xsdt_addr = rsdp->v2_xsdt_address;
|
uintptr_t xsdt_addr = rsdp->v2_xsdt_address;
|
||||||
MMU::Get().AllocatePage(xsdt_addr);
|
MMU::get().allocate_page(xsdt_addr);
|
||||||
entry_address_base = xsdt_addr + sizeof(SDTHeader);
|
entry_address_base = xsdt_addr + sizeof(SDTHeader);
|
||||||
entry_address_mask = (uintptr_t)0xFFFFFFFFFFFFFFFF;
|
entry_address_mask = (uintptr_t)0xFFFFFFFFFFFFFFFF;
|
||||||
entry_count = (((const SDTHeader*)xsdt_addr)->length - sizeof(SDTHeader)) / 8;
|
entry_count = (((const SDTHeader*)xsdt_addr)->length - sizeof(SDTHeader)) / 8;
|
||||||
entry_pointer_size = 8;
|
entry_pointer_size = 8;
|
||||||
MMU::Get().UnAllocatePage(xsdt_addr);
|
MMU::get().unallocate_page(xsdt_addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uintptr_t rsdt_addr = rsdp->rsdt_address;
|
uintptr_t rsdt_addr = rsdp->rsdt_address;
|
||||||
MMU::Get().AllocatePage(rsdt_addr);
|
MMU::get().allocate_page(rsdt_addr);
|
||||||
entry_address_base = rsdt_addr + sizeof(SDTHeader);
|
entry_address_base = rsdt_addr + sizeof(SDTHeader);
|
||||||
entry_address_mask = 0xFFFFFFFF;
|
entry_address_mask = 0xFFFFFFFF;
|
||||||
entry_count = (((const SDTHeader*)rsdt_addr)->length - sizeof(SDTHeader)) / 4;
|
entry_count = (((const SDTHeader*)rsdt_addr)->length - sizeof(SDTHeader)) / 4;
|
||||||
entry_pointer_size = 4;
|
entry_pointer_size = 4;
|
||||||
MMU::Get().UnAllocatePage(rsdt_addr);
|
MMU::get().unallocate_page(rsdt_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < entry_count; i++)
|
for (uint32_t i = 0; i < entry_count; i++)
|
||||||
{
|
{
|
||||||
uintptr_t entry_addr_ptr = entry_address_base + i * entry_pointer_size;
|
uintptr_t entry_addr_ptr = entry_address_base + i * entry_pointer_size;
|
||||||
MMU::Get().AllocatePage(entry_addr_ptr);
|
MMU::get().allocate_page(entry_addr_ptr);
|
||||||
|
|
||||||
uintptr_t entry_addr = *(uintptr_t*)entry_addr_ptr & entry_address_mask;
|
uintptr_t entry_addr = *(uintptr_t*)entry_addr_ptr & entry_address_mask;
|
||||||
MMU::Get().AllocatePage(entry_addr);
|
MMU::get().allocate_page(entry_addr);
|
||||||
|
|
||||||
BAN::ScopeGuard _([&]() {
|
BAN::ScopeGuard _([&]() {
|
||||||
MMU::Get().UnAllocatePage(entry_addr);
|
MMU::get().unallocate_page(entry_addr);
|
||||||
MMU::Get().UnAllocatePage(entry_addr_ptr);
|
MMU::get().unallocate_page(entry_addr_ptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
const SDTHeader* entry = (const SDTHeader*)entry_addr;
|
const SDTHeader* entry = (const SDTHeader*)entry_addr;
|
||||||
if (memcmp(entry->signature, "APIC", 4) == 0 && IsValidSDTHeader(entry))
|
if (memcmp(entry->signature, "APIC", 4) == 0 && is_valid_std_header(entry))
|
||||||
return entry_addr;
|
return entry_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
APIC* APIC::Create()
|
APIC* APIC::create()
|
||||||
{
|
{
|
||||||
uint32_t ecx, edx;
|
uint32_t ecx, edx;
|
||||||
CPUID::GetFeatures(ecx, edx);
|
CPUID::get_features(ecx, edx);
|
||||||
if (!(edx & CPUID::Features::EDX_APIC))
|
if (!(edx & CPUID::Features::EDX_APIC))
|
||||||
{
|
{
|
||||||
dprintln("Local APIC is not available");
|
dprintln("Local APIC is not available");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t rsdp_addr = LocateRSDP();
|
uintptr_t rsdp_addr = locate_rsdp();
|
||||||
if (!rsdp_addr)
|
if (!rsdp_addr)
|
||||||
{
|
{
|
||||||
dprintln("Could not locate RSDP");
|
dprintln("Could not locate RSDP");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t madt_addr = LocateMADT(rsdp_addr);
|
uintptr_t madt_addr = locate_madt(rsdp_addr);
|
||||||
if (!madt_addr)
|
if (!madt_addr)
|
||||||
{
|
{
|
||||||
dprintln("Could not find MADT in RSDP");
|
dprintln("Could not find MADT in RSDP");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMU::Get().AllocatePage(madt_addr);
|
MMU::get().allocate_page(madt_addr);
|
||||||
|
|
||||||
const MADT* madt = (const MADT*)madt_addr;
|
const MADT* madt = (const MADT*)madt_addr;
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ APIC* APIC::Create()
|
||||||
processor.processor_id = entry->entry0.acpi_processor_id;
|
processor.processor_id = entry->entry0.acpi_processor_id;
|
||||||
processor.apic_id = entry->entry0.apic_id;
|
processor.apic_id = entry->entry0.apic_id;
|
||||||
processor.flags = entry->entry0.flags & 0x03;
|
processor.flags = entry->entry0.flags & 0x03;
|
||||||
MUST(apic->m_processors.PushBack(processor));
|
MUST(apic->m_processors.push_back(processor));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
IOAPIC ioapic;
|
IOAPIC ioapic;
|
||||||
|
@ -256,7 +256,7 @@ APIC* APIC::Create()
|
||||||
ioapic.address = entry->entry1.ioapic_address;
|
ioapic.address = entry->entry1.ioapic_address;
|
||||||
ioapic.gsi_base = entry->entry1.gsi_base;
|
ioapic.gsi_base = entry->entry1.gsi_base;
|
||||||
ioapic.max_redirs = 0;
|
ioapic.max_redirs = 0;
|
||||||
MUST(apic->m_io_apics.PushBack(ioapic));
|
MUST(apic->m_io_apics.push_back(ioapic));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
apic->m_irq_overrides[entry->entry2.irq_source] = entry->entry2.gsi;
|
apic->m_irq_overrides[entry->entry2.irq_source] = entry->entry2.gsi;
|
||||||
|
@ -270,25 +270,25 @@ APIC* APIC::Create()
|
||||||
}
|
}
|
||||||
madt_entry_addr += entry->length;
|
madt_entry_addr += entry->length;
|
||||||
}
|
}
|
||||||
MMU::Get().UnAllocatePage((uintptr_t)madt);
|
MMU::get().unallocate_page((uintptr_t)madt);
|
||||||
|
|
||||||
if (apic->m_local_apic == 0 || apic->m_io_apics.Empty())
|
if (apic->m_local_apic == 0 || apic->m_io_apics.empty())
|
||||||
{
|
{
|
||||||
dprintln("MADT did not provide necessary information");
|
dprintln("MADT did not provide necessary information");
|
||||||
delete apic;
|
delete apic;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMU::Get().AllocatePage(apic->m_local_apic);
|
MMU::get().allocate_page(apic->m_local_apic);
|
||||||
for (auto& io_apic : apic->m_io_apics)
|
for (auto& io_apic : apic->m_io_apics)
|
||||||
{
|
{
|
||||||
MMU::Get().AllocatePage(io_apic.address);
|
MMU::get().allocate_page(io_apic.address);
|
||||||
io_apic.max_redirs = io_apic.Read(IOAPIC_MAX_REDIRS);
|
io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mask all interrupts
|
// Mask all interrupts
|
||||||
uint32_t sivr = apic->ReadFromLocalAPIC(LAPIC_SIV_REG);
|
uint32_t sivr = apic->read_from_local_apic(LAPIC_SIV_REG);
|
||||||
apic->WriteToLocalAPIC(LAPIC_SIV_REG, sivr | 0x1FF);
|
apic->write_to_local_apic(LAPIC_SIV_REG, sivr | 0x1FF);
|
||||||
|
|
||||||
#if DEBUG_PRINT_PROCESSORS
|
#if DEBUG_PRINT_PROCESSORS
|
||||||
for (auto& processor : apic->m_processors)
|
for (auto& processor : apic->m_processors)
|
||||||
|
@ -302,36 +302,36 @@ APIC* APIC::Create()
|
||||||
return apic;
|
return apic;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t APIC::ReadFromLocalAPIC(ptrdiff_t offset)
|
uint32_t APIC::read_from_local_apic(ptrdiff_t offset)
|
||||||
{
|
{
|
||||||
return *(uint32_t*)(m_local_apic + offset);
|
return *(uint32_t*)(m_local_apic + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIC::WriteToLocalAPIC(ptrdiff_t offset, uint32_t data)
|
void APIC::write_to_local_apic(ptrdiff_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
*(uint32_t*)(m_local_apic + offset) = data;
|
*(uint32_t*)(m_local_apic + offset) = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t APIC::IOAPIC::Read(uint8_t offset)
|
uint32_t APIC::IOAPIC::read(uint8_t offset)
|
||||||
{
|
{
|
||||||
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
||||||
ioapic[0] = offset;
|
ioapic[0] = offset;
|
||||||
return ioapic[4];
|
return ioapic[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIC::IOAPIC::Write(uint8_t offset, uint32_t data)
|
void APIC::IOAPIC::write(uint8_t offset, uint32_t data)
|
||||||
{
|
{
|
||||||
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
volatile uint32_t* ioapic = (volatile uint32_t*)address;
|
||||||
ioapic[0] = offset;
|
ioapic[0] = offset;
|
||||||
ioapic[4] = data;
|
ioapic[4] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIC::EOI(uint8_t)
|
void APIC::eoi(uint8_t)
|
||||||
{
|
{
|
||||||
WriteToLocalAPIC(LAPIC_EIO_REG, 0);
|
write_to_local_apic(LAPIC_EIO_REG, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIC::EnableIrq(uint8_t irq)
|
void APIC::enable_irq(uint8_t irq)
|
||||||
{
|
{
|
||||||
uint32_t gsi = m_irq_overrides[irq];
|
uint32_t gsi = m_irq_overrides[irq];
|
||||||
|
|
||||||
|
@ -347,22 +347,22 @@ void APIC::EnableIrq(uint8_t irq)
|
||||||
ASSERT(ioapic);
|
ASSERT(ioapic);
|
||||||
|
|
||||||
RedirectionEntry redir;
|
RedirectionEntry redir;
|
||||||
redir.lo_dword = ioapic->Read(IOAPIC_REDIRS + gsi * 2);
|
redir.lo_dword = ioapic->read(IOAPIC_REDIRS + gsi * 2);
|
||||||
redir.hi_dword = ioapic->Read(IOAPIC_REDIRS + gsi * 2 + 1);
|
redir.hi_dword = ioapic->read(IOAPIC_REDIRS + gsi * 2 + 1);
|
||||||
|
|
||||||
redir.vector = IRQ_VECTOR_BASE + irq;
|
redir.vector = IRQ_VECTOR_BASE + irq;
|
||||||
redir.mask = 0;
|
redir.mask = 0;
|
||||||
redir.destination = m_processors.Front().apic_id;
|
redir.destination = m_processors.front().apic_id;
|
||||||
|
|
||||||
ioapic->Write(IOAPIC_REDIRS + gsi * 2, redir.lo_dword);
|
ioapic->write(IOAPIC_REDIRS + gsi * 2, redir.lo_dword);
|
||||||
ioapic->Write(IOAPIC_REDIRS + gsi * 2 + 1, redir.hi_dword);
|
ioapic->write(IOAPIC_REDIRS + gsi * 2 + 1, redir.hi_dword);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APIC::IsInService(uint8_t irq)
|
bool APIC::is_in_service(uint8_t irq)
|
||||||
{
|
{
|
||||||
uint32_t dword = (irq + IRQ_VECTOR_BASE) / 32;
|
uint32_t dword = (irq + IRQ_VECTOR_BASE) / 32;
|
||||||
uint32_t bit = (irq + IRQ_VECTOR_BASE) % 32;
|
uint32_t bit = (irq + IRQ_VECTOR_BASE) % 32;
|
||||||
|
|
||||||
uint32_t isr = ReadFromLocalAPIC(LAPIC_IS_REG + dword * 0x10);
|
uint32_t isr = read_from_local_apic(LAPIC_IS_REG + dword * 0x10);
|
||||||
return isr & (1 << bit);
|
return isr & (1 << bit);
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ namespace CPUID
|
||||||
asm volatile ("cpuid": "=a"(out[0]), "=b"(out[0]), "=d"(out[1]), "=c"(out[2]) : "a"(code));
|
asm volatile ("cpuid": "=a"(out[0]), "=b"(out[0]), "=d"(out[1]), "=c"(out[2]) : "a"(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetVendor()
|
const char* get_vendor()
|
||||||
{
|
{
|
||||||
static char vendor[13] {};
|
static char vendor[13] {};
|
||||||
get_cpuid_string(0x00, (uint32_t*)vendor);
|
get_cpuid_string(0x00, (uint32_t*)vendor);
|
||||||
|
@ -20,7 +20,7 @@ namespace CPUID
|
||||||
return vendor;
|
return vendor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetFeatures(uint32_t& ecx, uint32_t& edx)
|
void get_features(uint32_t& ecx, uint32_t& edx)
|
||||||
{
|
{
|
||||||
uint32_t buffer[4] {};
|
uint32_t buffer[4] {};
|
||||||
get_cpuid(0x01, buffer);
|
get_cpuid(0x01, buffer);
|
||||||
|
@ -28,7 +28,7 @@ namespace CPUID
|
||||||
edx = buffer[3];
|
edx = buffer[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Is64Bit()
|
bool is_64_bit()
|
||||||
{
|
{
|
||||||
uint32_t buffer[4] {};
|
uint32_t buffer[4] {};
|
||||||
get_cpuid(0x80000000, buffer);
|
get_cpuid(0x80000000, buffer);
|
||||||
|
@ -39,7 +39,7 @@ namespace CPUID
|
||||||
return buffer[3] & (1 << 29);
|
return buffer[3] & (1 << 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* FeatStringECX(uint32_t feat)
|
const char* feature_string_ecx(uint32_t feat)
|
||||||
{
|
{
|
||||||
switch (feat)
|
switch (feat)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +78,7 @@ namespace CPUID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* FeatStringEDX(uint32_t feat)
|
const char* feature_string_edx(uint32_t feat)
|
||||||
{
|
{
|
||||||
switch (feat)
|
switch (feat)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
namespace Debug
|
namespace Debug
|
||||||
{
|
{
|
||||||
|
|
||||||
void DumpStackTrace()
|
void dump_stack_trace()
|
||||||
{
|
{
|
||||||
struct stackframe
|
struct stackframe
|
||||||
{
|
{
|
||||||
|
@ -37,10 +37,10 @@ namespace Debug
|
||||||
|
|
||||||
void putchar(char ch)
|
void putchar(char ch)
|
||||||
{
|
{
|
||||||
if (Serial::IsInitialized())
|
if (Serial::is_initialized())
|
||||||
return Serial::putchar(ch);
|
return Serial::putchar(ch);
|
||||||
if (TTY::IsInitialized())
|
if (TTY::is_initialized())
|
||||||
return TTY::PutCharCurrent(ch);
|
return TTY::putchar_current(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -207,9 +207,9 @@ namespace Input
|
||||||
{
|
{
|
||||||
bool waiting_response = false;
|
bool waiting_response = false;
|
||||||
|
|
||||||
if (!s_command_queue.Empty())
|
if (!s_command_queue.empty())
|
||||||
{
|
{
|
||||||
auto& command = s_command_queue.Front();
|
auto& command = s_command_queue.front();
|
||||||
if (command.target == target && command._sent && !command._done)
|
if (command.target == target && command._sent && !command._done)
|
||||||
waiting_response = true;
|
waiting_response = true;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ namespace Input
|
||||||
{
|
{
|
||||||
if (waiting_response)
|
if (waiting_response)
|
||||||
{
|
{
|
||||||
auto& command = s_command_queue.Front();
|
auto& command = s_command_queue.front();
|
||||||
|
|
||||||
if (raw == I8042_KB_RESEND)
|
if (raw == I8042_KB_RESEND)
|
||||||
{
|
{
|
||||||
|
@ -241,7 +241,7 @@ namespace Input
|
||||||
}
|
}
|
||||||
else if (raw == 0xEE && command.command == 0xEE)
|
else if (raw == 0xEE && command.command == 0xEE)
|
||||||
{
|
{
|
||||||
s_command_queue.Pop();
|
s_command_queue.pop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -261,7 +261,7 @@ namespace Input
|
||||||
{
|
{
|
||||||
if (waiting_response)
|
if (waiting_response)
|
||||||
{
|
{
|
||||||
auto& command = s_command_queue.Front();
|
auto& command = s_command_queue.front();
|
||||||
|
|
||||||
if (raw == I8042_MOUSE_ACK)
|
if (raw == I8042_MOUSE_ACK)
|
||||||
{
|
{
|
||||||
|
@ -288,9 +288,9 @@ namespace Input
|
||||||
bool right = s_mouse_data_buffer[0] & (1 << 1);
|
bool right = s_mouse_data_buffer[0] & (1 << 1);
|
||||||
bool middle = s_mouse_data_buffer[0] & (1 << 2);
|
bool middle = s_mouse_data_buffer[0] & (1 << 2);
|
||||||
|
|
||||||
if (left) MUST(s_mouse_button_event_queue.Push({ .button = MouseButton::Left }));
|
if (left) MUST(s_mouse_button_event_queue.push({ .button = MouseButton::Left }));
|
||||||
if (right) MUST(s_mouse_button_event_queue.Push({ .button = MouseButton::Right }));
|
if (right) MUST(s_mouse_button_event_queue.push({ .button = MouseButton::Right }));
|
||||||
if (middle) MUST(s_mouse_button_event_queue.Push({ .button = MouseButton::Middle }));
|
if (middle) MUST(s_mouse_button_event_queue.push({ .button = MouseButton::Middle }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_mouse_data_buffer[1] || s_mouse_data_buffer[2])
|
if (s_mouse_data_buffer[1] || s_mouse_data_buffer[2])
|
||||||
|
@ -298,7 +298,7 @@ namespace Input
|
||||||
int16_t rel_x = (int16_t)s_mouse_data_buffer[1] - ((s_mouse_data_buffer[0] << 4) & 0x100);
|
int16_t rel_x = (int16_t)s_mouse_data_buffer[1] - ((s_mouse_data_buffer[0] << 4) & 0x100);
|
||||||
int16_t rel_y = (int16_t)s_mouse_data_buffer[2] - ((s_mouse_data_buffer[0] << 3) & 0x100);
|
int16_t rel_y = (int16_t)s_mouse_data_buffer[2] - ((s_mouse_data_buffer[0] << 3) & 0x100);
|
||||||
|
|
||||||
MUST(s_mouse_move_event_queue.Push({ .dx = rel_x, .dy = rel_y }));
|
MUST(s_mouse_move_event_queue.push({ .dx = rel_x, .dy = rel_y }));
|
||||||
}
|
}
|
||||||
|
|
||||||
s_mouse_data_buffer_index = 0;
|
s_mouse_data_buffer_index = 0;
|
||||||
|
@ -307,35 +307,35 @@ namespace Input
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Kernel::Panic("Unknown target");
|
Kernel::panic("Unknown target");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
if (!s_command_queue.Empty())
|
if (!s_command_queue.empty())
|
||||||
{
|
{
|
||||||
auto& command = s_command_queue.Front();
|
auto& command = s_command_queue.front();
|
||||||
if (command.target != TARGET_KEYBOARD && command.target != TARGET_MOUSE)
|
if (command.target != TARGET_KEYBOARD && command.target != TARGET_MOUSE)
|
||||||
Kernel::Panic("Undefined target for command 0x{2H}", command.command);
|
Kernel::panic("Undefined target for command 0x{2H}", command.command);
|
||||||
|
|
||||||
if (command._sent == 0 && command._ack == 0)
|
if (command._sent == 0 && command._ack == 0)
|
||||||
{
|
{
|
||||||
command._sent++;
|
command._sent++;
|
||||||
if (!i8042_command(command.target, command.command))
|
if (!i8042_command(command.target, command.command))
|
||||||
Kernel::Panic("PS/2 command oof {}, 0x{2H}", command.target, command.command);
|
Kernel::panic("PS/2 command oof {}, 0x{2H}", command.target, command.command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command._sent == 1 && command._ack == 1 && command.has_data)
|
if (command._sent == 1 && command._ack == 1 && command.has_data)
|
||||||
{
|
{
|
||||||
command._sent++;
|
command._sent++;
|
||||||
if (!i8042_command(command.target, command.data))
|
if (!i8042_command(command.target, command.data))
|
||||||
Kernel::Panic("PS/2 data oof {}, 0x{2H}", command.target, command.data);
|
Kernel::panic("PS/2 data oof {}, 0x{2H}", command.target, command.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command._sent > 0 && PIT::ms_since_boot() > s_command_sent + 1000)
|
if (command._sent > 0 && PIT::ms_since_boot() > s_command_sent + 1000)
|
||||||
{
|
{
|
||||||
kprintln("PS/2 command 0x{2H} timed out on {}", command.command, command.target);
|
dprintln("PS/2 command 0x{2H} timed out on {}", command.command, command.target);
|
||||||
// Discard command on timeout?
|
// Discard command on timeout?
|
||||||
command._done = true;
|
command._done = true;
|
||||||
command.target = 0;
|
command.target = 0;
|
||||||
|
@ -349,14 +349,14 @@ namespace Input
|
||||||
{
|
{
|
||||||
case I8042_KB_RESET:
|
case I8042_KB_RESET:
|
||||||
if (s_command_response[0] != I8042_KB_SELF_TEST_PASS)
|
if (s_command_response[0] != I8042_KB_SELF_TEST_PASS)
|
||||||
Kernel::Panic("PS/2 Keyboard self test failed");
|
Kernel::panic("PS/2 Keyboard self test failed");
|
||||||
break;
|
break;
|
||||||
case I8042_KB_SET_SCAN_CODE_SET:
|
case I8042_KB_SET_SCAN_CODE_SET:
|
||||||
break;
|
break;
|
||||||
case I8042_KB_SET_LEDS:
|
case I8042_KB_SET_LEDS:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Kernel::Panic("PS/2 Keyboard unhandled command");
|
Kernel::panic("PS/2 Keyboard unhandled command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command.target == TARGET_MOUSE)
|
else if (command.target == TARGET_MOUSE)
|
||||||
|
@ -365,43 +365,43 @@ namespace Input
|
||||||
{
|
{
|
||||||
case I8042_MOUSE_RESET:
|
case I8042_MOUSE_RESET:
|
||||||
if (s_command_response[0] != I8042_MOUSE_SELF_TEST_PASS)
|
if (s_command_response[0] != I8042_MOUSE_SELF_TEST_PASS)
|
||||||
Kernel::Panic("PS/2 Mouse self test failed");
|
Kernel::panic("PS/2 Mouse self test failed");
|
||||||
if (s_command_response[1] != 0x00)
|
if (s_command_response[1] != 0x00)
|
||||||
Kernel::Panic("PS/2 Mouse invalid byte sent after self test");
|
Kernel::panic("PS/2 Mouse invalid byte sent after self test");
|
||||||
break;
|
break;
|
||||||
case I8042_MOUSE_ENABLE:
|
case I8042_MOUSE_ENABLE:
|
||||||
break;
|
break;
|
||||||
case I8042_MOUSE_DISABLE:
|
case I8042_MOUSE_DISABLE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Kernel::Panic("PS/2 Mouse unhandled command");
|
Kernel::panic("PS/2 Mouse unhandled command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s_command_response_index = 0;
|
s_command_response_index = 0;
|
||||||
s_command_queue.Pop();
|
s_command_queue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!s_key_event_queue.Empty())
|
while (!s_key_event_queue.empty())
|
||||||
{
|
{
|
||||||
if (s_key_event_callback)
|
if (s_key_event_callback)
|
||||||
s_key_event_callback(s_key_event_queue.Front());
|
s_key_event_callback(s_key_event_queue.front());
|
||||||
s_key_event_queue.Pop();
|
s_key_event_queue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!s_mouse_button_event_queue.Empty())
|
while (!s_mouse_button_event_queue.empty())
|
||||||
{
|
{
|
||||||
if (s_mouse_button_event_callback)
|
if (s_mouse_button_event_callback)
|
||||||
s_mouse_button_event_callback(s_mouse_button_event_queue.Front());
|
s_mouse_button_event_callback(s_mouse_button_event_queue.front());
|
||||||
s_mouse_button_event_queue.Pop();
|
s_mouse_button_event_queue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!s_mouse_move_event_queue.Empty())
|
while (!s_mouse_move_event_queue.empty())
|
||||||
{
|
{
|
||||||
if (s_mouse_move_event_callback)
|
if (s_mouse_move_event_callback)
|
||||||
s_mouse_move_event_callback(s_mouse_move_event_queue.Front());
|
s_mouse_move_event_callback(s_mouse_move_event_queue.front());
|
||||||
s_mouse_move_event_queue.Pop();
|
s_mouse_move_event_queue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ namespace Input
|
||||||
|
|
||||||
if (update_leds)
|
if (update_leds)
|
||||||
{
|
{
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_KEYBOARD,
|
.target = TARGET_KEYBOARD,
|
||||||
.command = I8042_KB_SET_LEDS,
|
.command = I8042_KB_SET_LEDS,
|
||||||
.data = s_led_states,
|
.data = s_led_states,
|
||||||
|
@ -510,9 +510,9 @@ namespace Input
|
||||||
|
|
||||||
if (key != Key::INVALID)
|
if (key != Key::INVALID)
|
||||||
{
|
{
|
||||||
auto error_or = s_key_event_queue.Push({ .key = key, .modifiers = modifiers, .pressed = pressed });
|
auto error_or = s_key_event_queue.push({ .key = key, .modifiers = modifiers, .pressed = pressed });
|
||||||
if (error_or.IsError())
|
if (error_or.is_error())
|
||||||
dwarnln("{}", error_or.GetError());
|
dwarnln("{}", error_or.get_error());
|
||||||
}
|
}
|
||||||
s_keyboard_key_buffer_size -= index + 1;
|
s_keyboard_key_buffer_size -= index + 1;
|
||||||
memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size);
|
memmove(s_keyboard_key_buffer, s_keyboard_key_buffer + index, s_keyboard_key_buffer_size);
|
||||||
|
@ -540,17 +540,17 @@ namespace Input
|
||||||
{
|
{
|
||||||
// Register callback and IRQ
|
// Register callback and IRQ
|
||||||
IDT::register_irq_handler(KEYBOARD_IRQ, keyboard_irq_handler);
|
IDT::register_irq_handler(KEYBOARD_IRQ, keyboard_irq_handler);
|
||||||
InterruptController::Get().EnableIrq(KEYBOARD_IRQ);
|
InterruptController::get().enable_irq(KEYBOARD_IRQ);
|
||||||
i8042_controller_command(I8042_ENABLE_FIRST_PORT);
|
i8042_controller_command(I8042_ENABLE_FIRST_PORT);
|
||||||
|
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_KEYBOARD,
|
.target = TARGET_KEYBOARD,
|
||||||
.command = I8042_KB_RESET,
|
.command = I8042_KB_RESET,
|
||||||
.resp_cnt = 1,
|
.resp_cnt = 1,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Set scan code set 2
|
// Set scan code set 2
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_KEYBOARD,
|
.target = TARGET_KEYBOARD,
|
||||||
.command = I8042_KB_SET_SCAN_CODE_SET,
|
.command = I8042_KB_SET_SCAN_CODE_SET,
|
||||||
.data = 0x02,
|
.data = 0x02,
|
||||||
|
@ -558,7 +558,7 @@ namespace Input
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Turn LEDs off
|
// Turn LEDs off
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_KEYBOARD,
|
.target = TARGET_KEYBOARD,
|
||||||
.command = I8042_KB_SET_LEDS,
|
.command = I8042_KB_SET_LEDS,
|
||||||
.data = s_led_states,
|
.data = s_led_states,
|
||||||
|
@ -570,17 +570,17 @@ namespace Input
|
||||||
{
|
{
|
||||||
// Register callback and IRQ
|
// Register callback and IRQ
|
||||||
IDT::register_irq_handler(MOUSE_IRQ, mouse_irq_handler);
|
IDT::register_irq_handler(MOUSE_IRQ, mouse_irq_handler);
|
||||||
InterruptController::Get().EnableIrq(MOUSE_IRQ);
|
InterruptController::get().enable_irq(MOUSE_IRQ);
|
||||||
i8042_controller_command(I8042_ENABLE_SECOND_PORT);
|
i8042_controller_command(I8042_ENABLE_SECOND_PORT);
|
||||||
|
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_MOUSE,
|
.target = TARGET_MOUSE,
|
||||||
.command = I8042_MOUSE_RESET,
|
.command = I8042_MOUSE_RESET,
|
||||||
.resp_cnt = 2,
|
.resp_cnt = 2,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mouse should be disabled when sending commands
|
// Mouse should be disabled when sending commands
|
||||||
MUST(s_command_queue.Push({
|
MUST(s_command_queue.push({
|
||||||
.target = TARGET_MOUSE,
|
.target = TARGET_MOUSE,
|
||||||
.command = I8042_MOUSE_ENABLE,
|
.command = I8042_MOUSE_ENABLE,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -5,23 +5,23 @@
|
||||||
|
|
||||||
static InterruptController* s_instance = nullptr;
|
static InterruptController* s_instance = nullptr;
|
||||||
|
|
||||||
InterruptController& InterruptController::Get()
|
InterruptController& InterruptController::get()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptController::Initialize(bool force_pic)
|
void InterruptController::initialize(bool force_pic)
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
|
|
||||||
PIC::MaskAll();
|
PIC::mask_all();
|
||||||
PIC::Remap();
|
PIC::remap();
|
||||||
|
|
||||||
if (!force_pic)
|
if (!force_pic)
|
||||||
s_instance = APIC::Create();
|
s_instance = APIC::create();
|
||||||
if (s_instance)
|
if (s_instance)
|
||||||
return;
|
return;
|
||||||
dprintln("Using PIC instead of APIC");
|
dprintln("Using PIC instead of APIC");
|
||||||
s_instance = PIC::Create();
|
s_instance = PIC::create();
|
||||||
}
|
}
|
|
@ -26,14 +26,14 @@
|
||||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
PIC* PIC::Create()
|
PIC* PIC::create()
|
||||||
{
|
{
|
||||||
MaskAll();
|
mask_all();
|
||||||
Remap();
|
remap();
|
||||||
return new PIC;
|
return new PIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC::Remap()
|
void PIC::remap()
|
||||||
{
|
{
|
||||||
uint8_t a1 = IO::inb(PIC1_DATA);
|
uint8_t a1 = IO::inb(PIC1_DATA);
|
||||||
uint8_t a2 = IO::inb(PIC2_DATA);
|
uint8_t a2 = IO::inb(PIC2_DATA);
|
||||||
|
@ -67,20 +67,20 @@ void PIC::Remap()
|
||||||
IO::outb(PIC2_DATA, a2);
|
IO::outb(PIC2_DATA, a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC::MaskAll()
|
void PIC::mask_all()
|
||||||
{
|
{
|
||||||
IO::outb(PIC1_DATA, 0xFF);
|
IO::outb(PIC1_DATA, 0xFF);
|
||||||
IO::outb(PIC2_DATA, 0xFF);
|
IO::outb(PIC2_DATA, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC::EOI(uint8_t irq)
|
void PIC::eoi(uint8_t irq)
|
||||||
{
|
{
|
||||||
if (irq >= 8)
|
if (irq >= 8)
|
||||||
IO::outb(PIC2_COMMAND, PIC_EOI);
|
IO::outb(PIC2_COMMAND, PIC_EOI);
|
||||||
IO::outb(PIC1_COMMAND, PIC_EOI);
|
IO::outb(PIC1_COMMAND, PIC_EOI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC::EnableIrq(uint8_t irq)
|
void PIC::enable_irq(uint8_t irq)
|
||||||
{
|
{
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
@ -98,7 +98,7 @@ void PIC::EnableIrq(uint8_t irq)
|
||||||
IO::outb(port, value);
|
IO::outb(port, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PIC::IsInService(uint8_t irq)
|
bool PIC::is_in_service(uint8_t irq)
|
||||||
{
|
{
|
||||||
uint16_t port = irq < 8 ? PIC1_COMMAND : PIC2_COMMAND;
|
uint16_t port = irq < 8 ? PIC1_COMMAND : PIC2_COMMAND;
|
||||||
uint8_t bit = irq < 8 ? irq : irq - 8;
|
uint8_t bit = irq < 8 ? irq : irq - 8;
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace PIT
|
||||||
void irq_handler()
|
void irq_handler()
|
||||||
{
|
{
|
||||||
s_system_time++;
|
s_system_time++;
|
||||||
Kernel::Scheduler::Get().Switch();
|
Kernel::Scheduler::get().switch_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ms_since_boot()
|
uint64_t ms_since_boot()
|
||||||
|
@ -47,7 +47,7 @@ namespace PIT
|
||||||
|
|
||||||
IDT::register_irq_handler(PIT_IRQ, irq_handler);
|
IDT::register_irq_handler(PIT_IRQ, irq_handler);
|
||||||
|
|
||||||
InterruptController::Get().EnableIrq(PIT_IRQ);
|
InterruptController::get().enable_irq(PIT_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace RTC
|
||||||
out.year = get_rtc_register(CMOS_REGISTER_YEAR);
|
out.year = get_rtc_register(CMOS_REGISTER_YEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::Time GetCurrentTime()
|
BAN::Time get_current_time()
|
||||||
{
|
{
|
||||||
BAN::Time last_time = {};
|
BAN::Time last_time = {};
|
||||||
BAN::Time time = {};
|
BAN::Time time = {};
|
||||||
|
|
|
@ -16,7 +16,7 @@ __BEGIN_DECLS
|
||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
void __stack_chk_fail(void)
|
void __stack_chk_fail(void)
|
||||||
{
|
{
|
||||||
Kernel::Panic("Stack smashing detected");
|
Kernel::panic("Stack smashing detected");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,40 +20,38 @@ namespace Kernel
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
void Scheduler::Initialize()
|
void Scheduler::initialize()
|
||||||
{
|
{
|
||||||
ASSERT(!s_instance);
|
ASSERT(!s_instance);
|
||||||
s_instance = new Scheduler();
|
s_instance = new Scheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheduler& Scheduler::Get()
|
Scheduler& Scheduler::get()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Thread& Scheduler::CurrentThread() const
|
const Thread& Scheduler::current_thread() const
|
||||||
{
|
{
|
||||||
return *m_current_iterator;
|
return *m_current_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::AddThread(void(*thread)())
|
//void Scheduler::AddThread(const BAN::Function<void()>& function)
|
||||||
{
|
//{
|
||||||
MUST(m_threads.EmplaceBack(thread));
|
// MUST(m_threads.EmplaceBack(function));
|
||||||
if (!m_current_iterator)
|
//}
|
||||||
m_current_iterator = m_threads.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scheduler::Switch()
|
void Scheduler::switch_thread()
|
||||||
{
|
{
|
||||||
static uint8_t cnt = 0;
|
static uint8_t cnt = 0;
|
||||||
if (cnt++ % ms_between_switch)
|
if (cnt++ % ms_between_switch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASSERT(InterruptController::Get().IsInService(PIT_IRQ));
|
ASSERT(InterruptController::get().is_in_service(PIT_IRQ));
|
||||||
|
|
||||||
ASSERT(m_threads.Size() > 0);
|
ASSERT(m_threads.size() > 0);
|
||||||
if (m_threads.Size() == 1)
|
if (m_threads.size() == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASSERT(m_current_iterator);
|
ASSERT(m_current_iterator);
|
||||||
|
@ -69,7 +67,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
// NOTE: this does not invalidate the next/next_iterator
|
// NOTE: this does not invalidate the next/next_iterator
|
||||||
// since we are working with linked list
|
// since we are working with linked list
|
||||||
m_threads.Remove(m_current_iterator);
|
m_threads.remove(m_current_iterator);
|
||||||
m_current_iterator = decltype(m_threads)::iterator();
|
m_current_iterator = decltype(m_threads)::iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +125,11 @@ namespace Kernel
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::Start()
|
void Scheduler::start()
|
||||||
{
|
{
|
||||||
ASSERT(m_threads.Size() > 0);
|
ASSERT(m_threads.size() > 0);
|
||||||
ASSERT(m_current_iterator);
|
|
||||||
|
m_current_iterator = m_threads.begin();
|
||||||
|
|
||||||
Thread& current = *m_current_iterator;
|
Thread& current = *m_current_iterator;
|
||||||
ASSERT(current.state() == Thread::State::NotStarted);
|
ASSERT(current.state() == Thread::State::NotStarted);
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Serial
|
||||||
|
|
||||||
static bool s_initialized = false;
|
static bool s_initialized = false;
|
||||||
|
|
||||||
void Initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
IO::outb(COM1_PORT + 1, 0x00); // Disable all interrupts
|
IO::outb(COM1_PORT + 1, 0x00); // Disable all interrupts
|
||||||
IO::outb(COM1_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
IO::outb(COM1_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||||
|
@ -30,7 +30,7 @@ namespace Serial
|
||||||
s_initialized = true;
|
s_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInitialized()
|
bool is_initialized()
|
||||||
{
|
{
|
||||||
return s_initialized;
|
return s_initialized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/PIT.h>
|
#include <kernel/PIT.h>
|
||||||
#include <kernel/RTC.h>
|
#include <kernel/RTC.h>
|
||||||
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Shell.h>
|
#include <kernel/Shell.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#define TTY_PRINT(...) Formatter::print([this](char c) { m_tty->PutChar(c); }, __VA_ARGS__)
|
#define TTY_PRINT(...) Formatter::print([this](char c) { m_tty->putchar(c); }, __VA_ARGS__)
|
||||||
#define TTY_PRINTLN(...) Formatter::println([this](char c) { m_tty->PutChar(c); }, __VA_ARGS__)
|
#define TTY_PRINTLN(...) Formatter::println([this](char c) { m_tty->putchar(c); }, __VA_ARGS__)
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -22,20 +23,20 @@ namespace Kernel
|
||||||
Shell::Shell(TTY* tty)
|
Shell::Shell(TTY* tty)
|
||||||
: m_tty(tty)
|
: m_tty(tty)
|
||||||
{
|
{
|
||||||
Input::register_key_event_callback({ &Shell::KeyEventCallback, this });
|
Input::register_key_event_callback({ &Shell::key_event_callback, this });
|
||||||
SetPrompt(s_default_prompt);
|
set_prompt(s_default_prompt);
|
||||||
MUST(m_buffer.PushBack(""_sv));
|
MUST(m_buffer.push_back(""_sv));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::SetPrompt(StringView prompt)
|
void Shell::set_prompt(StringView prompt)
|
||||||
{
|
{
|
||||||
m_prompt_length = 0;
|
m_prompt_length = 0;
|
||||||
m_prompt = String();
|
m_prompt = String();
|
||||||
|
|
||||||
bool skipping = false;
|
bool skipping = false;
|
||||||
for (size_t i = 0; i < prompt.Size(); i++)
|
for (size_t i = 0; i < prompt.size(); i++)
|
||||||
{
|
{
|
||||||
if (i < prompt.Size() - 1 && prompt[i] == '\\')
|
if (i < prompt.size() - 1 && prompt[i] == '\\')
|
||||||
{
|
{
|
||||||
if (prompt[i + 1] == '[')
|
if (prompt[i + 1] == '[')
|
||||||
skipping = true;
|
skipping = true;
|
||||||
|
@ -45,13 +46,13 @@ namespace Kernel
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUST(m_prompt.PushBack(prompt[i]));
|
MUST(m_prompt.push_back(prompt[i]));
|
||||||
if (!skipping)
|
if (!skipping)
|
||||||
m_prompt_length++;
|
m_prompt_length++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::Run()
|
void Shell::run()
|
||||||
{
|
{
|
||||||
TTY_PRINT("{}", m_prompt);
|
TTY_PRINT("{}", m_prompt);
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -61,25 +62,25 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> Shell::ParseArguments(StringView command) const
|
Vector<String> Shell::parse_arguments(StringView command) const
|
||||||
{
|
{
|
||||||
Vector<String> result;
|
Vector<String> result;
|
||||||
|
|
||||||
while (!command.Empty())
|
while (!command.empty())
|
||||||
{
|
{
|
||||||
while (!command.Empty() && isspace(command.Front()))
|
while (!command.empty() && isspace(command.front()))
|
||||||
command = command.Substring(1);
|
command = command.substring(1);
|
||||||
|
|
||||||
if (command.Empty())
|
if (command.empty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
MUST(result.PushBack(""_sv));
|
MUST(result.push_back(""_sv));
|
||||||
|
|
||||||
char quoted = '\0';
|
char quoted = '\0';
|
||||||
bool escape = false;
|
bool escape = false;
|
||||||
while (!command.Empty())
|
while (!command.empty())
|
||||||
{
|
{
|
||||||
char ch = command.Front();
|
char ch = command.front();
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case '"':
|
case '"':
|
||||||
|
@ -104,28 +105,28 @@ default_case:
|
||||||
{
|
{
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 'f': MUST(result.Back().PushBack('\f')); break;
|
case 'f': MUST(result.back().push_back('\f')); break;
|
||||||
case 'n': MUST(result.Back().PushBack('\n')); break;
|
case 'n': MUST(result.back().push_back('\n')); break;
|
||||||
case 'r': MUST(result.Back().PushBack('\r')); break;
|
case 'r': MUST(result.back().push_back('\r')); break;
|
||||||
case 't': MUST(result.Back().PushBack('\t')); break;
|
case 't': MUST(result.back().push_back('\t')); break;
|
||||||
case 'v': MUST(result.Back().PushBack('\v')); break;
|
case 'v': MUST(result.back().push_back('\v')); break;
|
||||||
case '"': MUST(result.Back().PushBack('"')); break;
|
case '"': MUST(result.back().push_back('"')); break;
|
||||||
case '\'': MUST(result.Back().PushBack('\'')); break;
|
case '\'': MUST(result.back().push_back('\'')); break;
|
||||||
case '\\': MUST(result.Back().PushBack('\\')); break;
|
case '\\': MUST(result.back().push_back('\\')); break;
|
||||||
default:
|
default:
|
||||||
char buffer[3] { '\\', ch, '\0' };
|
char buffer[3] { '\\', ch, '\0' };
|
||||||
MUST(result.Back().Append(buffer));
|
MUST(result.back().append(buffer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MUST(result.Back().PushBack(ch));
|
MUST(result.back().push_back(ch));
|
||||||
}
|
}
|
||||||
escape = false;
|
escape = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
command = command.Substring(1);
|
command = command.substring(1);
|
||||||
}
|
}
|
||||||
argument_done:
|
argument_done:
|
||||||
continue;
|
continue;
|
||||||
|
@ -134,93 +135,119 @@ argument_done:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::ProcessCommand(const Vector<String>& arguments)
|
void Shell::process_command(const Vector<String>& arguments)
|
||||||
{
|
{
|
||||||
if (arguments.Empty())
|
if (arguments.empty())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "date")
|
else if (arguments.front() == "date")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'date' does not support command line arguments");
|
TTY_PRINTLN("'date' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto time = RTC::GetCurrentTime();
|
auto time = RTC::get_current_time();
|
||||||
TTY_PRINTLN("{}", time);
|
TTY_PRINTLN("{}", time);
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "echo")
|
else if (arguments.front() == "echo")
|
||||||
{
|
{
|
||||||
if (arguments.Size() > 1)
|
if (arguments.size() > 1)
|
||||||
{
|
{
|
||||||
TTY_PRINT("{}", arguments[1]);
|
TTY_PRINT("{}", arguments[1]);
|
||||||
for (size_t i = 2; i < arguments.Size(); i++)
|
for (size_t i = 2; i < arguments.size(); i++)
|
||||||
TTY_PRINT(" {}", arguments[i]);
|
TTY_PRINT(" {}", arguments[i]);
|
||||||
}
|
}
|
||||||
TTY_PRINTLN("");
|
TTY_PRINTLN("");
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "clear")
|
else if (arguments.front() == "clear")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'clear' does not support command line arguments");
|
TTY_PRINTLN("'clear' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_tty->Clear();
|
m_tty->clear();
|
||||||
m_tty->SetCursorPosition(0, 0);
|
m_tty->set_cursor_position(0, 0);
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "time")
|
else if (arguments.front() == "time")
|
||||||
{
|
{
|
||||||
auto new_args = arguments;
|
auto new_args = arguments;
|
||||||
new_args.Remove(0);
|
new_args.remove(0);
|
||||||
auto start = PIT::ms_since_boot();
|
auto start = PIT::ms_since_boot();
|
||||||
ProcessCommand(new_args);
|
process_command(new_args);
|
||||||
auto duration = PIT::ms_since_boot() - start;
|
auto duration = PIT::ms_since_boot() - start;
|
||||||
TTY_PRINTLN("took {} ms", duration);
|
TTY_PRINTLN("took {} ms", duration);
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "memory")
|
else if (arguments.front() == "thread")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
|
{
|
||||||
|
TTY_PRINTLN("'thread' does not support command line arguments");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Scheduler::Get().AddThread(
|
||||||
|
// [this, arguments]()
|
||||||
|
// {
|
||||||
|
// auto start = PIT::ms_since_boot();
|
||||||
|
// while (PIT::ms_since_boot() < start + 5000);
|
||||||
|
// auto copy = arguments;
|
||||||
|
// copy.remove(0);
|
||||||
|
// ProcessCommand(copy);
|
||||||
|
// }
|
||||||
|
//);
|
||||||
|
Scheduler::get().add_thread(BAN::Function<void()>(
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
auto start = PIT::ms_since_boot();
|
||||||
|
while (PIT::ms_since_boot() < start + 3000);
|
||||||
|
TTY_PRINTLN("hello");
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else if (arguments.front() == "memory")
|
||||||
|
{
|
||||||
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'memory' does not support command line arguments");
|
TTY_PRINTLN("'memory' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
kmalloc_dump_info();
|
kmalloc_dump_info();
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "cpuinfo")
|
else if (arguments.front() == "cpuinfo")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'cpuinfo' does not support command line arguments");
|
TTY_PRINTLN("'cpuinfo' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ecx, edx;
|
uint32_t ecx, edx;
|
||||||
auto vendor = CPUID::GetVendor();
|
auto vendor = CPUID::get_vendor();
|
||||||
CPUID::GetFeatures(ecx, edx);
|
CPUID::get_features(ecx, edx);
|
||||||
|
|
||||||
TTY_PRINTLN("Vendor: '{}'", vendor);
|
TTY_PRINTLN("Vendor: '{}'", vendor);
|
||||||
TTY_PRINTLN("64-bit: {}", CPUID::Is64Bit());
|
TTY_PRINTLN("64-bit: {}", CPUID::is_64_bit());
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
if (ecx & ((uint32_t)1 << i))
|
if (ecx & ((uint32_t)1 << i))
|
||||||
TTY_PRINT("{}{}", first ? (first = false, "") : ", ", CPUID::FeatStringECX((uint32_t)1 << i));
|
TTY_PRINT("{}{}", first ? (first = false, "") : ", ", CPUID::feature_string_ecx((uint32_t)1 << i));
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
if (edx & ((uint32_t)1 << i))
|
if (edx & ((uint32_t)1 << i))
|
||||||
TTY_PRINT("{}{}", first ? (first = false, "") : ", ", CPUID::FeatStringEDX((uint32_t)1 << i));
|
TTY_PRINT("{}{}", first ? (first = false, "") : ", ", CPUID::feature_string_edx((uint32_t)1 << i));
|
||||||
if (!first)
|
if (!first)
|
||||||
TTY_PRINTLN("");
|
TTY_PRINTLN("");
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "random")
|
else if (arguments.front() == "random")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'random' does not support command line arguments");
|
TTY_PRINTLN("'random' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t ecx, edx;
|
uint32_t ecx, edx;
|
||||||
CPUID::GetFeatures(ecx, edx);
|
CPUID::get_features(ecx, edx);
|
||||||
if (!(ecx & CPUID::Features::ECX_RDRND))
|
if (!(ecx & CPUID::Features::ECX_RDRND))
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("cpu does not support RDRAND instruction");
|
TTY_PRINTLN("cpu does not support RDRAND instruction");
|
||||||
|
@ -234,9 +261,9 @@ argument_done:
|
||||||
TTY_PRINTLN(" 0x{8H}", random);
|
TTY_PRINTLN(" 0x{8H}", random);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (arguments.Front() == "reboot")
|
else if (arguments.front() == "reboot")
|
||||||
{
|
{
|
||||||
if (arguments.Size() != 1)
|
if (arguments.size() != 1)
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("'reboot' does not support command line arguments");
|
TTY_PRINTLN("'reboot' does not support command line arguments");
|
||||||
return;
|
return;
|
||||||
|
@ -249,36 +276,36 @@ argument_done:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("unrecognized command '{}'", arguments.Front());
|
TTY_PRINTLN("unrecognized command '{}'", arguments.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::ReRenderBuffer() const
|
void Shell::rerender_buffer() const
|
||||||
{
|
{
|
||||||
TTY_PRINT("\e[{}G{}\e[K", m_prompt_length + 1, m_buffer[m_cursor_pos.line]);
|
TTY_PRINT("\e[{}G{}\e[K", m_prompt_length + 1, m_buffer[m_cursor_pos.line]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetLastLength(StringView sv)
|
static uint32_t get_last_length(StringView sv)
|
||||||
{
|
{
|
||||||
if (sv.Size() >= 2 && ((uint8_t)sv[sv.Size() - 2] >> 5) == 0b110) return 2;
|
if (sv.size() >= 2 && ((uint8_t)sv[sv.size() - 2] >> 5) == 0b110) return 2;
|
||||||
if (sv.Size() >= 3 && ((uint8_t)sv[sv.Size() - 3] >> 4) == 0b1110) return 3;
|
if (sv.size() >= 3 && ((uint8_t)sv[sv.size() - 3] >> 4) == 0b1110) return 3;
|
||||||
if (sv.Size() >= 4 && ((uint8_t)sv[sv.Size() - 4] >> 3) == 0b11110) return 4;
|
if (sv.size() >= 4 && ((uint8_t)sv[sv.size() - 4] >> 3) == 0b11110) return 4;
|
||||||
return Math::min<uint32_t>(sv.Size(), 1);
|
return Math::min<uint32_t>(sv.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetNextLength(StringView sv)
|
static uint32_t get_next_length(StringView sv)
|
||||||
{
|
{
|
||||||
if (sv.Size() >= 2 && ((uint8_t)sv[0] >> 5) == 0b110) return 2;
|
if (sv.size() >= 2 && ((uint8_t)sv[0] >> 5) == 0b110) return 2;
|
||||||
if (sv.Size() >= 3 && ((uint8_t)sv[0] >> 4) == 0b1110) return 3;
|
if (sv.size() >= 3 && ((uint8_t)sv[0] >> 4) == 0b1110) return 3;
|
||||||
if (sv.Size() >= 4 && ((uint8_t)sv[0] >> 3) == 0b11110) return 4;
|
if (sv.size() >= 4 && ((uint8_t)sv[0] >> 3) == 0b11110) return 4;
|
||||||
return Math::min<uint32_t>(sv.Size(), 1);
|
return Math::min<uint32_t>(sv.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetUnicodeCharacterCount(StringView sv)
|
static uint32_t get_unicode_character_count(StringView sv)
|
||||||
{
|
{
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
for (uint32_t i = 0; i < sv.Size(); i++)
|
for (uint32_t i = 0; i < sv.size(); i++)
|
||||||
{
|
{
|
||||||
uint8_t ch = sv[i];
|
uint8_t ch = sv[i];
|
||||||
if ((ch >> 5) == 0b110) i += 1;
|
if ((ch >> 5) == 0b110) i += 1;
|
||||||
|
@ -289,7 +316,7 @@ argument_done:
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::KeyEventCallback(Input::KeyEvent event)
|
void Shell::key_event_callback(Input::KeyEvent event)
|
||||||
{
|
{
|
||||||
if (!event.pressed)
|
if (!event.pressed)
|
||||||
return;
|
return;
|
||||||
|
@ -301,11 +328,11 @@ argument_done:
|
||||||
case Input::Key::Backspace:
|
case Input::Key::Backspace:
|
||||||
if (m_cursor_pos.col > 0)
|
if (m_cursor_pos.col > 0)
|
||||||
{
|
{
|
||||||
TTY_PRINT("\e[D{} ", current_buffer.SV().Substring(m_cursor_pos.index));
|
TTY_PRINT("\e[D{} ", current_buffer.sv().substring(m_cursor_pos.index));
|
||||||
|
|
||||||
uint32_t len = GetLastLength(current_buffer.SV().Substring(0, m_cursor_pos.index));
|
uint32_t len = get_last_length(current_buffer.sv().substring(0, m_cursor_pos.index));
|
||||||
m_cursor_pos.index -= len;
|
m_cursor_pos.index -= len;
|
||||||
current_buffer.Erase(m_cursor_pos.index, len);
|
current_buffer.erase(m_cursor_pos.index, len);
|
||||||
m_cursor_pos.col--;
|
m_cursor_pos.col--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -314,15 +341,14 @@ argument_done:
|
||||||
case Input::Key::NumpadEnter:
|
case Input::Key::NumpadEnter:
|
||||||
{
|
{
|
||||||
TTY_PRINTLN("");
|
TTY_PRINTLN("");
|
||||||
auto arguments = ParseArguments(current_buffer.SV());
|
auto arguments = parse_arguments(current_buffer.sv());
|
||||||
if (!arguments.Empty())
|
if (!arguments.empty())
|
||||||
{
|
{
|
||||||
ProcessCommand(arguments);
|
process_command(arguments);
|
||||||
MUST(m_old_buffer.PushBack(current_buffer));
|
MUST(m_old_buffer.push_back(current_buffer));
|
||||||
m_buffer = m_old_buffer;
|
m_buffer = m_old_buffer;
|
||||||
MUST(m_buffer.PushBack(""_sv));
|
MUST(m_buffer.push_back(""_sv));
|
||||||
MUST(m_buffer.Back().Reserve(128));
|
m_cursor_pos.line = m_buffer.size() - 1;
|
||||||
m_cursor_pos.line = m_buffer.Size() - 1;
|
|
||||||
}
|
}
|
||||||
m_cursor_pos.col = 0;
|
m_cursor_pos.col = 0;
|
||||||
m_cursor_pos.index = 0;
|
m_cursor_pos.index = 0;
|
||||||
|
@ -340,16 +366,16 @@ argument_done:
|
||||||
case Input::Key::Left:
|
case Input::Key::Left:
|
||||||
if (m_cursor_pos.index > 0)
|
if (m_cursor_pos.index > 0)
|
||||||
{
|
{
|
||||||
uint32_t len = GetLastLength(current_buffer.SV().Substring(0, m_cursor_pos.index));
|
uint32_t len = get_last_length(current_buffer.sv().substring(0, m_cursor_pos.index));
|
||||||
m_cursor_pos.index -= len;
|
m_cursor_pos.index -= len;
|
||||||
m_cursor_pos.col--;
|
m_cursor_pos.col--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Input::Key::Right:
|
case Input::Key::Right:
|
||||||
if (m_cursor_pos.index < current_buffer.Size())
|
if (m_cursor_pos.index < current_buffer.size())
|
||||||
{
|
{
|
||||||
uint32_t len = GetNextLength(current_buffer.SV().Substring(m_cursor_pos.index));
|
uint32_t len = get_next_length(current_buffer.sv().substring(m_cursor_pos.index));
|
||||||
m_cursor_pos.index += len;
|
m_cursor_pos.index += len;
|
||||||
m_cursor_pos.col++;
|
m_cursor_pos.col++;
|
||||||
}
|
}
|
||||||
|
@ -360,20 +386,20 @@ argument_done:
|
||||||
{
|
{
|
||||||
const auto& new_buffer = m_buffer[m_cursor_pos.line - 1];
|
const auto& new_buffer = m_buffer[m_cursor_pos.line - 1];
|
||||||
m_cursor_pos.line--;
|
m_cursor_pos.line--;
|
||||||
m_cursor_pos.index = new_buffer.Size();
|
m_cursor_pos.index = new_buffer.size();
|
||||||
m_cursor_pos.col = GetUnicodeCharacterCount(new_buffer);
|
m_cursor_pos.col = get_unicode_character_count(new_buffer);
|
||||||
ReRenderBuffer();
|
rerender_buffer();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Input::Key::Down:
|
case Input::Key::Down:
|
||||||
if (m_cursor_pos.line < m_buffer.Size() - 1)
|
if (m_cursor_pos.line < m_buffer.size() - 1)
|
||||||
{
|
{
|
||||||
const auto& new_buffer = m_buffer[m_cursor_pos.line + 1];
|
const auto& new_buffer = m_buffer[m_cursor_pos.line + 1];
|
||||||
m_cursor_pos.line++;
|
m_cursor_pos.line++;
|
||||||
m_cursor_pos.index = new_buffer.Size();
|
m_cursor_pos.index = new_buffer.size();
|
||||||
m_cursor_pos.col = GetUnicodeCharacterCount(new_buffer);
|
m_cursor_pos.col = get_unicode_character_count(new_buffer);
|
||||||
ReRenderBuffer();
|
rerender_buffer();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -382,8 +408,8 @@ argument_done:
|
||||||
const char* utf8 = Input::key_event_to_utf8(event);
|
const char* utf8 = Input::key_event_to_utf8(event);
|
||||||
if (utf8)
|
if (utf8)
|
||||||
{
|
{
|
||||||
TTY_PRINT("{}{}", utf8, current_buffer.SV().Substring(m_cursor_pos.index));
|
TTY_PRINT("{}{}", utf8, current_buffer.sv().substring(m_cursor_pos.index));
|
||||||
MUST(current_buffer.Insert(utf8, m_cursor_pos.index));
|
MUST(current_buffer.insert(utf8, m_cursor_pos.index));
|
||||||
m_cursor_pos.index += strlen(utf8);
|
m_cursor_pos.index += strlen(utf8);
|
||||||
m_cursor_pos.col++;
|
m_cursor_pos.col++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ static TTY* s_tty = nullptr;
|
||||||
TTY::TTY(TerminalDriver* driver)
|
TTY::TTY(TerminalDriver* driver)
|
||||||
: m_terminal_driver(driver)
|
: m_terminal_driver(driver)
|
||||||
{
|
{
|
||||||
m_width = m_terminal_driver->Width();
|
m_width = m_terminal_driver->width();
|
||||||
m_height = m_terminal_driver->Height();
|
m_height = m_terminal_driver->height();
|
||||||
|
|
||||||
m_buffer = new Cell[m_width * m_height];
|
m_buffer = new Cell[m_width * m_height];
|
||||||
|
|
||||||
|
@ -34,20 +34,20 @@ TTY::TTY(TerminalDriver* driver)
|
||||||
s_tty = this;
|
s_tty = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::Clear()
|
void TTY::clear()
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < m_width * m_height; i++)
|
for (uint32_t i = 0; i < m_width * m_height; i++)
|
||||||
m_buffer[i] = { .foreground = m_foreground, .background = m_background, .character = ' ' };
|
m_buffer[i] = { .foreground = m_foreground, .background = m_background, .character = ' ' };
|
||||||
m_terminal_driver->Clear(m_background);
|
m_terminal_driver->clear(m_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::SetCursorPosition(uint32_t x, uint32_t y)
|
void TTY::set_cursor_position(uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
static uint32_t last_x = -1;
|
static uint32_t last_x = -1;
|
||||||
static uint32_t last_y = -1;
|
static uint32_t last_y = -1;
|
||||||
if (last_x != uint32_t(-1) && last_y != uint32_t(-1))
|
if (last_x != uint32_t(-1) && last_y != uint32_t(-1))
|
||||||
RenderFromBuffer(last_x, last_y); // Hacky way to clear previous cursor in graphics mode :D
|
render_from_buffer(last_x, last_y); // Hacky way to clear previous cursor in graphics mode :D
|
||||||
m_terminal_driver->SetCursorPosition(x, y);
|
m_terminal_driver->set_cursor_position(x, y);
|
||||||
last_x = m_column = x;
|
last_x = m_column = x;
|
||||||
last_y = m_row = y;
|
last_y = m_row = y;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ static uint16_t handle_unicode(uint8_t ch)
|
||||||
return ch & 0x7F;
|
return ch & 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::ResetAnsiEscape()
|
void TTY::reset_ansi_escape()
|
||||||
{
|
{
|
||||||
m_ansi_state.mode = '\0';
|
m_ansi_state.mode = '\0';
|
||||||
m_ansi_state.index = 0;
|
m_ansi_state.index = 0;
|
||||||
|
@ -107,7 +107,7 @@ void TTY::ResetAnsiEscape()
|
||||||
m_ansi_state.nums[1] = -1;
|
m_ansi_state.nums[1] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::HandleAnsiSGR()
|
void TTY::handle_ansi_sgr()
|
||||||
{
|
{
|
||||||
switch (m_ansi_state.nums[0])
|
switch (m_ansi_state.nums[0])
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,7 @@ void TTY::HandleAnsiSGR()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::HandleAnsiEscape(uint16_t ch)
|
void TTY::handle_ansi_escape(uint16_t ch)
|
||||||
{
|
{
|
||||||
switch (m_ansi_state.mode)
|
switch (m_ansi_state.mode)
|
||||||
{
|
{
|
||||||
|
@ -148,7 +148,7 @@ void TTY::HandleAnsiEscape(uint16_t ch)
|
||||||
m_ansi_state.mode = CSI;
|
m_ansi_state.mode = CSI;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
}
|
}
|
||||||
|
|
||||||
case CSI:
|
case CSI:
|
||||||
|
@ -169,39 +169,39 @@ void TTY::HandleAnsiEscape(uint16_t ch)
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_row = max<int32_t>(m_row - m_ansi_state.nums[0], 0);
|
m_row = max<int32_t>(m_row - m_ansi_state.nums[0], 0);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'B': // Curson Down
|
case 'B': // Curson Down
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_row = min<int32_t>(m_row + m_ansi_state.nums[0], m_height - 1);
|
m_row = min<int32_t>(m_row + m_ansi_state.nums[0], m_height - 1);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'C': // Cursor Forward
|
case 'C': // Cursor Forward
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_column = min<int32_t>(m_column + m_ansi_state.nums[0], m_width - 1);
|
m_column = min<int32_t>(m_column + m_ansi_state.nums[0], m_width - 1);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'D': // Cursor Back
|
case 'D': // Cursor Back
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_column = max<int32_t>(m_column - m_ansi_state.nums[0], 0);
|
m_column = max<int32_t>(m_column - m_ansi_state.nums[0], 0);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'E': // Cursor Next Line
|
case 'E': // Cursor Next Line
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_row = min<int32_t>(m_row + m_ansi_state.nums[0], m_height - 1);
|
m_row = min<int32_t>(m_row + m_ansi_state.nums[0], m_height - 1);
|
||||||
m_column = 0;
|
m_column = 0;
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'F': // Cursor Previous Line
|
case 'F': // Cursor Previous Line
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_row = max<int32_t>(m_row - m_ansi_state.nums[0], 0);
|
m_row = max<int32_t>(m_row - m_ansi_state.nums[0], 0);
|
||||||
m_column = 0;
|
m_column = 0;
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'G': // Cursor Horizontal Absolute
|
case 'G': // Cursor Horizontal Absolute
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
m_column = clamp<int32_t>(m_ansi_state.nums[0] - 1, 0, m_width - 1);
|
m_column = clamp<int32_t>(m_ansi_state.nums[0] - 1, 0, m_width - 1);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'H': // Cursor Position
|
case 'H': // Cursor Position
|
||||||
if (m_ansi_state.nums[0] == -1)
|
if (m_ansi_state.nums[0] == -1)
|
||||||
m_ansi_state.nums[0] = 1;
|
m_ansi_state.nums[0] = 1;
|
||||||
|
@ -209,59 +209,59 @@ void TTY::HandleAnsiEscape(uint16_t ch)
|
||||||
m_ansi_state.nums[1] = 1;
|
m_ansi_state.nums[1] = 1;
|
||||||
m_row = clamp<int32_t>(m_ansi_state.nums[0] - 1, 0, m_height - 1);
|
m_row = clamp<int32_t>(m_ansi_state.nums[0] - 1, 0, m_height - 1);
|
||||||
m_column = clamp<int32_t>(m_ansi_state.nums[1] - 1, 0, m_width - 1);
|
m_column = clamp<int32_t>(m_ansi_state.nums[1] - 1, 0, m_width - 1);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'J': // Erase in Display
|
case 'J': // Erase in Display
|
||||||
dprintln("Unsupported ANSI CSI character J");
|
dprintln("Unsupported ANSI CSI character J");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'K': // Erase in Line
|
case 'K': // Erase in Line
|
||||||
if (m_ansi_state.nums[0] == -1 || m_ansi_state.nums[0] == 0)
|
if (m_ansi_state.nums[0] == -1 || m_ansi_state.nums[0] == 0)
|
||||||
for (uint32_t i = m_column; i < m_width; i++)
|
for (uint32_t i = m_column; i < m_width; i++)
|
||||||
PutCharAt(' ', i, m_row);
|
putchar_at(' ', i, m_row);
|
||||||
else
|
else
|
||||||
dprintln("Unsupported ANSI CSI character K");
|
dprintln("Unsupported ANSI CSI character K");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'S': // Scroll Up
|
case 'S': // Scroll Up
|
||||||
dprintln("Unsupported ANSI CSI character S");
|
dprintln("Unsupported ANSI CSI character S");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'T': // Scroll Down
|
case 'T': // Scroll Down
|
||||||
dprintln("Unsupported ANSI CSI character T");
|
dprintln("Unsupported ANSI CSI character T");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'f': // Horizontal Vertical Position
|
case 'f': // Horizontal Vertical Position
|
||||||
dprintln("Unsupported ANSI CSI character f");
|
dprintln("Unsupported ANSI CSI character f");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
case 'm':
|
case 'm':
|
||||||
HandleAnsiSGR();
|
handle_ansi_sgr();
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
default:
|
default:
|
||||||
dprintln("Unsupported ANSI CSI character {}", ch);
|
dprintln("Unsupported ANSI CSI character {}", ch);
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintln("Unsupported ANSI mode");
|
dprintln("Unsupported ANSI mode");
|
||||||
return ResetAnsiEscape();
|
return reset_ansi_escape();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::RenderFromBuffer(uint32_t x, uint32_t y)
|
void TTY::render_from_buffer(uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
ASSERT(x < m_width && y < m_height);
|
ASSERT(x < m_width && y < m_height);
|
||||||
const auto& cell = m_buffer[y * m_width + x];
|
const auto& cell = m_buffer[y * m_width + x];
|
||||||
m_terminal_driver->PutCharAt(cell.character, x, y, cell.foreground, cell.background);
|
m_terminal_driver->putchar_at(cell.character, x, y, cell.foreground, cell.background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::PutCharAt(uint16_t ch, uint32_t x, uint32_t y)
|
void TTY::putchar_at(uint16_t ch, uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
ASSERT(x < m_width && y < m_height);
|
ASSERT(x < m_width && y < m_height);
|
||||||
auto& cell = m_buffer[y * m_width + x];
|
auto& cell = m_buffer[y * m_width + x];
|
||||||
cell.character = ch;
|
cell.character = ch;
|
||||||
cell.foreground = m_foreground;
|
cell.foreground = m_foreground;
|
||||||
cell.background = m_background;
|
cell.background = m_background;
|
||||||
m_terminal_driver->PutCharAt(ch, x, y, m_foreground, m_background);
|
m_terminal_driver->putchar_at(ch, x, y, m_foreground, m_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::PutChar(char ch)
|
void TTY::putchar(char ch)
|
||||||
{
|
{
|
||||||
Kernel::LockGuard guard(m_lock);
|
Kernel::LockGuard guard(m_lock);
|
||||||
|
|
||||||
|
@ -271,8 +271,8 @@ void TTY::PutChar(char ch)
|
||||||
|
|
||||||
if (m_ansi_state.mode != 0)
|
if (m_ansi_state.mode != 0)
|
||||||
{
|
{
|
||||||
HandleAnsiEscape(cp);
|
handle_ansi_escape(cp);
|
||||||
SetCursorPosition(m_column, m_row);
|
set_cursor_position(m_column, m_row);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ void TTY::PutChar(char ch)
|
||||||
m_ansi_state.mode = '\1';
|
m_ansi_state.mode = '\1';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PutCharAt(cp, m_column, m_row);
|
putchar_at(cp, m_column, m_row);
|
||||||
m_column++;
|
m_column++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -326,37 +326,37 @@ void TTY::PutChar(char ch)
|
||||||
// Render the whole buffer to the screen
|
// Render the whole buffer to the screen
|
||||||
for (uint32_t y = 0; y < m_height; y++)
|
for (uint32_t y = 0; y < m_height; y++)
|
||||||
for (uint32_t x = 0; x < m_width; x++)
|
for (uint32_t x = 0; x < m_width; x++)
|
||||||
RenderFromBuffer(x, y);
|
render_from_buffer(x, y);
|
||||||
|
|
||||||
m_column = 0;
|
m_column = 0;
|
||||||
m_row--;
|
m_row--;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCursorPosition(m_column, m_row);
|
set_cursor_position(m_column, m_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::Write(const char* data, size_t size)
|
void TTY::write(const char* data, size_t size)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < size; i++)
|
for (size_t i = 0; i < size; i++)
|
||||||
PutChar(data[i]);
|
putchar(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::WriteString(const char* data)
|
void TTY::write_string(const char* data)
|
||||||
{
|
{
|
||||||
while (*data)
|
while (*data)
|
||||||
{
|
{
|
||||||
PutChar(*data);
|
putchar(*data);
|
||||||
data++;
|
data++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTY::PutCharCurrent(char ch)
|
void TTY::putchar_current(char ch)
|
||||||
{
|
{
|
||||||
ASSERT(s_tty);
|
ASSERT(s_tty);
|
||||||
s_tty->PutChar(ch);
|
s_tty->putchar(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TTY::IsInitialized()
|
bool TTY::is_initialized()
|
||||||
{
|
{
|
||||||
return s_tty != nullptr;
|
return s_tty != nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
extern const struct bitmap_font font;
|
extern const struct bitmap_font font;
|
||||||
|
|
||||||
VesaTerminalDriver* VesaTerminalDriver::Create()
|
VesaTerminalDriver* VesaTerminalDriver::create()
|
||||||
{
|
{
|
||||||
if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER))
|
if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER))
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ VesaTerminalDriver* VesaTerminalDriver::Create()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MMU::Get().AllocateRange(framebuffer.addr, framebuffer.pitch * framebuffer.height);
|
MMU::get().allocate_range(framebuffer.addr, framebuffer.pitch * framebuffer.height);
|
||||||
|
|
||||||
auto* driver = new VesaTerminalDriver(
|
auto* driver = new VesaTerminalDriver(
|
||||||
framebuffer.width,
|
framebuffer.width,
|
||||||
|
@ -46,18 +46,18 @@ VesaTerminalDriver* VesaTerminalDriver::Create()
|
||||||
framebuffer.addr,
|
framebuffer.addr,
|
||||||
font
|
font
|
||||||
);
|
);
|
||||||
driver->SetCursorPosition(0, 0);
|
driver->set_cursor_position(0, 0);
|
||||||
driver->Clear(TerminalColor::BLACK);
|
driver->clear(TerminalColor::BLACK);
|
||||||
return driver;
|
return driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VesaTerminalDriver::~VesaTerminalDriver()
|
VesaTerminalDriver::~VesaTerminalDriver()
|
||||||
{
|
{
|
||||||
MMU::Get().UnAllocateRange(m_address, m_pitch * m_height);
|
MMU::get().unallocate_range(m_address, m_pitch * m_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VesaTerminalDriver::SetPixel(uint32_t offset, Color color)
|
void VesaTerminalDriver::set_pixel(uint32_t offset, Color color)
|
||||||
{
|
{
|
||||||
uint32_t* pixel = (uint32_t*)(m_address + offset);
|
uint32_t* pixel = (uint32_t*)(m_address + offset);
|
||||||
switch (m_bpp)
|
switch (m_bpp)
|
||||||
|
@ -71,7 +71,7 @@ void VesaTerminalDriver::SetPixel(uint32_t offset, Color color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VesaTerminalDriver::PutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg)
|
void VesaTerminalDriver::putchar_at(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg)
|
||||||
{
|
{
|
||||||
uint32_t glyph_index = 0;
|
uint32_t glyph_index = 0;
|
||||||
for (uint32_t i = 0; i < m_font.Chars; i++)
|
for (uint32_t i = 0; i < m_font.Chars; i++)
|
||||||
|
@ -95,14 +95,14 @@ void VesaTerminalDriver::PutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg
|
||||||
for (uint32_t dx = 0; dx < m_font.Width && x + dx < m_width; dx++)
|
for (uint32_t dx = 0; dx < m_font.Width && x + dx < m_width; dx++)
|
||||||
{
|
{
|
||||||
uint8_t bitmask = 1 << (font.Width - dx - 1);
|
uint8_t bitmask = 1 << (font.Width - dx - 1);
|
||||||
SetPixel(pixel_offset, glyph[dy] & bitmask ? fg : bg);
|
set_pixel(pixel_offset, glyph[dy] & bitmask ? fg : bg);
|
||||||
pixel_offset += m_bpp / 8;
|
pixel_offset += m_bpp / 8;
|
||||||
}
|
}
|
||||||
row_offset += m_pitch;
|
row_offset += m_pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VesaTerminalDriver::Clear(Color color)
|
void VesaTerminalDriver::clear(Color color)
|
||||||
{
|
{
|
||||||
if (m_bpp == 32)
|
if (m_bpp == 32)
|
||||||
{
|
{
|
||||||
|
@ -119,14 +119,14 @@ void VesaTerminalDriver::Clear(Color color)
|
||||||
uint32_t pixel_offset = row_offset;
|
uint32_t pixel_offset = row_offset;
|
||||||
for (uint32_t x = 0; x < m_width; x++)
|
for (uint32_t x = 0; x < m_width; x++)
|
||||||
{
|
{
|
||||||
SetPixel(pixel_offset, color);
|
set_pixel(pixel_offset, color);
|
||||||
pixel_offset += m_bpp / 8;
|
pixel_offset += m_bpp / 8;
|
||||||
}
|
}
|
||||||
row_offset += m_pitch;
|
row_offset += m_pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VesaTerminalDriver::SetCursorPosition(uint32_t x, uint32_t y)
|
void VesaTerminalDriver::set_cursor_position(uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
ASSERT(m_font.Height == 16 && m_font.Width == 8);
|
ASSERT(m_font.Height == 16 && m_font.Width == 8);
|
||||||
constexpr uint8_t cursor[] = {
|
constexpr uint8_t cursor[] = {
|
||||||
|
@ -159,7 +159,7 @@ void VesaTerminalDriver::SetCursorPosition(uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
uint8_t bitmask = 1 << (font.Width - dx - 1);
|
uint8_t bitmask = 1 << (font.Width - dx - 1);
|
||||||
if (cursor[dy] & bitmask)
|
if (cursor[dy] & bitmask)
|
||||||
SetPixel(pixel_offset, s_cursor_color);
|
set_pixel(pixel_offset, s_cursor_color);
|
||||||
pixel_offset += m_bpp / 8;
|
pixel_offset += m_bpp / 8;
|
||||||
}
|
}
|
||||||
row_offset += m_pitch;
|
row_offset += m_pitch;
|
||||||
|
|
|
@ -56,8 +56,6 @@ ParsedCommandLine ParseCommandLine()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TTY* tty1 = nullptr;
|
|
||||||
|
|
||||||
extern "C" void kernel_main()
|
extern "C" void kernel_main()
|
||||||
{
|
{
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
@ -67,7 +65,7 @@ extern "C" void kernel_main()
|
||||||
auto cmdline = ParseCommandLine();
|
auto cmdline = ParseCommandLine();
|
||||||
|
|
||||||
if (!cmdline.disable_serial)
|
if (!cmdline.disable_serial)
|
||||||
Serial::Initialize();
|
Serial::initialize();
|
||||||
if (g_multiboot_magic != 0x2BADB002)
|
if (g_multiboot_magic != 0x2BADB002)
|
||||||
{
|
{
|
||||||
dprintln("Invalid multiboot magic number");
|
dprintln("Invalid multiboot magic number");
|
||||||
|
@ -81,15 +79,15 @@ extern "C" void kernel_main()
|
||||||
IDT::initialize();
|
IDT::initialize();
|
||||||
dprintln("IDT initialized");
|
dprintln("IDT initialized");
|
||||||
|
|
||||||
MMU::Intialize();
|
MMU::intialize();
|
||||||
dprintln("MMU initialized");
|
dprintln("MMU initialized");
|
||||||
|
|
||||||
TerminalDriver* terminal_driver = VesaTerminalDriver::Create();
|
TerminalDriver* terminal_driver = VesaTerminalDriver::create();
|
||||||
ASSERT(terminal_driver);
|
ASSERT(terminal_driver);
|
||||||
dprintln("VESA initialized");
|
dprintln("VESA initialized");
|
||||||
tty1 = new TTY(terminal_driver);
|
TTY* tty1 = new TTY(terminal_driver);
|
||||||
|
|
||||||
InterruptController::Initialize(cmdline.force_pic);
|
InterruptController::initialize(cmdline.force_pic);
|
||||||
dprintln("Interrupt controller initialized");
|
dprintln("Interrupt controller initialized");
|
||||||
|
|
||||||
PIT::initialize();
|
PIT::initialize();
|
||||||
|
|
|
@ -55,10 +55,10 @@ static uintptr_t chunk_address(size_t index)
|
||||||
void kmalloc_initialize()
|
void kmalloc_initialize()
|
||||||
{
|
{
|
||||||
if (!(g_multiboot_info->flags & (1 << 6)))
|
if (!(g_multiboot_info->flags & (1 << 6)))
|
||||||
Kernel::Panic("Kmalloc: Bootloader didn't provide a memory map");
|
Kernel::panic("Kmalloc: Bootloader didn't provide a memory map");
|
||||||
|
|
||||||
if ((uintptr_t)&g_kernel_end > s_kmalloc_base)
|
if ((uintptr_t)&g_kernel_end > s_kmalloc_base)
|
||||||
Kernel::Panic("Kmalloc: Kernel end ({}) is over kmalloc base ({})", &g_kernel_end, (void*)s_kmalloc_base);
|
Kernel::panic("Kmalloc: Kernel end ({}) is over kmalloc base ({})", &g_kernel_end, (void*)s_kmalloc_base);
|
||||||
|
|
||||||
// Validate kmalloc memory
|
// Validate kmalloc memory
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
@ -81,7 +81,7 @@ void kmalloc_initialize()
|
||||||
|
|
||||||
if (!valid)
|
if (!valid)
|
||||||
{
|
{
|
||||||
Kernel::Panic("Kmalloc: Could not find {}.{} MB of memory",
|
Kernel::panic("Kmalloc: Could not find {}.{} MB of memory",
|
||||||
(s_kmalloc_eternal_end - s_kmalloc_base) / MB,
|
(s_kmalloc_eternal_end - s_kmalloc_base) / MB,
|
||||||
(s_kmalloc_eternal_end - s_kmalloc_base) % MB
|
(s_kmalloc_eternal_end - s_kmalloc_base) % MB
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
int putchar(int c)
|
int putchar(int c)
|
||||||
{
|
{
|
||||||
#if defined(__is_libk)
|
#if defined(__is_libk)
|
||||||
Kernel::Panic("Please use kprint() instead of stdio");
|
Kernel::panic("Please use kprint() instead of stdio");
|
||||||
#else
|
#else
|
||||||
abort();
|
abort();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,7 @@ __attribute__((__noreturn__))
|
||||||
void abort(void)
|
void abort(void)
|
||||||
{
|
{
|
||||||
#if defined(__is_libk)
|
#if defined(__is_libk)
|
||||||
Kernel::Panic("abort()");
|
Kernel::panic("abort()");
|
||||||
#else
|
#else
|
||||||
printf("abort()\n");
|
printf("abort()\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue