Update kernel

This commit is contained in:
Alex
2023-08-06 04:53:14 +03:00
parent 3b65386399
commit 2c51e4432f
181 changed files with 21873 additions and 21475 deletions

View File

@ -1,521 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_STD_ATOMIC_H__
#define __FENNIX_KERNEL_STD_ATOMIC_H__
#include <types.h>
#include <cstddef>
#include <debug.h>
namespace std
{
#define _atomic(T) T
#define builtin_atomic_n(name) __atomic_##name##_n
#define builtin_atomic(name) __atomic_##name
/**
* @brief Specifies the memory ordering constraints for atomic operations.
*
* This enum specifies the possible values for the memory order parameter of atomic operations.
*
* Possible values are:
*
* - memory_order_relaxed: There are no synchronization
* or ordering constraints imposed on other reads or writes,
* only this operation's atomicity is guaranteed.
*
* - memory_order_consume: A load operation with this
* memory order performs a consume operation on the
* affected memory location: no reads or writes in the
* current thread dependent on the value currently loaded
* can be reordered before this load.
*
* - memory_order_acquire: A load operation with this
* memory order performs the acquire operation on the
* affected memory location: no reads or writes in the
* current thread can be reordered before this load.
*
* - memory_order_release: A store operation with this
* memory order performs the release operation: no reads
* or writes in the current thread can be reordered after
* this store.
*
* - memory_order_acq_rel: A read-modify-write operation
* with this memory order is both an acquire operation
* and a release operation.
*
* - memory_order_seq_cst: A load operation with this
* memory order performs an acquire operation, a store
* performs a release operation, and read-modify-write
* performs both an acquire operation and a release
* operation, plus a single total order exists in which
* all threads observe all modifications in the same order.
*/
enum class memory_order : int
{
relaxed,
consume,
acquire,
release,
acq_rel,
seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
template <typename T>
class atomic
{
_atomic(T) value;
public:
atomic() noexcept : value(0) {}
atomic(T desired) noexcept : value(desired) {}
// atomic(const atomic &) = delete;
/**
* @brief Load the value of the atomic variable
*
* @note Order must be one of memory_order::relaxed, memory_order::consume, memory_order::acquire or memory_order::seq_cst
*
* @param order Memory order constraint to use
* @return The value of the atomic variable
*/
T load(memory_order order = memory_order::seq_cst) const noexcept
{
return builtin_atomic_n(load)(&this->value, static_cast<int>(order));
}
/**
* @copydoc load()
*/
T load(memory_order order = memory_order::seq_cst) const volatile noexcept
{
return builtin_atomic_n(load)(&this->value, static_cast<int>(order));
}
/**
* @brief Store the value of the atomic variable
*
* @note Order must be one of memory_order::relaxed, memory_order::release or memory_order::seq_cst
*
* @param desired The value to store
* @param order Memory order constraint to use
*/
void store(T desired, memory_order order = memory_order::seq_cst) noexcept
{
builtin_atomic_n(store)(&this->value, desired, static_cast<int>(order));
}
/**
* @copydoc store()
*/
void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept
{
builtin_atomic_n(store)(&this->value, desired, static_cast<int>(order));
}
/**
* @brief Exchange the value of the atomic variable
*
* @param desired The value to exchange
* @param order Memory order constraint to use
* @return The value of the atomic variable before the exchange
*/
T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept
{
return builtin_atomic_n(exchange)(&this->value, desired, static_cast<int>(order));
}
/**
* @copydoc exchange()
*/
T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept
{
return builtin_atomic_n(exchange)(&this->value, desired, static_cast<int>(order));
}
/**
* @brief Compare and exchange the value of the atomic variable
*
* @param expected The expected value
* @param desired The desired value
* @param success Memory order constraint to use if the exchange succeeds
* @param failure Memory order constraint to use if the exchange fails
* @return True if the exchange succeeded, false otherwise
*/
bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure);
}
/**
* @copydoc compare_exchange_weak()
*/
bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure);
}
/**
* @brief Compare and exchange the value of the atomic variable
*
* @param expected The expected value
* @param desired The desired value
* @param order Memory order constraint to use
* @return True if the exchange succeeded, false otherwise
*/
bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast<int>(order));
}
/**
* @copydoc compare_exchange_weak()
*/
bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast<int>(order));
}
/**
* @brief Compare and exchange the value of the atomic variable
*
* @param expected The expected value
* @param desired The desired value
* @param success Memory order constraint to use if the exchange succeeds
* @param failure Memory order constraint to use if the exchange fails
* @return True if the exchange succeeded, false otherwise
*/
bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure);
}
/**
* @copydoc compare_exchange_strong()
*/
bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure);
}
/**
* @brief Compare and exchange the value of the atomic variable
*
* @param expected The expected value
* @param desired The desired value
* @param order Memory order constraint to use
* @return True if the exchange succeeded, false otherwise
*/
bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast<int>(order));
}
/**
* @copydoc compare_exchange_strong()
*/
bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast<int>(order));
}
/**
* @brief Fetch and add the value of the atomic variable
*
* @param arg The value to add
* @param order Memory order constraint to use
* @return The value of the atomic variable before the addition
*/
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_add)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_add()
*/
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_add)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Fetch and subtract the value of the atomic variable
*
* @param arg The value to subtract
* @param order Memory order constraint to use
* @return The value of the atomic variable before the subtraction
*/
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_sub)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_sub()
*/
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_sub)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Fetch and bitwise AND the value of the atomic variable
*
* @param arg The value to AND
* @param order Memory order constraint to use
* @return The value of the atomic variable before the AND
*/
T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_and)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_and()
*/
T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_and)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Fetch and bitwise OR the value of the atomic variable
*
* @param arg The value to OR
* @param order Memory order constraint to use
* @return The value of the atomic variable before the OR
*/
T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_or)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_or()
*/
T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_or)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Fetch and bitwise XOR the value of the atomic variable
*
* @param arg The value to XOR
* @param order Memory order constraint to use
* @return The value of the atomic variable before the XOR
*/
T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_xor)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_xor()
*/
T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_xor)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Fetch and bitwise NAND the value of the atomic variable
*
* @param arg The value to NAND
* @param order Memory order constraint to use
* @return The value of the atomic variable before the NAND
*/
T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
{
return builtin_atomic(fetch_nand)(&this->value, arg, static_cast<int>(order));
}
/**
* @copydoc fetch_nand()
*/
T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
{
return builtin_atomic(fetch_nand)(&this->value, arg, static_cast<int>(order));
}
/**
* @brief Notify all threads waiting on this atomic variable
*/
void notify_all() noexcept
{
fixme("not implemented");
}
/**
* @copydoc notify_all()
*/
void notify_all() volatile noexcept
{
fixme("not implemented");
}
/**
* @brief Notify one thread waiting on this atomic variable
*/
void notify_one() noexcept
{
fixme("not implemented");
}
/**
* @copydoc notify_one()
*/
void notify_one() volatile noexcept
{
fixme("not implemented");
}
/**
* @brief Wait for the atomic variable to change
*
* @param old The value to wait for
* @param order Memory order constraint to use
*/
void wait(T old, std::memory_order order = std::memory_order::seq_cst) const noexcept
{
fixme("not implemented");
}
/**
* @copydoc wait()
*/
void wait(T old, std::memory_order order = std::memory_order::seq_cst) const volatile noexcept
{
fixme("not implemented");
}
/**
* @brief Check whether this atomic type is lock-free
* @return True if this atomic type is lock-free
*/
bool is_lock_free() const noexcept
{
fixme("not implemented");
return true;
}
/**
* @copydoc is_lock_free()
*/
bool is_lock_free() const volatile noexcept
{
fixme("not implemented");
return true;
}
/**
* @brief Equals true if this atomic type is always lock-free
*/
static constexpr bool is_always_lock_free = true;
T operator++() noexcept { return this->fetch_add(1) + 1; }
T operator--() noexcept { return this->fetch_sub(1) - 1; }
T operator++(int) noexcept { return this->fetch_add(1); }
T operator--(int) noexcept { return this->fetch_sub(1); }
T operator+=(T desired) noexcept { return this->fetch_add(desired) + desired; }
T operator-=(T desired) noexcept { return this->fetch_sub(desired) - desired; }
// T operator+=(std::ptrdiff_t desired) noexcept { return this->fetch_add(desired) + desired; }
// T operator-=(std::ptrdiff_t desired) noexcept { return this->fetch_sub(desired) - desired; }
T operator&=(T desired) noexcept { return this->fetch_and(desired) & desired; }
T operator|=(T desired) noexcept { return this->fetch_or(desired) | desired; }
T operator^=(T desired) noexcept { return this->fetch_xor(desired) ^ desired; }
T operator->() noexcept { return this->load(); }
T operator~() noexcept { return this->fetch_nand(-1); }
bool operator==(const atomic &other) const noexcept { return this->load() == other.load(); }
bool operator==(T other) const noexcept { return this->load() == other; }
atomic &operator=(const atomic &) = delete;
T operator=(T desired) noexcept
{
this->store(desired);
return desired;
}
operator bool() noexcept { return this->load() != 0; }
// operator T() noexcept { return this->load(); }
operator T() const noexcept { return this->load(); }
};
typedef atomic<bool> atomic_bool;
typedef atomic<char> atomic_char;
typedef atomic<signed char> atomic_schar;
typedef atomic<unsigned char> atomic_uchar;
typedef atomic<short> atomic_short;
typedef atomic<unsigned short> atomic_ushort;
typedef atomic<int> atomic_int;
typedef atomic<unsigned int> atomic_uint;
typedef atomic<long> atomic_long;
typedef atomic<unsigned long> atomic_ulong;
typedef atomic<long long> atomic_llong;
typedef atomic<unsigned long long> atomic_ullong;
typedef atomic<char16_t> atomic_char16_t;
typedef atomic<char32_t> atomic_char32_t;
typedef atomic<wchar_t> atomic_wchar_t;
typedef atomic<int8_t> atomic_int8_t;
typedef atomic<uint8_t> atomic_uint8_t;
typedef atomic<int16_t> atomic_int16_t;
typedef atomic<uint16_t> atomic_uint16_t;
typedef atomic<int32_t> atomic_int32_t;
typedef atomic<uint32_t> atomic_uint32_t;
typedef atomic<int64_t> atomic_int64_t;
typedef atomic<uint64_t> atomic_uint64_t;
typedef atomic<int_least8_t> atomic_int_least8_t;
typedef atomic<uint_least8_t> atomic_uint_least8_t;
typedef atomic<int_least16_t> atomic_int_least16_t;
typedef atomic<uint_least16_t> atomic_uint_least16_t;
typedef atomic<int_least32_t> atomic_int_least32_t;
typedef atomic<uint_least32_t> atomic_uint_least32_t;
typedef atomic<int_least64_t> atomic_int_least64_t;
typedef atomic<uint_least64_t> atomic_uint_least64_t;
typedef atomic<int_fast8_t> atomic_int_fast8_t;
typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
typedef atomic<int_fast16_t> atomic_int_fast16_t;
typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
typedef atomic<int_fast32_t> atomic_int_fast32_t;
typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
typedef atomic<int_fast64_t> atomic_int_fast64_t;
typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
typedef atomic<intptr_t> atomic_intptr_t;
typedef atomic<uintptr_t> atomic_uintptr_t;
typedef atomic<size_t> atomic_size_t;
typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
typedef atomic<intmax_t> atomic_intmax_t;
typedef atomic<uintmax_t> atomic_uintmax_t;
}
#undef builtin_atomic_n
#undef builtin_atomic
#endif // !__FENNIX_KERNEL_STD_ATOMIC_H__

View File

@ -20,6 +20,7 @@
#include <types.h>
#include <type_trails>
#include <debug.h>
// show debug messages
@ -249,24 +250,6 @@ namespace std
}
};
template <typename T>
struct remove_reference
{
typedef T type;
};
template <typename T>
struct remove_reference<T &>
{
typedef T type;
};
template <typename T>
struct remove_reference<T &&>
{
typedef T type;
};
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;

View File

@ -24,6 +24,7 @@
// show debug messages
// #define DEBUG_CPP_STRING 1
// #define DEBUG_CPP_STRING_VERBOSE 1
#ifdef DEBUG_CPP_STRING
#define strdbg(m, ...) debug(m, ##__VA_ARGS__)
@ -31,6 +32,12 @@
#define strdbg(m, ...)
#endif
#ifdef DEBUG_CPP_STRING_VERBOSE
#define v_strdbg(m, ...) debug(m, ##__VA_ARGS__)
#else
#define v_strdbg(m, ...)
#endif
// TODO: Somewhere the delete is called twice, causing a double free error.
namespace std
@ -55,51 +62,65 @@ namespace std
this->Capacity = this->Length + 1;
this->Data = new char[this->Capacity];
strcpy(this->Data, Str);
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
}
~string()
{
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
delete[] this->Data, this->Data = nullptr;
}
size_t length() const
{
strdbg("String length: %d", this->Length);
v_strdbg("String length: %d",
this->Length);
return this->Length;
}
size_t capacity() const
{
strdbg("String capacity: %d", this->Capacity);
v_strdbg("String capacity: %d",
this->Capacity);
return this->Capacity;
}
const char *c_str() const
{
strdbg("String data: \"%s\"", this->Data);
v_strdbg("String data: \"%s\"",
this->Data);
return this->Data;
}
void resize(size_t NewLength)
{
strdbg("String resize: %d", NewLength);
if (NewLength > this->Capacity)
if (NewLength < this->Capacity)
{
size_t newCapacity = NewLength + 1;
char *newData = new char[newCapacity];
this->Length = NewLength;
this->Data[this->Length] = '\0';
strcpy(newData, this->Data);
strdbg("old: %#lx, new: %#lx", this->Data, newData);
delete[] this->Data;
this->Data = newData;
this->Capacity = newCapacity;
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return;
}
size_t newCapacity = NewLength + 1;
char *newData = new char[newCapacity];
strcpy(newData, this->Data);
strdbg("old: %#lx, new: %#lx",
this->Data, newData);
delete[] this->Data;
this->Data = newData;
this->Length = NewLength;
this->Data[this->Length] = '\0';
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
this->Capacity = newCapacity;
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
}
void concat(const string &Other)
@ -108,7 +129,8 @@ namespace std
this->resize(NewLength);
strcat(this->Data, Other.Data);
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
}
bool empty() const
@ -392,14 +414,26 @@ namespace std
for (size_t i = 0; i < Str.Length; i++)
this->Data[Pos + i] = Str.Data[i];
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
}
void pop_back()
{
strdbg("String pop_back");
if (this->Length > 0)
{
this->Data[this->Length - 1] = '\0';
this->Length--;
}
}
string operator+(const string &Other) const
{
string result = *this;
result.concat(Other);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
result.Data, result.Data, result.Length, result.Capacity);
return result;
}
@ -407,21 +441,33 @@ namespace std
{
string result = *this;
result.concat(Other);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity);
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
result.Data, result.Data, result.Length, result.Capacity);
return result;
}
string &operator+=(const string &Other)
{
this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
string &operator+=(const char *Other)
{
this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
string &operator+=(char Other)
{
const char str[2] = {Other, '\0'};
this->concat(str);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
@ -430,15 +476,16 @@ namespace std
// string &operator=(const string &Other)
// {
// if (this != &Other)
// {
// delete[] this->Data;
// this->Data = Other.Data;
// this->Length = Other.Length;
// this->Capacity = Other.Capacity;
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
// }
// return *this;
// if (this != &Other)
// {
// delete[] this->Data;
// this->Data = Other.Data;
// this->Length = Other.Length;
// this->Capacity = Other.Capacity;
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
// this->Data, this->Data, this->Length, this->Capacity);
// }
// return *this;
// }
string &operator=(const char *Other)
@ -448,21 +495,24 @@ namespace std
delete[] this->Data;
this->Data = new char[this->Capacity];
strcpy(this->Data, Other);
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
string &operator<<(const string &Other)
{
this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
string &operator<<(const char *Other)
{
this->concat(Other);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
this->Data, this->Data, this->Length, this->Capacity);
return *this;
}
@ -478,6 +528,18 @@ namespace std
return this->Data[Index];
}
char &operator[](size_t Index)
{
strdbg("String index: %d", Index);
return this->Data[Index];
}
const char &operator[](size_t Index) const
{
strdbg("String index: %d", Index);
return this->Data[Index];
}
bool operator==(const string &Other) const
{
strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other.Data);
@ -513,25 +575,29 @@ namespace std
iterator &operator++()
{
++this->Pointer;
strdbg("String iterator incremented: %#lx", this->Pointer);
strdbg("String iterator incremented: %#lx",
this->Pointer);
return *this;
}
char &operator*()
{
strdbg("String iterator dereferenced: %#lx", this->Pointer);
strdbg("String iterator dereferenced: %#lx",
this->Pointer);
return *this->Pointer;
}
bool operator!=(const iterator &Other) const
{
strdbg("String iterator compared: %#lx != %#lx", this->Pointer, Other.Pointer);
strdbg("String iterator compared: %#lx != %#lx",
this->Pointer, Other.Pointer);
return this->Pointer != Other.Pointer;
}
bool operator==(const iterator &Other) const
{
strdbg("String iterator compared: %#lx == %#lx", this->Pointer, Other.Pointer);
strdbg("String iterator compared: %#lx == %#lx",
this->Pointer, Other.Pointer);
return this->Pointer == Other.Pointer;
}
};

View File

@ -21,111 +21,111 @@
#include <types.h>
#include <std/functional.hpp>
#include <std/utility.hpp>
#include <std/vector.hpp>
#include <std/list.hpp>
#include <vector>
namespace std
{
template <typename key_type, typename value_type>
class unordered_map
{
public:
typedef std::pair<key_type, value_type> key_value_pair;
typedef std::list<key_value_pair> bucket;
typedef typename std::vector<bucket>::iterator iterator;
typedef typename std::vector<bucket>::const_iterator const_iterator;
template <typename key_type, typename value_type>
class unordered_map
{
public:
typedef std::pair<key_type, value_type> key_value_pair;
typedef std::list<key_value_pair> bucket;
typedef typename std::vector<bucket>::iterator iterator;
typedef typename std::vector<bucket>::const_iterator const_iterator;
private:
static const size_t DEFAULT_NUM_BUCKETS = 10;
std::vector<bucket> bkts;
private:
static const size_t DEFAULT_NUM_BUCKETS = 10;
std::vector<bucket> bkts;
size_t hash(const key_type &key) const
{
std::hash<key_type> hash_function;
return hash_function(key) % this->bkts.size();
}
size_t hash(const key_type &key) const
{
std::hash<key_type> hash_function;
return hash_function(key) % this->bkts.size();
}
public:
unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {}
unordered_map(size_t num_buckets) : bkts(num_buckets) {}
public:
unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {}
unordered_map(size_t num_buckets) : bkts(num_buckets) {}
void insert(const key_value_pair &pair)
{
size_t bucket_index = hash(pair.first);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == pair.first)
{
it->second = pair.second;
return;
}
}
bkt.push_back(pair);
}
void insert(const key_value_pair &pair)
{
size_t bucket_index = hash(pair.first);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == pair.first)
{
it->second = pair.second;
return;
}
}
bkt.push_back(pair);
}
bool contains(const key_type &key) const
{
size_t bucket_index = hash(key);
const bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == key)
{
return true;
}
}
return false;
}
bool contains(const key_type &key) const
{
size_t bucket_index = hash(key);
const bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == key)
{
return true;
}
}
return false;
}
iterator find(const key_type &k)
{
size_t bucket_index = hash(k);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == k)
return it;
}
return bkt.end();
}
iterator find(const key_type &k)
{
size_t bucket_index = hash(k);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == k)
return it;
}
return bkt.end();
}
const_iterator find(const key_type &k) const
{
size_t bucket_index = hash(k);
const bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == k)
return it;
}
return bkt.end();
}
const_iterator find(const key_type &k) const
{
size_t bucket_index = hash(k);
const bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == k)
return it;
}
return bkt.end();
}
iterator end() noexcept { return this->bkts.end(); }
iterator end() { return this->bkts.end(); }
size_t size() const
{
size_t count = 0;
foreach (const auto &bkt in this->bkts)
count += bkt.size();
size_t size() const
{
size_t count = 0;
foreach (const auto &bkt in this->bkts)
count += bkt.size();
return count;
}
return count;
}
value_type &operator[](const key_type &key)
{
size_t bucket_index = hash(key);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == key)
return it->second;
}
bkt.emplace_back(key, value_type());
return bkt.back().second;
}
};
value_type &operator[](const key_type &key)
{
size_t bucket_index = hash(key);
bucket &bkt = this->bkts[bucket_index];
for (auto it = bkt.begin(); it != bkt.end(); ++it)
{
if (it->first == key)
return it->second;
}
bkt.emplace_back(key, value_type());
return bkt.back().second;
}
};
}
#endif // !__FENNIX_KERNEL_STD_UNORDERED_MAP_H__

View File

@ -1,286 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_STD_VECTOR_H__
#define __FENNIX_KERNEL_STD_VECTOR_H__
#include <types.h>
#include <assert.h>
#include <cstring>
namespace std
{
template <class T>
class vector
{
private:
size_t VectorSize = 0;
size_t VectorCapacity = 0;
T *VectorBuffer = nullptr;
public:
typedef T *iterator;
typedef const T *const_iterator;
NIF vector()
{
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( )");
#endif
VectorCapacity = 0;
VectorSize = 0;
VectorBuffer = 0;
}
NIF vector(size_t Size)
{
VectorCapacity = Size;
VectorSize = Size;
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( %lld )", Size);
#endif
VectorBuffer = new T[Size];
}
NIF vector(size_t Size, const T &Initial)
{
VectorSize = Size;
VectorCapacity = Size;
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( %lld %llx )", Size, Initial);
#endif
assert(Size > 0);
VectorBuffer = new T[Size];
for (size_t i = 0; i < Size; i++)
VectorBuffer[i] = Initial;
}
NIF vector(const vector<T> &v)
{
VectorSize = v.VectorSize;
VectorCapacity = v.VectorCapacity;
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: vector( <vector> )->Size: %lld", VectorSize);
#endif
if (!v.VectorBuffer || VectorSize <= 0)
return;
VectorBuffer = new T[VectorSize];
for (size_t i = 0; i < VectorSize; i++)
VectorBuffer[i] = v.VectorBuffer[i];
}
NIF ~vector()
{
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR INIT: ~vector( ~%lx )", VectorBuffer);
#endif
VectorSize = 0;
VectorCapacity = 0;
if (VectorBuffer != nullptr)
{
delete[] VectorBuffer, VectorBuffer = nullptr;
}
}
NIF void remove(size_t Position)
{
if (Position >= VectorSize)
return;
memset(&*(VectorBuffer + Position), 0, sizeof(T));
for (size_t i = 0; i < VectorSize - 1; i++)
{
*(VectorBuffer + Position + i) = *(VectorBuffer + Position + i + 1);
}
VectorSize--;
}
NIF void remove(const T &Value)
{
for (size_t i = 0; i < VectorSize; i++)
{
if (VectorBuffer[i] == Value)
{
remove(i);
return;
}
}
}
NIF T &null_elem()
{
static T null_elem{};
return null_elem;
}
NIF bool null_elem(size_t Index)
{
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
return false;
return true;
}
NIF T &next(size_t Position)
{
if (Position + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[Position + 1]))
return VectorBuffer[Position + 1];
warn("next( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
return this->null_elem();
}
NIF T &prev(size_t Position)
{
if (Position > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[Position - 1]))
return VectorBuffer[Position - 1];
warn("prev( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
return this->null_elem();
}
NIF T &next(const T &Value)
{
for (size_t i = 0; i < VectorSize; i++)
{
if (VectorBuffer[i] == Value)
{
if (i + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[i + 1]))
return VectorBuffer[i + 1];
else
break;
}
}
warn("next( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
return this->null_elem();
}
NIF T &prev(const T &Value)
{
for (size_t i = 0; i < VectorSize; i++)
{
if (VectorBuffer[i] == Value)
{
if (i > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[i - 1]))
return VectorBuffer[i - 1];
else
break;
}
}
warn("prev( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
return this->null_elem();
}
NIF size_t capacity() const { return VectorCapacity; }
NIF size_t size() const { return VectorSize; }
NIF bool empty() const;
NIF iterator begin() { return VectorBuffer; }
NIF iterator end() { return VectorBuffer + size(); }
NIF T &front() { return VectorBuffer[0]; }
NIF T &back() { return VectorBuffer[VectorSize - 1]; }
NIF void push_back(const T &Value)
{
if (VectorSize >= VectorCapacity)
reserve(VectorCapacity + 5);
VectorBuffer[VectorSize++] = Value;
}
NIF void pop_back() { VectorSize--; }
NIF void reverse()
{
if (VectorSize <= 1)
return;
for (size_t i = 0, j = VectorSize - 1; i < j; i++, j--)
{
T c = *(VectorBuffer + i);
*(VectorBuffer + i) = *(VectorBuffer + j);
*(VectorBuffer + j) = c;
}
}
NIF void reserve(size_t Capacity)
{
if (VectorBuffer == 0)
{
VectorSize = 0;
VectorCapacity = 0;
}
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR ALLOCATION: reverse( %lld )", Capacity);
#endif
T *NewBuffer = new T[Capacity];
size_t _Size = Capacity < VectorSize ? Capacity : VectorSize;
for (size_t i = 0; i < _Size; i++)
NewBuffer[i] = VectorBuffer[i];
VectorCapacity = Capacity;
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR ALLOCATION: reverse( <Capacity> )->Buffer:~%lld", VectorBuffer);
#endif
delete[] VectorBuffer;
VectorBuffer = NewBuffer;
}
NIF void resize(size_t Size)
{
reserve(Size);
VectorSize = Size;
}
NIF void clear()
{
VectorCapacity = 0;
VectorSize = 0;
if (VectorBuffer != nullptr)
{
delete[] VectorBuffer, VectorBuffer = nullptr;
}
}
NIF T *data() { return VectorBuffer; }
NIF T &operator[](size_t Index)
{
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
{
warn("operator[]( %lld ) is null (requested by %#lx)", Index, __builtin_return_address(0));
return this->null_elem();
}
return VectorBuffer[Index];
}
NIF vector<T> &operator=(const vector<T> &v)
{
delete[] VectorBuffer;
VectorSize = v.VectorSize;
VectorCapacity = v.VectorCapacity;
#ifdef DEBUG_MEM_ALLOCATION
debug("VECTOR ALLOCATION: operator=( <vector> )->Size:%lld", VectorSize);
#endif
VectorBuffer = new T[VectorSize];
for (size_t i = 0; i < VectorSize; i++)
VectorBuffer[i] = v.VectorBuffer[i];
return *this;
}
};
}
#endif // !__FENNIX_KERNEL_STD_VECTOR_H__