Commit 7f694c3b authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

More precise number handling incl. truncating numbers too large

parent ce08ea2a
......@@ -327,24 +327,31 @@ protected:
return next();
} else { return false; } }
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; }
if (d<double(std::numeric_limits<float>::min()) ) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); n=std::numeric_limits<float>::min(); return true; } // using isErrorFiltered result to return false (allowing user to bind with a larger type) would require a cachedNumber like in JSON
if ( double(std::numeric_limits<float>::max())<d) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); n=std::numeric_limits<float>::max(); return true; }
n=float(d); return true; }
skipTag();
if (isFloat16()) { n = double(toFloat16()); return next(); }
if (isFloat ()) { n = double(toFloat ()); return next(); }
if (isDouble ()) { n = toDouble () ; return next(); }
return false; }
bool tryBind ( float& n) { if (caching) { return caching->tryBind(n) && cacheOut(); }
skipTag();
if (isFloat16()) { n = float(toFloat16()); return next(); }
if (isFloat ()) { n = toFloat () ; return next(); }
if (isDouble ()) {
double d = toDouble();
if (d<std::numeric_limits<float>::min() ) { if (isErrorFiltered(qBindExpectedSmallerNumber)) { n=std::numeric_limits<float>::min(); return next(); } return false; }
if ( std::numeric_limits<float>::max()<d) { if (isErrorFiltered(qBindExpectedSmallerNumber)) { n=std::numeric_limits<float>::max(); return next(); } return false; }
n = d;
return next(); }
return false; }
bool tryBind ( quint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
skipTag();
if (!isUnsignedInteger()) { return false; }
t=toUnsignedInteger(); return true; }
t=toUnsignedInteger(); return next(); }
bool tryBind ( qint64& t) { if (caching) { return caching->tryBind(t) && cacheOut(); }
quint64 i; bool neg;
if (!getInteger(i,neg)) { return false; }
if ( neg && quint64(std::numeric_limits<qint64>::max())+1<i) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); t=std::numeric_limits<qint64>::min(); return true; } // using isErrorFiltered result to return false (allowing user to bind with a larger type) would require a cachedNumber like in JSON
if (!neg && quint64(std::numeric_limits<qint64>::max()) <i) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); t=std::numeric_limits<qint64>::max(); return true; }
t = neg ? -qint64(i) : qint64(i); return true;
}
skipTag();
if (isNegativeInteger()) { quint64 i = quint64(toNegativeInteger()); if (i<=quint64(std::numeric_limits<qint64>::max())+1) { t = -qint64(i); return next(); } else if (isErrorFiltered(qBindExpectedSmallerNumber)) { t=std::numeric_limits<qint64>::min(); return next(); } }
if (isUnsignedInteger()) { quint64 i = toUnsignedInteger() ; if (i<=quint64(std::numeric_limits<qint64>::max()) ) { t = qint64(i); return next(); } else if (isErrorFiltered(qBindExpectedSmallerNumber)) { t=std::numeric_limits<qint64>::max(); return next(); } }
return false; }
bool tryItem( QIdentifierLiteral u) { if (caching) { return caching->tryItem(u); }
QIdentifier s;
......@@ -410,18 +417,6 @@ protected:
QVariant context() const { return currentOffset(); }
private:
void skipTag() { if (isTag()) next(); }
bool getNumber(double& d) { skipTag();
if (isFloat16()) { d = double(toFloat16()); return next(); }
if (isFloat ()) { d = double(toFloat ()); return next(); }
if (isDouble ()) { d = toDouble () ; return next(); }
return false;
}
bool getInteger(quint64&i, bool& isNegative) { skipTag();
if (isNegativeInteger()) { i = quint64(toNegativeInteger()); isNegative = true ; return next(); }
if (isUnsignedInteger()) { i = toUnsignedInteger() ; isNegative = false; return next(); }
return false;
}
bool cacheOut() { if (!cacheLevel) {
caching = nullptr;
if (!device()->isSequential()) {
......
......@@ -806,15 +806,17 @@ struct QAbstractValueReader : public QAbstractValue
else { return false; } return true; }
// TODO Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); n=... return true;
virtual bool tryBind( qint8& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool tryBind( quint8& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool tryBind( qint16& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint16>::min() || std::numeric_limits< qint16>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool tryBind( quint16& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool tryBind( qint32& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint32>::min() || std::numeric_limits< qint32>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool tryBind( quint32& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool tryBind( qint64& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; qint64 v; v=s.utf8().toLongLong (&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal ); return false; }
virtual bool tryBind( quint64& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; quint64 v; v=s.utf8().toULongLong(&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal ); return false; }
virtual bool tryBind( float& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; float v; v=s.utf8().toFloat (&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal ); return false; }
virtual bool tryBind( qint8& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool tryBind( quint8& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool tryBind( qint16& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits<qint16>::min() || std::numeric_limits< qint16>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool tryBind( quint16& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool tryBind( qint32& n) { qint64 l; if (!tryBind(l)) return false; if (l<std::numeric_limits<qint32>::min() || std::numeric_limits< qint32>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool tryBind( quint32& n) { quint64 l; if (!tryBind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { isErrorFiltered(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool tryBind( qint64& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; qint64 v; v=s.utf8().toLongLong (&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal); return false; }
virtual bool tryBind( quint64& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; quint64 v; v=s.utf8().toULongLong(&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal); return false; }
virtual bool tryBind( float& n) { double d; if (!tryBind(d)) return false; if (d<std::numeric_limits< float>::min() ) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); n=std::numeric_limits<float>::min(); return true; } // using isErrorFiltered result to return false (allowing user to bind with a larger type) would require to cached the number read
if ( std::numeric_limits< float>::max()<d) { Q_VERIFY(isErrorFiltered(qBindExpectedSmallerNumber)); n=std::numeric_limits<float>::max(); return true; }
n=float(d); return true; }
virtual bool tryBind( double& n) { QUtf8Data s; if (!tryBind(s)) return false; bool isOk=false; double v; v=s.utf8().toDouble (&isOk); if (isOk) { n=v; return true; } isErrorFiltered(qBindExpectedDecimal ); return false; }
virtual bool tryBind( QByteArray& b) { QUtf8Data s; if (!tryBind(s)) return false; return toByteArray(b, s); }
virtual bool tryBind( QVariant& dst) {
......
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