mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-11 07:19:20 +00:00
Update kernel
This commit is contained in:
@ -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__
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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__
|
||||
|
@ -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__
|
Reference in New Issue
Block a user