-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmat_utils.h
181 lines (145 loc) · 5.43 KB
/
mat_utils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* mex_utils//mex_utils/mat_utils.h/mat_utils.h
*
* Created on: Jun 5, 2013
* Author: igkiou
*/
#ifndef MAT_UTILS_H_
#define MAT_UTILS_H_
#include <fstream>
#include <string>
#include <vector>
#include <ctype.h>
#include "mat.h"
#include "mex_utils.h"
/*
* TODO: Maybe change class hierarchy. It would be nice to have a hierarchy that
* contains a base class for opening and closing, input with read and peeking,
* output with write, and input/output with both. It would enforce read/write
* safety at compile time. Need to avoid diamond pattern. Maybe some form of
* static polymorphism, policy design or trait-based design. Alternatively, see
* whether derived types can delete virtual members of ancestors.
* TODO: Find safe way to handle mxArray headers, to make sure they don't
* accidentally get passed on later.
*/
namespace mex {
class Mat
class MatFile {
public:
// * "r" == read only.
// * "w" == write only (deletes any existing file with name <filename>).
// * "w4" == as "w", but create a MATLAB 4.0 MAT-file.
// * "w7.3" == as "w", but create a MATLAB 7.3 MAT-file.
// * "u" == update. Read and write allowed, existing file is not deleted.
explicit MatFile(const std::string& fileName) :
MatFile(fileName.c_str(), "u") {}
MatFile(const MatFile& other) = delete;
MatFile& operator=(const MatFile& other) = delete;
MatFile(MatFile&& other) = delete;
MatFile& operator=(MatFile&& other) = delete;
/*
* TODO: Maybe better to implement this by getting name list and scanning
* for queryname.
*/
virtual inline bool hasVariable(const std::string& variableName) const {
return (matGetVariableInfo(m_file, variableName.c_str()) != nullptr);
}
virtual inline std::vector<std::string> getVariableNames() const {
int numberVariables;
char** variableNames = (char**) matGetDir(m_file, &numberVariables);
mexAssert(variableNames != nullptr);
std::vector<std::string> retArg(variableNames,
variableNames + numberVariables);
mxFree(variableNames);
return retArg;
}
virtual inline MxArrayHeader getVariableInfo(const std::string& variableName) const {
mxArray* variableHeader = matGetVariableInfo(m_file,
variableName.c_str());
mexAssert(variableHeader != nullptr);
return MxArrayHeader(variableHeader);
}
virtual inline MxVariableHeader getNextVariableInfo() const {
const char* variableNameTemp;
mxArray* variableHeader = matGetNextVariableInfo(m_file,
&variableNameTemp);
mexAssert(variableHeader != nullptr);
std::string variableName = std::string(variableNameTemp);
mxFree((void *) variableNameTemp);
return MxVariableHeader{variableName, MxArrayHeader(variableHeader)};
}
template <typename MxArrayType>
virtual inline MxArrayType readVariable(const std::string& variableName) const {
mxArray* variable = matGetVariable(m_file, variableName.c_str());
mexAssert(variable != nullptr);
return MxArrayType(variable);
}
virtual inline MxArray readVariable(const std::string& variableName) const {
return readVariable<MxArray>(variableName);
}
template <typename MxArrayType>
virtual inline MxVariable readNextVariable() {
const char* variableNameTemp;
mxArray* variable = matGetNextVariable(m_file, &variableNameTemp);
mexAssert(variable != nullptr);
std::string variableName = std::string(variableNameTemp);
mxFree((void *) variableNameTemp);
return MxVariable{variableName, MxArrayType(variable)};
}
virtual inline MxVariable readNextVariable() {
return readNextVariable<MxArray>();
}
template <typename MxArrayType>
virtual inline void writeVariable(const MxArrayType& variable,
const std::string& variableName) {
int errorCode = matPutVariable(m_file, variableName.c_str(),
variable.get_array());
mexAssert(errorCode == 0);
}
virtual inline void writeVariable(const MxVariable& variable) {
writeVariable(*(variable.m_array), variable.m_name);
}
virtual inline void deleteVariable(const std::string& variableName) {
int errorCode = matDeleteVariable(m_file, variableName.c_str());
mexAssert(errorCode == 0);
}
~MatFile() {
int errorCode = matClose(m_file);
mexAssert(errorCode == 0);
}
protected:
MatFile(const char* fileName, const char* accessType) :
m_file(matOpen(fileName, accessType)) {
mexAssert(m_file != nullptr);
}
private:
/*
* TODO: Maybe declare const.
*/
MATFile* m_file;
};
class MatInputFile : public MatFile {
public:
explicit MatInputFile(const std::string& fileName) :
MatFile(fileName.c_str(), "r") {}
void writeVariable(const MxVariable& variable) override = delete;
void deleteVariable(const std::string& vaiableName) override = delete;
virtual ~MatInputFile() = default;
};
class MatOutputFile : MatFile {
public:
explicit MatOutputFile(const std::string& fileName) :
MatFile(fileName.c_str(), "w7.3") {}
bool hasVariable(const std::string& variableName) const override = delete;
std::vector<std::string> getVariableNames() const override = delete;
MxArrayHeader getVariableInfo(const std::string& variableName) const override = delete;
MxVariableHeader getNextVariableInfo() const override = delete;
template <typename MxArrayType>
MxArrayType readVariable(const std::string& variableName) const override = delete;
MxArray readVariable(const std::string& variableName) const override = delete;
template <typename MxArrayType>
MxVariable readNextVariable() override = delete;
virtual ~MatOutputFile() = default;
};
} /* namespace mex */
#endif /* MAT_UTILS_H_ */