// Copyright 2024-2025, Amlal El Mahrouss (amlal@nekernel.org) // Licensed under the Apache License, Version 2.0 (see LICENSE file) // Official repository: https://github.com/nekernel-org/nekernel #ifndef NEKIT_MUTABLEARRAY_H #define NEKIT_MUTABLEARRAY_H #include #include #include #define RTL_TRY_FIND_NODE(NAME, NODE) \ auto* NAME = NODE; \ while (NAME) { \ if (NAME->fIndex == Index) return NAME->fVal; \ NAME = NAME->fNext; \ } #define RTL_TRY_FIND_NODE2(NAME, NODE) \ auto* NAME = NODE; \ while (NAME) { \ if (NAME->fIndex == Index) return Ref{NAME->fVal}; \ NAME = NAME->fNext; \ } #define RTL_TRY_REMOVE_NODE(NODE) \ if (NODE && NODE->fIndex == Index) { \ NODE->fUsed = false; \ NODE->fIndex = 0; \ \ return true; \ } // FIXME: this is a shitty algorithm, because it is memory heavy. // Remove and occurences of that, and remove that class. namespace Kernel { template class MutableArray; template class NullableMutableArray; template class MutableLinkedList { public: T fVal; SizeT fIndex{0}; Boolean fUsed{false}; MutableLinkedList* fPrev{nullptr}; MutableLinkedList* fNext{nullptr}; }; template class NullableMutableArray { public: // explicit this. explicit NullableMutableArray() : fFirstNode(new MutableLinkedList()) {} /* * We free all the nodes allocated by the array * and store the next one inside "NextIt" */ virtual ~NullableMutableArray() { auto* It = fFirstNode; MutableLinkedList* NextIt = nullptr; while (It) { NextIt = It->fNext; delete It; It = NextIt; } } NullableMutableArray& operator=(const NullableMutableArray&) = default; NullableMutableArray(const NullableMutableArray&) = default; operator bool() { return Count() > 1; } public: T operator[](SizeT Index) const { RTL_TRY_FIND_NODE(first, fFirstNode); RTL_TRY_FIND_NODE(last, fLastNode); return _PlaceHolderValue; } SizeT Count() const { return fNodeCount; } public: Boolean Remove(SizeT Index) { RTL_TRY_REMOVE_NODE(fFirstNode); RTL_TRY_REMOVE_NODE(fLastNode); return false; } Boolean Add(const T val) { auto* iterationNode = fFirstNode; MUST_PASS(iterationNode); while (iterationNode) { if (!iterationNode->fUsed) { iterationNode->fVal = val; iterationNode->fIndex = 0; iterationNode->fUsed = true; ++fNodeCount; return true; } iterationNode = iterationNode->fNext; } return false; } private: /* Avoid useless lookups */ MutableLinkedList* fLastNode{nullptr}; MutableLinkedList* fFirstNode{nullptr}; /* Number of nodes inside of this dynamic array. */ Kernel::SizeT fNodeCount{0}; private: // don't remove that friend MutableArray; }; template class MutableArray : public NullableMutableArray { public: // explicit this. explicit MutableArray() = default; virtual ~MutableArray() = default; NE_COPY_DEFAULT(MutableArray) public: Boolean Add(const T val) { auto* iterationNode = fFirstNode; if (!iterationNode) { fFirstNode = new MutableLinkedList(); iterationNode = fFirstNode; } MUST_PASS(iterationNode); while (iterationNode) { if (!iterationNode->fUsed) { iterationNode->fVal = val; iterationNode->fIndex = 0; iterationNode->fUsed = true; ++fNodeCount; return true; } iterationNode = iterationNode->fNext; } return false; } public: Ref operator[](SizeT Index) const { RTL_TRY_FIND_NODE2(first, fFirstNode); RTL_TRY_FIND_NODE2(last, fLastNode); return {}; } SizeT Count() const { return fNodeCount; } bool Contains(T& value) { MutableLinkedList* first = fFirstNode; while (first) { if (first->fVal == value && first->fUsed) return true; first = first->fNext; } return false; } private: /* Avoid useless lookups */ MutableLinkedList* fLastNode{nullptr}; MutableLinkedList* fFirstNode{nullptr}; /* Number of nodes inside of this dynamic array. */ Kernel::SizeT fNodeCount{0}; }; } // namespace Kernel #endif