Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

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

Renamed to QTransmogrifier

parent 9e809e33
# Design
The core QBind implementation (excluding QAbstractValue implementations) is a few hundreds line of C++11 using templates defined
The core QTransmogrifier implementation (excluding QAbstractValue implementations) is a few hundreds line of C++11 using templates defined
in the headers, an abstract QAbstractValue class, and QAbstractValueWriter/QAbstractValueReader base classes.
## The key idea
QBind is more general than (de)serialization and should be understood as a generic way to traverse[^1] a C++ dataset and
QTransmogrifier is more general than (de)serialization and should be understood as a generic way to traverse[^1] a C++ dataset and
another generic dataset, binding the related parts together. In effect:
* the traversal may be partial, leaving out unrelated dataset parts (satisfying R2)
* the same traversal may be used to:
......@@ -16,7 +16,7 @@ another generic dataset, binding the related parts together. In effect:
Hence, from now on, we will use the term *bind* instead of the more restricted *(de)serialization* term.
This traversal is driven by QBind<T> methods which may use a QValueMode (Read,Write,...) to determine whether to read the generic dataset or write it according to the C++ one.
This traversal is driven by QTransmogrifier<T> methods which may use a QValueMode (Read,Write,...) to determine whether to read the generic dataset or write it according to the C++ one.
[^1]: *traverse* meaning to go through without returning back
......@@ -24,7 +24,7 @@ QDebug and QDataStream translate all data to a "flat" sequence of characters/byt
be determined for sure by reading the code that produced it. But R1, R2, R3 require that we describe our data in a little bit more
detail. Moreover, W1 and RW2 require that we choose a careful compromise between data format features.
QBind allows binding C++ `data` to a choice of:
QTransmogrifier allows binding C++ `data` to a choice of:
* `sequence` of adjacent `data` `item`s
* `record` of named `data` `item`s
* `null` value (meaning no information available on `data`)
......@@ -34,16 +34,16 @@ QBind allows binding C++ `data` to a choice of:
- numbers (integral/floating-point, unsigned/signed, 8/16/32/64 bits)
- *date/time (TBD)*
- *uuid (TBD)*
* Generically supported T values for which a specialized QBind<T>::bind() is defined
* Generically supported T values for which a specialized QTransmogrifier<T>::bind() is defined
We argue that QBind allows lossless conversions between all supported formats, and that the addition of optional metadata (RW3)
We argue that QTransmogrifier allows lossless conversions between all supported formats, and that the addition of optional metadata (RW3)
can address most peculiarities of the supported formats. However, it may not always conveniently address formats that do not have standard
ways of representing data structures such as XML (e.g. binding the Person type with enough metadata to conform the result to
[xCard schema](https://tools.ietf.org/html/rfc6351) would be cumbersome).
## QBind grammar
## QTransmogrifier grammar
The QBind traversal is formally described by the following recursive automaton:
The QTransmogrifier traversal is formally described by the following recursive automaton:
```mermaid
graph LR
subgraph QVal
......@@ -74,22 +74,22 @@ The automaton is implemented as follows:
- readers may read data not matching the expected transition
- ...
- In case of unsuccessfull transition the returned state type receives a null `QValueStatus` that transparently bypasses calls to `QAbstractValue`
- `bind<T>()` calls are forwarded to the actual `QAbstractValue` or generic `QBind` depending on `BindSupport<T>`:
- `bind<T>()` calls are forwarded to the actual `QAbstractValue` or generic `QTransmogrifier` depending on `BindSupport<T>`:
- BindNative : **QAbstractValue** interface method
- BindGeneric : **QBind** template specialization for T
- BindGeneric : **QTransmogrifier** template specialization for T
- Every `bind<T>()` starts from a QValue which is an un *unsafe* QValueStatus copy wrt well-formedness (these `unsafeItem()` copies are protected from incorrect use)
## C++ types extensibility
QBind is a functor templated on T type receiving a Value and T reference (either lvalue or rvalue reference) and returning the QValueStatus.
QTransmogrifier is a functor templated on T type receiving a Value and T reference (either lvalue or rvalue reference) and returning the QValueStatus.
Template specializations can be defined for any T and optionally refined for specific Cur<TImpl> with different sets of BindNative types.
A default QBind specialization attempts to call `T::bind(...)` to conveniently bind `T* this` without having to understand template syntax,
A default QTransmogrifier specialization attempts to call `T::bind(...)` to conveniently bind `T* this` without having to understand template syntax,
rvalue or forwarding references. Such custom implementations are facilitated by the fluent interface below.
## Convenient fluent interface
A convenient side-effect of encoding the QBind traversal in the type system is that smart C++ editors offer QBind-aware code completion
A convenient side-effect of encoding the QTransmogrifier traversal in the type system is that smart C++ editors offer QTransmogrifier-aware code completion
to the fluent interface making it similar to using an advanced XML editor for typing XML tags. Say, after typing `Value(myImpl).` the
editor will propose to either `bind(myData.item)`, or to construct a `sequence()`, `record()` or `null()` value.
......@@ -120,7 +120,7 @@ optimized and replaced with just the following operations:
[^1]: Experiments to use constexpr to bypass this step for writers that always return true did not seem to improve performance.
`QBind<T>` can define up to 3 bind() overloads to efficiently and conveniently handle lvalue references, const lvalue references, and
`QTransmogrifier<T>` can define up to 3 bind() overloads to efficiently and conveniently handle lvalue references, const lvalue references, and
rvalue references depending on T characteristics (which of copy/move is 1/possible and 2/efficient).
Compared to manually calling non-virtual, format-specific implementations, the overhead of always testing the validity of QAbstractValue*
......@@ -141,7 +141,7 @@ Other than that, write performance depends on several factors:
## Read robustness
Performance is not so important for Read. But compared to manually calling non-virtual, format-specific implementations, QBind
Performance is not so important for Read. But compared to manually calling non-virtual, format-specific implementations, QTransmogrifier
enforces well-formedness checks necessary to reliably read data coming from unknown sources (QAbstractValue implementations being responsible
for low-level checks).
......@@ -160,6 +160,6 @@ native types simplifying again the implementations (see TextWriter example).
QAbstractValueWriter and QAbstractValueReader provide partial QAbstractValue implementations simplifying the work of implementors and offering default textual representations.
*NB:* BindNative types could be extended by specifying BindSupport<T> trait but then, (de)serialization code must be specialized
for each TImpl. For instance, a QBind<QColor,QDataStream> may be implemented differently from QBind<QColor,QAbstractValue> but QBind<QColor>
for each TImpl. For instance, a QTransmogrifier<QColor,QDataStream> may be implemented differently from QTransmogrifier<QColor,QAbstractValue> but QTransmogrifier<QColor>
example shows that meta() can also be used to avoid specialized serialization code that breaks RW2 requirement. If meta() is deemed
enough, the BindSupport trait and TImpl template parameters can be removed.
......@@ -45,17 +45,17 @@ gcc:QMAKE_CXXFLAGS += -ftemplate-backtrace-limit=0
#QMAKE_EXTRA_COMPILERS += protoc
SOURCES += \
QBind.cpp \
QData.cpp \
QValue.cpp \
data.cpp \
main.cpp
HEADERS += \
QBind.h \
QCbor_impl.h \
QData.h \
QJson_impl.h \
QSettings_impl.h \
QValue.h \
QVariant_impl.h \
QModel_impl.h \
QData_impl.h \
......
......@@ -44,7 +44,7 @@
#include <QtCore/qiodevice.h>
#include <QtCore/qendian.h>
#include "QBind.h"
#include "QValue.h"
namespace cbor {
......@@ -98,7 +98,7 @@ enum {
} // cbor
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QCbor*> support
// QTransmogrifier<T,QCbor*> support
class QCborWriter : public QAbstractValueWriter // TODO Support CBOR tags for QAbstractValue BindNative types and multi-dimensional meta() (e.g. support qmColumns with http://cbor.schmorp.de/stringref, qmSizes with https://datatracker.ietf.org/doc/draft-ietf-cbor-array-tags/?include_text=1 )
{
......@@ -422,11 +422,11 @@ protected:
bool tryOut ( ) { if (caching) { return caching->tryOut() && cacheOut(); }
levels.pop();
while (hasNext()) {
_any();
tryAny();
}
return leaveContainer(); }
bool _any() { return next(); }
bool tryAny() { return next(); }
bool _isOk() const noexcept { return const_cast<QCborReader*>(this)->lastError()==QCborError::NoError; }
void _setChoice(bool b) { isChoice = b; }
void _reportError(QIdentifierLiteral e) { if (!isChoice) errors.append(Error{ e, currentOffset(), lastError() }); }
......@@ -467,14 +467,14 @@ private:
};
// //////////////////////////////////////////////////////////////////////////
// QBind<QCbor*,_> support
// QTransmogrifier<QCbor*,_> support
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
template<>
struct QBind<QCborValue> {
struct QTransmogrifier<QCborValue> {
static QValueStatus bind(QValue&& v, QCborValue&& j) {
if (v->mode()==Write) {
if (j.isMap ()) return v.bind(j.toMap ());
......@@ -514,7 +514,7 @@ struct QBind<QCborValue> {
};
template<>
struct QBind<QCborArray> {
struct QTransmogrifier<QCborArray> {
static QValueStatus bind(QValue&& v, QCborArray&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
......@@ -545,7 +545,7 @@ struct QBind<QCborArray> {
};
template<>
struct QBind<QCborMap> {
struct QTransmogrifier<QCborMap> {
static QValueStatus bind(QValue&& v, QCborMap&& j) {
if (v->mode()==Write) {
quint32 size=quint32(j.size());
......
......@@ -44,16 +44,16 @@
#include <QtCore/qdatastream.h>
#include <QtCore/qvariant.h>
#include "QBind.h"
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QDataStream*> support
// QTransmogrifier<T,QDataStream*> support
// 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 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()
class QDataWriter : public QAbstractValueWriter // allows runtime flexibility but requires QTransmogrifier<T> in addition to T::operator<<(QDataStream&) and does not warrant QDataStream operators compatibility if QTransmogrifier<T> ignores qmDataStreamVersion in meta()
{
Q_DISABLE_COPY(QDataWriter)
public:
......@@ -108,4 +108,4 @@ private:
// \remark Providing a general QDataReader may be deceiving because the QDataStream structure is implicit, thus
// a reader is usually assumed to statically know the data type to read based on the stream origin and version.
// Though QVariant can be used for parts which type are not statically known though, such as the dynamic type of a message coming from a socket.
// Finally, QDataStream version can be retrieved from meta() to adapt to data schema changes over the time \see QBind<QColor> for an example
// Finally, QDataStream version can be retrieved from meta() to adapt to data schema changes over the time \see QTransmogrifier<QColor> for an example
This diff is collapsed.
......@@ -47,11 +47,11 @@
#include <QtCore/qbuffer.h>
#include <QtGui/qcolor.h>
#include "QBind.h"
#include "QValue.h"
#include "QJson_impl.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<T,Q*Model> support
// QTransmogrifier<T,Q*Model> support
class QModelBind : public QAbstractValue
{
......
......@@ -43,10 +43,10 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstack.h>
#include "QBind.h"
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QVariant*> support for the fixed set of QSettingsWriter's BindNative types
// QSettings* support for the fixed set of QSettingsWriter's BindNative types
class QSettingsWriter : public QAbstractValueWriter
{
......@@ -55,8 +55,8 @@ public:
QSettingsWriter(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(qBindExpectedItem)); }
// Shortcuts
/**/ QValue value ( ) { return QValueStatus(this).value(); }
/**/ QSeq<QValueStatus> sequence(quint32* s=nullptr) { return QValueStatus(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> QValueStatus bind ( T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
bool tryBind ( quint8&& t) { settings->setValue(key(), int(t) ); return true; }
......
#include "QBind.h"
#include "QValue.h"
QIdentifierLiteral qBindExpectedItem ("ExpectedItem" );
QIdentifierLiteral qBindExpectedNull ("ExpectedNull" );
......
......@@ -42,10 +42,10 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstack.h>
#include "QBind.h"
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QVariant*> support for the fixed set of QVariantBuilder's BindNative types
// QVariant* support for the fixed set of QVariantBuilder's BindNative types
class QVariantBuilder : public QAbstractValueWriter
{
......
......@@ -43,10 +43,10 @@
#include <QtCore/qxmlstream.h>
#include "QBind.h"
#include "QValue.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<T,QXmlStreamWriter> support
// QXml* support
//! \warning Since XML has no standard way of encoding data structures, we choose a rather implicit one
//! based on the fact that XML elements are implicit data structures unless they contain text without elements,
......
# QBind, a convenient and efficient (de)serialization mechanism on top of Qt
# QTransmogrifier, a convenient and efficient (de)serialization mechanism on top of Qt
QBind was developed to demonstrate the feasibility and advantages of a novel (de)serialization mechanism on top of
QTransmogrifier was developed to demonstrate the feasibility and advantages of a novel (de)serialization mechanism on top of
existing [Qt](http://qt.io) [data formats](https://doc.qt.io/qt-5/topics-data-storage.html#) (Settings, QDataStream, Json, Cbor, Xml)
or [data model](https://doc.qt.io/qt-5/model-view-programming.html) and generic data types (containers, QVariant, QMetaObject, etc.).
It would greatly simplify writing/reading custom C++ data to/from them while providing more performance than existing approaches.
QBind requirements below are useful for most (de)serialization use cases. They would be mandatory to implement in Qt a tracing facility
QTransmogrifier requirements below are useful for most (de)serialization use cases. They would be mandatory to implement in Qt a tracing facility
allowing to analyse how software is used in the field and diagnose complex issues. Effectively:
- QDebug is conveniently used for debugging. But it may not be enough time- or space- efficient for running software
in the field, or require too much log parsing work to detect issues from multiple tracepoints or traces.
......@@ -13,7 +13,7 @@ allowing to analyse how software is used in the field and diagnose complex issue
high-performance and structured data. But analysing unexpected uses and issues in the field requires a lot more
tracepoints than can be conveniently defined statically.
> **DISCLAIMER:** QBind is not currently unit-tested but provided with a [sample and benchmark](main.cpp).
> **DISCLAIMER:** QTransmogrifier 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 QAbstractValue implementations. The README and [DESIGN](DESIGN.md) documentation should be read
> before trying to understand the implementation.
......@@ -64,15 +64,15 @@ See:
### A notable non-requirement
**QBind does not _automatically_ support (de)serialization of graphs unlike boost::serialization**. Pointers will be followed and in
**QTransmogrifier does not _automatically_ support (de)serialization of graphs unlike boost::serialization**. Pointers will be followed and in
case of a graph with a loop, the operation will result in a stack overflow. Hence, the user has to choose an appropriate encoding for his
graph data using some kind of "reference" values. We argue this makes the model translatable to much more data formats like Json since
it does not mandate native support for references. Moreover, QBind supports metadata as an optional way to encode such special values
it does not mandate native support for references. Moreover, QTransmogrifier supports metadata as an optional way to encode such special values
for data formats supporting it like [CBOR value sharing tags](http://cbor.schmorp.de/value-sharing) and XML.
## Examples
### Extending QBind to C++ types
### Extending QTransmogrifier to C++ types
One can rely on Qt reflection to bind a Q_OBJECT or Q_GADGET stored properties using `QBIND_GADGET_WITH_METAOBJECT` macro
```cpp
......@@ -108,7 +108,7 @@ struct Person
.out()
.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("phones" ,phones ) // recursively calls QTransmogrifier to take care of that part
.bind("comments",comments) // directly calls QAbstractValue since it natively supports QString
.bind("children",children)
; // automagically closes opened record()
......@@ -120,7 +120,7 @@ The value argument provides a fluent interface allowing to declaratively bind C+
* `sequence` of data items in a fixed (meaningful) order, possibly infinite
* `record` of named data items in any order
* Atomic values like `QString firstName`, `double height`, `int age`
* Generically supported T values for which a specialized QBind<T> is defined like `QVector<QString> phones`, `QList<E> children`
* Generically supported T values for which a specialized QTransmogrifier<T> is defined like `QVector<QString> phones`, `QList<E> children`
<details>
<summary>The same bind can read/write data in various formats with the same data (but varying metadata support)</summary>
......@@ -178,7 +178,7 @@ s.startMap();
s.endArray();
s.endMap();
```
*NB: QCborValue would be more convenient than QCborStreamWriter but it is much less efficient than QBind*
*NB: QCborValue would be more convenient than QCborStreamWriter but it is much less efficient than QTransmogrifier*
</details>
<details>
......@@ -242,11 +242,11 @@ if (/*... &&*/
</details>
It is also possible to define missing QBind specializations for any C++ type using external QBind class specializations.
It is also possible to define missing QTransmogrifier specializations for any C++ type using external QTransmogrifier class specializations.
Each specialization must implement at least the bind() method for lvalue references. It may also overload bind() for rvalue
references to support temporaries, and for const lvalue reference to efficiently support copyable types.
```cpp
template<> struct QBind<QColor> {
template<> struct QTransmogrifier<QColor> {
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()) {
......@@ -264,7 +264,7 @@ template<> struct QBind<QColor> {
};
```
### Extending QBind to custom formats
### Extending QTransmogrifier to custom formats
Defining a custom format for, say, console output only requires implementing a few `QAbstractValueWriter` abstract methods:
```cpp
......@@ -294,10 +294,10 @@ MyTextWriter(&ba) << 1.333333333333f << PI << ascii << false << color ;
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 `QAbstractValueWriter` and `QAbstractValueReader` are convenient base classes which implement most of `QAbstractValue` interface used by QBind<T> with
Both `QAbstractValueWriter` and `QAbstractValueReader` are convenient base classes which implement most of `QAbstractValue` interface used by QTransmogrifier<T> with
generic text representations of boolean, numbers, etc.
Since QBind supports QVal<_> on the right-hand side, translating between generic data formats or structures is a one-liner:
Since QTransmogrifier 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());
......@@ -329,7 +329,7 @@ By convention:
- `qmName` allows naming data items for, e.g. XML root element and sequence items
- ...
One can also customize binds using ad-hoc std::function like [flatten](tests/QBind/main.cpp#L996) or lambda below (mimicking Python list comprehensions):
One can also customize binds using ad-hoc std::function like [flatten](tests/QTransmogrifier/main.cpp#L996) or lambda below (mimicking Python list comprehensions):
```cpp
QStandardItemModel custom;
QModelWriter<>(&custom).sequence().with([&](QSeq<QValueStatus>&& s) {
......@@ -421,7 +421,7 @@ Phone(Phone::Home, "+44 1234567")
bf647479706502666e756d6265726b2b34342031323334353637ff
```
> WARNING: The QBind ability to adequately bind C++ types and formats is only limited by the set of natively supported C++ types and
> WARNING: The QTransmogrifier 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. `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
......@@ -429,7 +429,7 @@ bf647479706502666e756d6265726b2b34342031323334353637ff
### Write performance
Overall, QBind demonstrates write performance superior to existing Qt classes except QDataStream (which does not meet our W1
Overall, QTransmogrifier demonstrates write performance superior to existing Qt classes except QDataStream (which does not meet our W1
and read requirements). Not surprisingly, the performance depends on the kind of C++ data and data format used. Here are some
explanations about the best results:
- QByteArray obviously fails almost all our requirements since it does not even have a global version number as QDataStream does
......@@ -459,7 +459,7 @@ Regarding the worst performances:
- Variant which translates C++ types to an in-memory data structure of QVariantList and QVariantMap cannot perform very well
(without even storing metadata at all) because of the numerous small allocations that may cost much from time to time
- QJsonValue, QCborValue bad performance is explained the same way as Variant above
- More generally, it seems clear that pointer-based generic data structures cannot be as efficient as QBind to offer runtime
- More generally, it seems clear that pointer-based generic data structures cannot be as efficient as QTransmogrifier to offer runtime
choice of final data format
- The worst write results are obtained with the "Phone" dataset which conveniently uses QMetaObject stored properties and gathers
QMetaEnum names to make values more explicit in Text and Xml formats. It also impacts negatively overall Cbor performance that
......@@ -469,13 +469,13 @@ Regarding the worst performances:
## Conclusion
QBind is a (de)serialization mechanism that can be used on top of Qt, enabling convenient and efficient data transfers without
QTransmogrifier is a (de)serialization mechanism that can be used on top of Qt, enabling convenient and efficient data transfers without
loss among a lot of Qt data types and formats including Json, Cbor, QVariant..., QModel... QMetaObject, replacing **a lot** of
format-specific code with a few `T::bind()` or `QBind<T>::bind()` methods (where T can be defined by user, Qt, or a third-part).
format-specific code with a few `T::bind()` or `QTransmogrifier<T>::bind()` methods (where T can be defined by user, Qt, or a third-part).
It can reuse QDebug and QDataStream << and >> operators, although this requires more visible templates and loses the ability
to switch format at runtime. It can also evolve to something akin to Python list comprehensions for ad-hoc bind operations.
Integrated to Qt, QBind would enable the addition of a new kind of tracing facility, as dynamic and convenient as QDebug,
Integrated to Qt, QTransmogrifier would enable the addition of a new kind of tracing facility, as dynamic and convenient as QDebug,
and practically as efficient as Qt tracegen tool. Many existing QDebug tracepoints could be switched transparently
to the new facility. This would allow going beyond debugging or performance analysis, and tackling complex software issues
in the field involving multiple tracepoints or traces with adequate tools like Python, or the more academic
......
......@@ -2,7 +2,7 @@
#include <QtCore/qmetaobject.h>
#include "QBind.h"
#include "QValue.h"
class Phone {
Q_GADGET
......
......@@ -38,18 +38,18 @@
* **
* ****************************************************************************/
// The core of QBind proof-of-concept including:
// - a fluent interface for describing logical data structures, providing auto completion and well-formedness guarantees
// - a set of recursive QBind<T> functors binding QAbstractValue and T according to their logical data structure
// The core of QTransmogrifier proof-of-concept including:
// - a QValue fluent interface for describing logical data structures, providing auto completion and well-formedness guarantees
// - a set of recursive QTransmogrifier<T> functors binding QAbstractValue and T according to their logical data structure
#include "QBind.h"
#include "QValue.h"
// Extensible set of QAbstractValue implementations providing concrete syntax to the logical data structure in a specific Mode among Write, Read, ...
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder, QJsonVisitor and QBind<QJsonValue,_> support
#include "QJson_impl.h" // QJsonWriter, QJsonReader, QJsonBuilder, QJsonVisitor and QTransmogrifier<QJsonValue,_> support
#include "QCbor_impl.h" // QCborWriter demonstrating the performance potential of the approach
#include "QData_impl.h" // QDataReader, QDataWriter demonstrating a QDataStream with implicit types for benchmarking
#include "QVariant_impl.h" // QVariantBuilder, QVariantVisitor and QBind<QVariant,_> support
#include "QVariant_impl.h" // QVariantBuilder, QVariantVisitor and QTransmogrifier<QVariant,_> support
#include "QModel_impl.h" // Q*ModelWriter support
#include "QXml_impl.h" // QXmlWriter support
#include "QSettings_impl.h" // QSettings* support
......@@ -72,7 +72,7 @@
#include <tuple>
// //////////////////////////////////////////////////////////////////////////
// QBind-enabled types examples
// QValue-enabled types examples
// Using Qt's meta-object system
......@@ -92,7 +92,7 @@ struct Person
r = s.out();
r = r.bind("height" ,height );
r = r.bind("age" ,age ,-1); // reads null() as -1
r = r.bind("phones" ,phones ); // recursive calls to QBind will take care of that part
r = r.bind("phones" ,phones ); // recursive calls to QTransmogrifier will take care of that part
r = r.bind("comments",comments);
r = r.bind("children",children);
return r; // automagically closes opened record()
......@@ -102,7 +102,7 @@ struct Person
// For comparison purposes:
#include<QtCore/qdebug.h>
QDebug &operator<<(QDebug &out, const Person &p)
QDebug &operator<<(QDebug &out, const Person &p)
{
return out.nospace() << "Person(" // items count and names are implicit
<< p.firstName << ", " << p.lastName << ", " // sequence is implicit
......@@ -244,13 +244,13 @@ private:
};
// //////////////////////////////////////////////////////////////////////////
// QBind<T> examples using external bind methods
// QTransmogrifier<T> examples using external bind methods
#include <QtGui/qcolor.h>
//! QBind<QColor,_> with special support for QDataStream compatibility using meta()
//! QTransmogrifier<QColor> with special support for QDataStream compatibility using meta()
template<>
struct QBind<QColor> {
struct QTransmogrifier<QColor> {
static QValueStatus bind(QValue&& v, QColor&& c) {
QColor copy(c);
return bind(std::move(v),copy);
......@@ -1065,8 +1065,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,"QBind","sample");
QSettings nat( QSettings::UserScope,"QBind","sample");
QSettings ini(QSettings::IniFormat,QSettings::UserScope,"QTransmogrifier","sample");
QSettings nat( QSettings::UserScope,"QTransmogrifier","sample");
QVector<QSettingsReader::Error> errors;
//---------------------------------------------------------------------
START {
......
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