v2.0.0
Loading...
Searching...
No Matches
mna_io.cpp
Go to the documentation of this file.
1//=============================================================================================================
23
24//=============================================================================================================
25// INCLUDES
26//=============================================================================================================
27
28#include "mna_io.h"
29
30//=============================================================================================================
31// QT INCLUDES
32//=============================================================================================================
33
34#include <QFile>
35#include <QFileInfo>
36#include <QJsonDocument>
37#include <QJsonObject>
38#include <QCborValue>
39#include <QCborMap>
40#include <QDebug>
41
42//=============================================================================================================
43// USED NAMESPACES
44//=============================================================================================================
45
46using namespace MNALIB;
47
48//=============================================================================================================
49// STATIC CONSTANTS
50//=============================================================================================================
51
52static const QByteArray MNX_MAGIC = QByteArrayLiteral("MNX1");
53
54//=============================================================================================================
55// DEFINE METHODS
56//=============================================================================================================
57
58MnaProject MnaIO::read(const QString& path)
59{
60 const QFileInfo fi(path);
61 const QString suffix = fi.suffix().toLower();
62
63 if(suffix == QLatin1String("mna")) {
64 return readJson(path);
65 } else if(suffix == QLatin1String("mnx")) {
66 return readCbor(path);
67 }
68
69 qWarning() << "[MnaIO::read] Unknown extension:" << suffix;
70 return MnaProject();
71}
72
73//=============================================================================================================
74
75bool MnaIO::write(const MnaProject& project, const QString& path)
76{
77 const QFileInfo fi(path);
78 const QString suffix = fi.suffix().toLower();
79
80 if(suffix == QLatin1String("mna")) {
81 return writeJson(project, path);
82 } else if(suffix == QLatin1String("mnx")) {
83 return writeCbor(project, path);
84 }
85
86 qWarning() << "[MnaIO::write] Unknown extension:" << suffix;
87 return false;
88}
89
90//=============================================================================================================
91
92MnaProject MnaIO::readJson(const QString& path)
93{
94 QFile file(path);
95 if(!file.open(QIODevice::ReadOnly)) {
96 qWarning() << "[MnaIO::readJson] Cannot open file:" << path;
97 return MnaProject();
98 }
99
100 const QByteArray data = file.readAll();
101 file.close();
102
103 QJsonParseError parseError;
104 const QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
105 if(parseError.error != QJsonParseError::NoError) {
106 qWarning() << "[MnaIO::readJson] Parse error:" << parseError.errorString();
107 return MnaProject();
108 }
109
110 const QJsonObject root = doc.object();
111
112 // Version check: reject if major version differs
113 const QString fileVersion = root[QLatin1String("mna_version")].toString();
114 const int fileMajor = fileVersion.section(QLatin1Char('.'), 0, 0).toInt();
115 const int currentMajor = QString::fromLatin1(MnaProject::CURRENT_SCHEMA_VERSION).section(QLatin1Char('.'), 0, 0).toInt();
116 if(fileMajor != currentMajor) {
117 qWarning() << "[MnaIO::readJson] Incompatible major version:" << fileVersion
118 << "(expected major" << currentMajor << ")";
119 return MnaProject();
120 }
121
122 return MnaProject::fromJson(root);
123}
124
125//=============================================================================================================
126
127bool MnaIO::writeJson(const MnaProject& project, const QString& path)
128{
129 QFile file(path);
130 if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
131 qWarning() << "[MnaIO::writeJson] Cannot open file for writing:" << path;
132 return false;
133 }
134
135 const QJsonDocument doc(project.toJson());
136 const QByteArray data = doc.toJson(QJsonDocument::Indented);
137 const qint64 written = file.write(data);
138 file.close();
139
140 return (written == data.size());
141}
142
143//=============================================================================================================
144
145MnaProject MnaIO::readCbor(const QString& path)
146{
147 QFile file(path);
148 if(!file.open(QIODevice::ReadOnly)) {
149 qWarning() << "[MnaIO::readCbor] Cannot open file:" << path;
150 return MnaProject();
151 }
152
153 // Verify magic header
154 const QByteArray magic = file.read(MNX_MAGIC.size());
155 if(magic != MNX_MAGIC) {
156 qWarning() << "[MnaIO::readCbor] Invalid magic header in:" << path;
157 file.close();
158 return MnaProject();
159 }
160
161 const QByteArray cborData = file.readAll();
162 file.close();
163
164 const QCborValue cborVal = QCborValue::fromCbor(cborData);
165 if(!cborVal.isMap()) {
166 qWarning() << "[MnaIO::readCbor] Root CBOR value is not a map";
167 return MnaProject();
168 }
169
170 const QCborMap root = cborVal.toMap();
171
172 // Version check: reject if major version differs
173 const QString fileVersion = root[QLatin1String("mna_version")].toString();
174 const int fileMajor = fileVersion.section(QLatin1Char('.'), 0, 0).toInt();
175 const int currentMajor = QString::fromLatin1(MnaProject::CURRENT_SCHEMA_VERSION).section(QLatin1Char('.'), 0, 0).toInt();
176 if(fileMajor != currentMajor) {
177 qWarning() << "[MnaIO::readCbor] Incompatible major version:" << fileVersion
178 << "(expected major" << currentMajor << ")";
179 return MnaProject();
180 }
181
182 return MnaProject::fromCbor(root);
183}
184
185//=============================================================================================================
186
187bool MnaIO::writeCbor(const MnaProject& project, const QString& path)
188{
189 QFile file(path);
190 if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
191 qWarning() << "[MnaIO::writeCbor] Cannot open file for writing:" << path;
192 return false;
193 }
194
195 // Write magic header
196 if(file.write(MNX_MAGIC) != MNX_MAGIC.size()) {
197 qWarning() << "[MnaIO::writeCbor] Failed to write magic header";
198 file.close();
199 return false;
200 }
201
202 const QCborValue cborVal(project.toCbor());
203 const QByteArray cborData = cborVal.toCbor();
204 const qint64 written = file.write(cborData);
205 file.close();
206
207 return (written == cborData.size());
208}
Reader and writer for MNA project containers — .mna (JSON, human-editable) and .mnx (CBOR,...
MNE Analysis Container Format (mna/mnx).
static bool write(const MnaProject &project, const QString &path)
Definition mna_io.cpp:75
static MnaProject read(const QString &path)
Definition mna_io.cpp:58
QJsonObject toJson() const
static MnaProject fromJson(const QJsonObject &json)
static MnaProject fromCbor(const QCborMap &cbor)
static constexpr const char * CURRENT_SCHEMA_VERSION
Definition mna_project.h:76
QCborMap toCbor() const