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 3cb83167 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

QJsonReader caching out-of-order record items

parent a6d449d8
......@@ -64,7 +64,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:
friend class QJsonReader; //!< Calls methods below to cachedItems out-of-order _item(s)
friend class QJsonReader; //!< Calls methods below for out-of-order cachedItems
bool _sequence(quint32* s=nullptr) { Q_UNUSED(s); steps.push(Step(nullptr)); return true; }
bool _record (quint32* s=nullptr) { Q_UNUSED(s); steps.push(Step("" )); return true; }
bool _null ( ) { set(QJsonValue( )); return true; }
......@@ -213,7 +213,7 @@ private:
// --------------------------------------------------------------------------
#include "QVariant_impl.h" // as cached value reader and writer for out-of-order item keys
#include "QVariant_impl.h" // as caching value reader and writer for out-of-order item keys
class QJsonReader : public IReader
{
......@@ -221,7 +221,7 @@ class QJsonReader : public IReader
public:
QJsonReader(QIODevice* io) : io(io), cacheWriter(&cachedValue), cacheReader(&cachedValue) { Q_ASSERT(io); }
struct Step { int index; const char* end; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {} };
struct Step { int index; const char* end; QMap<QUtf8String,QJsonValue/*TODO use QVariant for meta() support*/> cachedItems; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {} };
struct Error { const char* error; int line; int column; int index; template<class T> T bind(Val<T>&& value) { QUtf8String utf8(error); utf8.append(' ').append(QUtf8String::number(line)).append(':').append(QUtf8String::number(column)); return value.bind(utf8.constData()); } };
QVector<Error> errors;
......@@ -230,18 +230,18 @@ 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:
bool _sequence(quint32* s=nullptr) { if (cached) { cacheLevel++; return cached->_sequence(s); }
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; }
bool _record (quint32* s=nullptr) { if (cached) { cacheLevel++; return cached->_record(s); }
bool _record (quint32* s=nullptr) { if (caching) { cacheLevel++; return caching->_record(s); }
if (get('{', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"}")); return true; } _reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (cached) { cacheLevel++; return cached->_null() && cacheOut(); }
bool _null ( ) { if (caching) { cacheLevel++; return caching->_null() && cacheOut(); }
if (get('n', "[{\"ntf-0123456789.") &&
get('u', "[{\"" ) &&
get('l', "[{\"" ) &&
get('l', "[{\"" )) {
return true;
} else { _reportError(qBindExpectedNull); return false; } }
bool _bind ( QUtf8String& s) { if (cached) { cacheLevel++; return cached->_bind(s.constData()) && cacheOut(); }
bool _bind ( QUtf8String& s) { if (caching) { cacheLevel++; return caching->_bind(s.constData()) && cacheOut(); }
QUtf8String u;
if ( get('"', "[{\"ntf-0123456789.")) { u.clear(); char c;
while ((c=getCharInString()) != '\0' ) { u.append(c); }
......@@ -249,7 +249,7 @@ protected:
return get('"');
} else { _reportError(qBindExpectedText); return false; } }
bool _bind ( QString& s) { QUtf8String u; if (_bind(u)) { s = QString::fromUtf8(u); return true; } return false; } // TODO Support user-defined QTextCodec
bool _bind ( bool& b) { if (cached) { cacheLevel++; return cached->_bind(bool(b)) && cacheOut(); }
bool _bind ( bool& b) { if (caching) { cacheLevel++; return caching->_bind(bool(b)) && cacheOut(); }
if (get('t', "[{\"ntf-0123456789.") &&
get('r', "[{\"" ) &&
get('u', "[{\"" ) &&
......@@ -263,61 +263,59 @@ protected:
get('e', "[{\"" )) { b=false;
return true;
} else { _reportError(qBindExpectedBoolean); return false; } }
bool _bind ( float& n) { if (cached) { cacheLevel++; return cached->_bind(double(n)) && cacheOut(); }
bool _bind ( float& n) { if (caching) { cacheLevel++; return caching->_bind(double(n)) && cacheOut(); }
double d; quint64 i; bool neg; bool r=getNumber(d,i,neg); if (r) { if ( d<double( std::numeric_limits<float >::min())||
double( std::numeric_limits<float >::max())<d) { n = float(d); return true; } _reportError(qBindExpectedSmallerNumber ); } return false; }
bool _bind ( double& n) { if (cached) { cacheLevel++; return cached->_bind(double(n)) && cacheOut(); }
bool _bind ( double& n) { if (caching) { cacheLevel++; return caching->_bind(double(n)) && cacheOut(); }
double d; quint64 i; bool neg; bool r=getNumber(d,i,neg); if (r) { n = d ; } return r; }
bool _bind ( quint64& t) { if (cached) { cacheLevel++; return cached->_bind(double(t)) && cacheOut(); }
bool _bind ( quint64& t) { if (caching) { cacheLevel++; return caching->_bind(double(t)) && cacheOut(); }
double d; quint64 i; bool neg; bool r=getNumber(d,i,neg); if (r) { if (!neg ) { t = i ; return true; } _reportError(qBindExpectedPositiveNumber); } return false; }
bool _bind ( qint64& t) { if (cached) { cacheLevel++; return cached->_bind(double(t)) && cacheOut(); }
bool _bind ( qint64& t) { if (caching) { cacheLevel++; return caching->_bind(double(t)) && cacheOut(); }
double d; quint64 i; bool neg; bool r=getNumber(d,i,neg); if (r) { if (!neg && quint64( std::numeric_limits<qint64>::max())<i) { t = qint64(i); return true; }
if ( neg && quint64(-std::numeric_limits<qint64>::min())<i) { t = -qint64(i); return true; } _reportError(qBindExpectedSmallerNumber ); } return false; }
bool cacheOut() { Q_ASSERT(cacheLevel>0);
cacheLevel--;
if (cacheLevel==1) { cached=nullptr; }
if (cacheLevel==0) { cachedItems.clear(); }
bool cacheOut() { Q_ASSERT(cacheLevel);
if (!--cacheLevel) { caching=nullptr; }
return true; }
bool _out ( ) { if (cached) { return cached->_out() && cacheOut(); }
bool _out ( ) { if (caching) { return caching->_out() && cacheOut(); }
auto level = levels.pop();
while (get(',', level.end)) {
_any();
}
return get(*level.end, "}"); }
bool _item( QName u) { if (cached) { return cached->_item(u); }
bool _item( QName u) { if (caching) { return caching->_item(u); }
QUtf8String s;
while (true) {
if (cachedItems.contains(u)) {
cachedValue = cachedItems.take(u);
if (levels.last().cachedItems.contains(u)) { // must be checked before we consume _item(s)
cachedValue = levels.last().cachedItems.take(u);
cacheReader.reset(&cachedValue);
cached = &cacheReader; // let outer Cursor drive QJsonReader depending on bound T
Q_ASSERT(cacheLevel<=1); cacheLevel = 1;
Q_ASSERT(!cacheLevel);
caching = &cacheReader; // let outer Cursor drive QJsonReader depending on bound T
return true;
}
else if (!_item(s)) {
else if (!_item(s)) { // record() end reached
return false;
}
else if (u == s ) {
return true ;
}
else {
else { // read cachedValue using a dedicated Cursor and QBind<Val<Cursor>> accepting value of any 'shape' (outer QBind is specialized on outer T which is not usually generic enough)
cachedValue = QJsonValue();
cacheWriter.reset(&cachedValue);
if (!Cursor(this).value().bind(Cursor(&cacheWriter).value())) return false;
cachedItems.insert(s, cachedValue);
continue; // until error or u==s or
levels.last().cachedItems.insert(s, cachedValue);
continue; // until !_item(s) or u==s
}
}}
bool _item(QUtf8String& k) { if (cached) { return cached->_item(k); }
bool _item(QUtf8String& k) { if (caching) { return caching->_item(k); }
Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
}
level.index++;
return _bind(k) && get(':',level.end); }
bool _item( ) { if (cached) { return cached->_item(); }
bool _item( ) { if (caching) { return caching->_item(); }
Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
......@@ -438,12 +436,10 @@ private:
// Read/Write caching of out-of-order item keys
quint8 cacheLevel = 0;
QMap<QUtf8String,QJsonValue> cachedItems ; //!< Only used if cacheLevel==1
QUtf8String cachedKey ; //!< Only used when cacheLevel==1
QJsonValue cachedValue ; //!< Only used AFTER --cacheLevel==1
IBind* cached = nullptr; //!< Only used when cacheLevel>=1 && key!=expectedKey
QJsonVisitor cacheReader ; //!< Only used as cached
QJsonBuilder cacheWriter ;
IBind* caching = nullptr; //!< Only used when cacheLevel>=1 && key!=expectedKey
QJsonVisitor cacheReader ; //!< Only used as caching
};
// //////////////////////////////////////////////////////////////////////////
......
......@@ -63,6 +63,7 @@ protected:
template<typename T>
bool _bind ( T&& t) { set(QVariant::fromValue(t)); return true; }
bool _bind ( const char* u) { set(QVariant (u)); return true; }
bool _null ( ) { set(QVariant ( )); return true; }
bool _sequence(quint32* =nullptr) { levels.push(Level(nullptr)); return true; }
......
......@@ -207,7 +207,6 @@ int main(int argc, char *argv[])
QVariant v;
b.open(QIODevice::ReadWrite);
QDataStream d(&b);
#if 0
GROUP("<builtin")
{
START {
......@@ -487,7 +486,6 @@ int main(int argc, char *argv[])
STOP("Writable>Json",QString::fromUtf8(b.buffer()));
}
GROUP_STOP
#endif
GROUP("Read+Write")
{
QBuffer json;
......@@ -500,8 +498,6 @@ int main(int argc, char *argv[])
#endif
Person p;
QVector<QJsonReader ::Error> jsonReaderErrors ;
QVector<QJsonVisitor::Error> jsonVisitorErrors;
#if 0
START {
json.seek(0); b.seek(0); b.buffer().clear();
QJsonReader r(&json);
......@@ -516,7 +512,6 @@ int main(int argc, char *argv[])
jsonReaderErrors = r.errors;
}
STOP("Json>JsonValue",QString::fromUtf8(QJsonDocument(v.toObject()).toJson()+Text(jsonReaderErrors)));
#endif
START {
json.seek(0); p = {};
QJsonReader r(&json);
......@@ -524,12 +519,20 @@ int main(int argc, char *argv[])
jsonReaderErrors = r.errors;
}
STOP("Json>T",QString::fromUtf8(Text(p)+Text(jsonReaderErrors)))
#if 0
QBuffer roundtripJson;
roundtripJson.open(QIODevice::ReadWrite);
START {
roundtripJson.seek(0);
QJsonWriter(&roundtripJson).bind(p);
}
STOP("T>Json",QString::fromUtf8(roundtripJson.buffer()))
START {
v = QJsonValue();
QJsonBuilder(&v).bind(p);
}
STOP("T>JsonValue",QString::fromUtf8(QJsonDocument(v.toObject()).toJson()));
QVector<QJsonVisitor::Error> jsonVisitorErrors;
START {
p = {};
QJsonVisitor r(&v);
......@@ -627,10 +630,8 @@ int main(int argc, char *argv[])
QCborWriter(&b).bind(v);
}
STOP("JsonValue>Cbor",QString::fromUtf8(b.buffer().toHex()));
#endif
}
GROUP_STOP
#if 0
{
QVector<Person> persons;
persons << person << person << person;
......@@ -655,6 +656,5 @@ int main(int argc, char *argv[])
QModelWriter(&m).meta({{qmSizes ,"4,4" }}).bind(transform);
}
}
#endif
return (fclose(samples)==0) &/*anyway*/ (fclose(results)==0);
}
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