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

Fixed QJsonReader when expecting numbers

parent 063d80f5
......@@ -73,6 +73,7 @@ static QName qBindExpectedSequence = "Expected sequence" ;
static QName qBindExpectedRecord = "Expected record" ;
static QName qBindExpectedText = "Expected text" ;
static QName qBindExpectedBytes = "Expected bytes" ;
static QName qBindExpectedInteger = "Expected integer" ;
static QName qBindExpectedDecimal = "Expected decimal" ;
static QName qBindExpectedSmallerNumber = "Expected smaller number" ;
static QName qBindExpectedPositiveNumber= "Expected positive number";
......
......@@ -230,7 +230,7 @@ public:
/**/ Seq<Cursor> sequence(quint32* s=nullptr) { return Cursor(this).value().sequence(s); }
template<typename T> Cursor bind ( T&& t) { return Cursor(this).value().bind(std::forward<T>(t)); }
protected:
enum CachedNumber : quint8 { None=0, Double=1, Integer=2 }; //!< To be used as bitwise or combination
enum CachedNumber : quint8 { None=0, Integer, FloatingPoint };
bool _sequence(quint32* s=nullptr) { if (caching) { cacheLevel++; return caching->_sequence(s); }
if (get('[', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"]")); return true; } _reportError(qBindExpectedSequence); return false; }
......@@ -266,15 +266,26 @@ protected:
return true;
} else { _reportError(qBindExpectedBoolean); return false; } }
bool _bind ( float& n) { if (caching) { cacheLevel++; return caching->_bind(double(n)) && cacheOut(); }
if ((getNumber()|Double )==Double ) { if ( d<double( std::numeric_limits<float >::min())||
double( std::numeric_limits<float >::max())<d) { n = float(d); cachedNumber=None; return true; } _reportError(qBindExpectedSmallerNumber ); } return false; }
if (getNumber()==None) return false; // already reported qBindExpectedDecimal
if (d<double( std::numeric_limits<float >::min())||
double( std::numeric_limits<float >::max())<d) { _reportError(qBindExpectedSmallerNumber ); return false; }
n = float(d); cachedNumber=None; return true; }
bool _bind ( double& n) { if (caching) { cacheLevel++; return caching->_bind(double(n)) && cacheOut(); }
if ((getNumber()|Double )==Double ) { n = d ; cachedNumber=None; } return true ; }
if (getNumber()==None) return false; // already reported qBindExpectedDecimal
n = d ; cachedNumber=None; return true; }
bool _bind ( quint64& t) { if (caching) { cacheLevel++; return caching->_bind(double(t)) && cacheOut(); }
if ((getNumber()|Integer)==Integer) { if (!neg ) { t = i ; cachedNumber=None; return true; } _reportError(qBindExpectedPositiveNumber); } return false; }
auto r=getNumber();
if (r==None) return false; // already reported qBindExpectedDecimal
if (r==FloatingPoint) { _reportError(qBindExpectedInteger); return false; }
if (neg) { _reportError(qBindExpectedPositiveNumber); return false; }
t = i ; cachedNumber=None; return true; }
bool _bind ( qint64& t) { if (caching) { cacheLevel++; return caching->_bind(double(t)) && cacheOut(); }
if ((getNumber()|Integer)==Integer) { if (!neg && quint64( std::numeric_limits<qint64>::max())<i) { t = qint64(i); cachedNumber=None; return true; }
if ( neg && quint64(-std::numeric_limits<qint64>::min())<i) { t = -qint64(i); cachedNumber=None; return true; } _reportError(qBindExpectedSmallerNumber ); } return false; }
auto r=getNumber();
if (r==None) return false; // already reported qBindExpectedDecimal
if (r==FloatingPoint) { _reportError(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; }
_reportError(qBindExpectedSmallerNumber ); return false; }
bool cacheOut() { Q_ASSERT(cacheLevel);
if (!--cacheLevel) { caching=nullptr; }
return true; }
......@@ -332,21 +343,21 @@ private:
CachedNumber getNumber() {
if (cachedNumber!=None) return cachedNumber;
neg = get('-', "[{\"0123456789.");
neg = get('-', "[{\"ntf-0123456789.");
qint8 digit;
if ((digit = getDigit()) < 0) {
_reportError(qBindExpectedDecimal);
return None; // do not accept no digit otherwise we may accept an empty mantissa or string!
}
cachedNumber=CachedNumber(quint8(Integer)|Double);
cachedNumber=Integer;
i=0; d=0;
do {// TODO return Double on overflow (precision being limited by the type)
do {// TODO return FloatingPoint on overflow (precision being limited by the type)
i=i*10+quint8(digit); d=d*10+digit;
}
while (0 <= (digit = getDigit())); // accept many leading '0' which is more permissive than JSON
if ( get('.')) {
cachedNumber=Double;
cachedNumber=FloatingPoint;
// roughly
// d = i;
// m_stream >> decimal // except it would eat exponent
......@@ -364,7 +375,7 @@ private:
while (0 <= (digit = getDigit())) {
exponent=exponent*10+digit; // TODO detect overflow
}
// TODO return Double on overflow (precision being limited by the type)
// TODO return FloatingPoint on overflow (precision being limited by the type)
d *=10^(isNegativeExponent ? -exponent : exponent);
}
// TODO if (!next(",]}") {}
......
......@@ -207,6 +207,7 @@ int main(int argc, char *argv[])
QVariant v;
b.open(QIODevice::ReadWrite);
QDataStream d(&b);
/*
GROUP("<builtin")
{
START {
......@@ -486,11 +487,12 @@ int main(int argc, char *argv[])
STOP("Writable>Json",QString::fromUtf8(b.buffer()));
}
GROUP_STOP
*/
GROUP("Read+Write")
{
QBuffer json;
json.open(QIODevice::ReadOnly);
json.buffer() = "_{ \"names\": [ _\"John\" _, \"Doe\"] , \"age\":null, \"height\":_1.75, \"phones\": [ \"+44 1234567\" , \"+44 2345678\" ], \"\":\"superfluous item\" _} ";
json.buffer() = "_{ \"names\": [ _\"John\" _, \"Doe\"] , \"age\"_:_null, \"height\":_1.75, \"phones\": [ \"+44 1234567\" , \"+44 2345678\" ], \"\":\"superfluous item\" _} ";
// 0 22 41 55 70
QJsonValue v;
#if QT_VERSION>=QT_VERSION_CHECK(5,12,0)
......@@ -509,7 +511,7 @@ int main(int argc, char *argv[])
START {
json.seek(0); v = QJsonValue();
QJsonReader r(&json);
r.bind(v); // FIXME
r.bind(v);
jsonReaderErrors = r.errors;
}
STOP("Json>JsonValue",QString::fromUtf8(QJsonDocument(v.toObject()).toJson()+Text(jsonReaderErrors)));
......
Supports Markdown
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