Fw/DataStructures/docs/ExternalArray.md
ExternalArray is a final class template
defined in Fw/DataStructures.
It represents an
array with external storage.
It stores a pointer to the backing memory M.
ExternalArray has the following template parameters.
| Kind | Name | Purpose |
|---|---|---|
typename | T | The type of an array element |
Array statically asserts that T is assignable to T&.
ExternalArray has the following private member variables.
| Name | Type | Purpose | Default Value |
|---|---|---|---|
m_elements | T* | Pointer to backing memory or nullptr | nullptr |
m_size | FwSizeType | Stores the size (number of elements) of the array | 0 |
m_destroyElementsOnRelease | bool | Whether to destroy the array elements when the backing storage is released | false |
<a name="Public-Constructors-and-Destructors"></a>
ExternalArray()
Initialize the member variables with their default values.
Example:
ExternalArray<U32> a;
ExternalArray(T* elements, FwSizeType size)
elements must point to a primitive array of at least size
elements of type T.
Call setStorage(elements, size).
Example:
constexpr FwSizeType size = 3;
U32 elements[size];
ExternalArray<U32> a(elements, size);
ExternalArray(ByteArray data, FwSizeType size)
data must be aligned according to
getByteArrayAlignment() and must
contain at least getByteArraySize(size) bytes.
Call setStorage(data, size).
Example:
constexpr FwSizeType size = 3;
constexpr U8 alignment = ExternalArray<U32>::byteArrayAlignment();
constexpr FwSizeType byteArraySize = ExternalArray<U32>::getByteArraySize(size);
alignas(alignment) U8 bytes[byteArraySize];
ExternalArray<U32> a(ByteArray(&bytes[0], sizeof bytes), size);
ExternalArray(const ExternalArray<T>& a)
Set m_elements = a.m_elements and m_size = a.m_size.
Example:
constexpr FwSizeType size = 3;
U32 elements[size];
// Call the constructor providing backing storage
ExternalArray<U32> a1(elements, size);
// Call the copy constructor
ExternalArray<U32> a2(a1);
~ExternalArray()
Call releaseStorage().
T& operator[](FwSizeType i)
const T& operator[](FwSizeType i) const
Assert that m_elements != nullptr.
Assert that i < m_size.
Return m_elements[i].
Example:
constexpr FwSizeType size = 3;
U32 elements[size] = {};
ExternalArray<U32> a(elements, size);
// Constant access
ASSERT_EQ(a[0], 0);
// Mutable access
a[0]++;
ASSERT_EQ(a[0], 1);
// Out-of-bounds access
ASSERT_DEATH(a[size], "Assert");
ExternalArray<T>& operator=(const ExternalArray<T>& a)
If &a == this then do nothing.
Otherwise set m_elements = a.m_elements and m_size = a.m_size.
Example:
constexpr FwSizeType size = 3;
U32 elements[size];
ExternalArray<U32> a1(elements, size);
ExternalArray<U32> a2;
a2 = a1;
void copyDataFrom(const ExternalArray<T>& a)
If &a != this
Let size be the minimum of m_size and a.m_size
For each i in [0, size), set m_elements[i] = a.m_elements[i]
Example:
constexpr FwSizeType size = 10;
U32 elements1[size];
ExternalArray<U32> a1(elements, size);
for (FwSizeType i = 0; i < size; i++) {
a1[i] = i;
}
U32 elements2[size];
ExternalArray<U32> a2(elements, size);
a2.copyDataFrom(a1);
for (FwSizeType i = 0; i < size; i++) {
ASSERT_EQ(a2[i], a1[i]);
}
T* getElements()
const T* getElements() const
Return m_elements.
Example:
constexpr FwSizeType size = 3;
U32 elements[size];
ExternalArray<U32> a(elements, size);
// Mutable pointer
auto& elements1 = a.getElements();
ASSERT_EQ(elements1[0], 0);
elements1[0] = 1;
// Constant pointer
const auto& elements2 = a.getElements();
ASSERT_EQ(elements2[0], 1);
FwSizeType getSize()
Return m_size.
Example:
constexpr FwSizeType size = 3;
U32 elements[size];
ExternalArray<U32> a(elements, size);
const auto size1 = a.getSize();
ASSERT_EQ(size1, size);
void setStorage(T* elements, FwSizeType size)
elements must point to a primitive array of at least size
elements of type T.
Call releaseStorage().
Set m_elements = elements and m_size = size and m_destroyElementsOnRelease = true.
Example:
ExternalArray<U32> a;
constexpr FwSizeType size = 3;
U32 elements[size];
a.setStorage(elements, size);
void setStorage(ByteArray data, FwSizeType size)
data must be correctly aligned according to getByteArrayAlignment
and must contain at least getByteArraySize(size) bytes.
Assert that data.bytes != nullptr.
Assert that data.bytes is correctly aligned for type T.
Assert that size * sizeof(T) <= data.size.
Call releaseStorage().
Initialize m_elements with data.bytes.
Construct the objects pointed to by m_elements in place.
Initialize m_size with size.
Set m_destroyElementsOnRelease = true.
Example:
constexpr FwSizeType size = 3;
constexpr U8 alignment = ExternalArray<U32>::byteArrayAlignment();
constexpr FwSizeType byteArraySize = ExternalArray<U32>::getByteArraySize(size);
alignas(alignment) U8 bytes[byteArraySize];
ExternalArray<U32> a;
a.setStorage(ByteArray(&bytes[0], sizeof bytes), size);
static constexpr U8 getByteArrayAlignment()
Return alignof(T).
Example:
const U8 byteArrayAlignment = ExternalArray<U32>::getByteArrayAlignment(size);
ASSERT_EQ(byteArrayAlignment, alignof(U32));
static constexpr FwSizeType getByteArraySize(FwSizeType size)
Return size * sizeof(T).
Example:
const FwSizeType size = 10;
const FwSizeType byteArraySize = ExternalArray<U32>::getByteArraySize(size);
ASSERT_EQ(byteArraySize, 10 * sizeof(U32));
void releaseStorage()
If m_destroyElementsOnRelease then
Call the destructor on each element of m_elements.
Set m_destroyElementsOnRelease = false.