Commit 79abcda4 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

Fixed QJsonReader cachelevel

More precise null handling including qBindExpectedValue for values that
are not null and not among the expecte values (say a QVariant other than
list/map and basic types...)
parent 51dab6dc
......@@ -294,10 +294,10 @@ protected:
skipTag(); if (isArray () && enterContainer()) { levels.push(Level()); return true; } handleError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* s=nullptr) { if (caching) { cacheLevel++; return caching->tryRecord(s); }
skipTag(); if (isMap () && enterContainer()) { levels.push(Level()); return true; } handleError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (caching) { cacheLevel++; return caching->tryNull() && cacheOut(); }
skipTag(); if (isNull () && next ()) { return true; } handleError(qBindExpectedNull ); return false; }
bool tryNull ( ) { if (caching) { return caching->tryNull() && cacheOut(); }
skipTag(); if ((isNull() || isUndefined()) && next()) { return true; } handleError(qBindExpectedNull); return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s)) { u = s.toUtf8(); return true; } return false; }
bool tryBind ( QString& s) { if (caching) { cacheLevel++; return caching->tryBind(s) && cacheOut(); }
bool tryBind ( QString& s) { if (caching) { return caching->tryBind(s) && cacheOut(); }
skipTag(); if (isString()) {
s.resize(0);
auto r = readString();
......@@ -313,7 +313,7 @@ protected:
}
return true;
} else { handleError(qBindExpectedText); return false; } }
bool tryBind ( QByteArray& s) { if (caching) { cacheLevel++; return caching->tryBind(s) && cacheOut(); }
bool tryBind ( QByteArray& s) { if (caching) { return caching->tryBind(s) && cacheOut(); }
skipTag(); if (isByteArray()) {
s.resize(0);
auto r = readByteArray();
......@@ -329,12 +329,12 @@ protected:
}
return true;
} else { handleError(qBindExpectedBytes); return false; } }
bool tryBind ( bool& b) { if (caching) { cacheLevel++; return caching->tryBind(b) && cacheOut(); }
bool tryBind ( bool& b) { if (caching) { return caching->tryBind(b) && cacheOut(); }
skipTag(); if (isBool()) {
b=toBool();
return next();
} else { handleError(qBindExpectedBoolean); return false; } }
bool tryBind ( double& n) { if (caching) { cacheLevel++; return caching->tryBind(n) && cacheOut(); }
bool tryBind ( double& n) { if (caching) { return caching->tryBind(n) && cacheOut(); }
return getNumber(n); }
bool tryBind ( float& n) { double d;
if (!tryBind(d)) { return false; }
......@@ -342,12 +342,12 @@ protected:
double(std::numeric_limits<float>::max()) <d) { handleError(qBindExpectedSmallerNumber); return false; }
n=float(d); return true; }
bool tryBind ( quint64& t) { if (caching) { cacheLevel++; return caching->tryBind(t) && cacheOut(); }
bool tryBind ( quint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
quint64 i; bool neg;
if (!getInteger(i,neg)) { handleError(qBindExpectedInteger ); return false; }
if ( neg ) { handleError(qBindExpectedPositiveInteger); return false; }
t=i; return true; }
bool tryBind ( qint64& t) { if (caching) { cacheLevel++; return caching->tryBind(t) && cacheOut(); }
bool tryBind ( qint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
quint64 i; bool neg;
if (!getInteger(i,neg)) { handleError(qBindExpectedInteger ); return false; }
if ( neg ) { if (quint64(-std::numeric_limits<qint64>::min())<i) { handleError(qBindExpectedSmallerNumber); return false; } t=-qint64(i); return true; }
......@@ -409,7 +409,7 @@ protected:
return false;
}
return true; }
bool tryOut ( ) { if (caching) { return caching->tryOut() && cacheOut(); }
bool tryOut ( ) { if (caching) { bool out = caching->tryOut(); if (out) { --cacheLevel; cacheOut(); } return out; }
levels.pop();
while (hasNext()) {
tryAny();
......@@ -433,9 +433,8 @@ private:
handleError(qBindExpectedInteger); return false;
}
bool cacheOut() { Q_ASSERT(cacheLevel);
if (!--cacheLevel) {
caching=nullptr;
bool cacheOut() { if (!cacheLevel) {
caching = nullptr;
if (!device()->isSequential()) {
device()->seek(cachingAfter);
}
......@@ -471,7 +470,8 @@ struct QTransmogrifier<QCborValue> {
if (j.isDouble ()) return v.bind(j.toDouble ());
if (j.isString ()) return v.bind(j.toString ());
if (j.isByteArray()) return v.bind(j.toByteArray());
return v.null();
if (j.isNull() || j.isUndefined() || j.isInvalid() || v->handleError(qBindExpectedValue)) return v.null();
return QValueStatus();
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
......@@ -491,9 +491,9 @@ struct QTransmogrifier<QCborValue> {
j = QCborValue(double(u)); v->setErrorHandler(suspended); return r; }
double d; if ((r = v.bind(d))) { j = QCborValue( d ); v->setErrorHandler(suspended); return r; }
QByteArray y; if ((r = v.bind(y))) { j = QCborValue( y ); v->setErrorHandler(suspended); return r; }
/**/ if ((r = v.null( ))) { j = QCborValue( ); v->setErrorHandler(suspended); return r; }
r = v.null();
v->setErrorHandler(suspended);
v->handleError(qBindIgnoredItem);
if (r || v->handleError(qBindExpectedValue)) { j = QCborValue(); }
return r;
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
......
......@@ -120,7 +120,7 @@ public:
protected:
bool trySequence(quint32* =nullptr) { if (current().isArray ()) { steps.push(Step()); return true; } handleError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (current().isObject()) { steps.push(Step()); return true; } handleError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current().isNull ()) { return true; } handleError(qBindExpectedNull ); return false; }
bool tryNull ( ) { if (current().isNull() || current().isUndefined()) { return true; } handleError(qBindExpectedNull ); return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s) ) { u = s .toUtf8 (); return true; } return false; }
bool tryBind ( QString& v) { if (current().isString()) { v = current().toString(); return true; } handleError(qBindExpectedText ); return false; }
bool tryBind ( bool& v) { if (current().isBool ()) { v = current().toBool (); return true; } handleError(qBindExpectedBoolean ); return false; }
......@@ -251,14 +251,14 @@ protected:
if (get('[', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"]")); return true; } handleError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* s=nullptr) { if (caching) { cacheLevel++; return caching->tryRecord(s); }
if (get('{', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"}")); return true; } handleError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (caching) { cacheLevel++; return caching->tryNull() && cacheOut(); }
bool tryNull ( ) { if (caching) { return caching->tryNull() && cacheOut(); }
if (get('n', "[{\"ntf-0123456789.") &&
get('u', "[{\"" ) &&
get('l', "[{\"" ) &&
get('l', "[{\"" )) {
get('u', ",}]") &&
get('l', ",}]") &&
get('l', ",}]")) {
return true;
} else { handleError(qBindExpectedNull); return false; } }
bool tryBind ( QUtf8Data& s) { if (caching) { cacheLevel++; return caching->tryBind(s) && cacheOut(); }
bool tryBind ( QUtf8Data& s) { if (caching) { return caching->tryBind(s) && cacheOut(); }
QByteArray u;
if ( get('"', "[{\"ntf-0123456789.")) { u.resize(0); char c;
while ((c=getCharInString()) != '\0' ) { u.append(c); }
......@@ -266,7 +266,7 @@ protected:
return get('"');
} else { handleError(qBindExpectedText); return false; } }
bool tryBind ( QString& s) { QUtf8Data u; if (tryBind(u)) { s = QString(u.utf8()); return true; } return false; }
bool tryBind ( bool& b) { if (caching) { cacheLevel++; return caching->tryBind(bool(b)) && cacheOut(); }
bool tryBind ( bool& b) { if (caching) { return caching->tryBind(b) && cacheOut(); }
if (get('t', "[{\"ntf-0123456789.") &&
get('r', "[{\"" ) &&
get('u', "[{\"" ) &&
......@@ -280,28 +280,28 @@ protected:
get('e', "[{\"" )) { b=false;
return true;
} else { handleError(qBindExpectedBoolean); return false; } }
bool tryBind ( float& n) { if (caching) { cacheLevel++; return caching->tryBind(double(n)) && cacheOut(); }
bool tryBind ( float& n) { if (caching) { return caching->tryBind(n) && cacheOut(); }
if (getNumber()==None) return false; // already reported qBindExpectedDecimal
if (d<double( std::numeric_limits<float >::min())||
double( std::numeric_limits<float >::max())<d) { handleError(qBindExpectedSmallerNumber); return false; }
n = float(d); cachedNumber=None; return true; }
bool tryBind ( double& n) { if (caching) { cacheLevel++; return caching->tryBind(double(n)) && cacheOut(); }
bool tryBind ( double& n) { if (caching) { return caching->tryBind(n) && cacheOut(); }
if (getNumber()==None) return false; // already reported qBindExpectedDecimal
n = d ; cachedNumber=None; return true; }
bool tryBind ( quint64& t) { if (caching) { cacheLevel++; return caching->tryBind(double(t)) && cacheOut(); }
bool tryBind ( quint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
auto r=getNumber();
if (r==None) return false; // already reported qBindExpectedDecimal
if (r==FloatingPoint) { handleError(qBindExpectedInteger); return false; }
if (neg) { handleError(qBindExpectedPositiveInteger); return false; }
t = i ; cachedNumber=None; return true; }
bool tryBind ( qint64& t) { if (caching) { cacheLevel++; return caching->tryBind(double(t)) && cacheOut(); }
bool tryBind ( qint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
auto r=getNumber();
if (r==None) return false; // already reported qBindExpectedDecimal
if (r==FloatingPoint) { handleError(qBindExpectedInteger); return false; }
if (!neg && i<quint64( std::numeric_limits<qint64>::max())) { t = qint64(i); cachedNumber=None; return true; }
if ( neg && i<quint64(-std::numeric_limits<qint64>::min())) { t = -qint64(i); cachedNumber=None; return true; }
handleError(qBindExpectedSmallerNumber ); return false; }
bool tryBind ( QVariant& dst) {
handleError(qBindExpectedSmallerNumber); return false; }
bool tryBind ( QVariant& dst) { if (caching) { return caching->tryBind(dst) && cacheOut(); }
auto suspended = setErrorHandler();
quint32 size=0; QIdentifier key; QVariant item;
......@@ -317,11 +317,11 @@ protected:
dst = QVariant(QString::fromUtf8(s.utf8())) ; return true;
}
setErrorHandler(suspended);
if (!tryNull()) handleError(QIdentifierLiteral("ExpectedOneOfBooleanDecimalBytesTextSequenceRecordNull"));
if (!tryNull()) handleError(qBindExpectedValue);
dst = QVariant(); return true;
}
bool tryOut ( ) { if (caching) { return caching->tryOut() && cacheOut(); }
bool tryOut ( ) { if (caching) { bool out = caching->tryOut(); if (out) { cacheLevel--; cacheOut(); } return out; }
auto level = levels.pop();
while (get(',', level.end)) {
tryAny();
......@@ -372,7 +372,7 @@ protected:
return true; }
bool isValid() const noexcept { return io; }
bool handleError(QIdentifierLiteral e, QString context = QString()) { return errorHandler ? errorHandler(e, QString("at (%1,%2) ").arg(line).arg(column).append(context)) : false; }
bool handleError(QIdentifierLiteral e, QString context = QString()) { return errorHandler ? errorHandler(e, QString("(%1:%2)").arg(line).arg(column).append(context)) : false; }
private:
CachedNumber getNumber() {
if (cachedNumber!=None) return cachedNumber;
......@@ -492,15 +492,16 @@ private:
CachedNumber cachedNumber = None;
double d; quint64 i; bool neg;
bool cacheOut() { Q_ASSERT(cacheLevel);
if (!--cacheLevel) { caching=nullptr; }
bool cacheOut() { if (!cacheLevel) {
caching = nullptr;
}
return true; }
// Read/Write caching of out-of-order item keys
quint8 cacheLevel = 0;
QJsonValue cachedValue ; //!< Only used AFTER --cacheLevel==1
QJsonBuilder cacheWriter ;
QAbstractValue* caching = nullptr; //!< Only used when cacheLevel>=1 && key!=expectedKey
QAbstractValue* caching = nullptr; //!< Only used when cacheLevel>=1 && key!=expectedKey
QJsonVisitor cacheReader ; //!< Only used as caching
};
......@@ -520,7 +521,8 @@ struct QTransmogrifier<QJsonValue> {
if (j.isBool ()) return v.bind(j.toBool ());
if (j.isDouble()) return v.bind(j.toDouble());
if (j.isString()) return v.bind(j.toString());
return v.null();
if (j.isNull() || j.isUndefined() || v->handleError(qBindExpectedValue)) return v.null();
return QValueStatus();
}
else { Q_ASSERT_X(false, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
......@@ -538,9 +540,10 @@ struct QTransmogrifier<QJsonValue> {
qint64 i; if ((r = v.bind(i))) { j = QJsonValue(double(i)); return r; }
quint64 u; if ((r = v.bind(u))) { j = QJsonValue(double(u)); return r; }
double d; if ((r = v.bind(d))) { j = QJsonValue( d ); return r; }
r = v.null();
v->setErrorHandler(suspended);
if (!(r = v.null())) r.handleError(qBindExpectedValue);
/**/ j = QJsonValue( ); return r;
if (r || v->handleError(qBindExpectedValue)) { j = QJsonValue(); };
return r;
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
......
......@@ -595,7 +595,7 @@ protected:
using QAbstractValue::tryBind; // full overload set so that following overloads calls work (instead of calling themselves and overflowing the call stack)
virtual bool tryNull( ) { return hidden() ? true : I<=d ? itemBind()->tryNull() : read().isNull () ; }
virtual bool tryNull( ) { return hidden() ? true : I<=d ? itemBind()->tryNull() : read().isNull () || !read().isValid(); }
virtual bool tryBind( QString&& u) { return hidden() ? true : I<=d ? itemBind()->tryBind(std::move(u)) : u==read().toString() ; }
virtual bool tryBind( bool&& b) { return hidden() ? true : I<=d ? itemBind()->tryBind(std::move(b)) : b==read().toBool () ; }
virtual bool tryBind( float&& f) { return hidden() ? true : I<=d ? itemBind()->tryBind(std::move(f)) : qFuzzyCompare(f,read().toFloat ()); }
......
......@@ -348,12 +348,12 @@ public:
/**/ T_ bind ( QLatin1String l) { return outer->tryBind (l) ? std::move(outer) : T_ (); }
/**/ T_ bind ( QStringView u) { return outer->tryBind (u) ? std::move(outer) : T_ (); }
template<typename T> T_ bind ( T&& t) { return outer->tryBind(std::forward <T>(t )) ? std::move(outer) : T_(); }
template<typename T> T_ bind (T& t, T&& defaultT) { return outer->tryBind(QDefaultValue<T>{t,defaultT}) ? std::move(outer) : T_(); }
template<typename T> T_ bind( T&& t) { return outer->tryBind(std::forward <T>(t )) ? std::move(outer) : T_(); }
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())) ? std::move(outer) : T_(); }
template<typename T> T_ with(T& t, QValFunction<T> customBind) { return customBind(t, std::move(unsafeThis())) ? std::move(outer) : T_(); }
// Literal metadata support
QVal<T_> meta(const char* n, const char* m) { return meta(QIdentifierLiteral(n),QAsciiData(m)); }
......@@ -385,7 +385,7 @@ public:
QValueStatus* operator->() noexcept { return outer.operator ->(); }
operator QValueStatus() { return out(); /* calls T_::operator QValueStatus() if T_ != QValueStatus */ }
/**/ T_ out() { return outer-> tryOut() ? std::move(outer) : T_ (); }
/**/ 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_>>(); }
// Shortcuts
......@@ -574,7 +574,6 @@ struct QAbstractValueWriter : public QAbstractValue
}
return tryOut();
}
if (src.isNull() ) return tryNull();
if (src.userType() // TODO src.type if QUtf8Data becomes a Qt type
==qMetaTypeId<QUtf8Data>()) return tryBind(src.value< QUtf8Data>());
if (src.type()==QVariant::String ) return tryBind(src.value< QString>());
......@@ -605,7 +604,8 @@ struct QAbstractValueWriter : public QAbstractValue
return tryBind(binaryVariant);
}
return tryNull();
if (src.isNull() || !src.isValid() || handleError(qBindExpectedValue)) return tryNull();
return false;
}
virtual bool tryBind( QUtf8Data& r) { QUtf8Data copy(r); return tryBind(std::move(copy)); }
......@@ -846,7 +846,7 @@ QSeq<T_> QSeq<T_>::forEach(Ts& ts,
// For Q_DEFINE_ZAP_WITH_METAOBJECT below
template<class T>
QValueStatus qzap(QValue&& v, T* t) {
QValueStatus qMetaZap(QValue&& v, T* t) {
auto rw = v->mode();
auto mo = T::staticMetaObject;
auto r = v.meta(qmName,QAsciiData(mo.className())).record();
......@@ -876,17 +876,16 @@ QValueStatus qzap(QValue&& v, T* t) {
if (!pv.isValid() && !v->handleError(qBindIgnoredItem)) {
return QValueStatus();
}
else if (!pv.isNull()) {
else {
QIdentifier id(p.name());
auto i = r.item(id);
if (p.isEnumType()) {
if (pv.isValid() && p.isEnumType()) {
pv.convert(QVariant::Int);
i = i.meta(qmName, p.isFlagType() ?
QAsciiData(p.enumerator().valueToKeys(pv.value<int>())) :
QAsciiData(p.enumerator().valueToKey (pv.value<int>())));
}
if (pv.isNull() ) r = i.null();
else if (pv.userType()==qMetaTypeId<QUtf8Data>() // TODO pv.type if QUtf8Data becomes a Qt type
if (pv.userType()==qMetaTypeId<QUtf8Data>() // TODO pv.type if QUtf8Data becomes a Qt type
) r = i.bind(pv.value< QUtf8Data>());
else if (pv.type()==QVariant::String ) r = i.bind(pv.value< QString>());
else if (pv.type()==QVariant::Char ) r = i.bind(pv. toString());
......@@ -907,7 +906,7 @@ QValueStatus qzap(QValue&& v, T* t) {
// See QT_FOR_EACH_STATIC_PRIMITIVE_TYPE in qmetatype.h
else if (pv.canConvert<QVariantList>() ) r = i.bind(pv.value<QVariantList>()); // TODO avoid interim data structure
else if (pv.canConvert<QVariantMap >() ) r = i.bind(pv.value<QVariantMap >()); // TODO avoid interim data structure
else r = i.bind(pv); // FIXME remove one QVariant level as in QAbstractValueWriter::tryBind(QVariant&&)
else if (pv.isNull() || (!pv.isValid() && v->handleError(qBindExpectedValue))) r = i.null();
}
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
......@@ -917,21 +916,23 @@ QValueStatus qzap(QValue&& v, T* t) {
}
//! Default bind(QValue&&) based on static QMetaObject reflection
#define Q_DEFINE_ZAP_WITH_METAOBJECT(Class) QValueStatus zap(QValue&& v) { return qzap<Class>(std::move(v), this); }
#define Q_DEFINE_ZAP_WITH_METAOBJECT(Class) QValueStatus 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) {
if (v->mode()==Read) {
if (v->mode()!=Read) {
return v.bind(t.value);
} else {
auto suspended = v->setErrorHandler();
auto r=v.null();
auto r = v.bind(t.value);
v->setErrorHandler(suspended);
if (r) {
if (!r) {
t.value = t.defaultValue;
return r;
return v.null();
}
return r;
}
return v.bind(t.value);
}
static QValueStatus zap(QValue&& v, QDefaultValue<T>& t) {
return bind(std::move(v),std::move(t));
......@@ -1165,29 +1166,31 @@ struct QTransmogrifier<QValue> {
/**/ dstRec.out();
return srcRec.out();
}
if ( (srcRes = src.null())) {
return dst.null();
}
QUtf8Data u; if ((srcRes = src.bind( u))) { dst.bind( u); return srcRes; } //! \remark QUtf8Data has common valus with QString but is more precise and efficient
QString t; if ((srcRes = src.bind( t))) { dst.bind( t); return srcRes; }
QUtf8Data u; if ((srcRes = src.bind( u))) { dst.bind( u); src->setErrorHandler(suspended); return srcRes; } //! \remark QUtf8Data has common valus with QString but is more precise and efficient
QString t; if ((srcRes = src.bind( t))) { dst.bind( t); src->setErrorHandler(suspended); return srcRes; }
// Explicitely handled types (not value text representation convertible to those types
QByteArray a; if ((srcRes = src.bind( a))) { dst.bind( a); return srcRes; }
bool b; if ((srcRes = src.bind( b))) { dst.bind( b); return srcRes; }
quint8 u8; if ((srcRes = src.bind( u8))) { dst.bind( u8); return srcRes; } //! \remark quint8 has common values with qint8 but is preferred for convenience and static guarantees (no negative values)
qint8 l8; if ((srcRes = src.bind( l8))) { dst.bind( l8); return srcRes; }
quint16 u16; if ((srcRes = src.bind(u16))) { dst.bind(u16); return srcRes; } //! \remark Bigger numeric types can only be handled if QAbstractValue refuses to lose sign or leading digits
qint16 l16; if ((srcRes = src.bind(l16))) { dst.bind(l16); return srcRes; }
quint32 u32; if ((srcRes = src.bind(u32))) { dst.bind(u32); return srcRes; }
qint32 l32; if ((srcRes = src.bind(l32))) { dst.bind(l32); return srcRes; }
quint64 u64; if ((srcRes = src.bind(u64))) { dst.bind(u64); return srcRes; }
qint64 l64; if ((srcRes = src.bind(l64))) { dst.bind(l64); return srcRes; }
float f; if ((srcRes = src.bind( f))) { dst.bind( f); return srcRes; } //! \remark Floating point numeric types can only be handled if QAbstractValue refuses to lose non zero decimals
double d; if ((srcRes = src.bind( d))) { dst.bind( d); return srcRes; } //! \remark Double-precision floating point numeric types can only be handled if QAbstractValue refuses to lose leading digits or precision
QByteArray a; if ((srcRes = src.bind( a))) { dst.bind( a); src->setErrorHandler(suspended); return srcRes; }
bool b; if ((srcRes = src.bind( b))) { dst.bind( b); src->setErrorHandler(suspended); return srcRes; }
quint8 u8; if ((srcRes = src.bind( u8))) { dst.bind( u8); src->setErrorHandler(suspended); return srcRes; } //! \remark quint8 has common values with qint8 but is preferred for convenience and static guarantees (no negative values)
qint8 l8; if ((srcRes = src.bind( l8))) { dst.bind( l8); src->setErrorHandler(suspended); return srcRes; }
quint16 u16; if ((srcRes = src.bind(u16))) { dst.bind(u16); src->setErrorHandler(suspended); return srcRes; } //! \remark Bigger numeric types can only be handled if QAbstractValue refuses to lose sign or leading digits
qint16 l16; if ((srcRes = src.bind(l16))) { dst.bind(l16); src->setErrorHandler(suspended); return srcRes; }
quint32 u32; if ((srcRes = src.bind(u32))) { dst.bind(u32); src->setErrorHandler(suspended); return srcRes; }
qint32 l32; if ((srcRes = src.bind(l32))) { dst.bind(l32); src->setErrorHandler(suspended); return srcRes; }
quint64 u64; if ((srcRes = src.bind(u64))) { dst.bind(u64); src->setErrorHandler(suspended); return srcRes; }
qint64 l64; if ((srcRes = src.bind(l64))) { dst.bind(l64); src->setErrorHandler(suspended); return srcRes; }
float f; if ((srcRes = src.bind( f))) { dst.bind( f); src->setErrorHandler(suspended); return srcRes; } //! \remark Floating point numeric types can only be handled if QAbstractValue refuses to lose non zero decimals
double d; if ((srcRes = src.bind( d))) { dst.bind( d); src->setErrorHandler(suspended); return srcRes; } //! \remark Double-precision floating point numeric types can only be handled if QAbstractValue refuses to lose leading digits or precision
// TODO Other BindNative types we do not want to treat as text: QDateTime, QUuid
src->setErrorHandler(suspended);
srcRes.handleError(qBindExpectedValue);
srcRes = src.null();
if (!srcRes) {
src->setErrorHandler(suspended);
if (src->handleError(qBindExpectedValue)) { dst.null(); }
return QValueStatus();
}
srcRes->setErrorHandler(suspended);
return srcRes;
}
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.)
......
......@@ -168,7 +168,7 @@ protected:
bool trySequence(quint32* =nullptr) { if (current()->type()==QVariant::List ) { levels.push(Level()); return true; } handleError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (current()->type()==QVariant::Map ) { levels.push(Level()); return true; } handleError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current()->isNull() ) { return true; } handleError(qBindExpectedNull ); return false; }
bool tryNull ( ) { if (current()->isNull() || !current()->isValid()) { return true; } handleError(qBindExpectedNull ); return false; }
bool tryItem(QIdentifier& k) { levels.last().key=k; return (levels.last().item = current(1)->toMap ().value(QString(levels.last().key.latin1()), QVariant())).isValid(); }
bool tryItem( ) { levels.last().idx++; return (levels.last().item = current(1)->toList().value( levels.last().idx , QVariant())).isValid(); }
......
......@@ -57,7 +57,7 @@ Bindable |
Bindable>Cbor |bf647479706502666e756d6265726b2b34342031323334353637ff
Bindable>Json |{"type":2,"number":"+44 1234567"}
Person<>Json |================================================================================
Json>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] | at (0,1) IgnoredCharacter, at (0,15) IgnoredCharacter, at (0,23) IgnoredCharacter, at (0,40) IgnoredCharacter
Json>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] | (0:1)IgnoredCharacter, (0:15)IgnoredCharacter, (0:23)IgnoredCharacter, (0:40)IgnoredCharacter, (0:58)IgnoredCharacter, (0:102)IgnoredCharacter
P>Json |{"names":["John","Doe"],"height":1.7500000000000002,"age":-1,"phones":[],"comments":"","children":[]}
Json>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] |
P>JsonValue |{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]}
......
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