Commit 0ebc889f authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

Simplified and fixed QSettingsReader

parent a59a4cc1
......@@ -43,6 +43,8 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstack.h>
#include <algorithm>
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
......@@ -80,15 +82,15 @@ protected:
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 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().toInt()); key.chop(1); return true; }
bool tryRecordOut () { Q_UNUSED( pop() ) key.chop(1); 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 pop() {
int pop() {
auto last=key.lastIndexOf('/')+1;
auto popped=key.mid(last);
auto popped=key.midRef(last).toInt();
key.truncate(last);
return popped;
}
......@@ -103,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)); }
......@@ -136,30 +131,32 @@ protected:
bool tryBind( float& t) { return set(t); }
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; } // QSettings is ambiguous as arrays are also groups, so one should always test sequence before record which is unfortunate
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) { 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 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 tryOut () { if (levels.size()<=1) return false; 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; Level(QIdentifier n=QIdentifier()) : key(n) {} };
QStack<Level> levels;
QStringList allKeys;
QString key;
};
[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
size=2
[phones]
size=0
......
......@@ -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 /ExpectedItem:UnexpectedItem, /ExpectedItem:UnexpectedEnd, /ExpectedItem:Stopped, /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
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