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/

Commit e2e2a17d authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

Use a QValueEnd type with jus the bool result to hide QValueStatus

undesirable methods like value() that allowed to concatenate QValues in,
say, a JSON stream
parent c50b87ac
......@@ -465,7 +465,7 @@ private:
template<>
struct QTransmogrifier<QCborValue> {
static QValueStatus zap(QValue&& v, QCborValue&& j) {
static QValueEnd zap(QValue&& v, QCborValue&& j) {
if (v->mode()==Write) {
if (j.isMap ()) return v.bind(j.toMap ());
if (j.isArray ()) return v.bind(j.toArray ());
......@@ -480,7 +480,7 @@ struct QTransmogrifier<QCborValue> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QCborValue& j) {
static QValueEnd zap(QValue&& v, QCborValue& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......@@ -507,7 +507,7 @@ struct QTransmogrifier<QCborValue> {
template<>
struct QTransmogrifier<QCborArray> {
static QValueStatus zap(QValue&& v, QCborArray&& j) {
static QValueEnd zap(QValue&& v, QCborArray&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.sequence(&size));
......@@ -518,7 +518,7 @@ struct QTransmogrifier<QCborArray> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QCborArray& j) {
static QValueEnd zap(QValue&& v, QCborArray& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......@@ -538,7 +538,7 @@ struct QTransmogrifier<QCborArray> {
template<>
struct QTransmogrifier<QCborMap> {
static QValueStatus zap(QValue&& v, QCborMap&& j) {
static QValueEnd zap(QValue&& v, QCborMap&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto r(v.record(&size));
......@@ -553,7 +553,7 @@ struct QTransmogrifier<QCborMap> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QCborMap& j) {
static QValueEnd zap(QValue&& v, QCborMap& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......
......@@ -65,7 +65,7 @@ public:
QValue value ( ) { return QValueStatus(this).value(); }
QSequence sequence(quint32* s=nullptr) { return QValueStatus(this).value().sequence(s); }
template<typename T> QValueStatus zap(T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
template<typename T> QValueEnd zap(T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
friend class QValueStatus;
bool trySequence(quint32* s=nullptr) { if (s) *io << *s; return true; }
......
......@@ -240,7 +240,7 @@ public:
}
struct Step { int index; const char* end; QMap<QIdentifier,QJsonValue/*TODO QVariant for meta() support*/> cachedItems; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {} };
struct Error { QIdentifierLiteral error; int line; int column; int index; QValueStatus zap(QValue&& value) { QByteArray u(error.utf8()); u.append(' ').append(QByteArray::number(line)).append(':').append(QByteArray::number(column)); return value.bind(QUtf8Data(u)); } };
struct Error { QIdentifierLiteral error; int line; int column; int index; QValueEnd zap(QValue&& value) { QByteArray u(error.utf8()); u.append(' ').append(QByteArray::number(line)).append(':').append(QByteArray::number(column)); return value.bind(QUtf8Data(u)); } };
QVector<Error> errors;
// Shortcuts
......@@ -523,7 +523,7 @@ private:
template<>
struct QTransmogrifier<QJsonValue> {
static QValueStatus zap(QValue&& v, QJsonValue&& j) {
static QValueEnd zap(QValue&& v, QJsonValue&& j) {
if (v->mode()==Write) {
if (j.isObject()) return v.bind(j.toObject());
if (j.isArray ()) return v.bind(j.toArray ());
......@@ -536,7 +536,7 @@ struct QTransmogrifier<QJsonValue> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QJsonValue& j) {
static QValueEnd zap(QValue&& v, QJsonValue& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......@@ -561,7 +561,7 @@ struct QTransmogrifier<QJsonValue> {
template<>
struct QTransmogrifier<QJsonArray> {
static QValueStatus zap(QValue&& v, QJsonArray&& j) {
static QValueEnd zap(QValue&& v, QJsonArray&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.sequence(&size));
......@@ -572,7 +572,7 @@ struct QTransmogrifier<QJsonArray> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QJsonArray& j) {
static QValueEnd zap(QValue&& v, QJsonArray& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......@@ -592,7 +592,7 @@ struct QTransmogrifier<QJsonArray> {
template<>
struct QTransmogrifier<QJsonObject> {
static QValueStatus zap(QValue&& v, QJsonObject&& j) {
static QValueEnd zap(QValue&& v, QJsonObject&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
auto s(v.record(&size));
......@@ -604,7 +604,7 @@ struct QTransmogrifier<QJsonObject> {
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QJsonObject& j) {
static QValueEnd zap(QValue&& v, QJsonObject& j) {
if (v->mode()==Write) {
return zap(std::move(v),std::move(j));
}
......
......@@ -237,6 +237,8 @@ template<class T_> class QVal;
#include <type_traits>
template<class T> using RemoveCvRef = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
struct QValueEnd { bool isValid = false; };
//! A QValueStatus is a move-only, non-owning pointer to QAbstractValue
//!
//! Its public interface only allows checking the status of resulting QAbstractValue operation(s) using operator bool() and to handleError().
......@@ -264,6 +266,7 @@ public:
explicit operator bool() const noexcept { return impl && impl->isValid(); } //!< Drives QTransmogrifier<T>::bind() traversal
QValueStatus* operator ->() noexcept { return this; }
QVal<QValueStatus> value() noexcept ;
operator QValueEnd() { return QValueEnd{impl!=nullptr}; }
QValueErrorHandler setErrorHandler(QValueErrorHandler newHandler = nullptr) { return Q_LIKELY(impl) ? impl->setErrorHandler(newHandler) : nullptr; }
bool handleError(QIdentifierLiteral name, QString context = QString()) { return Q_LIKELY(impl) ? impl->handleError(name, context) : false; }
......@@ -321,11 +324,11 @@ using QRecord = QRec<QValueStatus>;
#include <functional>
#ifndef NO_COMPILER_RTTI_OR_EXCEPTIONS
template<typename T> using QValFunction = QValueStatus(*)(T &,QValue &&) ;
template<class Ts> using QSeqFunction = QSequence (*)(Ts&,QSequence&&) ;
template<typename T> using QValFunction = QValueEnd(*)(T &,QValue &&) ;
template<class Ts> using QSeqFunction = QSequence(*)(Ts&,QSequence&&) ;
#endif
/**/ using QValLambda = std::function<QValueStatus(QValue &&)>;
/**/ using QSeqLambda = std::function<QSequence (QSequence&&)>;
/**/ using QValLambda = std::function<QValueEnd(QValue &&)>;
/**/ using QSeqLambda = std::function<QSequence(QSequence&&)>;
template<class T_> class QVal
{
......@@ -354,8 +357,8 @@ public:
template<typename T> T_ bind(T& t, T&& defaultT) { return outer->tryBind(QDefaultValue<T>{t,defaultT}) ? std::move(outer) : T_(); }
// Custom bind support
/**/ T_ with( QValLambda customBind) { return customBind( std::move(unsafeThis())) ? std::move(outer) : T_(); }
template<typename T> T_ with(T& t, QValFunction<T> customBind) { return customBind(t, std::move(unsafeThis())) ? std::move(outer) : T_(); }
/**/ T_ with( QValLambda customBind) { return customBind( std::move(unsafeThis())).isValid ? std::move(outer) : T_(); }
template<typename T> T_ with(T& t, QValFunction<T> customBind) { return customBind(t, std::move(unsafeThis())).isValid ? std::move(outer) : T_(); }
// Literal metadata support
QVal<T_> meta(const char* n, const char* m) { return meta(QIdentifierLiteral(n),QAsciiData(m)); }
......@@ -385,7 +388,7 @@ public:
explicit operator bool() const noexcept { return outer.operator bool(); } //!< Drives QTransmogrifier<T>::bind() traversal
QValueStatus* operator->() noexcept { return outer.operator ->(); }
operator QValueStatus() { return out(); /* calls T_::operator QValueStatus() if T_ != QValueStatus */ }
operator QValueEnd() { return out(); /* calls T_::operator QValueEnd() if T_ != QValueEnd */ }
/**/ T_ out() { return outer-> tryOut() ? std::move(outer) : T_ (); }
QVal<QSeq<T_>> item() { return outer->tryItem() ? QVal<QSeq<T_>>(std::move(*this)) : QVal<QSeq<T_>>(); }
......@@ -430,7 +433,7 @@ public:
explicit operator bool() const noexcept { return outer.operator bool(); } //!< Drives QTransmogrifier<T>::bind() traversal
QValueStatus* operator->() noexcept { return outer.operator ->(); }
operator QValueStatus() { return out(); /* calls T_::operator QValueStatus() if T_ != QValueStatus */ }
operator QValueEnd() { return out(); /* calls T_::operator QValueEnd() if T_ != QValueEnd */ }
/**/ T_ out ( ) { return outer->tryOut ( ) ? std::move(outer) : T_ (); }
QVal<QRec<T_>> item(QIdentifier& n) { return outer->tryItem( n ) ? QVal<QRec<T_>>(std::move(*this)) : QVal<QRec<T_>>(); }
......@@ -475,13 +478,13 @@ private:
//!
template<typename T, typename TEnabledIf=void>
struct QTransmogrifier {
static QValueStatus zap(QValue&& value, T& t) { return t .zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,T&)
static QValueStatus zap(QValue&& value,const T& t) { return const_cast<T&>(t).zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,const T&)
static QValueStatus zap(QValue&& value, T&& t) { return t .zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,T&&)
static QValueEnd zap(QValue&& value, T& t) { return t .zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,T&)
static QValueEnd zap(QValue&& value,const T& t) { return const_cast<T&>(t).zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,const T&)
static QValueEnd zap(QValue&& value, T&& t) { return t .zap(std::move(value)); } // In case of error, define a T::bind(QValue) method or external QTransmogrifier<T>::bind(QValue,T&&)
};
template<class T>
bool QValueStatus::tryBind(BindGeneric, T&& t) { return bool(QTransmogrifier<RemoveCvRef<T>>::zap(QValue(_unsafeCopy()),std::forward<T>(t))); }
bool QValueStatus::tryBind(BindGeneric, T&& t) { return QTransmogrifier<RemoveCvRef<T>>::zap(QValue(_unsafeCopy()),std::forward<T>(t)).isValid; }
// //////////////////////////////////////////////////////////////////////////
// Base QAbstractValue implementations for Read and Write QValueMode
......@@ -806,7 +809,7 @@ public:
template<typename T> QBindable(T& t) : f(/*captured T ref */[&t] (QValue&& v) { return v.bind(t); } ) {}
template<typename T> QBindable(T&& t) : f(/*captured T copy*/[ t] (QValue&& v) { return v.bind(t); } ) {}
QValueStatus zap(QValue&& v) { return f(std::move(v)); }
QValueEnd zap(QValue&& v) { return f(std::move(v)); }
};
// //////////////////////////////////////////////////////////////////////////
......@@ -852,7 +855,7 @@ QSeq<T_> QSeq<T_>::forEach(Ts& ts,
// For Q_DEFINE_ZAP_WITH_METAOBJECT below
template<class T>
QValueStatus qMetaZap(QValue&& v, T* t) {
QValueEnd qMetaZap(QValue&& v, T* t) {
auto rw = v->mode();
auto mo = T::staticMetaObject;
auto r = v.meta(qmName,QAsciiData(mo.className())).record();
......@@ -923,11 +926,11 @@ QValueStatus qMetaZap(QValue&& v, T* t) {
}
//! Default bind(QValue&&) based on static QMetaObject reflection
#define Q_DEFINE_ZAP_WITH_METAOBJECT(Class) QValueStatus zap(QValue&& v) { return qMetaZap<Class>(std::move(v), this); }
#define Q_DEFINE_ZAP_WITH_METAOBJECT(Class) QValueEnd zap(QValue&& v) { return qMetaZap<Class>(std::move(v), this); }
template<typename T>
struct QTransmogrifier<QDefaultValue<T>> {
static QValueStatus zap(QValue&& v, QDefaultValue<T>&& t) {
static QValueEnd zap(QValue&& v, QDefaultValue<T>&& t) {
if (v->mode()!=Read) {
return v.bind(t.value);
} else {
......@@ -945,10 +948,10 @@ struct QTransmogrifier<QDefaultValue<T>> {
template<typename T>
struct QTransmogrifier<T, typename std::enable_if<std::is_unsigned<T>::value && std::is_integral<T>::value && !std::is_same<T,bool>::value>::type> {
static QValueStatus zap(QValue&& v, T&& t) {
static QValueEnd zap(QValue&& v, T&& t) {
return v.bind(quint64(t));
}
static QValueStatus zap(QValue&& v, T& t) {
static QValueEnd zap(QValue&& v, T& t) {
if (v->mode()==Write) {
return bind(std::move(v),T(t));
}
......@@ -960,10 +963,10 @@ struct QTransmogrifier<T, typename std::enable_if<std::is_unsigned<T>::value &&
};
template<typename T>
struct QTransmogrifier<T, typename std::enable_if<std::is_signed<T>::value && std::is_integral<T>::value && !std::is_same<T,bool>::value>::type> {
static QValueStatus zap(QValue&& v, T&& t) {
static QValueEnd zap(QValue&& v, T&& t) {
return v.bind(qint64(t));
}
static QValueStatus zap(QValue&& v, T& t) {
static QValueEnd zap(QValue&& v, T& t) {
if (v->mode()==Write) {
return bind(std::move(v),T(t));
}
......@@ -978,7 +981,7 @@ struct QTransmogrifier<T, typename std::enable_if<std::is_signed<T>::value && st
template<typename T, unsigned Size>
struct QTransmogrifier<T[Size]> {
static QValueStatus zap(QValue&& v, T(& ts)[Size]) {
static QValueEnd zap(QValue&& v, T(& ts)[Size]) {
if (v->mode()==Write) {
quint32 size=Size;
auto s(v.sequence(&size));
......@@ -1008,7 +1011,7 @@ struct QTransmogrifier<T[Size]> {
template<typename T>
struct QTransmogrifier<QVector<T>> {
static QValueStatus zap(QValue&& v, QVector<T>&& ts) {
static QValueEnd zap(QValue&& v, QVector<T>&& ts) {
if (v->mode()==Write) {
quint32 size=ts.size();
auto s(v.sequence(&size));
......@@ -1019,7 +1022,7 @@ struct QTransmogrifier<QVector<T>> {
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QVector<T>& ts) {
static QValueEnd zap(QValue&& v, QVector<T>& ts) {
if (v->mode()==Write) {
quint32 size=ts.size();
auto s(v.sequence(&size));
......@@ -1054,7 +1057,7 @@ struct QTransmogrifier<QVector<T>> {
template<typename T>
struct QTransmogrifier<QList<T>> {
static QValueStatus zap(QValue&& v, QList<T>&& ts) {
static QValueEnd zap(QValue&& v, QList<T>&& ts) {
if (v->mode()==Write) {
quint32 size=quint32(ts.size());
auto s(v.sequence(&size));
......@@ -1065,7 +1068,7 @@ struct QTransmogrifier<QList<T>> {
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QList<T>& ts) {
static QValueEnd zap(QValue&& v, QList<T>& ts) {
if (v->mode()==Write) {
quint32 size=quint32(ts.size());
auto s(v.sequence(&size));
......@@ -1101,7 +1104,7 @@ struct QTransmogrifier<QList<T>> {
template<typename T>
struct QTransmogrifier<QMap<QString,T>> {
static QValueStatus zap(QValue&& v, QMap<QString,T>&& ts) {
static QValueEnd zap(QValue&& v, QMap<QString,T>&& ts) {
if (v->mode()==Write) {
quint32 size=quint32(ts.size());
auto s(v.record(&size));
......@@ -1112,7 +1115,7 @@ struct QTransmogrifier<QMap<QString,T>> {
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.any(); }
}
static QValueStatus zap(QValue&& v, QMap<QString,T>& ts) {
static QValueEnd zap(QValue&& v, QMap<QString,T>& ts) {
if (v->mode()==Write) {
quint32 size=quint32(ts.size());
auto s(v.record(&size));
......@@ -1140,7 +1143,7 @@ struct QTransmogrifier<QMap<QString,T>> {
template<> //!< \remark Enumerating types where BindSupport<_> = BindNative with C++11 seems hard, so we just handle the set of default QAbstractValue BindNative types
struct QTransmogrifier<QValue> {
static QValueStatus zap(QValue&& src, QValue&& dst) {
static QValueEnd zap(QValue&& src, QValue&& dst) {
if (src->mode()==Read && dst->mode()==Write) {
QValueStatus srcRes;
auto suspended = src->setErrorHandler();
......@@ -1196,7 +1199,7 @@ struct QTransmogrifier<QValue> {
else if (src->mode()==Write && dst->mode()==Read) { return zap(std::move(dst),std::move(src)); } // To return reader's QValueStatus instead of writer's QValueStatus since it should contain more information (mismatches, etc.)
else { Q_ASSERT_X(!src || !dst, Q_FUNC_INFO, "Unsupported src->mode() and dst->mode()"); return src.null(); }
}
static QValueStatus zap(QValue&& v1, QValue& v2) {
static QValueEnd zap(QValue&& v1, QValue& v2) {
return zap(std::move(v1),std::move(v2));
}
};
......@@ -99,7 +99,7 @@ struct Person
{
QString firstName, lastName; double height; int age; QVector<QString> phones; QString comments; QList<Person> children;
QValueStatus zap(QValue&& value) { // works with value->mode()==Read as well as Write
QValueEnd zap(QValue&& value) { // works with value->mode()==Read as well as Write
return value
.record("Person") // aggregates a usually small number of named items in any order (Person is an optional meta-name for the record that may be ignored)
.sequence("names") // aggregates any number of items in a fixed order, just to illustrate a basic mapping between struct Person and a more general data schema
......@@ -247,8 +247,8 @@ Each specialization must implement at least the bind() method for lvalue referen
references to support temporaries, and for const lvalue reference to efficiently support copyable types.
```cpp
template<> struct QTransmogrifier<QColor> {
static QValueStatus zap(QValue&& v, QColor&& c) { QColor copy(c); return bind(std::move(v),copy); } // supports writing temporaries and const QColor&
static QValueStatus zap(QValue&& v, QColor& c) {
static QValueEnd zap(QValue&& v, QColor&& c) { QColor copy(c); return bind(std::move(v),copy); } // supports writing temporaries and const QColor&
static QValueEnd zap(QValue&& v, QColor& c) {
if (!c.isValid()) {
return v.null();
}
......
......@@ -84,7 +84,7 @@ struct Person
{
int id; QString firstName, lastName; double height; int age; QVector<Phone> phones; QString comments; QList<Person> children;
QValueStatus zap(QValue&& value) { // works with value->mode()==Read as well as Write
QValueEnd zap(QValue&& value) { // works with value->mode()==Read as well as Write
return value
.record("Person")
.sequence("names")
......@@ -137,7 +137,7 @@ struct PersonsView
{
QList<Person>& persons;
QValueStatus zap(QValue&& value) {
QValueEnd zap(QValue&& value) {
return value
.meta(qmChildren,"children")
.meta(qmColumns ,"names,height,age,phones,comments") // to optimize multi-dimensional data formats
......@@ -151,7 +151,7 @@ struct PersonsTable {
QList<Person>& persons;
PersonsTable(QList<Person>& ps) : persons(ps) {}
QValueStatus zap(QValue&& v) {
QValueEnd zap(QValue&& v) {
if (v->mode()==Read) {
ids.clear();
orphans.clear();
......@@ -254,11 +254,11 @@ private:
//! QTransmogrifier<QColor> with special support for QDataStream compatibility using meta()
template<>
struct QTransmogrifier<QColor> {
static QValueStatus zap(QValue&& v, QColor&& c) {
static QValueEnd zap(QValue&& v, QColor&& c) {
QColor copy(c);
return zap(std::move(v),copy);
}
static QValueStatus zap(QValue&& v, QColor& c) {
static QValueEnd zap(QValue&& v, QColor& c) {
if (!c.isValid()) {
return v.null();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment