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

Partially renamed as in Qt proposal

parent b59d09c6
This diff is collapsed.
......@@ -25,4 +25,4 @@ QIdentifierLiteral qmChildren ("children" );
QIdentifierLiteral qmName ("name" );
QIdentifierLiteral qmColor ("color" );
Val<Cursor> Cursor::value() noexcept { return Val<Cursor>(std::move(*this)); }
QValue QValueStatus::value() noexcept { return QValue(std::move(*this)); }
This diff is collapsed.
This diff is collapsed.
......@@ -8,10 +8,10 @@ bool AsciiIdentifier::isValid(const char* s, int size)
if (s[i] < 0x20/*' '*/ || 0x7F/*DEL*/ == s[i])
return false;
if (i==0 && (s[i]!='_' && (s[0]<'A' || 'z'<s[0] || ('Z'<s[0] && s[0]<'a'))))
qWarning("Non alphabetic first character may not be supported by IBind");
qWarning("Non alphabetic first character may not be supported by QAbstractValue");
if (i< 0 && (s[i]!='_' && (s[i]<'0' || 'z'<s[i] || ('9'<s[i] && s[i]<'A')
|| ('Z'<s[i] && s[i]<'a'))))
qWarning("Non alphanumeric or underscore character may not be supported by IBind");
qWarning("Non alphanumeric or underscore character may not be supported by QAbstractValue");
}
return true;
}
......
......@@ -52,49 +52,49 @@
// TODO Use QByteArray directly
//! \warning As with QDataStream, QDataWriter and QDataReader must bind compatible C++ data types, and QDataStream ByteOrder, FloatingPointPrecision and Version
//! \remark When not statically known, such information can be transmitted using meta("type",...) although some IBind implementations may not support it
class QDataWriter : public IWriter // allows runtime flexibility but requires QBind<T> in addition to T::operator<<(QDataStream&) and does not warrant QDataStream operators compatibility if QBind<T> ignores qmDataStreamVersion in meta()
//! \remark When not statically known, such information can be transmitted using meta("type",...) although some QAbstractValue implementations may not support it
class QDataWriter : public QAbstractValueWriter // allows runtime flexibility but requires QBind<T> in addition to T::operator<<(QDataStream&) and does not warrant QDataStream operators compatibility if QBind<T> ignores qmDataStreamVersion in meta()
{
Q_DISABLE_COPY(QDataWriter)
public:
QDataWriter(QDataStream* io) : io(io) { Q_ASSERT(io); version = QAsciiData(QByteArray::number(io->version())); }
BindMode mode() const noexcept { return BindMode::Write; }
QValueMode mode() const noexcept { return QValueMode::Write; }
// Shortcuts
Val<Cursor> value ( ) { return Cursor(this).value(); }
Seq<Cursor> sequence(quint32* s=nullptr) { return Cursor(this).value().sequence(s); }
QValue value ( ) { return QValueStatus(this).value(); }
QSeq<QValueStatus> sequence(quint32* s=nullptr) { return QValueStatus(this).value().sequence(s); }
template<typename T> Cursor bind(T&& t) { return Cursor(this).value().bind(std::forward<T>(t)); }
template<typename T> QValueStatus bind(T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
friend class Cursor;
bool _sequence(quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _record (quint32* s=nullptr) { if (s) *io << *s; return true; }
bool _null ( ) { *io << nullptr; return true; }
bool _bind ( QUtf8DataView u) { QByteArray ba = QByteArray::fromRawData(u.data(), u.size()+int(sizeof('\0'))); return static_cast<IBind*>(this)->_bind(ba); }
friend class QValueStatus;
bool trySequence(quint32* s=nullptr) { if (s) *io << *s; return true; }
bool tryRecord (quint32* s=nullptr) { if (s) *io << *s; return true; }
bool tryNull ( ) { *io << nullptr; return true; }
bool tryBind ( QUtf8DataView u) { QByteArray ba = QByteArray::fromRawData(u.data(), u.size()+int(sizeof('\0'))); return static_cast<QAbstractValue*>(this)->tryBind(ba); }
bool _bind ( QUtf8Data&& t) { *io << t.utf8(); return true; }
bool _bind ( QString&& t) { *io << t; return true; }
bool _bind ( bool&& t) { *io << t; return true; }
bool _bind ( qint8&& t) { *io << t; return true; }
bool _bind ( quint8&& t) { *io << t; return true; }
bool _bind ( qint16&& t) { *io << t; return true; }
bool _bind ( quint16&& t) { *io << t; return true; }
bool _bind ( qint32&& t) { *io << t; return true; }
bool _bind ( quint32&& t) { *io << t; return true; }
bool _bind ( qint64&& t) { *io << t; return true; }
bool _bind ( quint64&& t) { *io << t; return true; }
bool _bind ( float&& t) { *io << t; return true; }
bool _bind ( double&& t) { *io << t; return true; }
bool _bind ( QByteArray&& t) { *io << t; return true; }
bool _bind ( QVariant&& t) { *io << t; return true; }
bool tryBind ( QUtf8Data&& t) { *io << t.utf8(); return true; }
bool tryBind ( QString&& t) { *io << t; return true; }
bool tryBind ( bool&& t) { *io << t; return true; }
bool tryBind ( qint8&& t) { *io << t; return true; }
bool tryBind ( quint8&& t) { *io << t; return true; }
bool tryBind ( qint16&& t) { *io << t; return true; }
bool tryBind ( quint16&& t) { *io << t; return true; }
bool tryBind ( qint32&& t) { *io << t; return true; }
bool tryBind ( quint32&& t) { *io << t; return true; }
bool tryBind ( qint64&& t) { *io << t; return true; }
bool tryBind ( quint64&& t) { *io << t; return true; }
bool tryBind ( float&& t) { *io << t; return true; }
bool tryBind ( double&& t) { *io << t; return true; }
bool tryBind ( QByteArray&& t) { *io << t; return true; }
bool tryBind ( QVariant&& t) { *io << t; return true; }
bool _isOk() noexcept { return io && io->status()==QDataStream::Ok; }
bool _out ( ) { return true; }
bool _item( ) { return true; }
bool _item(QIdentifier& ) { return true; } // record keys are implicit, maps should be serialized as a sequence of records with key and value items
bool _item(QIdentifierLiteral) { return true; } // for QBaseWriter
bool tryOut ( ) { return true; }
bool tryItem( ) { return true; }
bool tryItem(QIdentifier& ) { return true; } // record keys are implicit, maps should be serialized as a sequence of records with key and value items
bool tryItem(QIdentifierLiteral) { return true; } // for QBaseWriter
void _meta(QIdentifierLiteral& n, QAsciiData& m) { if (n.isNull()) n=qmDataStreamVersion; if (n == qmDataStreamVersion) m=version; }
private:
......
This diff is collapsed.
This diff is collapsed.
......@@ -48,31 +48,31 @@
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QVariant*> support for the fixed set of QSettingsWriter's BindNative types
class QSettingsWriter : public IWriter
class QSettingsWriter : public QAbstractValueWriter
{
Q_DISABLE_COPY(QSettingsWriter)
public:
QSettingsWriter(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(qBindExpectedItem)); }
// Shortcuts
/**/ Val<Cursor> value ( ) { return Cursor(this).value(); }
/**/ 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)); }
/**/ QValue value ( ) { return QValueStatus(this).value(); }
/**/ QSeq<QValueStatus> sequence(quint32* s=nullptr) { return QValueStatus(this).value().sequence ( s); }
template<typename T> QValueStatus bind ( T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
bool _bind ( quint8&& t) { settings->setValue(key(), int(t) ); return true; }
bool _bind ( quint16&& t) { settings->setValue(key(), int(t) ); return true; }
bool _bind ( quint32&& t) { settings->setValue(key(), int(t) ); return true; }
bool _bind (QUtf8DataView u) { settings->setValue(key(), QString::fromUtf8(u.data(), u.size())); return true; }
bool _bind ( QStringView s) { settings->setValue(key(), s.toString() ); return true; }
bool _bind ( QString&& s) { settings->setValue(key(), s ); return true; }
bool _null ( ) { settings->setValue(key(), QVariant() ); return true; }
bool _sequence(quint32* =nullptr) { settings->beginGroup(key()); levels.push(Level( )); return true; }
bool _record (quint32* =nullptr) { settings->beginGroup(key()); levels.push(Level(qBindExpectedItem)); return true; }
bool _item(QIdentifier& n) { levels.last().key=n; return true; }
bool _item( ) { levels.last().idx++; return true; }
bool _out ( ) { 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 tryNull ( ) { settings->setValue(key(), QVariant() ); return true; }
bool trySequence(quint32* =nullptr) { settings->beginGroup(key()); levels.push(Level( )); return true; }
bool tryRecord (quint32* =nullptr) { settings->beginGroup(key()); levels.push(Level(qBindExpectedItem)); 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; }
private:
QString key() {
Q_ASSERT(!levels.isEmpty());
......@@ -89,14 +89,14 @@ private:
// --------------------------------------------------------------------------
class QSettingsReader : public IReader
class QSettingsReader : public QAbstractValueReader
{
Q_DISABLE_COPY(QSettingsReader)
public:
Q_ENABLE_MOVE(QSettingsReader, std::swap(isChoice, o.isChoice); )
QSettingsReader(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(qBindExpectedItem)); }
struct Error { QIdentifierLiteral error; QAsciiData path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8Data(error.utf8()+' '+path.utf8())); } };
struct Error { QIdentifierLiteral error; QAsciiData path; template<class T> T bind(QVal<T>&& value) { return value.bind(QUtf8Data(error.utf8()+' '+path.utf8())); } };
QVector<Error> errors;
QAsciiData currentPath() {
......@@ -109,34 +109,34 @@ public:
}
// Shortcuts
template<typename T> Cursor bind(T&& t) { return Cursor(this).value().bind(std::forward<T>(t)); }
template<typename T> QValueStatus bind(T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
template<typename T>
bool _bind(T& t) { return set(t, "Expected declared metatype T"); }
bool tryBind(T& t) { return set(t, "Expected declared metatype T"); }
bool _bind(QUtf8Data& t) { return set(t, qBindExpectedText ); }
bool _bind( QString& t) { return set(t, qBindExpectedText ); }
bool _bind( bool& t) { return set(t, qBindExpectedBoolean); }
bool _bind( QByteArray& t) { return set(t, qBindExpectedBytes ); }
bool tryBind(QUtf8Data& t) { return set(t, qBindExpectedText ); }
bool tryBind( QString& t) { return set(t, qBindExpectedText ); }
bool tryBind( bool& t) { return set(t, qBindExpectedBoolean); }
bool tryBind( QByteArray& t) { return set(t, qBindExpectedBytes ); }
// Convert numerical types to strictly larger ones // TODO convert all compatible values
bool _bind( qint8& t) { return set(t, qBindExpectedInteger ); }
bool _bind( qint16& t) { return set(t, qBindExpectedInteger ); }
bool _bind( qint32& t) { return set(t, qBindExpectedInteger ); }
bool _bind( qint64& t) { return set(t, qBindExpectedInteger ); }
bool _bind( quint8& t) { return set(t, qBindExpectedPositiveNumber); }
bool _bind( quint16& t) { return set(t, qBindExpectedPositiveNumber); }
bool _bind( quint32& t) { return set(t, qBindExpectedPositiveNumber); }
bool _bind( quint64& t) { return set(t, qBindExpectedPositiveNumber); }
bool _bind( float& t) { return set(t, qBindExpectedDecimal ); }
bool _bind( double& t) { return set(t, qBindExpectedDecimal ); }
bool _sequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } _reportError(qBindExpectedSequence); return false; }
bool _record (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } _reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (settings->value(key()).isNull()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool _item(QIdentifier& k) { levels.last().key=k ; return true; }
bool _item( ) { levels.last().idx++ ; return true; }
bool _out ( ) { levels.pop(); settings->endGroup(); return true; }
bool tryBind( qint8& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint16& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint32& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint64& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( quint8& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint16& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint32& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint64& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( float& t) { return set(t, qBindExpectedDecimal ); }
bool tryBind( double& t) { return set(t, qBindExpectedDecimal ); }
bool trySequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } _reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (settings->value(key()).isNull()) { return true; } _reportError(qBindExpectedNull ); return false; }
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 _isOk() { return settings; }
void _setChoice(bool v) { isChoice=v; }
......
This diff is collapsed.
......@@ -58,38 +58,38 @@
//! \see https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
//! \note Selecting heterogeneous sequence items reliably can still be made using XPath "*[i]"
//! \note A more explicit encoding variant could add implicit type information as an attribute to enable roundtrips to/from other generic data structures at the expense of space
class QXmlWriter : public IWriter
class QXmlWriter : public QAbstractValueWriter
{
Q_DISABLE_COPY(QXmlWriter)
public:
QXmlWriter(QXmlStreamWriter* io) : io(io) { Q_ASSERT(io); }
BindMode mode() const noexcept { return BindMode::Write; }
QValueMode mode() const noexcept { return QValueMode::Write; }
// Shortcuts
Val<Cursor> value ( ) { return Cursor(this).value(); }
Seq<Cursor> sequence(quint32* s=nullptr) { return Cursor(this).value().sequence(s); }
QValue value ( ) { return QValueStatus(this).value(); }
QSeq<QValueStatus> sequence(quint32* s=nullptr) { return QValueStatus(this).value().sequence(s); }
template<typename T> Cursor bind(T&& t) { return Cursor(this).value().bind(std::forward<T>(t)); }
template<typename T> QValueStatus bind(T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
bool _sequence(quint32* =nullptr) { io->writeStartElement(tag("sequence").latin1()); att(); return true; }
bool _record (quint32* =nullptr) { io->writeStartElement(tag("record" ).latin1()); att(); return true; }
bool _null ( ) { io->writeEmptyElement(tag("null" ).latin1()); att(); return true; }
bool _bind ( QUtf8DataView u) { writeText("string" ,QString::fromUtf8(u.data(), u.size())); return true; }
bool _bind ( QStringView s) { writeText("string" , s.toString() ); return true; }
bool _bind ( QString&& s) { writeText("string" , s ); return true; }
bool _bind ( bool&& b) { writeText("boolean", b ? QStringLiteral("true") : QStringLiteral("false")); return true; }
bool _bind ( qint64&& n) { static QString s; s.setNum( n ); writeText("integer" , s); return true; }
bool _bind ( quint64&& n) { static QString s; s.setNum( n ); writeText("integer" , s); return true; }
bool _bind ( float&& n) { static QString s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); writeText("decimal" , s); return true; } // with specific precision
bool _bind ( double&& n) { static QString s; s.setNum( n ,'g',std::numeric_limits<double>::max_digits10); writeText("decimal" , s); return true; } // with specific precision
bool _bind ( QByteArray&& s) { QString h; h.reserve(s.size()*2+2+1); h.append("0x").append(s.toHex().toUpper()) ; writeText("hexBinary", h); return true; }
bool trySequence(quint32* =nullptr) { io->writeStartElement(tag("sequence").latin1()); att(); return true; }
bool tryRecord (quint32* =nullptr) { io->writeStartElement(tag("record" ).latin1()); att(); return true; }
bool tryNull ( ) { io->writeEmptyElement(tag("null" ).latin1()); att(); return true; }
bool tryBind ( QUtf8DataView u) { writeText("string" ,QString::fromUtf8(u.data(), u.size())); return true; }
bool tryBind ( QStringView s) { writeText("string" , s.toString() ); return true; }
bool tryBind ( QString&& s) { writeText("string" , s ); return true; }
bool tryBind ( bool&& b) { writeText("boolean", b ? QStringLiteral("true") : QStringLiteral("false")); return true; }
bool tryBind ( qint64&& n) { static QString s; s.setNum( n ); writeText("integer" , s); return true; }
bool tryBind ( quint64&& n) { static QString s; s.setNum( n ); writeText("integer" , s); return true; }
bool tryBind ( float&& n) { static QString s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); writeText("decimal" , s); return true; } // with specific precision
bool tryBind ( double&& n) { static QString s; s.setNum( n ,'g',std::numeric_limits<double>::max_digits10); writeText("decimal" , s); return true; } // with specific precision
bool tryBind ( QByteArray&& s) { QString h; h.reserve(s.size()*2+2+1); h.append("0x").append(s.toHex().toUpper()) ; writeText("hexBinary", h); return true; }
bool _isOk() noexcept { return !io->hasError(); }
bool _out ( ) { io->writeEndElement(); return true; }
bool _item( ) { return true; }
bool _item(QIdentifier& n) { name=n; return true; }
bool tryOut ( ) { io->writeEndElement(); return true; }
bool tryItem( ) { return true; }
bool tryItem(QIdentifier& n) { name=n; return true; }
void _meta(QIdentifierLiteral &n, QAsciiData &m);
private:
class Atts : public std::vector<std::pair<QIdentifierLiteral,QAsciiData>>
......
......@@ -15,7 +15,7 @@ allowing to analyse how software is used in the field and diagnose complex issue
> **DISLAIMER:** QBind is not currently unit-tested but provided with a [sample and benchmark](main.cpp).
> Also, the implementation is written in a concise style that supported the multiple refactorings but does not help explaining it.
> This is especially true for the various IBind implementations. The README and [DESIGN](DESIGN.md) documentation should be read
> This is especially true for the various QAbstractValue implementations. The README and [DESIGN](DESIGN.md) documentation should be read
> before trying to understand the implementation.
See:
......@@ -99,7 +99,7 @@ struct Person
{
QString firstName, lastName; double height; int age; QVector<QString> phones; QString comments; QList<Person> children;
Cursor bind(Val<Cursor>&& value) { // works with value->mode()==Read as well as Write
QValueStatus bind(QValue&& value) { // works with value->mode()==Read as well as Write
return value
.record("Person") // aggregates a usually small number of named items in any order (Person is an optional meta-name for the record that may be ignored)
.sequence("names") // aggregates any number of items in a fixed order, just to illustrate a basic mapping between struct Person and a more general data schema
......@@ -109,7 +109,7 @@ struct Person
.bind("height" ,height ) // remember named items such as "names" and "height" may appear in any order in a record()
.bind("age" ,age ,-1) // reads null() or missing values as the default value: -1
.bind("phones" ,phones ) // recursively calls QBind to take care of that part
.bind("comments",comments) // directly calls IBind since it natively supports QString
.bind("comments",comments) // directly calls QAbstractValue since it natively supports QString
.bind("children",children)
; // automagically closes opened record()
}
......@@ -247,12 +247,12 @@ Each specialization must implement at least the bind() method for lvalue referen
references to support temporaries, and for const lvalue reference to efficiently support copyable types.
```cpp
template<> struct QBind<QColor> {
static Cursor bind(Val<Cursor>&& v, QColor&& c) { QColor copy(c); return bind(std::move(v),copy); } // supports writing temporaries and const QColor&
static Cursor bind(Val<Cursor>&& v, QColor& c) {
static QValueStatus bind(QValue&& v, QColor&& c) { QColor copy(c); return bind(std::move(v),copy); } // supports writing temporaries and const QColor&
static QValueStatus bind(QValue&& v, QColor& c) {
if (!c.isValid()) {
return v.null();
}
Rec<Cursor> r = v.record();
QRec<QValueStatus> r = v.record();
switch(c.spec()) {
case QColor::Spec::Rgb : r = r.sequence("RGB" ).bind(c.red ()).bind(c.green ()).bind(c.blue ()); break;
case QColor::Spec::Hsl : r = r.sequence("HSL" ).bind(c.hslHue()).bind(c.hslSaturation()).bind(c.lightness()); break;
......@@ -266,20 +266,20 @@ template<> struct QBind<QColor> {
### Extending QBind to custom formats
Defining a custom format for, say, console output only requires implementing a few `IWriter` abstract methods:
Defining a custom format for, say, console output only requires implementing a few `QAbstractValueWriter` abstract methods:
```cpp
class MyTextWriter : public IWriter
class MyTextWriter : public QAbstractValueWriter
{
//...
protected:
bool _sequence(quint32* =nullptr) { ba->append("[") ; return true; }
bool _record (quint32* =nullptr) { ba->append("[") ; return true; }
bool _null ( ) { return true; }
bool _bind ( const char* u8) { ba->append( u8) ; return true; }
bool _item (QIdentifierLiteral n) { ba->append(" ").append(n).append(":"); return true; }
bool _item ( ) { ba->append(" ") ; return true; }
bool _out ( ) { ba->append("]") ; return true; }
bool trySequence(quint32* =nullptr) { ba->append("[") ; return true; }
bool tryRecord (quint32* =nullptr) { 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; }
//...
};
```
......@@ -292,12 +292,12 @@ MyTextWriter(&ba) << 1.333333333333f << PI << ascii << false << color ;
// [ 1.33333 3.14159 ascii characters are common in QDebug false [ RGB:[ 45 0 186] base:255]
```
Implementing a custom reader requires implementing a few `IReader` methods. This is always more complex because reading
Implementing a custom reader requires implementing a few `QAbstractValueReader` methods. This is always more complex because reading
needs to perform much more checks and may have to report transient errors instead of returning `true` as `MyTextWriter` does.
Both `IWriter` and `IReader` are convenient base classes which implement most of `IBind` interface used by QBind<T> with
Both `QAbstractValueWriter` and `QAbstractValueReader` are convenient base classes which implement most of `QAbstractValue` interface used by QBind<T> with
generic text representations of boolean, numbers, etc.
Since QBind supports Val<_> on the right-hand side, translating between generic data formats or structures is a one-liner:
Since QBind supports QVal<_> on the right-hand side, translating between generic data formats or structures is a one-liner:
```cpp
// baIn = {"names":["John","Doe"],"height":1.7500000000000002,"age":-1,"phones":["+44 1234567","+44 2345678"],"comments":"","children":[]}
QJsonReader(&baIn).bind(QCborWriter(&baOut).value());
......@@ -332,14 +332,14 @@ By convention:
One can also customize binds using ad-hoc std::function like [flatten](tests/QBind/main.cpp#L996) or lambda below (mimicking Python list comprehensions):
```cpp
QStandardItemModel custom;
QModelWriter<>(&custom).sequence().with([&](Seq<Cursor>&& s) {
QModelWriter<>(&custom).sequence().with([&](QSeq<QValueStatus>&& s) {
for (auto&& person : persons) {
s = s.record()
.item("first name")
.meta(qmColor, person.age >= 42 ? "green" : "blue")
.bind(person.firstName)
.item("office phone")
.with([&](Val<Cursor>&& v) {
.with([&](QValue&& v) {
for (auto&& phone : person.phones) {
if (phone._t == Phone::Office) {
return v.bind(phone._n);
......@@ -422,7 +422,7 @@ bf647479706502666e756d6265726b2b34342031323334353637ff
```
> WARNING: The QBind ability to adequately bind C++ types and formats is only limited by the set of natively supported C++ types and
> the support of meta() by each format. `IBind` natively supports QDataStream::operator<<() types and could be extended to include
> the support of meta() by each format. `QAbstractValue` natively supports QDataStream::operator<<() types and could be extended to include
> native types which can have efficient binary representations like QUuid. Alternatively, the fluent interface currently contains an
> optional TImpl parameter that could be used to define another set of natively supported C++ types, or removed to simplify the fluent
> interface.
......
This diff is collapsed.
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