matio-cpp  v0.2.5
A C++ wrapper of the matio library, with memory ownership handling, to read and write .mat files.
StructArray.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Fondazione Istituto Italiano di Tecnologia
3  *
4  * This software may be modified and distributed under the terms of the
5  * BSD-2-Clause license (https://opensource.org/licenses/BSD-2-Clause).
6  */
7 
8 
9 #include <matioCpp/StructArray.h>
10 
11 bool matioCpp::StructArray::checkCompatibility(const matvar_t* inputPtr, matioCpp::VariableType variableType, matioCpp::ValueType) const
12 {
15  {
16  std::cerr << "[matioCpp::StructArray::checkCompatibility] The variable type is not compatible with a struct array." << std::endl;
17  return false;
18  }
19 
20  if (inputPtr->isComplex)
21  {
22  std::cerr << "[matioCpp::StructArray::checkCompatibility] Cannot use a complex variable into a non-complex one." << std::endl;
23  return false;
24  }
25 
26  return true;
27 }
28 
30 {
31  size_t emptyDimensions[] = {0, 0};
32  initializeVariable("unnamed_struct_array",
34  matioCpp::ValueType::VARIABLE, emptyDimensions,
35  nullptr);
36 }
37 
39 {
40  size_t emptyDimensions[] = {0, 0};
41  initializeVariable(name,
43  matioCpp::ValueType::VARIABLE, emptyDimensions,
44  nullptr);
45 }
46 
48 {
49  for (matioCpp::StructArray::index_type dim : dimensions)
50  {
51  if (dim == 0)
52  {
53  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] Zero dimension detected." << std::endl;
54  assert(false);
55  }
56  }
57 
58  initializeVariable(name,
61  nullptr);
62 }
63 
65 {
66  bool abort = false;
67  matioCpp::StructArray::index_type totalElements = 1;
68  for (matioCpp::StructArray::index_type dim : dimensions)
69  {
70  totalElements *= dim;
71  }
72 
73  if (totalElements != elements.size())
74  {
75  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] The size of elements vector does not match the provided dimensions. The total number is different." << std::endl;
76  assert(false);
77  abort = true;
78  }
79 
80 
81  if (!abort && elements.size() > 0)
82  {
83  size_t firstNumberOfFields = elements[0].numberOfFields();
84  char * const * firstFields = elements[0].getStructFields();
85 
86  std::vector<matvar_t*> vectorOfPointers(totalElements * firstNumberOfFields + 1, nullptr);
87 
88  size_t innerIndex = 0;
89 
90  for (size_t i = 0; (i < totalElements) && !abort; ++i)
91  {
92  if (!elements[i].isValid())
93  {
94  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] The element at index "<< i << " (0-based) is not valid." << std::endl;
95  abort = true;
96  assert(false);
97  }
98 
99  if (elements[i].numberOfFields() != firstNumberOfFields)
100  {
101  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] The element at index "<< i << " (0-based) has a number of fields different from the others. All Structs are supposed to have the same set of fields." << std::endl;
102  abort = true;
103  assert(false);
104  }
105  char * const * otherFields = elements[i].getStructFields();
106 
107  for (size_t field = 0; (field < firstNumberOfFields) && !abort; ++field)
108  {
109  if (strcmp(firstFields[field], otherFields[field]) != 0)
110  {
111  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] The element at index "<< i << " (0-based) has a set of fields different from the others. All Structs are supposed to have the same set of fields." << std::endl;
112  abort = true;
113  assert(false);
114  }
115  vectorOfPointers[innerIndex] = matioCpp::MatvarHandler::GetMatvarDuplicate(elements[i][field].toMatio());
116  innerIndex++;
117  }
118  }
119  assert(innerIndex == totalElements * firstNumberOfFields);
120 
121  if (!abort)
122  {
123  initializeVariable(name,
125  matioCpp::ValueType::VARIABLE, dimensions,
126  vectorOfPointers.data());
127  }
128  else
129  {
130  initializeVariable(name,
132  matioCpp::ValueType::VARIABLE, dimensions,
133  nullptr);
134  }
135 
136  }
137  else
138  {
139  initializeVariable(name,
141  matioCpp::ValueType::VARIABLE, dimensions,
142  nullptr);
143  }
144 
145 }
146 
148 {
149  for (matioCpp::StructArray::index_type dim : dimensions)
150  {
151  if (dim == 0)
152  {
153  std::cerr << "[ERROR][matioCpp::StructArray::StructArray] Zero dimension detected." << std::endl;
154  assert(false);
155  }
156  }
157 
158  initializeVariable(name,
160  matioCpp::ValueType::VARIABLE, dimensions,
161  nullptr);
162 
163  for (const std::string& field : fields)
164  {
165  addField(field);
166  }
167 }
168 
170 {
171  fromOther(other);
172 }
173 
175 {
176  fromOther(std::forward<StructArray>(other));
177 }
178 
180  : matioCpp::Variable(handler)
181 {
182  if (!handler.get() || !checkCompatibility(handler.get(), handler.variableType(), handler.valueType()))
183  {
184  assert(false);
185  size_t emptyDimensions[] = {0, 0};
186  initializeVariable("unnamed_struct_array",
188  matioCpp::ValueType::VARIABLE, emptyDimensions,
189  nullptr);
190  }
191 }
192 
194 {
195 
196 }
197 
199 {
200  fromOther(other);
201  return *this;
202 }
203 
205 {
206  fromOther(std::forward<StructArray>(other));
207  return *this;
208 }
209 
211 {
212  matioCpp::StructArray::index_type totalElements = 1;
213  for (matioCpp::StructArray::index_type dim : dimensions)
214  {
215  totalElements *= dim;
216  }
217 
218  if (totalElements != elements.size())
219  {
220  std::cerr << "[ERROR][matioCpp::StructArray::fromVectorOfStructs] The size of elements vector does not match the provided dimensions. The total number is different." << std::endl;
221  return false;
222  }
223 
224 
225  if (elements.size() > 0)
226  {
227  size_t firstNumberOfFields = elements[0].numberOfFields();
228  char * const * firstFields = elements[0].getStructFields();
229 
230  std::vector<matvar_t*> vectorOfPointers(totalElements * firstNumberOfFields + 1, nullptr);
231 
232  size_t innerIndex = 0;
233 
234  for (size_t i = 0; i < totalElements; ++i)
235  {
236  if (!elements[i].isValid())
237  {
238  std::cerr << "[ERROR][matioCpp::StructArray::fromVectorOfStructs] The element at index "<< i << " (0-based) is not valid." << std::endl;
239  return false;
240  }
241 
242  if (elements[i].numberOfFields() != firstNumberOfFields)
243  {
244  std::cerr << "[ERROR][matioCpp::StructArray::fromVectorOfStructs] The element at index "<< i << " (0-based) has a number of fields different from the others. All Structs are supposed to have the same set of fields." << std::endl;
245  return false;
246  }
247  char * const * otherFields = elements[i].getStructFields();
248 
249  for (size_t field = 0; field < firstNumberOfFields; ++field)
250  {
251  if (strcmp(firstFields[field], otherFields[field]) != 0)
252  {
253  std::cerr << "[ERROR][matioCpp::StructArray::fromVectorOfStructs] The element at index "<< i << " (0-based) has a set of fields different from the others. All Structs are supposed to have the same set of fields." << std::endl;
254  return false;
255  }
256  vectorOfPointers[innerIndex] = matioCpp::MatvarHandler::GetMatvarDuplicate(elements[i][field].toMatio());
257  innerIndex++;
258  }
259  }
260  assert(innerIndex == totalElements * firstNumberOfFields);
261 
262 
263  return initializeVariable(name(),
265  matioCpp::ValueType::VARIABLE, dimensions,
266  vectorOfPointers.data());
267  }
268  else
269  {
270 
271  return initializeVariable(name(),
273  matioCpp::ValueType::VARIABLE, dimensions,
274  nullptr);
275  }
276 }
277 
279 {
280  assert(dimensions().size() > 0 && numberOfElements() > 0 && "[matioCpp::StructArray::rawIndexFromIndices] The array is empty.");
281  assert(el.size() > 0 == dimensions().size() > 0 && "[matioCpp::StructArray::rawIndexFromIndices] The input vector el should have the same number of dimensions of the array.");
282  assert(el[0] < dimensions()[0] && "[matioCpp::StructArray::rawIndexFromIndices] The required element is out of bounds.");
283 
284  typename matioCpp::StructArray::index_type index = 0;
285  typename matioCpp::StructArray::index_type previousDimensionsFactorial = 1;
286 
287  for (size_t i = 0; i < el.size(); ++i)
288  {
289  assert(el[i] < dimensions()[i] && "[matioCpp::StructArray::rawIndexFromIndices] The required element is out of bounds.");
290  index += el[i] * previousDimensionsFactorial;
291  previousDimensionsFactorial *= dimensions()[i];
292  }
293 
294  return index;
295 }
296 
298 {
299  el.resize(dimensions().size());
300 
301  if (rawIndex >= numberOfElements())
302  {
303  std::cerr << "[ERROR][matioCpp::StructArray::indicesFromRawIndex] rawIndex is greater than the number of elements." << std::endl;
304  return false;
305  }
306 
307  size_t previousDimensionsFactorial = dimensions()[0];
308 
309  //First we fill el with the factorial of the dimensions
310 
311  for (size_t i = 1; i < el.size(); ++i)
312  {
313  el[i - 1] = previousDimensionsFactorial;
314  previousDimensionsFactorial *= dimensions()[i];
315  }
316 
317  size_t remainder = rawIndex;
318 
319  for (size_t i = el.size() - 1; i > 0; --i)
320  {
321  el[i] = remainder / el[i - 1];
322  remainder -= el[i] * el[i - 1];
323  }
324  el[0] = remainder;
325 
326  return true;
327 }
328 
330 {
331  return changeName(newName);
332 }
333 
335 {
336  matioCpp::StructArray newArray(name(), newDimensions);
337  fromOther(std::move(newArray));
338 }
339 
341 {
342  return getArrayNumberOfElements();
343 }
344 
346 {
347  return getStructNumberOfFields();
348 }
349 
351 {
353  char * const * matvarOutput = getStructFields();
354  if (matvarOutput)
355  {
356  size_t numberOfFields = getStructNumberOfFields();
357  output.reserve(numberOfFields);
358  for (size_t i = 0; i < numberOfFields; ++i)
359  {
360  output.emplace_back(matvarOutput[i]);
361  }
362  }
363 
364  return output;
365 }
366 
368 {
369  fromOther(std::move(StructArray(name())));
370 }
371 
373 {
374  return getStructFieldIndex(field) < numberOfFields();
375 }
376 
378 {
379  return getStructFieldIndex(field);
380 }
381 
383 {
384  if (!addStructField(newField))
385  {
386  std::cerr << "[ERROR][matioCpp::StructArray::addField] Failed to add field " << newField << "." <<std::endl;
387  }
388  return true;
389 }
390 
392 {
393  for (const std::string& field : newFields)
394  {
395  if (!addField(field))
396  {
397  return false;
398  }
399  }
400  return true;
401 }
402 
404 {
405  return setElement(rawIndexFromIndices(el), newValue);
406 }
407 
409 {
410  assert(el < numberOfElements() && "The requested element is out of bounds.");
411 
412  char * const * arrayFields = getStructFields();
413  char * const * structFields = newValue.getStructFields();
414 
415  if (numberOfFields() != newValue.numberOfFields())
416  {
417  std::cerr << "[ERROR][matioCpp::StructArray::setElement] The input struct is supposed to have the same number of fields of the struct array." <<std::endl;
418  return false;
419  }
420 
421  for (size_t i = 0; i < numberOfFields(); ++i)
422  {
423  if (strcmp(arrayFields[i], structFields[i]) != 0)
424  {
425  std::cerr << "[ERROR][matioCpp::StructArray::setElement] The field " << structFields[i] << " of the input struct is supposed to be " << arrayFields[i]
426  << ". Cannot insert in a struct array a new field in a single element." <<std::endl;
427  return false;
428  }
429 
430  bool ok = setStructField(i, newValue(i), el);
431  if (!ok)
432  {
433  std::cerr << "[ERROR][matioCpp::StructArray::setElement] Failed to set field " << structFields[i] << "." <<std::endl;
434  return false;
435  }
436  }
437 
438  return true;
439 }
440 
442 {
443  matioCpp::StructArray::index_type linearindex = rawIndexFromIndices(el);
444  return matioCpp::StructArray::Element(linearindex, this);
445 }
446 
448 {
449  matioCpp::StructArray::index_type linearindex = rawIndexFromIndices(el);
450  return matioCpp::StructArray::ConstElement(linearindex, this);
451 }
452 
454 {
455  assert(el < numberOfElements());
456  return matioCpp::StructArray::Element(el, this);
457 }
458 
460 {
461  assert(el < numberOfElements());
462  return matioCpp::StructArray::ConstElement(el, this);
463 }
464 
466 {
467  matioCpp::StructArray::index_type linearindex = rawIndexFromIndices(el);
468  return matioCpp::StructArray::Element(linearindex, this);
469 }
470 
472 {
473  matioCpp::StructArray::index_type linearindex = rawIndexFromIndices(el);
474  return matioCpp::StructArray::ConstElement(linearindex, this);
475 }
476 
478 {
479  assert(el < numberOfElements());
480  return matioCpp::StructArray::Element(el, this);
481 }
482 
484 {
485  assert(el < numberOfElements());
486  return matioCpp::StructArray::ConstElement(el, this);
487 }
488 
489 
static matvar_t * GetMatvarDuplicate(const matvar_t *inputPtr)
Get a duplicate of the input matvar pointer/.
ValueType valueType() const
Get the value type of the pointer.
virtual matvar_t * get() const =0
Get the shared matvar_t pointer.
VariableType variableType() const
Get the variable type of the pointer.
StructArray is a particular type of Variable specialized for array of structs.
Definition: StructArray.h:21
bool fromVectorOfStructs(const std::vector< index_type > &dimensions, const std::vector< matioCpp::Struct > &elements)
Set from a vector of Variables.
bool addField(const std::string &newField)
Add a new field to all the structs.
void clear()
Clear the struct array.
index_type numberOfFields() const
Get the total number of fields in the struct.
Element operator()(const std::vector< index_type > &el)
Access specified element.
index_type rawIndexFromIndices(const std::vector< index_type > &el) const
Get the linear index corresponding to the provided indices.
bool setName(const std::string &newName)
Change the name of the Variable.
void resize(const std::vector< index_type > &newDimensions)
Resize the array.
StructArrayElement< true > ConstElement
Non-const version of StructArrayElement.
Definition: StructArray.h:41
size_t getFieldIndex(const std::string &field) const
Get the index of the specified field in the struct by performing a linear search.
StructArray()
Const version of Element.
Definition: StructArray.cpp:29
bool isFieldExisting(const std::string &field) const
Check if a field is existing It performs a linear search over the output of fields().
Element operator[](const std::vector< index_type > &el)
Access specified element.
StructArrayElement< false > Element
The type used for indices.
Definition: StructArray.h:39
std::vector< std::string > fields() const
Get the list of fields.
bool indicesFromRawIndex(size_t rawIndex, std::vector< index_type > &el) const
Get the indices given the raw index.
~StructArray()
Destructor.
bool addFields(const std::vector< std::string > &newFields)
Add the fields to all the structs.
StructArray & operator=(const StructArray &other)
Assignement operator (copy) from another StructArray.
index_type numberOfElements() const
Get the total number of elements in the array.
bool setElement(const std::vector< index_type > &el, const matioCpp::Struct &newValue)
Set the element at the specified position.
Struct is a particular type of Variable specialized for structs.
Definition: Struct.h:18
index_type numberOfFields() const
Get the total number of fields in the struct.
Definition: Struct.cpp:136
The matioCpp::Variable class is the equivalent of matvar_t in matio.
Definition: Variable.h:23
char *const * getStructFields() const
Get the list of fields in the variable, considered as a struct.
Definition: Variable.cpp:229
matioCpp::VariableType variableType() const
Get the VariableType.
Definition: Variable.cpp:506
bool initializeVariable(const std::string &name, const VariableType &variableType, const ValueType &valueType, matioCpp::Span< const size_t > dimensions, void *data)
Initialize the variable.
Definition: Variable.cpp:16
T data(T... args)
T emplace_back(T... args)
T endl(T... args)
T move(T... args)
VariableType
Define the type of variable.
ValueType
The list of types for an element of a certain variable type.
T reserve(T... args)
T resize(T... args)
T size(T... args)