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

Fixed JSON handling of QVariant (not distinguishable from text, so, one

as to read text and only if asked by user type, convert to QVariant)
parent 186694ed
......@@ -614,36 +614,19 @@ struct IReader : public IBind
virtual bool _bind( quint64& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; quint64 v; v=s.toULongLong(&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( float& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; float v; v=s.toFloat (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( double& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; double v; v=s.toDouble (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( QByteArray& b) { QUtf8String s; if (!_bind(s) || !s.startsWith("0x") || s.size()%2==1) return false;
b.reserve((s.size()-2)/2);
auto toHex = [](char a) -> char { return '0'<=a && a<='9' ? a-'0' : 'A'<=a && a<='F' ? a-'A' : 'a'<=a && a<='f' ? a-'a' : -1; };
for (int i=0; i < b.size(); i++) {
char highDigit=toHex(s[2+2*i]), lowDigit=toHex(s[2+2*i+1]);
if (highDigit<0 || lowDigit<0)
return false;
b.append(char(highDigit<<4)+lowDigit);
}
return true;
}
virtual bool _bind( QByteArray& b) { QUtf8String s; if (!_bind(s)) return false; return toByteArray(b, s); }
virtual bool _bind( QVariant& dst) {
_setChoice(true);
quint32 size=0; QUtf8String key; QVariant item;
if (_sequence(&size)) { QVariantList l; while (_item( )) { l.append( _bind(item) ? item : QVariant()); } dst = l; return _out(); }
if (_record (&size)) { QVariantMap l; while (_item(key)) { l.insert(key, _bind(item) ? item : QVariant()); } dst = l; return _out(); }
bool b; if (_bind(b)) { dst = QVariant(b); return true; }
quint64 u; if (_bind(u)) { dst = QVariant(u); return true; }
qint64 l; if (_bind(l)) { dst = QVariant(l); return true; }
double d; if (_bind(d)) { dst = QVariant(d); return true; }
QByteArray binaryVariant; if (_bind(binaryVariant)) {
QVariant v;
QDataStream s(binaryVariant); s >> v;
if (s.status()==QDataStream::Ok) {
dst = v;
return true;
}
}
QString t; if (_bind(t)) { dst = QVariant(t); return true; }
bool b; if (_bind( b)) { dst = QVariant(b); return true; }
quint64 u; if (_bind( u)) { dst = QVariant(u); return true; }
qint64 l; if (_bind( l)) { dst = QVariant(l); return true; }
double d; if (_bind( d)) { dst = QVariant(d); return true; }
QByteArray ba; if (_bind(ba)) { toVariant(dst,ba); return true; }
QString t; if (_bind( t)) { dst = QVariant(t); return true; }
_setChoice(false);
if (!_null()) _reportError("Expected boolean|decimal|bytes|text|sequence|record|null");
/**/ dst = QVariant( ); return true;
......@@ -703,6 +686,27 @@ struct IReader : public IBind
QString s; // matches any type with usually less encoding work than QUtf8String (which only captures efficiently utf-8 whereas QChar easily captures Latin1 in addition to ASCII)
return _bind(s);
}
protected:
bool toByteArray(QByteArray& b, QUtf8String s) {
if (!s.startsWith("0x") || s.size()%2==1) return false;
b.reserve((s.size()-2)/2);
auto toHex = [](char a) -> char { return '0'<=a && a<='9' ? a-'0' : 'A'<=a && a<='F' ? a-'A' : 'a'<=a && a<='f' ? a-'a' : -1; };
for (int i=0; i < b.size(); i++) {
char highDigit=toHex(s[2+2*i]), lowDigit=toHex(s[2+2*i+1]);
if (highDigit<0 || lowDigit<0)
return false;
b.append(char(highDigit<<4)+lowDigit);
}
return true;
}
//! QByteArray may either contain a QVariant serialized by QDataStream or raw bytes
void toVariant(QVariant& v, QByteArray b) {
QDataStream s(b); s >> v;
if (s.status()==QDataStream::Ok) {
return;
}
v = QVariant(b);
}
};
// //////////////////////////////////////////////////////////////////////////
......@@ -755,35 +759,13 @@ TResult qbind(Val<TResult>&& v, T* t) {
if (p.isStored()) {
if (rw==Read) {
QVariant pv;
auto name = p.name();
r = r.bind(name,pv);
int converted = 0;
bool isConverted = false;
if (p.isFlagType()) {
converted = p.enumerator().keysToValue(pv.toString().toUtf8(), &isConverted);
}
else if (p.isEnumType()) {
converted = p.enumerator().keyToValue(pv.toString().toUtf8(), &isConverted);
}
if (isConverted) {
pv = converted;
}
if ((!r && p.isResettable() && !p.resetOnGadget(t) )||
( r && !p.writeOnGadget(t, pv))) {
v->reportError("TODO");
r = r.bind(p.name(),pv);
if ((!r && p.isResettable() && !p.resetOnGadget(t)) || !p.writeOnGadget(t, pv)) {
v->reportError(qBindIgnoredItem);
}
}
if (rw==Write) {
QVariant pv = p.readOnGadget(t);
if (p.isFlagType() /*&& pv.canConvert<int>()*/) {
r = r.bind(p.name(), p.enumerator().valueToKeys(pv.toInt()));
}
else if (p.isEnumType() /*&& pv.canConvert<int>()*/) {
r = r.bind(p.name(), p.enumerator().valueToKey(pv.toInt()));
}
else {
r = r.bind(p.name(), pv);
}
else if (rw==Write) {
r = r.bind(p.name(), p.readOnGadget(t));
}
else { Q_ASSERT_X(!v, Q_FUNC_INFO, "Unsupported v->mode()"); return v.null(); }
}
......
......@@ -292,6 +292,25 @@ protected:
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 _bind ( QVariant& dst) {
_setChoice(true);
quint32 size=0; QUtf8String key; QVariant item;
if ( _sequence(&size)) { _setChoice(false); QVariantList l; while (_item( )) { l.append( _bind(item) ? item : QVariant()); } dst = l; return _out(); }
if ( _record (&size)) { _setChoice(false); QVariantMap l; while (_item(key)) { l.insert(key, _bind(item) ? item : QVariant()); } dst = l; return _out(); }
bool b; if (_bind(b)) { _setChoice(false); dst = QVariant(b ); return true; }
quint64 u; if (_bind(u)) { _setChoice(false); dst = QVariant(u ); return true; } // may fail after consuming integer part
qint64 l; if (_bind(l)) { _setChoice(false); dst = QVariant(l ); return true; } // may fail after consuming integer part
double d; if (_bind(d)) { _setChoice(false); dst = QVariant(d+/*integer part consumed by one of*/u+l); return true; }
QUtf8String s; if (_bind(s)) { _setChoice(false);
QByteArray b;
if ( toByteArray(b, s)) { toVariant(dst, b); return true; }
dst = QVariant(QString::fromUtf8(s)); return true;
}
_setChoice(false);
if (!_null()) _reportError("Expected boolean|decimal|bytes|text|sequence|record|null");
dst = QVariant(); return true;
}
bool _out ( ) { if (caching) { return caching->_out() && cacheOut(); }
auto level = levels.pop();
......
......@@ -633,8 +633,8 @@ int main(int argc, char *argv[])
GROUP("Person<>Json")//====================================================
{
QBuffer json; json.open(QIODevice::ReadOnly);
json.buffer() = "_{ \"names\": [ _\"John\" _, \"Doe\"] , \"age\"_:_null, \"height\":_1.75, \"phones\": [ {\"type\":\"Home\", \"number\":\"+44 1234567\"} , {\"type\":\"Office\", \"number\":\"+44 2345678\"} ], \"\":\"superfluous item\" _} ";
// 0 22 41 55 70
json.buffer() = "_{ \"names\": [ _\"John\" _, \"Doe\"] , \"age\"_:_null, \"height\":_1.75, \"phones\": [ {\"type\":\"Home\",\"number\":\"+44 1234567\"} , {\"type\":\"Office\",\"number\":\"+44 2345678\"} ], \"\":\"superfluous item\" _} ";
// 1 15 23 4042 58 184
Person p;
QBuffer roundtrip; roundtrip.open(QIODevice::ReadWrite);
QJsonValue jv;
......@@ -695,8 +695,8 @@ int main(int argc, char *argv[])
{
QBuffer cbor; cbor.open(QIODevice::ReadOnly);
cbor.buffer() = QByteArray::fromHex(
"A5656E616D657382644A6F686E63446F6563616765F666686569676874F93F006670686F6E6573826B2B343420313233343536376B2B3434203233343536373860707375706572666C756F7573206974656D");
// { "names": [ "John" , "Doe" ],"age":null,"height": 1.75, "phones": [ {"type":"Home","+44 1234567"} , {"type":"Home","+44 2345678"} ], "":"superfluous item" }
"A5656E616D657382644A6F686E63446F6563616765F666686569676874F93F006670686F6E657382A264747970650166E756D6265726B2B34342031323334353637A264747970650266E756D6265726B2B3434203233343536373860707375706572666C756F7573206974656D");
// { "names": [ "John" , "Doe"] , "age":null, "height":1.75, "phones": [ {"type":1,"number":"+44 1234567"} , {"type":2,"number":"+44 2345678"} ], "":"superfluous item" }
Person p;
QBuffer roundtrip; roundtrip.open(QIODevice::ReadWrite);
QJsonValue jv;
......@@ -850,7 +850,6 @@ int main(int argc, char *argv[])
QStandardItemModel matrixModel; QModelWriter<>(&matrixModel,false).meta({{qmSizes ,"4,3"}}).bind(transform);
QDialog dlg;
dlg.setWindowTitle(QString("Support: ")+Text(Phone{ Phone::Office, "+33 123" }));
auto layout = new QHBoxLayout(&dlg); dlg.setLayout(layout);
auto tree = new QTreeView (&dlg); layout->addWidget(tree ); tree ->setModel(& treeModel); for(int i=0; i<treeModel.columnCount(); i++) tree ->resizeColumnToContents(i);
auto table = new QTableView (&dlg); layout->addWidget(table ); table ->setModel(& tableModel); table ->resizeColumnsToContents();
......
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