matio-cpp  v0.2.5
A C++ wrapper of the matio library, with memory ownership handling, to read and write .mat files.
MatvarHandler.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 
11 
13 {
14  m_ptr = nullptr;
15  m_mode = DeleteMode::DoNotDelete;
18 }
19 
21 {
22  changePointer(ptr, deleteMode);
23 }
24 
26 {
27  //It does nothing by default. The ownership determines when to delete the pointer
28 }
29 
31 {
32  //The previous pointer is not deleted since it is the ownership triggering it
33  m_ptr = ptr;
34  m_mode = deleteMode;
37  get_types_from_matvart(m_ptr, m_varType, m_valueType);
38 }
39 
41 {
42  DeletePointer(m_ptr, m_mode);
43  m_ptr = nullptr;
44 }
45 
47 {
48  return m_ptr;
49 }
50 
52 {
53  return m_varType;
54 }
55 
57 {
58  return m_valueType;
59 }
60 
62 {
63  return m_mode;
64 }
65 
67 {
68  return m_ptr != other.m_ptr;
69 }
70 
72 {
73  if (deleteMode == DeleteMode::Delete || deleteMode == DeleteMode::ShallowDelete)
74  {
75  if (deleteMode == DeleteMode::ShallowDelete)
76  {
77  ptr->data = nullptr; //When doing a shallow copy, the data pointer is copied.
78  //Hence, by freeing the shallowCopy, also the data would be deallocated.
79  //This avoids matio to attempt freeing the data
80  // See https://github.com/tbeu/matio/issues/158
81  }
82  Mat_VarFree(ptr);
83  }
84 }
85 
86 void matioCpp::MatvarHandler::Ownership::dropDependencies(matvar_t *previouslyOwned)
87 {
88  if (!previouslyOwned)
89  {
90  return;
91  }
92 
93  std::unordered_map<matvar_t*, Dependency>::iterator it = m_dependencyTree.find(previouslyOwned);
94 
95  if (it == m_dependencyTree.end())
96  {
97  return;
98  }
99 
100  for (matvar_t* child : it->second.dependencies)
101  {
102  dropDependencies(child);
103  }
104 
105  PointerInfo::DeletePointer(previouslyOwned, it->second.mode);
106 
107  m_dependencyTree.erase(previouslyOwned);
108 }
109 
111  : m_main(pointerToDeallocate)
112 {
113 
114 }
115 
117 {
118  dropAll();
119 }
120 
122 {
123  return (test && ((test == (m_main.lock()->pointer())) || (m_dependencyTree.find(test) != m_dependencyTree.end())));
124 }
125 
127 {
128  assert(owner);
129  if (owned)
130  {
131  Dependency dep;
132  dep.mode = mode;
133  if (*(owner->m_ptr) != *(m_main.lock()))
134  {
135  dep.parent = owner->m_ptr->pointer();
136 
137  assert(m_dependencyTree.find(dep.parent) != m_dependencyTree.end());
138 
139  m_dependencyTree[dep.parent].dependencies.insert(owned);
140  }
141 
142  m_dependencyTree[owned] = dep;
143  }
144 }
145 
146 void matioCpp::MatvarHandler::Ownership::drop(matvar_t *previouslyOwned)
147 {
148  if (!previouslyOwned)
149  {
150  return;
151  }
152 
153  std::unordered_map<matvar_t*, Dependency>::iterator it = m_dependencyTree.find(previouslyOwned);
154 
155  if (it == m_dependencyTree.end())
156  {
157  return;
158  }
159 
160  std::unordered_map<matvar_t*, Dependency>::iterator parent = m_dependencyTree.find(it->second.parent);
161 
162  if ((it->second.parent != m_main.lock()->pointer()) && (parent != m_dependencyTree.end()))
163  {
164  parent->second.dependencies.erase(previouslyOwned);
165  }
166 
167  dropDependencies(previouslyOwned);
168 
169  m_dependencyTree.erase(previouslyOwned);
170 }
171 
173 {
174  std::shared_ptr<PointerInfo> locked = m_main.lock();
175  if (locked)
176  {
177  locked->deletePointer();
178  }
179 
180  for(std::pair<matvar_t*, Dependency> dep : m_dependencyTree)
181  {
182  PointerInfo::DeletePointer(dep.first, dep.second.mode);
183  }
184 
185  m_dependencyTree.clear();
186 }
187 
189  : m_ptr(std::make_shared<PointerInfo>())
190 {
191 }
192 
193 matioCpp::MatvarHandler::MatvarHandler(matvar_t *inputPtr, DeleteMode deleteMode)
194  : m_ptr(std::make_shared<PointerInfo>(inputPtr, deleteMode))
195 {
196 
197 }
198 
200  : m_ptr(other.m_ptr)
201 {
202 
203 }
204 
206  : m_ptr(other.m_ptr)
207 {
208 
209 }
210 
212 {
213  return m_ptr->valueType();
214 }
215 
217 {
218  return m_ptr->variableType();
219 }
220 
221 matvar_t *matioCpp::MatvarHandler::GetMatvarDuplicate(const matvar_t *inputPtr)
222 {
223  std::string errorPrefix = "[ERROR][matioCpp::MatvarHandler::GetMatvarDuplicate] ";
224  if (!inputPtr)
225  {
226  return nullptr;
227  }
228 
229  VariableType outputVariableType;
230  ValueType outputValueType;
231  matvar_t* outputPtr;
232 
233  if (!matioCpp::get_types_from_matvart(inputPtr, outputVariableType, outputValueType))
234  {
235  std::cerr << errorPrefix << "The inputPtr is not supported." << std::endl;
236  return nullptr;
237  }
238 
239  if (outputVariableType == matioCpp::VariableType::CellArray) // It is a different case because Mat_VarDuplicate segfaults with a CellArray
240  {
241  SharedMatvar shallowCopy = SharedMatvar::GetMatvarShallowDuplicate(inputPtr); // Shallow copy to remove const
242 
243  size_t totalElements = 1;
244 
245  for (int i = 0; i < inputPtr->rank; ++i)
246  {
247  totalElements *= inputPtr->dims[i];
248  }
249 
250  std::vector<matvar_t*> vectorOfPointers(totalElements, nullptr);
251  for (size_t i = 0; i < totalElements; ++i)
252  {
253  matvar_t* internalPointer = Mat_VarGetCell(shallowCopy.get(), static_cast<int>(i));
254  if (internalPointer)
255  {
256  vectorOfPointers[i] = GetMatvarDuplicate(internalPointer); //Deep copy
257  }
258  }
259 
260  outputPtr = Mat_VarCreate(inputPtr->name, inputPtr->class_type, inputPtr->data_type, inputPtr->rank, inputPtr->dims, vectorOfPointers.data(), 0);
261  }
262  else if ((outputVariableType == matioCpp::VariableType::Struct) || (outputVariableType == matioCpp::VariableType::StructArray))
263  {
264  SharedMatvar shallowCopy = SharedMatvar::GetMatvarShallowDuplicate(inputPtr); // Shallow copy to remove const
265 
266  size_t totalElements = 1;
267 
268  for (int i = 0; i < inputPtr->rank; ++i)
269  {
270  totalElements *= inputPtr->dims[i];
271  }
272 
273  size_t numberOfFields = Mat_VarGetNumberOfFields(shallowCopy.get());
274 
275  std::vector<matvar_t*> vectorOfPointers(totalElements * numberOfFields + 1, nullptr); //The vector of pointers has to be nullptr terminated.
276 
277  size_t innerIndex = 0;
278  for (size_t i = 0; i < totalElements; ++i)
279  {
280  for (size_t field = 0; field < numberOfFields; ++field)
281  {
282  matvar_t* internalPointer = Mat_VarGetStructFieldByIndex(shallowCopy.get(), field, i);
283  if (internalPointer)
284  {
285  vectorOfPointers[innerIndex] = GetMatvarDuplicate(internalPointer); //Deep copy
286  }
287  innerIndex++;
288  }
289  }
290  assert(innerIndex == totalElements * numberOfFields);
291 
292  outputPtr = Mat_VarCreate(inputPtr->name, inputPtr->class_type, inputPtr->data_type, inputPtr->rank, inputPtr->dims, vectorOfPointers.data(), 0);
293  }
294  else
295  {
296  outputPtr = Mat_VarDuplicate(inputPtr, 1); //0 Shallow copy, 1 Deep copy
297  }
298 
299  return outputPtr;
300 
301 }
302 
303 void matioCpp::MatvarHandler::DeleteMatvar(matvar_t *pointerToDelete, DeleteMode mode)
304 {
305  PointerInfo::DeletePointer(pointerToDelete, mode);
306 }
void drop(matvar_t *previouslyOwned)
Drop a previously owned pointer and deleted if necessary.
bool isOwning(matvar_t *test)
Check if an input pointer is owned by this ownership object.
void own(matvar_t *owned, const MatvarHandler *owner, matioCpp::DeleteMode mode)
Add a pointer to the list of owned pointers.
Ownership(std::weak_ptr< PointerInfo > pointerToDeallocate)
Constructor.
void dropAll()
Drops all the previously owned pointers and free those that need to be deallocated,...
matvar_t * pointer()
Get the matvar pointer.
void deletePointer()
Delete the matvar pointer.
ValueType valueType() const
Get the value type.
VariableType variableType() const
Get the variable type.
bool operator!=(const PointerInfo &other) const
Comparison operator.
void changePointer(matvar_t *ptr, DeleteMode deleteMode)
Change the input pointer.
DeleteMode deleteMode() const
Get the deletion mode.
static void DeletePointer(matvar_t *ptr, DeleteMode deleteMode)
Delete the given pointer given the mode.
static matvar_t * GetMatvarDuplicate(const matvar_t *inputPtr)
Get a duplicate of the input matvar pointer/.
static void DeleteMatvar(matvar_t *pointerToDelete, DeleteMode mode=DeleteMode::Delete)
Delete the specified Matvar.
ValueType valueType() const
Get the value type of the pointer.
MatvarHandler()
Default constructor.
std::shared_ptr< PointerInfo > m_ptr
Shared pointer to a PointerInfo.
VariableType variableType() const
Get the variable type of the pointer.
static SharedMatvar GetMatvarShallowDuplicate(const matvar_t *inputPtr)
Get the shallow duplicate of an input Matvar.
virtual matvar_t * get() const final
Docs inherited.
T data(T... args)
T end(T... args)
T endl(T... args)
T erase(T... args)
T find(T... args)
DeleteMode
The delete mode of matvar_t pointers.
@ ShallowDelete
The handler does not delete the pointer.
@ Delete
The handler deletes the pointer but not the data.
VariableType
Define the type of variable.
bool get_types_from_matvart(const matvar_t *input, VariableType &outputVariableType, ValueType &outputValueType)
Get the VariableType and the ValueType from a matvar_t pointer.
ValueType
The list of types for an element of a certain variable type.
STL namespace.
matioCpp::DeleteMode mode
The set of dependencies.
matvar_t * parent
Deletion mode for the dependency.