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

65
include_std/algorithm Normal file
View File

@ -0,0 +1,65 @@
/*
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/>.
*/
#pragma once
namespace std
{
template <typename InputIt, typename OutputIt>
OutputIt copy(InputIt first, InputIt last, OutputIt result)
{
while (first != last)
{
*result = *first;
++result;
++first;
}
return result;
}
template <typename T>
void swap(T &a, T &b)
{
T temp = move(a);
a = move(b);
b = move(temp);
}
template <typename T>
constexpr const T &min(const T &a, const T &b)
{
return (a < b) ? a : b;
}
template <typename T>
constexpr const T &max(const T &a, const T &b)
{
return (a > b) ? a : b;
}
template <class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T &value)
{
while (first != last)
{
if (*first == value)
return first;
++first;
}
return last;
}
}

View File

@ -20,31 +20,31 @@
#include <debug.h>
#define assert(x) \
do \
{ \
if (!(x)) \
{ \
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
while (1) \
; \
} \
} while (0)
#define assert(x) \
do \
{ \
if (!(x)) \
{ \
error("Assertion failed! [%s] [%s:%s:%d]", \
#x, __FILE__, __FUNCTION__, __LINE__); \
int3; \
while (true) \
; \
} \
} while (0)
#define assert_allow_continue(x) \
do \
{ \
if (!(x)) \
{ \
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
} \
} while (0)
#define assert_allow_continue(x) \
do \
{ \
if (!(x)) \
{ \
error("Assertion failed! [%s] [%s:%s:%d]", \
#x, __FILE__, __FUNCTION__, __LINE__); \
} \
} while (0)
#define static_assert(x) \
switch (x) \
case 0: \
case (x):
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
#define static_assert _Static_assert
#endif
#endif // !__FENNIX_KERNEL_ASSERT_H__

View File

@ -16,4 +16,651 @@
*/
#pragma once
#include <std/atomic.hpp>
#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
/**
* 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
};
/**
* Relaxed memory order
*
* No synchronization or ordering constraints
* imposed on other reads or writes.
* Only atomicity is guaranteed. */
inline constexpr memory_order memory_order_relaxed =
memory_order::relaxed;
/**
* Consume memory order
*
* 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. Writes to data-dependent variables in
* other threads that release the same atomic
* variable are visible in the current thread.
*/
inline constexpr memory_order memory_order_consume =
memory_order::consume;
/** Acquire memory order
*
* 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. All writes in other threads that release
* the same atomic variable are visible in the
* current thread. */
inline constexpr memory_order memory_order_acquire =
memory_order::acquire;
/** Release memory order
*
* 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. All writes in the current
* thread are visible in other threads that acquire
* the same atomic variable, and writes that carry
* a dependency into the atomic variable become
* visible in other threads that consume the same
* atomic. */
inline constexpr memory_order memory_order_release =
memory_order::release;
/** Acquire-release memory order
*
* A read-modify-write operation with this memory
* order is both an acquire operation and a release
* operation. No memory reads or writes in the
* current thread can be reordered before the load,
* nor after the store. All writes in other threads
* that release the same atomic variable are visible
* before the modification, and the modification is
* visible in other threads that acquire the same
* atomic variable. */
inline constexpr memory_order memory_order_acq_rel =
memory_order::acq_rel;
/** Sequentially-consistent memory order
*
* 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.
* Additionally, a single total order exists in which
* all threads observe all modifications in the same
* order. */
inline constexpr memory_order memory_order_seq_cst =
memory_order::seq_cst;
template <typename T>
class atomic
{
_atomic(T) value;
public:
atomic() : value(0) {}
atomic(T desired) : value(desired) {}
// atomic(const atomic &) = delete;
/**
* 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
{
return builtin_atomic_n(load)(&this->value,
static_cast<int>(order));
}
/**
* @copydoc load()
*/
T load(memory_order order = memory_order::seq_cst) const volatile
{
return builtin_atomic_n(load)(&this->value,
static_cast<int>(order));
}
/**
* 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)
{
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
{
builtin_atomic_n(store)(&this->value, desired,
static_cast<int>(order));
}
/**
* 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)
{
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
{
return builtin_atomic_n(exchange)(&this->value, desired,
static_cast<int>(order));
}
/**
* 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,
memory_order success,
memory_order failure)
{
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,
memory_order success,
memory_order failure) volatile
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
desired, false, success,
failure);
}
/**
* 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,
memory_order order =
memory_order_seq_cst)
{
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,
memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
desired, false, order,
static_cast<int>(order));
}
/**
* 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,
memory_order success,
memory_order failure)
{
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,
memory_order success,
memory_order failure) volatile
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
desired, true, success,
failure);
}
/**
* 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,
memory_order order =
memory_order_seq_cst)
{
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,
memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
desired, true, order,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_add)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_add()
*/
T fetch_add(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_add)(&this->value, arg,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_sub)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_sub()
*/
T fetch_sub(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_sub)(&this->value, arg,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_and)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_and()
*/
T fetch_and(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_and)(&this->value, arg,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_or)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_or()
*/
T fetch_or(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_or)(&this->value, arg,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_xor)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_xor()
*/
T fetch_xor(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_xor)(&this->value, arg,
static_cast<int>(order));
}
/**
* 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, memory_order order =
memory_order_seq_cst)
{
return builtin_atomic(fetch_nand)(&this->value, arg,
static_cast<int>(order));
}
/**
* @copydoc fetch_nand()
*/
T fetch_nand(T arg, memory_order order =
memory_order_seq_cst) volatile
{
return builtin_atomic(fetch_nand)(&this->value, arg,
static_cast<int>(order));
}
/**
* Notify all threads waiting on this atomic variable
*/
void notify_all() { stub; }
/**
* @copydoc notify_all()
*/
void notify_all() volatile { stub; }
/**
* Notify one thread waiting on this atomic variable
*/
void notify_one() { stub; }
/**
* @copydoc notify_one()
*/
void notify_one() volatile { stub; }
/**
* 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, memory_order order =
memory_order::seq_cst) const
{
while (this->load(order) == old)
;
}
/**
* Check whether this atomic type is lock-free
* @return True if this atomic type is lock-free
*/
bool is_lock_free() const
{
stub;
return true;
}
/**
* @copydoc is_lock_free()
*/
bool is_lock_free() const volatile
{
stub;
return true;
}
/**
* Equals true if this atomic type is always lock-free
*/
static constexpr bool is_always_lock_free = true;
/************************************************/
T operator++() { return this->fetch_add(1) + 1; }
// T operator++() volatile { return this->fetch_add(1) + 1; }
T operator++(int) { return this->fetch_add(1); }
// T operator++(int) volatile { return this->fetch_add(1); }
/************************************************/
T operator--() { return this->fetch_sub(1) - 1; }
// T operator--() volatile { return this->fetch_sub(1) - 1; }
T operator--(int) { return this->fetch_sub(1); }
// T operator--(int) volatile { return this->fetch_sub(1); }
/************************************************/
T operator+=(T arg) { return this->fetch_add(arg) + arg; }
// T operator+=(T arg) volatile { return this->fetch_add(arg) + arg; }
// T operator+=(ptrdiff_t arg) { return this->fetch_add(arg) + arg; }
// T operator+=(ptrdiff_t arg) volatile { return this->fetch_add(arg) + arg; }
/************************************************/
T operator-=(T arg) { return this->fetch_sub(arg) - arg; }
// T operator-=(T arg) volatile { return this->fetch_sub(arg) - arg; }
// T operator-=(ptrdiff_t arg) { return this->fetch_sub(arg) - arg; }
// T operator-=(ptrdiff_t arg) volatile { return this->fetch_sub(arg) - arg; }
/************************************************/
T operator&=(T arg) { return this->fetch_and(arg) & arg; }
// T operator&=(T arg) volatile { return this->fetch_and(arg) & arg; }
T operator|=(T arg) { return this->fetch_or(arg) | arg; }
// T operator|=(T arg) volatile { return this->fetch_or(arg) | arg; }
T operator^=(T arg) { return this->fetch_xor(arg) ^ arg; }
// T operator^=(T arg) volatile { return this->fetch_xor(arg) ^ arg; }
/************************************************/
T operator=(T desired)
{
this->store(desired);
return desired;
}
// T operator=(T desired) volatile
// {
// this->store(desired);
// return desired;
// }
atomic &operator=(const atomic &other) = delete;
atomic &operator=(const atomic &other) volatile = delete;
/************************************************/
/* non standard functions */
T operator->() { return this->load(); }
T operator~() { return this->fetch_nand(-1); }
operator bool() { return this->load() != 0; }
operator T() const { return this->load(); }
bool operator==(const atomic &other) const { return this->load() == other.load(); }
bool operator==(T other) const { return this->load() == other; }
};
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

View File

@ -19,6 +19,6 @@
namespace std
{
typedef unsigned long size_t;
typedef long ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
}

View File

@ -18,135 +18,392 @@
#ifndef _ERRNO_H
#define _ERRNO_H
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
/** @brief Operation not permitted */
#define EPERM 1
/** @brief No such file or directory */
#define ENOENT 2
/** @brief No such process */
#define ESRCH 3
/** @brief Interrupted system call */
#define EINTR 4
/** @brief I/O error */
#define EIO 5
/** @brief No such device or address */
#define ENXIO 6
/** @brief Argument list too long */
#define E2BIG 7
/** @brief Exec format error */
#define ENOEXEC 8
/** @brief Bad file number */
#define EBADF 9
/** @brief No child processes */
#define ECHILD 10
/** @brief Try again */
#define EAGAIN 11
/** @brief Out of memory */
#define ENOMEM 12
/** @brief Permission denied */
#define EACCES 13
/** @brief Bad address */
#define EFAULT 14
/** @brief Block device required */
#define ENOTBLK 15
/** @brief Device or resource busy */
#define EBUSY 16
/** @brief File exists */
#define EEXIST 17
/** @brief Cross-device link */
#define EXDEV 18
/** @brief No such device */
#define ENODEV 19
/** @brief Not a directory */
#define ENOTDIR 20
/** @brief Is a directory */
#define EISDIR 21
/** @brief Invalid argument */
#define EINVAL 22
/** @brief File table overflow */
#define ENFILE 23
/** @brief Too many open files */
#define EMFILE 24
/** @brief Not a typewriter */
#define ENOTTY 25
/** @brief Text file busy */
#define ETXTBSY 26
/** @brief File too large */
#define EFBIG 27
/** @brief No space left on device */
#define ENOSPC 28
/** @brief Illegal seek */
#define ESPIPE 29
/** @brief Read-only file system */
#define EROFS 30
/** @brief Too many links */
#define EMLINK 31
/** @brief Broken pipe */
#define EPIPE 32
/** @brief Math argument out of domain of func */
#define EDOM 33
/** @brief Math result not representable */
#define ERANGE 34
/** @brief Resource deadlock would occur */
#define EDEADLK 35
/** @brief File name too long */
#define ENAMETOOLONG 36
/** @brief No record locks available */
#define ENOLCK 37
/** @brief Function not implemented */
#define ENOSYS 38
/** @brief Directory not empty */
#define ENOTEMPTY 39
/** @brief Too many symbolic links encountered */
#define ELOOP 40
/** @brief No message of desired type */
#define ENOMSG 42
/** @brief Identifier removed */
#define EIDRM 43
/** @brief Channel number out of range */
#define ECHRNG 44
/** @brief Level 2 not synchronized */
#define EL2NSYNC 45
/** @brief Level 3 halted */
#define EL3HLT 46
/** @brief Level 3 reset */
#define EL3RST 47
/** @brief Link number out of range */
#define ELNRNG 48
/** @brief Protocol driver not attached */
#define EUNATCH 49
/** @brief No CSI structure available */
#define ENOCSI 50
/** @brief Level 2 halted */
#define EL2HLT 51
/** @brief Invalid exchange */
#define EBADE 52
/** @brief Invalid request descriptor */
#define EBADR 53
/** @brief Exchange full */
#define EXFULL 54
/** @brief No anode */
#define ENOANO 55
/** @brief Invalid request code */
#define EBADRQC 56
/** @brief Invalid slot */
#define EBADSLT 57
/** @brief Bad font file format */
#define EBFONT 59
/** @brief Device not a stream */
#define ENOSTR 60
/** @brief No data available */
#define ENODATA 61
/** @brief Timer expired */
#define ETIME 62
/** @brief Out of streams resources */
#define ENOSR 63
/** @brief Machine is not on the network */
#define ENONET 64
/** @brief Package not installed */
#define ENOPKG 65
/** @brief Object is remote */
#define EREMOTE 66
/** @brief Link has been severed */
#define ENOLINK 67
/** @brief Advertise error */
#define EADV 68
/** @brief Srmount error */
#define ESRMNT 69
/** @brief Communication error on send */
#define ECOMM 70
/** @brief Protocol error */
#define EPROTO 71
/** @brief Multihop attempted */
#define EMULTIHOP 72
/** @brief RFS specific error */
#define EDOTDOT 73
/** @brief Not a data message */
#define EBADMSG 74
/** @brief Value too large for defined data type */
#define EOVERFLOW 75
/** @brief Name not unique on network */
#define ENOTUNIQ 76
/** @brief File descriptor in bad state */
#define EBADFD 77
/** @brief Remote address changed */
#define EREMCHG 78
/** @brief Can not access a needed shared library */
#define ELIBACC 79
/** @brief Accessing a corrupted shared library */
#define ELIBBAD 80
/** @brief .lib section in a.out corrupted */
#define ELIBSCN 81
/** @brief Attempting to link in too many shared libraries */
#define ELIBMAX 82
/** @brief Cannot exec a shared library directly */
#define ELIBEXEC 83
/** @brief Illegal byte sequence */
#define EILSEQ 84
/** @brief Interrupted system call should be restarted */
#define ERESTART 85
/** @brief Streams pipe error */
#define ESTRPIPE 86
/** @brief Too many users */
#define EUSERS 87
/** @brief Socket operation on non-socket */
#define ENOTSOCK 88
/** @brief Destination address required */
#define EDESTADDRREQ 89
/** @brief Message too long */
#define EMSGSIZE 90
/** @brief Protocol wrong type for socket */
#define EPROTOTYPE 91
/** @brief Protocol not available */
#define ENOPROTOOPT 92
/** @brief Protocol not supported */
#define EPROTONOSUPPORT 93
/** @brief Socket type not supported */
#define ESOCKTNOSUPPORT 94
/** @brief Operation not supported on transport endpoint */
#define EOPNOTSUPP 95
/** @brief Protocol family not supported */
#define EPFNOSUPPORT 96
/** @brief Address family not supported by protocol */
#define EAFNOSUPPORT 97
/** @brief Address already in use */
#define EADDRINUSE 98
/** @brief Cannot assign requested address */
#define EADDRNOTAVAIL 99
/** @brief Network is down */
#define ENETDOWN 100
/** @brief Network is unreachable */
#define ENETUNREACH 101
/** @brief Network dropped connection because of reset */
#define ENETRESET 102
/** @brief Software caused connection abort */
#define ECONNABORTED 103
/** @brief Connection reset by peer */
#define ECONNRESET 104
/** @brief No buffer space available */
#define ENOBUFS 105
/** @brief Transport endpoint is already connected */
#define EISCONN 106
/** @brief Transport endpoint is not connected */
#define ENOTCONN 107
/** @brief Cannot send after transport endpoint shutdown */
#define ESHUTDOWN 108
/** @brief Too many references: cannot splice */
#define ETOOMANYREFS 109
/** @brief Connection timed out */
#define ETIMEDOUT 110
/** @brief Connection refused */
#define ECONNREFUSED 111
/** @brief Host is down */
#define EHOSTDOWN 112
/** @brief No route to host */
#define EHOSTUNREACH 113
/** @brief Operation already in progress */
#define EALREADY 114
/** @brief Operation now in progress */
#define EINPROGRESS 115
/** @brief Stale NFS file handle */
#define ESTALE 116
/** @brief Structure needs cleaning */
#define EUCLEAN 117
/** @brief Not a XENIX named type file */
#define ENOTNAM 118
/** @brief No XENIX semaphores available */
#define ENAVAIL 119
/** @brief Is a named type file */
#define EISNAM 120
/** @brief Remote I/O error */
#define EREMOTEIO 121
/** @brief Quota exceeded */
#define EDQUOT 122
/** @brief No medium found */
#define ENOMEDIUM 123
/** @brief Wrong medium type */
#define EMEDIUMTYPE 124
/** @brief Operation Canceled */
#define ECANCELED 125
/** @brief Required key not available */
#define ENOKEY 126
/** @brief Key has expired */
#define EKEYEXPIRED 127
/** @brief Key has been revoked */
#define EKEYREVOKED 128
/** @brief Key was rejected by service */
#define EKEYREJECTED 129
/** @brief Owner died */
#define EOWNERDEAD 130
/** @brief State not recoverable */
#define ENOTRECOVERABLE 131
extern int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())

30
include_std/float.h Normal file
View File

@ -0,0 +1,30 @@
/*
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/>.
*/
#pragma once
/* Stubs */
#define FLT_RADIX 2
#if a64
#define DBL_MANT_DIG 53
#define DBL_MAX_10_EXP 308
#define DBL_MAX 1.7976931348623157e+308
#elif a32
#define DBL_MANT_DIG 24
#define DBL_MAX_10_EXP 38
#define DBL_MAX 3.4028234663852886e+38
#endif

30
include_std/functional Normal file
View File

@ -0,0 +1,30 @@
/*
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/>.
*/
#pragma once
namespace std
{
template <typename T>
struct equal_to
{
bool operator()(const T &lhs, const T &rhs) const
{
return lhs == rhs;
}
};
}

66
include_std/mutex Normal file
View File

@ -0,0 +1,66 @@
/*
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/>.
*/
#pragma once
#include <types.h>
#include <task.hpp>
#include <atomic>
#include <vector>
namespace std
{
/**
* A mutex implementation.
*
* @note The TaskManager must be
* initialized before using this class.
*/
class mutex
{
private:
atomic_bool Locked = false;
vector<Tasking::TCB *> Waiting;
Tasking::TCB *Holder = nullptr;
public:
void lock();
bool try_lock();
void unlock();
mutex() = default;
mutex(const mutex &) = delete;
~mutex() = default;
};
template <class Mutex>
class lock_guard
{
private:
Mutex &m;
public:
explicit lock_guard(Mutex &mutex)
: m(mutex) { m.lock(); }
~lock_guard() { m.unlock(); }
lock_guard(const lock_guard &) = delete;
lock_guard &operator=(const lock_guard &) = delete;
};
}

View File

@ -22,7 +22,8 @@
#define __FENNIX_KERNEL_STD_H__
#include <types.h>
#include <std/atomic.hpp>
#include <atomic>
#include <vector>
#include <std/functional.hpp>
#include <std/list.hpp>
#include <std/smart_ptr.hpp>
@ -30,7 +31,6 @@
#include <std/string.hpp>
#include <std/unordered_map.hpp>
#include <std/utility.hpp>
#include <std/vector.hpp>
/**
* @brief // stub namespace for std::align_val_t and new operator

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__

View File

@ -20,6 +20,4 @@
#include <types.h>
#endif // !__FENNIX_KERNEL_STDARG_H__

45
include_std/type_trails Normal file
View File

@ -0,0 +1,45 @@
/*
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/>.
*/
#pragma once
namespace std
{
template <typename T>
struct is_trivially_copyable
{
static constexpr bool value = __is_trivially_copyable(T);
};
template <class T>
struct remove_reference
{
typedef T type;
};
template <class T>
struct remove_reference<T &>
{
typedef T type;
};
template <class T>
struct remove_reference<T &&>
{
typedef T type;
};
}

29
include_std/utility Normal file
View File

@ -0,0 +1,29 @@
/*
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/>.
*/
#pragma once
#include <type_trails>
namespace std
{
template <typename T>
typename std::remove_reference<T>::type &&move(T &&arg)
{
return static_cast<typename std::remove_reference<T>::type &&>(arg);
}
}

View File

@ -16,4 +16,288 @@
*/
#pragma once
#include <std/vector.hpp>
#include <types.h>
#include <type_trails>
#include <functional>
#include <algorithm>
#include <assert.h>
#include <cstring>
#include <utility>
// #define DEBUG_VECTOR_MESSAGES 1
#ifdef DEBUG_VECTOR_MESSAGES
#define vDebug(m, ...) debug(m, ##__VA_ARGS__)
#else
#define vDebug(m, ...)
#endif
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;
vector() { vDebug("%#lx: ( empty init )", this); }
vector(size_t Size)
: VectorSize(Size),
VectorCapacity(Size),
VectorBuffer(new T[Size])
{
vDebug("%#lx: ( init w/size: %lld )", this, Size);
}
vector(size_t Size, const T &Initial)
: VectorSize(Size),
VectorCapacity(Size),
VectorBuffer(new T[Size])
{
vDebug("%#lx: ( init w/size: %lld, initial vector: %llx )", this,
Size, Initial);
assert(Size > 0);
for (size_t i = 0; i < Size; i++)
VectorBuffer[i] = Initial;
}
vector(const vector<T> &v)
: VectorSize(v.VectorSize),
VectorCapacity(v.VectorCapacity),
VectorBuffer(nullptr)
{
vDebug("%#lx: ( vector copy: %#lx )", this, &v);
if (!v.VectorBuffer || VectorSize <= 0)
return;
VectorBuffer = new T[VectorSize];
std::copy(v.VectorBuffer, v.VectorBuffer + VectorSize, VectorBuffer);
}
~vector()
{
vDebug("%#lx: ( deinit )", this);
VectorSize = 0;
VectorCapacity = 0;
if (VectorBuffer != nullptr)
{
delete[] VectorBuffer;
VectorBuffer = nullptr;
}
}
void erase(iterator Position)
{
vDebug("%#lx: Erasing element at position %lld (v. size: %lld)", this,
Position - this->VectorBuffer, this->VectorSize);
if (Position == this->end())
{
warn("%#lx: Cannot erase element at end of vector", this);
return;
}
assert(Position >= this->VectorBuffer);
assert(Position < this->VectorBuffer + this->VectorSize);
size_t index = Position - this->VectorBuffer;
if (std::is_trivially_copyable<T>::value)
{
this->VectorBuffer[index] = T();
vDebug("%#lx: %#lx is trivially copyable", this,
&this->VectorBuffer[index]);
}
else
{
this->VectorBuffer[index].~T();
vDebug("%#lx: %#lx is not trivially copyable", this,
&this->VectorBuffer[index]);
}
for (size_t i = index; i < this->VectorSize - 1; ++i)
{
this->VectorBuffer[i] = std::move(this->VectorBuffer[i + 1]);
}
this->VectorSize--;
}
T &next(size_t Position)
{
if (Position + 1 < this->VectorSize)
return this->VectorBuffer[Position + 1];
warn("%#lx: next( %lld ) is null (requested by %#lx)", this,
Position, __builtin_return_address(0));
return {};
}
T &prev(size_t Position)
{
if (Position > 0)
return this->VectorBuffer[Position - 1];
warn("%#lx: prev( %lld ) is null (requested by %#lx)", this,
Position, __builtin_return_address(0));
return {};
}
T &next(const T &Value)
{
for (size_t i = 0; i < this->VectorSize; i++)
{
if (std::equal_to<T>()(this->VectorBuffer[i], Value))
{
if (i + 1 < this->VectorSize)
return this->VectorBuffer[i + 1];
else
break;
}
}
warn("%#lx: next( %#lx ) is null (requested by %#lx)", this,
Value, __builtin_return_address(0));
return {};
}
T &prev(const T &Value)
{
for (size_t i = 0; i < this->VectorSize; i++)
{
if (std::equal_to<T>()(this->VectorBuffer[i], Value))
{
if (i > 0)
return this->VectorBuffer[i - 1];
else
break;
}
}
warn("%#lx: prev( %#lx ) is null (requested by %#lx)", this,
Value, __builtin_return_address(0));
return {};
}
void push_back(const T &Value)
{
vDebug("%#lx: push_back( %#lx )", this, Value);
if (this->VectorSize >= this->VectorCapacity)
{
size_t newCapacity = this->VectorCapacity == 0
? 1
: this->VectorCapacity * 2;
reserve(newCapacity);
}
this->VectorBuffer[this->VectorSize++] = Value;
}
void reverse()
{
if (this->VectorSize <= 1)
return;
for (size_t i = 0, j = this->VectorSize - 1; i < j; i++, j--)
{
T &elem1 = this->VectorBuffer[i];
T &elem2 = this->VectorBuffer[j];
std::swap(elem1, elem2);
}
}
void reserve(size_t Capacity)
{
assert(!(Capacity <= VectorCapacity));
T *NewBuffer = new T[Capacity];
size_t Size = std::min(Capacity, this->VectorSize);
for (size_t i = 0; i < Size; i++)
NewBuffer[i] = std::move(this->VectorBuffer[i]);
vDebug("%#lx: reserve( %lld )->Buffer:~%#lx", this,
Capacity, this->VectorBuffer);
delete[] this->VectorBuffer;
this->VectorBuffer = NewBuffer;
this->VectorCapacity = Capacity;
}
void resize(size_t Size)
{
reserve(Size);
this->VectorSize = Size;
}
void clear()
{
this->VectorCapacity = 0;
this->VectorSize = 0;
if (VectorBuffer != nullptr)
{
delete[] this->VectorBuffer;
this->VectorBuffer = nullptr;
}
}
T &operator[](size_t Index)
{
if (Index >= this->VectorSize || !this->VectorBuffer)
{
warn("%#lx: operator[]( %lld ) is null (requested by %#lx)", this,
Index, __builtin_return_address(0));
static T null_elem{};
return null_elem;
}
return this->VectorBuffer[Index];
}
vector<T> &operator=(const vector<T> &v)
{
if (this == &v)
return *this;
delete[] this->VectorBuffer;
this->VectorSize = v.VectorSize;
this->VectorCapacity = v.VectorCapacity;
vDebug("%#lx: operator=( <vector> )->Size:%lld", this,
this->VectorSize);
this->VectorBuffer = new T[this->VectorSize];
for (size_t i = 0; i < this->VectorSize; i++)
this->VectorBuffer[i] = v.VectorBuffer[i];
return *this;
}
void pop_back() { this->VectorSize--; }
T &front() { return this->VectorBuffer[0]; }
T &back() { return this->VectorBuffer[this->VectorSize - 1]; }
T *data() { return this->VectorBuffer; }
bool empty() const { return this->VectorSize == 0; }
size_t capacity() const { return this->VectorCapacity; }
size_t size() const { return this->VectorSize; }
iterator begin() { return this->VectorBuffer; }
iterator end() { return this->VectorBuffer + size(); }
const_iterator begin() const { return this->VectorBuffer; }
const_iterator end() const { return this->VectorBuffer + size(); }
};
}