Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

QData_impl.h 6.26 KB
Newer Older
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
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
/****************************************************************************
 * **
 * ** Copyright (C) 2018 MinMaxMedical.
 * ** All rights reserved.
 * ** Contact: MinMaxMedical <InCAS@MinMaxMedical.com>
 * **
 * ** This file is part of the modmedLog module.
 * **
 * ** $QT_BEGIN_LICENSE:BSD$
 * ** You may use this file under the terms of the BSD license as follows:
 * **
 * ** "Redistribution and use in source and binary forms, with or without
 * ** modification, are permitted provided that the following conditions are
 * ** met:
 * **   * Redistributions of source code must retain the above copyright
 * **     notice, this list of conditions and the following disclaimer.
 * **   * Redistributions in binary form must reproduce the above copyright
 * **     notice, this list of conditions and the following disclaimer in
 * **     the documentation and/or other materials provided with the
 * **     distribution.
 * **   * Neither the name of MinMaxMedical S.A.S. and its Subsidiary(-ies) nor
 * **     the names of its contributors may be used to endorse or promote
 * **     products derived from this software without specific prior written
 * **     permission.
 * **
 * ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 * ** $QT_END_LICENSE$
 * **
 * ****************************************************************************/
#pragma once

#include <type_traits>

#include <QtCore/qdatastream.h>
#include <QtCore/qvariant.h>

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
47
#include "QValue.h"
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
48
49

// //////////////////////////////////////////////////////////////////////////
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
50
// QDataStream* support
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
51

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
52
53
// TODO Use QByteArray directly

54
//! \warning As with QDataStream, QDataWriter and QDataReader must bind compatible C++ data types, and QDataStream ByteOrder, FloatingPointPrecision and Version
55
//! \remark When not statically known, such information can be transmitted using meta("type",...) although some QAbstractValue implementations may not support it
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
56
class QDataWriter : public QAbstractValueWriter // allows runtime flexibility but requires QTransmogrifier<T> in addition to T::operator<<(QDataStream&) and does not warrant QDataStream operators compatibility if QTransmogrifier<T> ignores qmDataStreamVersion in meta()
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
57
58
59
{
    Q_DISABLE_COPY(QDataWriter)
public:
60
    QDataWriter(QDataStream* io) : io(io) { Q_ASSERT(io); version = QAsciiData(QByteArray::number(io->version())); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
61

62
    QValueMode mode() const noexcept { return QValueMode::Write; }
63

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
64
    // Shortcuts
65
66
    QValue    value   (                  ) { return QCur(this).value(); }
    QSequence sequence(quint32* s=nullptr) { return QCur(this).value().sequence(s); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
67

68
    template<typename T> QValueEnd zap(T&& t) { return QCur(this).value().bind(std::forward<T>(t)); }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
69
protected:
70
    friend class QCur;
71
72
73
74
    bool trySequence(quint32* s=nullptr) { if (s) *io <<       *s; return true; }
    bool tryRecord  (quint32* s=nullptr) { if (s) *io <<       *s; return true; }
    bool tryNull    (                  ) {        *io <<  nullptr; return true; }
    bool tryBind    (   QUtf8DataView u) { QByteArray ba = QByteArray::fromRawData(u.data(), u.size()+int(sizeof('\0'))); return static_cast<QAbstractValue*>(this)->tryBind(ba); }
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
    bool tryBind    (     QUtf8Data&& t) {        *io << t.utf8(); return true; }
    bool tryBind    (       QString&& t) {        *io <<        t; return true; }
    bool tryBind    (          bool&& t) {        *io <<        t; return true; }
    bool tryBind    (         qint8&& t) {        *io <<        t; return true; }
    bool tryBind    (        quint8&& t) {        *io <<        t; return true; }
    bool tryBind    (        qint16&& t) {        *io <<        t; return true; }
    bool tryBind    (       quint16&& t) {        *io <<        t; return true; }
    bool tryBind    (        qint32&& t) {        *io <<        t; return true; }
    bool tryBind    (       quint32&& t) {        *io <<        t; return true; }
    bool tryBind    (        qint64&& t) {        *io <<        t; return true; }
    bool tryBind    (       quint64&& t) {        *io <<        t; return true; }
    bool tryBind    (         float&& t) {        *io <<        t; return true; }
    bool tryBind    (        double&& t) {        *io <<        t; return true; }
    bool tryBind    (    QByteArray&& t) {        *io <<        t; return true; }
    bool tryBind    (      QVariant&& t) {        *io <<        t; return true; }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
91

EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
92
    bool isValid() const noexcept { return io && io->status()==QDataStream::Ok; }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
93

94
95
96
97
    bool tryOut (                  ) { return true; }
    bool tryItem(                  ) { return true; }
    bool tryItem(QIdentifier&      ) { return true; } // record keys are implicit, maps should be serialized as a sequence of records with key and value items
    bool tryItem(QIdentifierLiteral) { return true; } // for QBaseWriter
98

99
    void _meta(QIdentifierLiteral& n, QAsciiData& m) { if (n.isNull()) n=qmDataStreamVersion; if (n == qmDataStreamVersion) m=version; }
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
100
101
private:
    QDataStream* io;
102
    QAsciiData version;
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
103
104
105
106
};

// --------------------------------------------------------------------------

107
108
109
110
// TODO QDataReader
// \remark Providing a general QDataReader may be deceiving because the QDataStream structure is implicit, thus
// a reader is usually assumed to statically know the data type to read based on the stream origin and version.
// Though QVariant can be used for parts which type are not statically known though, such as the dynamic type of a message coming from a socket.
EXT Arnaud Clère's avatar
EXT Arnaud Clère committed
111
// Finally, QDataStream version can be retrieved from meta() to adapt to data schema changes over the time \see QTransmogrifier<QColor> for an example