20 #include <QDataStream>
38 virtual bool toFile(QFile& out,
short dataVersion)
const {
return false; }
52 DF_POINT_COORDS_64_BITS =
56 DF_SCALAR_VAL_32_BITS = 2,
87 CVLog::Error(
"Write error (disk full or no access right?)");
96 CVLog::Error(
"Read error (corrupted file or no access right?)");
130 unsigned count = 1) {
132 for (
unsigned i = 0; i <
count; ++i, ++out) {
138 for (
unsigned i = 0; i <
count; ++i, ++out) {
151 unsigned count = 1) {
153 for (
unsigned i = 0; i <
count; ++i, ++out) {
159 for (
unsigned i = 0; i <
count; ++i, ++out) {
172 template <
class Type,
int N,
class ComponentType>
174 assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
183 ::uint8_t componentCount =
static_cast<::uint8_t
>(N);
184 if (out.write((
const char*)&componentCount, 1) < 0)
188 ::uint32_t elementCount =
static_cast<::uint32_t
>(data.size());
189 if (out.write((
const char*)&elementCount, 4) < 0)
196 const char* _data = (
const char*)data.data();
197 qint64 byteCount =
static_cast<qint64
>(elementCount);
198 byteCount *=
sizeof(Type);
199 while (byteCount != 0) {
200 static const qint64 s_maxByteSaveCount =
202 qint64 saveCount =
std::min(byteCount, s_maxByteSaveCount);
203 if (out.write(_data, saveCount) < 0)
206 byteCount -= saveCount;
218 template <
class Type,
int N,
class ComponentType>
222 const QString& verboseDescription) {
223 ::uint8_t componentCount = 0;
224 ::uint32_t elementCount = 0;
225 if (!ReadArrayHeader(in, dataVersion, componentCount, elementCount)) {
228 if (componentCount != N) {
233 QString(
"Loading %0: %1 elements and %2 dimension(s)")
234 .arg(verboseDescription)
236 .arg(componentCount));
241 data.resize(elementCount);
242 }
catch (
const std::bad_alloc&) {
250 static const qint64 MaxElementPerChunk =
251 (
static_cast<qint64
>(1) << 24);
252 assert(
sizeof(ComponentType) * N ==
sizeof(Type));
253 qint64 byteCount =
static_cast<qint64
>(data.size()) *
254 (
sizeof(ComponentType) * N);
255 char* dest = (
char*)data.data();
256 while (byteCount > 0) {
257 qint64 chunkSize =
std::min(MaxElementPerChunk, byteCount);
258 if (in.read(dest, chunkSize) < 0) {
261 byteCount -= chunkSize;
277 template <
class Type,
int N,
class ComponentType,
class FileComponentType>
279 std::vector<Type>& data,
282 const QString& verboseDescription,
283 FileComponentType* _autoOffset =
nullptr) {
284 ::uint8_t componentCount = 0;
285 ::uint32_t elementCount = 0;
286 if (!ReadArrayHeader(in, dataVersion, componentCount, elementCount)) {
289 if (componentCount != N) {
294 QString(
"Loading %0: %1 elements and %2 dimension(s)")
295 .arg(verboseDescription)
297 .arg(componentCount));
302 data.resize(elementCount);
303 }
catch (
const std::bad_alloc&) {
310 FileComponentType dummyArray[N]{0};
312 ComponentType* _data = (ComponentType*)data.data();
314 size_t elementSize =
sizeof(FileComponentType) * N;
318 if (in.read((
char*)dummyArray, elementSize) >= 0) {
319 for (
unsigned k = 0; k < N; ++k) {
320 _autoOffset[k] = dummyArray[k];
328 for (
unsigned i = 1; i < elementCount; ++i) {
329 if (in.read((
char*)dummyArray, elementSize) >= 0) {
330 for (
unsigned k = 0; k < N; ++k) {
331 *_data++ =
static_cast<ComponentType
>(
332 dummyArray[k] - _autoOffset[k]);
340 for (
unsigned i = 0; i < elementCount; ++i) {
341 if (in.read((
char*)dummyArray,
342 sizeof(FileComponentType) * N) >= 0) {
343 for (
unsigned k = 0; k < N; ++k) {
345 static_cast<ComponentType
>(dummyArray[k]);
360 ::uint8_t& componentCount,
361 ::uint32_t& elementCount) {
362 assert(in.isOpen() && (in.openMode() & QIODevice::ReadOnly));
367 if (in.read((
char*)&componentCount, 1) < 0)
371 if (in.read((
char*)&elementCount, 4) < 0)
float PointCoordinateType
Type of the coordinates of a (N-D) point.
static bool PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Serializable object interface.
static bool CorruptError()
Sends a custom error message (corrupted file) and returns 'false'.
virtual bool isSerializable() const
Returns whether object is serializable of not.
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
virtual ~ccSerializableObject()=default
Destructor.
static bool ReadError()
Sends a custom error message (read error) and returns 'false'.
DeserializationFlags
Deserialization flags (bit-field)
@ DF_POINT_COORDS_64_BITS
virtual short minimumFileVersion() const =0
Returns the minimum file version required to save this instance.
static bool WriteError()
Sends a custom error message (write error) and returns 'false'.
virtual bool toFile(QFile &out, short dataVersion) const
Saves data to binary stream.
virtual bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap)
Loads data from binary stream.
static bool MemoryError()
Sends a custom error message (not enough memory) and returns 'false'.
static bool GenericArrayFromFile(std::vector< Type > &data, QFile &in, short dataVersion, const QString &verboseDescription)
Helper: loads a vector structure from file.
static bool GenericArrayToFile(const std::vector< Type > &data, QFile &out)
Helper: saves a vector to file.
static void ScalarsFromDataStream(QDataStream &stream, int flags, ScalarType *out, unsigned count=1)
static bool ReadArrayHeader(QFile &in, short dataVersion, ::uint8_t &componentCount, ::uint32_t &elementCount)
static bool GenericArrayFromTypedFile(std::vector< Type > &data, QFile &in, short dataVersion, const QString &verboseDescription, FileComponentType *_autoOffset=nullptr)
static void CoordsFromDataStream(QDataStream &stream, int flags, PointCoordinateType *out, unsigned count=1)
static short GenericArrayToFileMinVersion()
Returns the minimum file version to save/load a 'generic array'.