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->m_elements = a.m_elements;
86  this->m_size = a.m_size;
87  }
88  return *this;
89  }
90 
92  void copyDataFrom(const ExternalArray<T>& a) {
93  const FwSizeType size = FW_MIN(this->m_size, a.m_size);
94  for (FwSizeType i = 0; i < size; i++) {
95  (*this)[i] = a[i];
96  }
97  }
98 
101  T* getElements() { return this->m_elements; }
102 
105  const T* getElements() const { return this->m_elements; }
106 
109  FwSizeType getSize() const { return this->m_size; }
110 
112  void setStorage(T* elements,
113  FwSizeType size
114  ) {
115  this->releaseStorage();
116  this->m_elements = elements;
117  this->m_size = size;
118  this->m_destroyElementsOnRelease = false;
119  }
120 
123  void setStorage(ByteArray data,
124  FwSizeType size
125  ) {
126  // Check that data.bytes is not null
127  FW_ASSERT(data.bytes != nullptr);
128  // Check that data.bytes is properly aligned
129  FW_ASSERT(reinterpret_cast<uintptr_t>(data.bytes) % alignof(T) == 0);
130  // Check that data.size is large enough to hold the array
131  FW_ASSERT(size * sizeof(T) <= data.size);
132  // Release the backing storage
133  this->releaseStorage();
134  // Initialize the array members
135  this->m_elements = reinterpret_cast<T*>(data.bytes);
136  // Construct the array members in place
137  // This step ensures that each array element holds a valid object
138  // into which we can assign data
139  for (FwSizeType i = 0; i < size; i++) {
140  // This code trips an alignment check in clang-tidy
141  // However the alignment has been checked by FW_ASSERT above
142  (void)new (&this->m_elements[i]) T(); // NOLINT
143  }
144  // Set the size
145  this->m_size = size;
146  // Destroy elements on release of storage
147  this->m_destroyElementsOnRelease = true;
148  }
149 
150  public:
151  // ----------------------------------------------------------------------
152  // Public static functions
153  // ----------------------------------------------------------------------
154 
157  static constexpr U8 getByteArrayAlignment() { return alignof(T); }
158 
162  static constexpr FwSizeType getByteArraySize(FwSizeType size
163  ) {
164  return size * sizeof(T);
165  }
166 
167  private:
168  // ----------------------------------------------------------------------
169  // Private member functions
170  // ----------------------------------------------------------------------
171 
173  void releaseStorage() {
174  if ((this->m_elements != nullptr) && this->m_destroyElementsOnRelease) {
175  for (FwSizeType i = 0; i < this->m_size; i++) {
176  this->m_elements[i].~T();
177  }
178  this->m_destroyElementsOnRelease = false;
179  }
180  }
181 
182  private:
183  // ----------------------------------------------------------------------
184  // Private member variables
185  // ----------------------------------------------------------------------
186 
188  T* m_elements = nullptr;
189 
191  FwSizeType m_size = 0;
192 
194  bool m_destroyElementsOnRelease = false;
195 };
196 
197 } // namespace Fw
198 
199 #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.
Definition: BasicTypes.h:92
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:53
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
#define FW_ASSERT(...)
Definition: Assert.hpp:14
const FwSizeType size
The size.
Definition: ByteArray.hpp:43