Commit a59a4cc1 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

Started to split tryOut in seq/rec variants

Improved QSettingsWriter
parent 2e29e5e7
......@@ -408,10 +408,15 @@ protected:
return false;
}
return true; }
bool tryOut ( ) { if (caching) { bool out = caching->tryOut(); if (out) { --cacheLevel; cacheOut(); } return out; }
levels.pop();
while (hasNext()) { tryAny(); }
return leaveContainer(); }
bool trySequenceOut() { if (caching) { bool out = caching->trySequenceOut(); if (out) { --cacheLevel; cacheOut(); } return out; }
levels.pop();
while (hasNext()) { tryAny(); }
return leaveContainer(); }
bool tryOut () { if (caching) { bool out = caching->tryRecordOut (); if (out) { --cacheLevel; cacheOut(); } return out; }
levels.pop();
while (hasNext()) { tryAny(); }
return leaveContainer(); }
bool isValid() const noexcept { return const_cast<QCborReader*>(this)->lastError()==QCborError::NoError; }
QVariant context() const { return currentOffset(); }
......
......@@ -330,12 +330,19 @@ protected:
return false;
}
bool tryOut ( ) { if (caching) { bool out = caching->tryOut(); if (out) { cacheLevel--; cacheOut(); } return out; }
auto level = levels.pop();
while (get(',', "}]")) {
tryAny();
}
return get(*level.end, "}]"); }
bool trySequenceOut() { if (caching) { bool out = caching->trySequenceOut(); if (out) { cacheLevel--; cacheOut(); } return out; }
auto level = levels.pop();
while (get(',', "}]")) {
tryAny();
}
return get(*level.end, "}]"); }
bool tryOut () { if (caching) { bool out = caching->tryRecordOut (); if (out) { cacheLevel--; cacheOut(); } return out; }
auto level = levels.pop();
while (get(',', "}]")) {
tryAny();
}
return get(*level.end, "}]"); }
bool tryItem(QIdentifierLiteral u) { if (caching) { return caching->tryItem(u); }
QIdentifier s;
while (true) {
......
......@@ -58,44 +58,43 @@ class QSettingsWriter : public QAbstractValueWriter
{
Q_DISABLE_COPY(QSettingsWriter)
public:
QSettingsWriter(QSettings* s) : settings(s) { Q_ASSERT(s); settings->beginGroup("test"); } // FIXME remove extra beginGroup
QSettingsWriter(QSettings* s) : settings(s) { Q_ASSERT(s); }
QVariant context() const { return key; }
// Shortcuts
/**/ QValue value ( ) { return QCur(this).value(); }
/**/ QSequence sequence(quint32* s=nullptr) { return QCur(this).value().sequence(s); }
template<typename T> QValueEnd bind ( T&& t) { return QCur(this).value().bind(std::forward<T>(t)); }
protected:
bool tryBind ( quint8&& t) { settings->setValue(key(), int(t) ); return true; }
bool tryBind ( quint16&& t) { settings->setValue(key(), int(t) ); return true; }
bool tryBind ( quint32&& t) { settings->setValue(key(), int(t) ); return true; }
bool tryBind (QUtf8DataView u) { settings->setValue(key(), QString::fromUtf8(u.data(), u.size())); return true; }
bool tryBind ( QStringView s) { settings->setValue(key(), s.toString() ); return true; }
bool tryBind ( QString&& s) { settings->setValue(key(), s ); return true; }
bool tryAny () { settings->setValue(key(), QVariant() ); return true; }
bool tryNull() { settings->setValue(key(), QVariant::fromValue(nullptr)); return true; }
bool trySequence(quint32* =nullptr) { levels.push(Level( )); settings->beginGroup(key()); return true; } // TODO use beginWriteArray
bool tryRecord (quint32* =nullptr) { levels.push(Level(qBindExpectedItem)); settings->beginGroup(key()); return true; }
bool tryItem(QIdentifier& n) { levels.last().key=n; return true; }
bool tryItem( ) { levels.last().idx++; return true; }
bool tryOut ( ) {
levels.pop();
settings->endGroup();
return true;
}
bool tryBind ( quint8&& t) { settings->setValue(key, int(t) ); return true; }
bool tryBind ( quint16&& t) { settings->setValue(key, int(t) ); return true; }
bool tryBind ( quint32&& t) { settings->setValue(key, int(t) ); return true; }
bool tryBind (QUtf8DataView u) { settings->setValue(key, QString::fromUtf8(u.data(), u.size())); return true; }
bool tryBind ( QStringView s) { settings->setValue(key, s.toString() ); return true; }
bool tryBind ( QString&& s) { settings->setValue(key, s ); return true; }
bool tryAny () { return true; }
bool tryNull() { settings->setValue(key, QVariant::fromValue(nullptr)); return true; }
bool trySequence(quint32* =nullptr) { if (!key.isEmpty()) key+='/'; return true; }
bool tryRecord (quint32* =nullptr) { if (!key.isEmpty()) key+='/'; return true; }
bool tryItem(QIdentifier& n) { Q_UNUSED(pop() ) key+=n.latin1(); return true; }
bool tryItem( ) { auto n=QString::number(pop().toInt()+1); key+=n ; return true; }
bool trySequenceOut() { settings->setValue(key+"size", pop().toInt()); key.chop(1); return true; }
bool tryRecordOut () { Q_UNUSED( pop() ) key.chop(1); return true; }
private:
QString key() {
return levels.size()==0 ? QString("") :
!levels.last().key.isNull()
? QString (levels.last().key.latin1())
: QString::number(levels.last().idx );
QString pop() {
auto last=key.lastIndexOf('/')+1;
auto popped=key.mid(last);
key.truncate(last);
return popped;
}
QSettings* settings;
struct Level { QIdentifier key; quint32 idx=0; Level(QIdentifier k=QIdentifier()) : key(k) {} };
QStack<Level> levels = QStack<Level>(); //!< minimal dynamic context to implement out() and ensure actual building in case QSettingsWriter is abandoned
QString key;
};
// --------------------------------------------------------------------------
......@@ -138,13 +137,13 @@ protected:
bool tryBind( double& t) { return set(t); }
bool trySequence(quint32* =nullptr) { if (settings->allKeys().contains(key()+"/size")) { levels.push(Level( )); return true; } return false; }
bool tryRecord (quint32* =nullptr) { if (settings->allKeys().contains(key()+"/" )) { levels.push(Level(qBindExpectedItem)); return true; } return false; }
bool tryRecord (quint32* =nullptr) { if (settings->allKeys().contains(key()+"/" )) { levels.push(Level(qBindExpectedItem)); return true; } return false; } // QSettings is ambiguous as arrays are also groups, so one should always test sequence before record which is unfortunate
bool tryNull() { return settings->value(key()).isNull(); }
bool tryItem(QIdentifier& k) { levels.last().key=k; return true; }
bool tryItem(QIdentifierLiteral n) { levels.last().key=n; return true; }
bool tryItem( ) { levels.last().idx++; return true; }
bool tryItem(QIdentifier& k) { if (!levels.last().key.isNull() && settings->allKeys().contains( key()+'/'+levels.last().key.latin1())) { levels.last().key=k; return true; } return false; }
bool tryItem(QIdentifierLiteral n) { if (!levels.last().key.isNull() && settings->allKeys().contains( key()+'/'+levels.last().key.latin1())) { levels.last().key=n; return true; } return false; }
bool tryItem( ) { if ( levels.last().key.isNull() && settings->value(key()+"/size").toInt() >= levels.last().idx ) { levels.last().idx++; return true; } return false; }
bool tryOut () { if (levels.size()<=1) return false; levels.pop(); settings->endGroup(); return true; }
......@@ -161,6 +160,6 @@ private:
}
QSettings* settings;
struct Level { QIdentifier key; int idx=-1; bool isGroup=true; Level(QIdentifier n=QIdentifier(), bool isGroup=true) : key(n), isGroup(isGroup) {} };
struct Level { QIdentifier key; int idx=-1; Level(QIdentifier n=QIdentifier()) : key(n) {} };
QStack<Level> levels;
};
......@@ -134,6 +134,9 @@ struct QAbstractValue {
virtual bool tryItem(QIdentifierLiteral n) = 0;
virtual bool tryOut ( ) = 0; //!< End of sequence or record
virtual bool trySequenceOut() { return tryOut(); }
virtual bool tryRecordOut () { return tryOut(); }
virtual bool tryBind( QUtf8DataView u) = 0;
virtual bool tryBind( const char* u) = 0;
virtual bool tryBind( QAsciiDataView a) = 0;
......@@ -325,7 +328,9 @@ protected:
bool tryItem(QIdentifierLiteral n) { return Q_LIKELY(impl) && impl->tryItem(n); }
bool tryItem(QIdentifier& n) { return Q_LIKELY(impl) && impl->tryItem(n); }
bool tryItem( ) { return Q_LIKELY(impl) && impl->tryItem( ); }
bool tryOut ( ) { return Q_LIKELY(impl) && impl->tryOut ( ); }
bool trySequenceOut() { return Q_LIKELY(impl) && impl->trySequenceOut(); }
bool tryRecordOut () { return Q_LIKELY(impl) && impl->tryRecordOut (); }
template<typename T> bool tryBind(T&& t);
private:
......@@ -485,7 +490,7 @@ public:
~QSeq() {
if (isValid() &&
outer->isErrorFiltered(qBindUnexpectedEnd) &&
!outer->tryOut()) {
!outer->trySequenceOut()) {
outer->stop();
}
}
......@@ -494,7 +499,7 @@ public:
bool isValid() const noexcept { return outer.isValid(); } //!< Drives QTransmogrifier<T>::bind() traversal
QCur* operator->() noexcept { return outer.operator->(); }
T_ out() { return outer->tryOut() ? std::move(outer) : T_(); }
T_ out() { return outer->trySequenceOut() ? std::move(outer) : T_(); }
QVal<QSeq<T_>> item() { return outer->tryItem() ? QVal<QSeq<T_>>(std::move(*this)) : QVal<QSeq<T_>>(); }
......@@ -539,7 +544,7 @@ public:
~QRec() {
if (isValid() &&
outer->isErrorFiltered(qBindUnexpectedEnd) &&
!outer->tryOut()) {
!outer->tryRecordOut()) {
outer->stop();
}
}
......@@ -548,7 +553,7 @@ public:
bool isValid() const noexcept { return outer.isValid(); } //!< Drives QTransmogrifier<T>::bind() traversal
QCur* operator->() noexcept { return outer.operator->(); }
T_ out() { return outer->tryOut() ? std::move(outer) : T_(); }
T_ out() { return outer->tryRecordOut() ? std::move(outer) : T_(); }
QVal<QRec<T_>> item(QIdentifier& n) { return outer->tryItem(n) || (outer->isErrorFiltered(qBindUnexpectedItem, n.latin1()) && false) ? QVal<QRec<T_>>(std::move(*this)) : QVal<QRec<T_>>(); }
QVal<QRec<T_>> item(QIdentifierLiteral n) { return outer->tryItem(n) || (outer->isErrorFiltered(qBindUnexpectedItem, n.latin1()) && false) ? QVal<QRec<T_>>(std::move(*this)) : QVal<QRec<T_>>(); }
......@@ -676,7 +681,7 @@ struct QAbstractValueWriter : public QAbstractValue
return false;
}
}
return tryOut();
return trySequenceOut();
}
if (src.canConvert<QVariantMap >()) { // TODO _meta(qmColumns,"key,value") trySequence() ...
QAssociativeIterable ts = src.value<QAssociativeIterable>();
......@@ -692,7 +697,7 @@ struct QAbstractValueWriter : public QAbstractValue
return false;
}
}
return tryOut();
return tryRecordOut();
}
if (src.userType()
==qMetaTypeId<QUtf8Data>()) return tryBind(src.value< QUtf8Data>());
......@@ -818,8 +823,8 @@ struct QAbstractValueReader : public QAbstractValue
{
QSuspendedValueErrorHandler(this);
quint32 size=0; QIdentifier key; QVariant item;
if (trySequence(&size)) { QVariantList l; while (tryItem( )) { if (!tryBind(item)) { item = QVariant(); if (!(isErrorFiltered(qBindUnexpectedValue) && tryAny())) { stop(); return true; } } l.append( item); } dst = l; return tryOut(); }
if (tryRecord (&size)) { QVariantMap l; while (tryItem(key)) { if (!tryBind(item)) { item = QVariant(); if (!(isErrorFiltered(qBindUnexpectedValue) && tryAny())) { stop(); return true; } } l.insert(key.latin1(), item); } dst = l; return tryOut(); }
if (trySequence(&size)) { QVariantList l; while (tryItem( )) { if (!tryBind(item)) { item = QVariant(); if (!(isErrorFiltered(qBindUnexpectedValue) && tryAny())) { stop(); return true; } } l.append( item); } dst = l; return trySequenceOut(); }
if (tryRecord (&size)) { QVariantMap l; while (tryItem(key)) { if (!tryBind(item)) { item = QVariant(); if (!(isErrorFiltered(qBindUnexpectedValue) && tryAny())) { stop(); return true; } } l.insert(key.latin1(), item); } dst = l; return tryRecordOut (); }
bool b; if (tryBind( b)) { dst = QVariant(b); return true; }
quint64 u; if (tryBind( u)) { dst = QVariant(u); return true; }
qint64 l; if (tryBind( l)) { dst = QVariant(l); return true; }
......@@ -866,8 +871,8 @@ struct QAbstractValueReader : public QAbstractValue
virtual bool tryAny() {
QSuspendedValueErrorHandler(this);
if ( (trySequence() && tryOut())
||(tryRecord () && tryOut())) {
if ( (trySequence() && trySequenceOut())
||(tryRecord () && tryRecordOut ())) {
return true;
}
bool b; // usually easier to check than types below
......
......@@ -273,14 +273,16 @@ class MyTextWriter : public QAbstractValueWriter
//...
protected:
bool trySequence(quint32* =nullptr) { ba->append("[") ; return true; }
bool tryRecord (quint32* =nullptr) { ba->append("[") ; return true; }
bool tryRecord (quint32* =nullptr) { ba->append("{") ; return true; }
bool tryAny ( ) { ba->append("*") ; return true; }
bool tryNull ( ) { return true; }
bool tryBind ( const char* u8) { ba->append( u8) ; return true; }
bool tryItem (QIdentifierLiteral n) { ba->append(" ").append(n).append(":"); return true; }
bool tryItem ( ) { ba->append(" ") ; return true; }
bool tryOut ( ) { ba->append("]") ; return true; }
bool trySequenceOut( ) { ba->append("]") ; return true; }
bool tryRecordOut ( ) { ba->append("}") ; return true; }
//...
};
```
......
......@@ -306,7 +306,7 @@ public:
template<typename T> QValueEnd bind (T&& t) { return QCur(this).value() .bind(std::forward<T>(t)); }
protected:
bool trySequence(quint32* =nullptr) { if (0<level++) utf8->append("["); return true; }
bool tryRecord (quint32* =nullptr) { if (0<level++) utf8->append("["); return true; }
bool tryRecord (quint32* =nullptr) { if (0<level++) utf8->append("{"); return true; }
bool tryAny ( ) { utf8->append("*"); return true; }
bool tryNull ( ) { return true; }
bool tryBind ( QUtf8DataView u) { utf8->append(u.data(), u.size()); return true; }
......@@ -315,7 +315,9 @@ protected:
bool tryItem(QIdentifier& n) { utf8->append(" ").append(n.utf8()).append(":"); return true; }
bool tryItem( ) { utf8->append(" ") ; return true; }
bool tryOut ( ) { if (0<--level) utf8->append("]") ; return true; }
bool trySequenceOut() { if (0<--level) utf8->append("]"); return true; }
bool tryRecordOut () { if (0<--level) utf8->append("}"); return true; }
void _meta(QIdentifierLiteral& n, QAsciiData& m) { if (n==qmName) utf8->append('(').append(m.utf8()).append(")"); }
private:
......@@ -1092,8 +1094,8 @@ int main(int argc, char *argv[])
{
QFileInfo iniFile(QDir::currentPath()+"/../QBind");
QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,iniFile.path());
QSettings ini(QSettings::IniFormat,QSettings::UserScope,"QTransmogrifier","sample");
QSettings nat( QSettings::UserScope,"QTransmogrifier","sample");
QSettings ini(QSettings::IniFormat,QSettings::UserScope,"QBind","sample");
QSettings nat( QSettings::UserScope,"QBind","sample");
//---------------------------------------------------------------------
START {
QSettingsWriter(&nat).bind(person);
......
[names]
1=John
2=Doe
size=2
[General]
height=1.75
age=18
comments=unicode is likely U+01 \x1 + U+1F \x1f + U+A4 \xa4 U+B0 \xb0 U+D8 \xd8 U+FF \xff
[names]
1=John
2=Doe
[phones]
size=0
[children]
size=0
builtin |================================================================================
QDebug |1.33333 3.14159 ascii characters are common in QDebug false QColor(ARGB 1, 0.176471, 0, 0.729412)
Text | 1.33333 3.14159 ascii characters are common in QDebug false [ RGB:[ 45 0 186] base:255]
Text | 1.33333 3.14159 ascii characters are common in QDebug false { RGB:[ 45 0 186] base:255}
Json |[1.33333337,3.1415926535897931,"ascii characters are common in QDebug",false,{"RGB":[45,0,186],"base":255}]
Xml |<sequence><decimal>1.33333337</decimal><decimal>3.1415926535897931</decimal><string>ascii characters are common in QDebug</string><boolean>false</boolean><record><RGB><integer>45</integer><integer>0</integer><integer>186</integer></RGB><base>255</base></record></sequence>
Variant | 1.33333 3.14159 ascii characters are common in QDebug false [ RGB:[ 45 0 186] base:255]
Variant | 1.33333 3.14159 ascii characters are common in QDebug false { RGB:[ 45 0 186] base:255}
Cbor |85fa3faaaaabfb400921fb54442d187825617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567f4bf635247429f182d0018baff646261736518ffff
QCborStream |85fa3faaaaabfb400921fb54442d187825617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567f4bf635247429f182d0018baff646261736518ffff
Data |3ff5555560000000400921fb54442d1800000026617363696920636861726163746572732061726520636f6d6d6f6e20696e20514465627567000001ffff2d2d0000baba0000
......@@ -57,12 +57,12 @@ 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:[] | 0 1:UnexpectedData, 0 15:UnexpectedData, 0 23:UnexpectedData, 0 40:UnexpectedData, 0 58:UnexpectedData, 0 102:UnexpectedData, comments [ 0 102]:UnexpectedItem, 0 102:UnexpectedEnd, 0 103:UnexpectedValue, 0 104:Stopped
P>Json |{"names":["John","Doe"],"height":1.75,"age":-1,"phones":[],"comments":"","children":[]}
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.75,"names":["John","Doe"],"phones":[]}
P>JsonValue |{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]}
JsonValue>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] |
Json>JsonValue|{"age":-1,"children":[],"comments":"","height":1.75,"names":["John","Doe"],"phones":[]} |
JsonValue>Json|{"age":-1,"children":[],"comments":"","height":1.75,"names":["John","Doe"],"phones":[]}
Json>JsonValue|{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]} |
JsonValue>Json|{"age":-1,"children":[],"comments":"","height":1.7500000000000004,"names":["John","Doe"],"phones":[]}
Json>Cbor |bf656e616d65739f644a6f686e63446f65ff66686569676874fa3fe0000063616765206670686f6e65739fff68636f6d6d656e747360686368696c6472656e9fffff
Person-Cbor |================================================================================
Cbor>P |(Person) names:[ John Doe] height:1.75 age:-1 phones:[] comments: children:[] | comments 41:UnexpectedItem, 41:UnexpectedEnd, 58:UnexpectedValue, 58:Stopped
......@@ -76,5 +76,5 @@ CborValue>Cbor|a6656e616d657382644a6f686e63446f6566686569676874fb3ffc00000000000
Cbor>Json |{"names":["John","Doe"],"height":1.75,"age":-1,"phones":[],"comments":"","children":[]} |
Person-Settings|================================================================================
P>Settings |(Person) names:[ John Doe] height:1.75 age:18 phones:[] comments:unicode is likely U+01  + U+1F  + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ children:[]
Settings>P |(Person) names:[ John Doe] height:1.75 age:18 phones:[] comments:unicode is likely U+01  + U+1F  + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ children:[] | /ExpectedItem:ExpectedRecord, /names:ExpectedSequence, /names:ExpectedText, /names:ExpectedText, /names:UnexpectedEnd, /names:Stopped, /names:UnexpectedValue
Settings>P |(Person) names:[ John Doe] height:1.75 age:18 phones:[] comments:unicode is likely U+01  + U+1F  + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ children:[] | /ExpectedItem:ExpectedRecord, names /ExpectedItem:UnexpectedItem, /ExpectedItem:UnexpectedEnd, /ExpectedItem:Stopped, /ExpectedItem:UnexpectedValue
P>Settings |QBind
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