F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
ExternalArray.hpp
Go to the documentation of this file.
1 // ======================================================================
2 // \file ExternalArray.hpp
3 // \author bocchino
4 // \brief A bounds-checked array with external memory
5 // ======================================================================
6 
7 #ifndef Fw_ExternalArray_HPP
8 #define Fw_ExternalArray_HPP
9 
10 #include <cstdint>
11 #include <new>
12 #include <type_traits>
13 
14 #include "Fw/FPrimeBasicTypes.hpp"
15 #include "Fw/Types/Assert.hpp"
16 #include "Fw/Types/ByteArray.hpp"
17 
18 namespace Fw {
19 
20 template <typename T>
21 class ExternalArray final {
22  // ----------------------------------------------------------------------
23  // Static assertions
24  // ----------------------------------------------------------------------
25 
26  static_assert(std::is_assignable<T&, T>::value, "T must be assignable to T&");
27 
28  public:
29  // ----------------------------------------------------------------------
30  // Public constructors and destructors
31  // ----------------------------------------------------------------------
32 
35 
38  ExternalArray(T* elements,
39  FwSizeType size
40  )
41  : m_elements(elements), m_size(size) {}
42 
47  FwSizeType size
48  ) {
49  this->setStorage(data, size);
50  }
51 
53  ExternalArray(const ExternalArray<T>& a) : m_elements(a.m_elements), m_size(a.m_size) {}
54 
56  ~ExternalArray() { this->releaseStorage(); }
57 
58  public:
59  // ----------------------------------------------------------------------
60  // Public member functions
61  // ----------------------------------------------------------------------
62 
65  T& operator[](const FwSizeType i
66  ) {
67  FW_ASSERT(this->m_elements != nullptr);
68  FW_ASSERT(i < this->m_size, static_cast<FwAssertArgType>(i));
69  return this->m_elements[i];
70  }
71 
74  const T& operator[](const FwSizeType i
75  ) const {
76  FW_ASSERT(this->m_elements != nullptr);
77  FW_ASSERT(i < this->m_size, static_cast<FwAssertArgType>(i));
78  return this->m_elements[i];
79  }
80 
84  if (&a != this) {
85  this->setStorage(a.m_elements, a.m_size);
86  }
87  return *this;
88  }
89 
91  void copyDataFrom(const ExternalArray<T>& a) {
92  const FwSizeType size = FW_MIN(this->m_size, a.m_size);
93  for (FwSizeType i = 0; i < size; i++) {
94  (*this)[i] = a[i];
95  }
96  }
97 
100  T* getElements() { return this->m_elements; }
101 
104  const T* getElements() const { return this->m_elements; }
105 
108  FwSizeType getSize() const { return this->m_size; }
109 
111  void setStorage(T* elements,
112  FwSizeType size
113  ) {
114  // Check that elements is not null if the array is nonempty
115  FW_ASSERT((elements != nullptr) || (size == 0), static_cast<FwAssertArgType>(size));
116  if (elements == this->m_elements) {
117  // The incoming pointer aliases the existing storage, so do not
118  // release the storage or change the ownership flag
119  this->m_size = size;
120  } else {
121  this->releaseStorage();
122  this->m_elements = elements;
123  this->m_size = size;
124  this->m_destroyElementsOnRelease = false;
125  }
126  }
127 
130  void setStorage(ByteArray data,
131  FwSizeType size
132  ) {
133  // Check that data.bytes is not null
134  FW_ASSERT(data.bytes != nullptr);
135  // Check that data.bytes is properly aligned
136  FW_ASSERT(reinterpret_cast<uintptr_t>(data.bytes) % alignof(T) == 0);
137  // Check that data.size is large enough to hold the array
138  // The division form is used because size * sizeof(T) can overflow FwSizeType
139  FW_ASSERT(size <= data.size / sizeof(T));
140  // Release the backing storage
141  this->releaseStorage();
142  // Initialize the array members
143  this->m_elements = reinterpret_cast<T*>(data.bytes);
144  // Construct the array members in place
145  // This step ensures that each array element holds a valid object
146  // into which we can assign data
147  for (FwSizeType i = 0; i < size; i++) {
148  // This code trips an alignment check in clang-tidy
149  // However the alignment has been checked by FW_ASSERT above
150  (void)new (&this->m_elements[i]) T(); // NOLINT
151  }
152  // Set the size
153  this->m_size = size;
154  // Destroy elements on release of storage
155  this->m_destroyElementsOnRelease = true;
156  }
157 
158  public:
159  // ----------------------------------------------------------------------
160  // Public static functions
161  // ----------------------------------------------------------------------
162 
165  static constexpr U8 getByteArrayAlignment() { return alignof(T); }
166 
170  static constexpr FwSizeType getByteArraySize(FwSizeType size
171  ) {
172  return size * sizeof(T);
173  }
174 
175  private:
176  // ----------------------------------------------------------------------
177  // Private member functions
178  // ----------------------------------------------------------------------
179 
181  void releaseStorage() {
182  if ((this->m_elements != nullptr) && this->m_destroyElementsOnRelease) {
183  for (FwSizeType i = 0; i < this->m_size; i++) {
184  this->m_elements[i].~T();
185  }
186  this->m_destroyElementsOnRelease = false;
187  }
188  }
189 
190  private:
191  // ----------------------------------------------------------------------
192  // Private member variables
193  // ----------------------------------------------------------------------
194 
196  T* m_elements = nullptr;
197 
199  FwSizeType m_size = 0;
200 
202  bool m_destroyElementsOnRelease = false;
203 };
204 
205 } // namespace Fw
206 
207 #endif
PlatformSizeType FwSizeType
~ExternalArray()
Destructor.
void setStorage(T *elements, FwSizeType size)
Set the backing storage (typed data)
ExternalArray()
Zero-argument constructor.
T & operator[](const FwSizeType i)
#define FW_MIN(a, b)
MIN macro (deprecated in C++, use std::min)
Definition: BasicTypes.h:99
ExternalArray(const ExternalArray< T > &a)
Copy constructor.
ExternalArray(ByteArray data, FwSizeType size)
const T * getElements() const
A variable-length byte array.
Definition: ByteArray.hpp:23
void setStorage(ByteArray data, FwSizeType size)
ExternalArray(T *elements, FwSizeType size)
FwSizeType getSize() const
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
void copyDataFrom(const ExternalArray< T > &a)
Copy the data from a.
U8 *const bytes
The bytes.
Definition: ByteArray.hpp:40
ExternalArray< T > & operator=(const ExternalArray< T > &a)
static constexpr U8 getByteArrayAlignment()
static constexpr FwSizeType getByteArraySize(FwSizeType size)
const T & operator[](const FwSizeType i) const
Implementation of malloc based allocator.
#define FW_ASSERT(...)
Definition: Assert.hpp:14
const FwSizeType size
The size.
Definition: ByteArray.hpp:43