GEGELATI
arrayWrapper.h
1
37#ifndef ARRAY_WRAPPER_H
38#define ARRAY_WRAPPER_H
39
40#include <functional>
41#include <map>
42#include <regex>
43#include <sstream>
44#include <stdexcept>
45#include <typeindex>
46#include <typeinfo>
47
48#include "data/constant.h"
49#include "data/dataHandler.h"
50#include "data/demangle.h"
51#include "data/hash.h"
52
53namespace Data {
54
68 template <class T> class ArrayWrapper : public DataHandler
69 {
70 static_assert(std::is_fundamental<T>::value ||
71 std::is_same<T, Data::Constant>(),
72 "Template class PrimitiveTypeArray<T> can only be used "
73 "for primitive types.");
74
75 private:
88 mutable std::map<std::type_index, size_t> cachedAddressSpace;
89
90 protected:
99 const size_t nbElements;
100
105 std::vector<T>* containerPtr;
106
118 void checkAddressAndType(const std::type_info& type,
119 const size_t& address) const;
120
124 virtual size_t updateHash() const override;
125
126 public:
137 ArrayWrapper(size_t size = 8, std::vector<T>* ptr = nullptr)
138 : nbElements{size}
139 {
140 this->setPointer(ptr);
141 };
142
144 virtual ~ArrayWrapper() = default;
145
147 ArrayWrapper(const ArrayWrapper<T>& other) = default;
148
155 virtual DataHandler* clone() const override;
156
158 virtual bool canHandle(const std::type_info& type) const override;
159
161 virtual size_t getAddressSpace(
162 const std::type_info& type) const override;
163
165 virtual size_t getLargestAddressSpace(void) const override;
166
175
177 void resetData() override;
178
190 void setPointer(std::vector<T>* ptr);
191
193 virtual UntypedSharedPtr getDataAt(const std::type_info& type,
194 const size_t address) const override;
195
197 virtual std::vector<size_t> getAddressesAccessed(
198 const std::type_info& type, const size_t address) const override;
199
200#ifdef CODE_GENERATION
202 virtual const std::type_info& getNativeType() const override;
203
205 virtual std::vector<size_t> getDimensionsSize() const override;
206#endif
207 };
208
209 template <class T>
210 bool ArrayWrapper<T>::canHandle(const std::type_info& type) const
211 {
212 if (typeid(T) == type) {
213 return true;
214 }
215
216 // Use the code in getAddressSpace to check if the type is supported.
217 return (this->getAddressSpace(type) > 0);
218 }
219
220 template <class T>
221 void ArrayWrapper<T>::checkAddressAndType(const std::type_info& type,
222 const size_t& address) const
223 {
224 size_t addressSpace = this->getAddressSpace(type);
225 // check type
226 if (addressSpace == 0) {
227 std::stringstream message;
228 message << "Data type " << DEMANGLE_TYPEID_NAME(type.name())
229 << " cannot be accessed in a "
230 << DEMANGLE_TYPEID_NAME(typeid(*this).name()) << ".";
231 throw std::invalid_argument(message.str());
232 }
233
234 // check location
235 if (address >= addressSpace) {
236 std::stringstream message;
237 message << "Data type " << DEMANGLE_TYPEID_NAME(type.name())
238 << " cannot be accessed at address " << address
239 << ", address space size is " << addressSpace << ".";
240 throw std::out_of_range(message.str());
241 }
242 }
243
244 // Declare class for clone method
245 template <class T> class PrimitiveTypeArray;
246
247 template <class T> inline DataHandler* ArrayWrapper<T>::clone() const
248 {
249 // Create a constantCopy of the ArrayWrapper content.
250 DataHandler* result = new PrimitiveTypeArray<T>(*this);
251
252 return result;
253 }
254
255 template <class T>
256 size_t ArrayWrapper<T>::getAddressSpace(const std::type_info& type) const
257 {
258 // Has the addresSpaceSize been cached
259 auto iter = this->cachedAddressSpace.find(type);
260 if (iter != this->cachedAddressSpace.end()) {
261 return iter->second;
262 }
263
264 if (type == typeid(T)) {
265 this->cachedAddressSpace.emplace(type, this->nbElements);
266 return this->nbElements;
267 }
268
269 // If the type is an array of the primitive type
270 // with a size inferior to the container.
271 std::string typeName = DEMANGLE_TYPEID_NAME(type.name());
272 std::string regex{DEMANGLE_TYPEID_NAME(typeid(T).name())};
273 regex.append("\\s*(const\\s*)?\\[([0-9]+)\\]");
274 std::regex arrayType(regex);
275 std::cmatch cm;
276 if (std::regex_match(typeName.c_str(), cm, arrayType)) {
277 int size = std::atoi(cm[2].str().c_str());
278 if (size <= this->nbElements) {
279 size_t result = this->nbElements - size + 1;
280 this->cachedAddressSpace.emplace(type, result);
281 return result;
282 }
283 }
284 // Default case
285 return 0;
286 }
287
288 template <class T>
290 const std::type_info& type, const size_t address) const
291 {
292 // Initialize the result
293 std::vector<size_t> result;
294
295 // If the accessed address is valid fill the result.
296 const size_t space = this->getAddressSpace(type);
297 if (space > address) {
298 // For the native type.
299 if (type == typeid(T)) {
300 result.push_back(address);
301 }
302 else {
303 // Else, the type is the array type.
304 for (int i = 0; i < (this->nbElements - space + 1); i++) {
305 result.push_back(address + i);
306 }
307 }
308 }
309 return result;
310 }
311
312 template <class T>
314 const std::type_info& type, const size_t address) const
315 {
316 if (this->containerPtr == nullptr) {
317 throw std::runtime_error("Null pointer access.");
318 }
319#ifndef NDEBUG
320 // Throw exception in case of invalid arguments.
321 checkAddressAndType(type, address);
322#endif
323
324 if (type == typeid(T)) {
325 UntypedSharedPtr result(
326 &(this->containerPtr->at(address)),
327 UntypedSharedPtr::emptyDestructor<const T>());
328 return result;
329 }
330
331 // Else, the only other supported type is cstyle array.
332
333 // Allocate the array
334 size_t arraySize = this->nbElements - this->getAddressSpace(type) + 1;
335 T* array = new T[arraySize];
336
337 // Copy its content
338 for (size_t idx = 0; idx < arraySize; idx++) {
339 array[idx] = this->containerPtr->at(address + idx);
340 }
341
342 // Create the UntypedSharedPtr
343 UntypedSharedPtr result{
344 std::make_shared<UntypedSharedPtr::Model<const T[]>>(array)};
345 return result;
346 }
347
348 template <class T> size_t ArrayWrapper<T>::getLargestAddressSpace() const
349 {
350 // Currently, largest addres space is for the template Type T.
351 return this->nbElements;
352 }
353
355 {
356 this->invalidCachedHash = true;
357 }
358
359 template <class T> void ArrayWrapper<T>::resetData()
360 {
361 // Does nothing;
362 }
363
364 template <class T>
365 inline void ArrayWrapper<T>::setPointer(std::vector<T>* ptr)
366 {
367 // Null ptr case
368 if (ptr == nullptr) {
369 this->containerPtr = ptr;
370 this->invalidCachedHash = true;
371 return;
372 }
373
374 // Else
375 // Check the size of the given vector
376 if (ptr->size() != nbElements) {
377 std::stringstream message;
378 message << "Size of pointed data (" << ptr->size()
379 << ") does not correspond to the size of the ArrayWrapper ("
380 << this->nbElements << ").";
381 throw std::domain_error(message.str());
382 }
383
384 // Else
385 this->containerPtr = ptr;
386 this->invalidCachedHash = true;
387 }
388
389 template <class T> inline size_t ArrayWrapper<T>::updateHash() const
390 {
391 // Null pointer case
392 if (this->containerPtr == nullptr) {
393 return this->cachedHash = 0;
394 }
395
396 // reset
397 this->cachedHash = Data::Hash<size_t>()(this->id);
398
399 // hasher
400 Data::Hash<T> hasher;
401
402 for (T dataElement : *(this->containerPtr)) {
403 // Rotate by 1 because otherwise, xor is comutative.
404 this->cachedHash =
405 (this->cachedHash >> 1) | (this->cachedHash << 63);
406 this->cachedHash ^= hasher((T)dataElement);
407 }
408
409 // Validate the cached hash value
410 this->invalidCachedHash = false;
411
412 return this->cachedHash;
413 }
414
415#ifdef CODE_GENERATION
416 template <class T>
417 const std::type_info& ArrayWrapper<T>::getNativeType() const
418 {
419 const std::type_info& a = typeid(T);
420 return a;
421 }
422
423 template <class T>
424 std::vector<size_t> ArrayWrapper<T>::getDimensionsSize() const
425 {
426 std::vector<size_t> sizes = {nbElements};
427 return sizes;
428 }
429#endif
430
431} // namespace Data
432#endif // !ARRAY_WRAPPER_H
433
434// Include PrimitiveTypeArray to ensure availability of the used clone method.
435#include "data/primitiveTypeArray.h"
Definition: arrayWrapper.h:69
ArrayWrapper(const ArrayWrapper< T > &other)=default
Default copy constructor.
std::vector< T > * containerPtr
Pointer to the array containing the data accessed through the ArrayWrapper.
Definition: arrayWrapper.h:105
virtual ~ArrayWrapper()=default
Default destructor.
void resetData() override
Inherited from DataHandler. Does nothing.
Definition: arrayWrapper.h:359
ArrayWrapper(size_t size=8, std::vector< T > *ptr=nullptr)
Constructor for the ArrayWrapper class.
Definition: arrayWrapper.h:137
void invalidateCachedHash()
Invalidate the hash of the container.
Definition: arrayWrapper.h:354
const size_t nbElements
Number of elements contained pointer vector.
Definition: arrayWrapper.h:99
virtual size_t getLargestAddressSpace(void) const override
Inherited from DataHandler.
Definition: arrayWrapper.h:348
virtual DataHandler * clone() const override
Return a PrimitiveTypeArray<T> where all data of the ArrayWrapper has been copied.
Definition: arrayWrapper.h:247
virtual std::vector< size_t > getDimensionsSize() const override
Inherited from DataHandler.
Definition: arrayWrapper.h:424
virtual size_t getAddressSpace(const std::type_info &type) const override
Inherited from DataHandler.
Definition: arrayWrapper.h:256
virtual size_t updateHash() const override
Implementation of the updateHash method.
Definition: arrayWrapper.h:389
virtual UntypedSharedPtr getDataAt(const std::type_info &type, const size_t address) const override
Inherited from DataHandler.
Definition: arrayWrapper.h:313
virtual std::vector< size_t > getAddressesAccessed(const std::type_info &type, const size_t address) const override
Inherited from DataHandler.
Definition: arrayWrapper.h:289
void setPointer(std::vector< T > *ptr)
Set the pointer of the ArrayWrapper.
Definition: arrayWrapper.h:365
virtual const std::type_info & getNativeType() const override
Inherited from DataHandler.
Definition: arrayWrapper.h:417
void checkAddressAndType(const std::type_info &type, const size_t &address) const
Definition: arrayWrapper.h:221
virtual bool canHandle(const std::type_info &type) const override
Inherited from DataHandler.
Definition: arrayWrapper.h:210
Base class for all sources of data to be accessed by a TPG Instruction executed within a Program.
Definition: dataHandler.h:54
Definition: primitiveTypeArray.h:54
Class behaving as a std::shared_ptr whose type is not templated.
Definition: untypedSharedPtr.h:72
Definition: array2DWrapper.h:44