diff options
Diffstat (limited to 'themes/src/list.h')
| -rw-r--r-- | themes/src/list.h | 245 | 
1 files changed, 245 insertions, 0 deletions
diff --git a/themes/src/list.h b/themes/src/list.h new file mode 100644 index 0000000..25b236a --- /dev/null +++ b/themes/src/list.h @@ -0,0 +1,245 @@ +#pragma once +#include <cstdlib> +#include <cstring> +#include "Logger.h" + +#define FOREACH(list)												\ +	for (i32 idx = 0; idx < list.numElements; idx++) \ +		if (auto value = &list[idx]) \ +		 +namespace matte { +	template <typename T> +	struct List { +		T* data = nullptr; +		size_t capacity = 0; +		size_t numElements = 0; +		bool growDynamically = true; + +		void allocate(size_t size); +		void add(T& element); +		void add(T&& element); +		void add(T* element); +		bool grow(size_t newSize); +		void set(T& value, size_t index); +		void set(T&& value, size_t index); +		void set(T* value, size_t index); +		void remove(size_t index); +		void clear(); +		void deallocate(); +		bool isEmpty() { +			return data == nullptr || numElements == 0; +		} +		T& getValue(int index) const; +		T& operator[](int idx) const; +		void binarySort(int (*f)(const T& first, const T& second)); +		void setFromArray(T* arry, int size) { +			allocate(size); +			memcpy(data, arry, size * sizeof(T)); +			numElements = size; +		} +		void remove(int index) { +			if (index >= numElements) { +				logger_error("Cannot remove element at index: %d", index); +				return; +			} + +			 +			if (index == numElements - 1) { +				numElements--; +				return; +			} +			 +			memmove(&data[index], &data[index + 1], sizeof(T) * (numElements - index)); +			numElements--; +		} +	}; + +	template <typename T> +	void List<T>::allocate(size_t size) { +		if (size == 0 || size == capacity) { +			numElements = 0; +			return; +		} + +		if (data != nullptr) { +			deallocate(); +		} + +		data = static_cast<T*>(malloc(sizeof(T) * size)); +		capacity = size; +		numElements = 0; +	} + +	template <typename T> +	bool List<T>::grow(size_t newSize) { +		if (!growDynamically) { +            logger_error("Cannot grow list: growDynamically is disabled"); +			return false; +		} + +		if (newSize == 0) { +            logger_error("Cannot grow list: newSize is zero!"); +			return false; +		} + +		T* newData = static_cast<T*>(malloc(sizeof(T) * newSize)); + +		if (data != nullptr) { +			memcpy(newData, data, numElements * sizeof(T)); +			delete data; +		} + +		data = newData; +		capacity = newSize; +		return true; +	} + +	template <typename T> +	void List<T>::set(T& value, size_t index) { +		if (index >= capacity && !grow(index * 2)) { +			return; +		} + +		memcpy(&data[index], value, sizeof(T)); +	} + +	template <typename T> +	void List<T>::set(T&& value, size_t index) { +		if (index >= capacity && !grow(index * 2)) { +			return; +		} + +		data[index] = value; +	} + +	template <typename T> +	void List<T>::set(T* value, size_t index) { +		if (index >= capacity && !grow(index * 2)) { +			return; +		} + +		memcpy(&data[index], value, sizeof(T)); +	} + +	template <typename T> +	void List<T>::add(T* element) { +		if (data == nullptr) { +			allocate(2); +		} + +		if (element == nullptr) { +			logger_error("Element not defined"); +			return; +		} + +		size_t newNumElements = numElements + 1; +		if (newNumElements > capacity) { +			if (!grow(2 * capacity)) { +				logger_error("Trying to add to list but unable to grow the array"); +				return; +			} +		} + +		memcpy(&data[numElements], element, sizeof(T)); +		numElements = newNumElements; +	} + +	template <typename T> +	void List<T>::add(T& element) { +		if (data == nullptr) { +			allocate(2); +		} + +		size_t newNumElements = numElements + 1; +		if (newNumElements > capacity) { +			if (!grow(2 * capacity)) { +				logger_error("Trying to add to list but unable to grow the array"); +				return; +			} +		} + +		memcpy(&data[numElements], &element, sizeof(T)); +		numElements = newNumElements; +	} + +	template <typename T> +	void List<T>::add(T&& element) { +		if (data == nullptr) { +			allocate(2); +		} + +		size_t newNumElements = numElements + 1; +		if (newNumElements > capacity) { +			if (!grow(2 * capacity)) { +				logger_error("Trying to add to list but unable to grow the array"); +				return; +			} +		} + +		memcpy(&data[numElements], &element, sizeof(T)); +		numElements = newNumElements; +	} + +	template <typename T> +	void List<T>::remove(size_t idx) { +		if (idx >= numElements) { +			logger_error("Index is outside of the list: %d >= %d", idx, numElements); +			return; +		} + +		for (; idx < numElements - 1; idx++) { +			data[idx] = data[idx + 1]; +		} + +		numElements--; +	} + +	template <typename T> +	void List<T>::deallocate() { +		if (data != nullptr) { +			free(data); +			data = nullptr; +		} + +		capacity = 0; +		numElements = 0; +	} + +	template <typename T> +	void List<T>::clear() { +		numElements = 0; +	} + +	template <typename T> +	T& List<T>::getValue(int idx) const { +		return data[idx]; +	} + +	template <typename T> +	T& List<T>::operator[](int idx) const { +		return data[idx]; +	} + +	template <typename T> +	void List<T>::binarySort(int (*f)(const T& first, const T& second)) { +		if (data == nullptr) { +			return; +		} + +		for (size_t idx = 0; idx < numElements - 1; idx++) { +			int minIdx = idx; +			T firstValue = data[idx]; + +			for (int innerIdx = idx + 1; innerIdx < numElements; innerIdx++) {\ +				T secondValue = data[innerIdx]; +				if (f(data[idx], data[innerIdx]) > 0) { +					minIdx= innerIdx; +				} +			} + +			T temp = data[minIdx]; +			memmove(&data[minIdx], &data[idx], sizeof(T)); +			memmove(&data[idx], &temp, sizeof(T)); +		} +	}		 +}  | 
