#ifndef FSFW_CONTAINER_ARRAYLIST_H_ #define FSFW_CONTAINER_ARRAYLIST_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" /** * @brief A List that stores its values in an array. * @details * The underlying storage is an array that can be allocated by the class * itself or supplied via ctor. * * @ingroup container */ template class ArrayList { template friend class SerialArrayListAdapter; public: static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); /** * This is the allocating constructor. * It allocates an array of the specified size. * @param maxSize */ ArrayList(count_t maxSize) : size(0), maxSize_(maxSize), allocated(true) { entries = new T[maxSize]; } /** * This is the non-allocating constructor * * It expects a pointer to an array of a certain size and initializes * itself to it. * * @param storage the array to use as backend * @param maxSize size of storage * @param size size of data already present in storage */ ArrayList(T *storage, count_t maxSize, count_t size = 0) : size(size), entries(storage), maxSize_(maxSize), allocated(false) { } /** * Copying is forbiden by declaring copy ctor and copy assignment deleted * It is too ambigous in this case. * (Allocate a new backend? Use the same? What to do in an modifying call?) */ ArrayList(const ArrayList& other) = delete; const ArrayList& operator=(const ArrayList& other) = delete; /** * Number of Elements stored in this List */ count_t size; /** * Destructor, if the allocating constructor was used, it deletes the array. */ virtual ~ArrayList() { if (allocated) { delete[] entries; } } /** * An Iterator to go trough an ArrayList * * It stores a pointer to an element and increments the * pointer when incremented itself. */ class Iterator { public: /** * Empty ctor, points to NULL */ Iterator(): value(0) {} /** * Initializes the Iterator to point to an element * * @param initialize */ Iterator(T *initialize) { value = initialize; } /** * The current element the iterator points to */ T *value; Iterator& operator++() { value++; return *this; } Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } Iterator& operator--() { value--; return *this; } Iterator operator--(int) { Iterator tmp(*this); operator--(); return tmp; } T& operator*() { return *value; } const T& operator*() const { return *value; } T *operator->() { return value; } const T *operator->() const { return value; } }; friend bool operator==(const ArrayList::Iterator& lhs, const ArrayList::Iterator& rhs) { return (lhs.value == rhs.value); } friend bool operator!=(const ArrayList::Iterator& lhs, const ArrayList::Iterator& rhs) { return not (lhs.value == rhs.value); } /** * Iterator pointing to the first stored elmement * * @return Iterator to the first element */ Iterator begin() const { return Iterator(&entries[0]); } /** * returns an Iterator pointing to the element after the last stored entry * * @return Iterator to the element after the last entry */ Iterator end() const { return Iterator(&entries[size]); } T & operator[](count_t i) const { return entries[i]; } /** * The first element * * @return pointer to the first stored element */ T *front() { return entries; } /** * The last element * * does not return a valid pointer if called on an empty list. * * @return pointer to the last stored element */ T *back() { return &entries[size - 1]; //Alternative solution //return const_cast(static_cast(*this).back()); } const T* back() const{ return &entries[size-1]; } /** * The maximum number of elements this List can contain * * @return maximum number of elements */ size_t maxSize() const { return this->maxSize_; } /** * Insert a new element into the list. * * The new element is inserted after the last stored element. * * @param entry * @return * -@c FULL if the List is full * -@c RETURN_OK else */ ReturnValue_t insert(T entry) { if (size >= maxSize_) { return FULL; } entries[size] = entry; ++size; return HasReturnvaluesIF::RETURN_OK; } /** * clear the List * * This does not actually clear all entries, it only sets the size to 0. */ void clear() { size = 0; } count_t remaining() { return (maxSize_ - size); } protected: /** * pointer to the array in which the entries are stored */ T *entries; /** * remembering the maximum size */ size_t maxSize_; /** * true if the array was allocated and needs to be deleted in the destructor. */ bool allocated; }; #endif /* FSFW_CONTAINER_ARRAYLIST_H_ */