Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gk646/cxstructs
Browse files Browse the repository at this point in the history
  • Loading branch information
gk646 committed Apr 10, 2024
2 parents c86e205 + 53c43f6 commit 010f1ba
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 84 deletions.
40 changes: 21 additions & 19 deletions include/cxstructs/StackHashMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ class StackHashMap {
size_type size_ = 0;
int rand_ = rand();

[[nodiscard]] inline constexpr size_t impl_hash_func(const K& key) const noexcept {
[[nodiscard]] constexpr size_t impl_hash_func(const K& key) const noexcept {
if constexpr ((N & (N - 1)) == 0) { //Power of 2 optimization
return hash_func_(key) & (N - 1);
}
return (hash_func_(key) * rand_) % N;
}

inline void add_node(size_t hash, const_key_ref key, auto val) noexcept {
void add_node(size_t hash, const_key_ref key, auto val) noexcept {
if (!register_[hash]) {
if constexpr (std::is_trivially_copyable_v<K> && std::is_trivially_copyable_v<V>) {
data_[hash].key = key;
Expand All @@ -96,7 +96,7 @@ class StackHashMap {
}
}

inline void insert_non_empty(const K& key, auto val) noexcept {
void insert_non_empty(const K& key, auto val) noexcept {
Node org_data[N];
bool org_register[N];
std::memcpy(org_data, data_, N * sizeof(Node));
Expand Down Expand Up @@ -180,7 +180,7 @@ class StackHashMap {
}

//Call can result in endless loop at high load factor
inline void insert(const K& key, V&& val) noexcept {
void insert(const K& key, V&& val) noexcept {
CX_ASSERT(size_ < N, "Trying to add to full StackHashMap");
CX_STACK_ABORT_IMPL();

Expand All @@ -194,7 +194,7 @@ class StackHashMap {
}

//Call can result in endless loop at high load factor
inline void insert(const K& key, const V& val) noexcept {
void insert(const K& key, const V& val) noexcept {
CX_ASSERT(size_ < N, "Trying to add to full StackHashMap");
CX_STACK_ABORT_IMPL();

Expand All @@ -207,7 +207,7 @@ class StackHashMap {
add_node(hash, key, val);
}

inline void insert(const std::pair<const K, V>& keyValue) noexcept {
void insert(const std::pair<const K, V>& keyValue) noexcept {
CX_ASSERT(size_ < N, "Trying to add to full StackHashMap");
CX_STACK_ABORT_IMPL();

Expand All @@ -223,23 +223,25 @@ class StackHashMap {
add_node(hash, key, val);
}

inline V& operator[](const K& key) noexcept {
auto operator[](const K& key) noexcept -> V& {
const size_t hash = impl_hash_func(key);

if (!register_[hash]) {
add_node(hash, key, V());
return data_[hash].val;
} else if (data_[hash].key == key) {
}

if (data_[hash].key == key) {
return data_[hash].val;
}

insert(key, V());
return data_[impl_hash_func(key)].val;
}

[[nodiscard]] size_type size() const noexcept { return size_; }
[[nodiscard]] auto size() const noexcept -> size_type { return size_; }

inline bool erase(const K& key) noexcept {
auto erase(const K& key) noexcept -> bool {
const size_t hash = impl_hash_func(key);
if (register_[hash]) {
if constexpr (!std::is_trivial_v<K>) {
Expand All @@ -255,24 +257,24 @@ class StackHashMap {
return false;
}

[[nodiscard]] inline bool contains(const K& key) const noexcept {
[[nodiscard]] auto contains(const K& key) const noexcept -> bool {
const size_t hash = impl_hash_func(key);
return register_[hash] && data_[hash].key == key;
}

//The multiplier for the hash | Set to 1 if you supply a perfect hash function | Resets on collision
inline void set_rand(int rand) noexcept { rand_ = rand; }
void set_rand(int rand) noexcept { rand_ = rand; }

inline void clear() noexcept {
void clear() noexcept {
std::memset(register_, false, N);
size_ = 0;
}

[[nodiscard]] inline bool empty() const noexcept { return !register_.any(); }
[[nodiscard]] auto empty() const noexcept -> bool { return !register_.any(); }

[[nodiscard]] inline float load_factor() const noexcept { return (float)size_ / (float)N; }
[[nodiscard]] auto load_factor() const noexcept -> float { return (float)size_ / (float)N; }

[[nodiscard]] inline size_t get_hash(const K& key) const noexcept { return impl_hash_func(key); }
[[nodiscard]] auto get_hash(const K& key) const noexcept -> size_t { return impl_hash_func(key); }

// Iterator support
class KeyIterator {
Expand Down Expand Up @@ -319,6 +321,7 @@ class StackHashMap {
size_t size_;
size_t index_;
};

class ValueIterator {
public:
using iterator_category = std::forward_iterator_tag;
Expand Down Expand Up @@ -371,8 +374,7 @@ class StackHashMap {
using pointer = Node*;
using reference = Node&;

explicit PairIterator(Node* ptr, bool* reg, size_t size)
: ptr_(ptr), reg_(reg), size_(size), index_(0) {
explicit PairIterator(Node* ptr, bool* reg, size_t size) : ptr_(ptr), reg_(reg), size_(size) {
if (!reg_[index_]) {
++(*this);
}
Expand Down Expand Up @@ -407,7 +409,7 @@ class StackHashMap {
Node* ptr_;
bool* reg_;
size_t size_;
size_t index_;
size_t index_{0};
};

KeyIterator key_begin() { return KeyIterator(data_, register_, N); }
Expand Down
53 changes: 20 additions & 33 deletions include/cxstructs/StackVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,61 +137,48 @@ class StackVector {
}
const T* data() { return data_; }

// Iterator support
class Iterator {
template <typename PtrType>
class IteratorTemplate {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using value_type = std::remove_const_t<PtrType>; // Remove const for value_type
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
using pointer = PtrType*;
using reference = PtrType&;

explicit Iterator(pointer ptr) : ptr_(ptr) {}
explicit IteratorTemplate(pointer ptr) : ptr_(ptr) {}

reference operator*() const { return *ptr_; }
pointer operator->() { return ptr_; }
pointer operator->() const { return ptr_; }

// Prefix increment
Iterator& operator++() {
IteratorTemplate& operator++() {
ptr_++;
return *this;
}

// Postfix increment
Iterator operator++(int) {
Iterator tmp = *this;
IteratorTemplate operator++(int) {
IteratorTemplate tmp = *this;
++(*this);
return tmp;
}

friend bool operator==(const Iterator& a, const Iterator& b) { return a.ptr_ == b.ptr_; };
friend bool operator!=(const Iterator& a, const Iterator& b) { return a.ptr_ != b.ptr_; };
friend bool operator==(const IteratorTemplate& a, const IteratorTemplate& b) {
return a.ptr_ == b.ptr_;
}
friend bool operator!=(const IteratorTemplate& a, const IteratorTemplate& b) {
return a.ptr_ != b.ptr_;
}

private:
pointer ptr_;
};

Iterator erase(Iterator pos) {
// Direct pointer arithmetic on the underlying pointers to find the index
auto posPtr = &(*pos); // Convert Iterator to pointer
size_type index = posPtr - &(*begin()); // Use underlying pointers for subtraction

// Move elements after pos one position to the left
std::move(posPtr + 1, &(*end()), posPtr);

// Destroy the last element (now a duplicate) if it's not trivially
// destructible
if constexpr (!std::is_trivially_destructible_v<T>) {
data_[size_ - 1].~T();
}

// Adjust the size
--size_;

// Return iterator to the next element after the erased one
// Convert back to Iterator at the correct position
return Iterator(data_ + index);
}
using Iterator = IteratorTemplate<T>;
using ConstIterator = IteratorTemplate<const T>;
ConstIterator begin() const { return ConstIterator(&data_[0]); }
ConstIterator end() const { return ConstIterator(&data_[size_]); }
Iterator begin() { return Iterator(&data_[0]); }
Iterator end() { return Iterator(&data_[size_]); }

Expand Down
27 changes: 14 additions & 13 deletions include/cxutil/cxbits.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "../cxconfig.h"
#include <cstdlib>
#include <print>
#include <type_traits> //For type traits

//Assumes little endian for all operations
Expand Down Expand Up @@ -64,7 +65,7 @@ enum Endianness { LITTLE_ENDIAN, BIG_ENDIAN };
template <typename T, typename U>
struct is_same_size_and_sign {
static constexpr bool value =
(sizeof(T) == sizeof(U)) && (std::is_signed<T>::value == std::is_signed<U>::value);
(sizeof(T) == sizeof(U)) && (std::is_signed_v<T> == std::is_signed_v<U>);
};

template <typename T, typename U, bool SameSizeAndSign>
Expand All @@ -82,8 +83,8 @@ struct ConcatType<T, U, true> {
template <typename T, typename U, size_t PadToBytes>
struct ConcatPaddingType {
// Calculate the total size needed, considering padding.
inline static constexpr size_t paddedSize = PadToBytes > sizeof(T) ? PadToBytes : sizeof(T);
inline static constexpr size_t totalSize =
static constexpr size_t paddedSize = PadToBytes > sizeof(T) ? PadToBytes : sizeof(T);
static constexpr size_t totalSize =
paddedSize + (PadToBytes > sizeof(U) ? PadToBytes : sizeof(U));

// Select the smallest standard integer type that fits the total size.
Expand All @@ -106,7 +107,7 @@ struct ConcatPaddingType {

template <typename T, typename U, size_t PadToBytes>
inline auto bits_concat_ex(T first, U second) {
static_assert(std::is_integral<T>::value && std::is_integral<U>::value,
static_assert(std::is_integral_v<T> && std::is_integral_v<U>,
"Only integer types are supported.");

using ResultType = typename ConcatPaddingType<T, U, PadToBytes>::type;
Expand All @@ -126,8 +127,8 @@ inline auto bits_concat_ex(T first, U second) {
* @return
*/
template <typename T>
inline constexpr auto bits_concat(T first, T second) {
static_assert(std::is_integral<T>::value, "Only integer types are supported.");
constexpr auto bits_concat(T first, T second) {
static_assert(std::is_integral_v<T>, "Only integer types are supported.");
constexpr auto same = is_same_size_and_sign<T, T>::value;
constexpr bool fits = !std::is_same_v<typename ConcatType<T, T, same>::type, void>;
static_assert(fits, "Resulting type is too large to represent.");
Expand All @@ -144,14 +145,14 @@ inline constexpr auto bits_concat(T first, T second) {
*/
template <typename T>
inline void bits_print(T num) {
static_assert(std::is_integral<T>::value, "Only integral types are supported.");
static_assert(std::is_integral_v<T>, "Only integral types are supported.");

constexpr size_t numBits = sizeof(T) * 8; // Total bits in type T
char bitRepresentation[numBits + 1]; // +1 for null terminator
bitRepresentation[numBits] = '\0'; // Null-terminate the string

for (size_t i = 0; i < numBits; ++i) {
bitRepresentation[(numBits-1) -i] = (num & (T(1) << i)) ? '1' : '0';
bitRepresentation[(numBits - 1) - i] = (num & (T(1) << i)) ? '1' : '0';
}

fputs(bitRepresentation, stdout);
Expand All @@ -167,18 +168,18 @@ inline void bits_print(T num) {
*/
template <typename T>
inline void bits_print_bytes(const T& num, Endianness endian = LITTLE_ENDIAN) {
static_assert(std::is_integral<T>::value, "Only integral types are supported.");
static_assert(std::is_integral_v<T>, "Only integral types are supported.");

const size_t numBytes = sizeof(T);
const auto* bytePointer = reinterpret_cast<const unsigned char*>(&num);

if (endian == LITTLE_ENDIAN) {
for (size_t i = 0; i < numBytes; ++i) {
printf("%02X ", bytePointer[i]);
std::print("{:02X} ", bytePointer[i]);
}
} else {
for (size_t i = numBytes; i > 0; --i) {
printf("%02X ", bytePointer[i - 1]);
std::print("{:02X} ", bytePointer[i - 1]);
}
}
fputc('\n', stdout);
Expand All @@ -194,8 +195,8 @@ inline void bits_print_bytes(const T& num, Endianness endian = LITTLE_ENDIAN) {
* @return a number of type r created from the specified bit range
*/
template <typename R, typename T>
inline constexpr R bits_get(T num, uint8_t off = 0) {
static_assert(std::is_integral<T>::value, "Only integer type are supported.");
constexpr auto bits_get(T num, uint8_t off = 0) -> R {
static_assert(std::is_integral_v<T>, "Only integer type are supported.");
return static_cast<R>(num >> off);
}

Expand Down
Loading

0 comments on commit 010f1ba

Please sign in to comment.