...
 
Commits (3)
......@@ -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) {
......
......@@ -43,6 +43,8 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstack.h>
#include <algorithm>
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
......@@ -58,44 +60,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()+1); key+=n ; return true; }
bool trySequenceOut() { settings->setValue(key+"size", pop()); 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 );
int pop() {
auto last=key.lastIndexOf('/')+1;
auto popped=key.midRef(last).toInt();
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;
};
// --------------------------------------------------------------------------
......@@ -104,16 +105,9 @@ class QSettingsReader : public QAbstractValueReader
{
Q_DISABLE_COPY(QSettingsReader)
public:
QSettingsReader(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(qBindExpectedItem)); }
QVariant context() const {
QString path;
for (auto&& l : levels) {
if (l.key.isNull()) { path.append('/').append(QString::number(l.idx)); }
else { path.append('/').append(l.key.latin1()); }
}
return path;
}
QSettingsReader(QSettings* s) : settings(s) { Q_ASSERT(s); allKeys=settings->allKeys(); }
QVariant context() const { return key; }
// Shortcuts
template<typename T> QValueEnd bind(T&& t) { return QCur(this).value().bind(std::forward<T>(t)); }
......@@ -137,28 +131,32 @@ protected:
bool tryBind( float& t) { return set(t); }
bool tryBind( double& t) { return set(t); }
bool trySequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } return false; }
bool tryRecord (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } return false; }
bool trySequence(quint32* =nullptr) { if (key.isEmpty()) return true; if (allKeys.contains(key+"/size")) { key+='/'; return true; } return false; }
bool tryRecord (quint32* =nullptr) { if (key.isEmpty()) return true; if ( keyStartsWith(key+'/' )) { key+='/'; 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 tryNull() { return settings->value(key()).isNull(); }
bool tryItem(QIdentifier& k) { Q_UNUSED(pop() ) key+=k.latin1(); return keyStartsWith(key); }
bool tryItem(QIdentifierLiteral k) { Q_UNUSED(pop() ) key+=k.latin1(); return keyStartsWith(key); }
bool tryItem( ) { auto n=QString::number(pop()+1); auto group=key; key+=n; return settings->value(group+"size").toInt() >= n; }
bool tryItem(QIdentifier& k) { levels.last().key=k ; return true; }
bool tryItem( ) { levels.last().idx++ ; return true; }
bool tryOut ( ) { levels.pop(); settings->endGroup(); return true; }
bool tryOut() { Q_UNUSED(pop()) key.chop(1); return true; }
bool tryAny() { return true; }
bool isValid() const noexcept { return settings; }
private:
template<typename T>
bool set(T& t) { QVariant v = settings->value(key()); if (v.convert(qMetaTypeId<T>())) { t = v.value<T>(); return true; } return false; }
QString key() {
Q_ASSERT(!levels.isEmpty());
return !levels.last().key.isNull()
? QString (levels.last().key.latin1())
: QString::number(levels.last().idx );
bool set(T& t) { QVariant v = settings->value(key); if (v.convert(qMetaTypeId<T>())) { t = v.value<T>(); return true; } return false; }
bool keyStartsWith(const QString& key) { return std::find_if(allKeys.cbegin(), allKeys.cend(), [key](const QString& found) { return found.startsWith(key); }) != allKeys.cend(); }
int pop() {
auto last=key.lastIndexOf('/')+1;
auto popped=key.midRef(last).toInt();
key.truncate(last);
return popped;
}
QSettings* settings;
struct Level { QIdentifier key; int idx=-1; bool isGroup=true; Level(QIdentifier n=QIdentifier(), bool isGroup=true) : key(n), isGroup(isGroup) {} };
QStack<Level> levels;
QStringList allKeys;
QString key;
};
This diff is collapsed.
......@@ -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);
......
......@@ -6,3 +6,10 @@ comments=unicode is likely U+01 \x1 + U+1F \x1f + U+A4 \xa4 U+B0 \xb0 U+D8 \xd8
[names]
1=John
2=Doe
size=2
[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:[] | names /ExpectedItem/-1:UnexpectedItem, /ExpectedItem/-1:UnexpectedEnd, /ExpectedItem: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:[] | names/1:UnexpectedEnd, names:UnexpectedEnd, :UnexpectedValue
P>Settings |QBind