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

Added a QByteArray bench + WIP using meta

parent 128cb5d8
......@@ -448,7 +448,7 @@ template<> struct BindSupport< double> : BindNative {};
template<> struct BindSupport< QByteArray> : BindNative {};
template<> struct BindSupport< QVariant> : BindNative {};
static char *qulltoa2(char *p, qulonglong n, int base=10)
static char *qulltoa2(char *p, qulonglong n, int base=10) //!< Reproduced here for benchmark purposes only
{
*--p = '\0';
const char b = 'a' - 10;
......@@ -459,7 +459,7 @@ static char *qulltoa2(char *p, qulonglong n, int base=10)
} while (n);
return p;
}
static char * qlltoa2(char *p, qlonglong n, int base=10)
static char * qlltoa2(char *p, qlonglong n, int base=10) //!< Reproduced here for benchmark purposes only
{
if (n < 0) {
p = qulltoa2(p, qulonglong(-(1 + n)) + 1, base);
......
......@@ -110,32 +110,48 @@ struct Person
#include<QtCore/qdatastream.h>
QDataStream &operator<<(QDataStream &out, const Person &p)
{
return out
return out // record, items count and names are implicit
<< p.firstName << p.lastName // sequence is implicit
<< p.height
<< p.age
<< p.phones
<< p.comments
<< p.children;
<< p.children
; // no record delimiter
}
//! Same as operator<<(QDataStream&, Person&) with no possibility to detect errors other than premature end of QDataStream
QDataStream &operator>>(QDataStream &in, Person &p)
{
return in
>> p.firstName >> p.lastName // sequence is implicit
>> p.height
>> p.age
>> p.phones
>> p.comments
>> p.children;
return in >> p.firstName >> p.lastName >> p.height >> p.age >> p.phones >> p.comments >> p.children;
}
// Using an external bind method and special support for QDataStream using QMetaData
// Using inheritance to complement an existing bind with QMetaData
struct Persons : public QVector<Person> {
Cursor bind(Val<Cursor>&& value) {
return value
.meta({{qmChildren,"children"},{qmColumns,"names,height,age,phones,comments"}}) // to optimize multi-dimensional data formats
.bind(static_cast<QVector<Person>>(*this))
;
}
};
// //////////////////////////////////////////////////////////////////////////
// QBind<T> examples using external bind methods
#include <QtGui/qcolor.h>
//! QBind<QColor,_> with special support for QDataStream compatibility using QMetaData
template<>
struct QBind<QColor> {
static Cursor bind(Val<Cursor>&& v, QColor&& src) {
static Cursor bind(Val<Cursor>&& v, QColor&& c) {
QColor copy(c);
return bind(std::move(v),copy);
}
static Cursor bind(Val<Cursor>&& v, QColor& c) {
if (!c.isValid()) {
return v.null();
}
QMetaData m;
v=v.meta(m);
auto dataStreamVersion = m.find(qmDataStreamVersion);
......@@ -143,65 +159,58 @@ struct QBind<QColor> {
if (dataStreamVersion->second.toInt()<7) { v->reportError("Unsupported QDataStream.version()");
return v.null();
}
return v.sequence().bind(qint8(src.spec())).bind(quint16(src.alpha())).bind(quint16(src.cyan())).bind(quint16(src.magenta())).bind(quint16(src.yellow())).bind(quint16(src.black()));
}
if (!src.isValid()) {
return v.null();
return v.sequence().bind(qint8(c.spec())).bind(quint16(c.alpha())).bind(quint16(c.cyan())).bind(quint16(c.magenta())).bind(quint16(c.yellow())).bind(quint16(c.black()));
}
Rec<Cursor> r = v.record();
switch(src.spec()) {
case QColor::Spec::Rgb : r = r.sequence("RGB" ).bind(quint8(src.red ())).bind(quint8(src.green ())).bind(quint8(src.blue ())) .out(); break;
case QColor::Spec::Hsl : r = r.sequence("HSL" ).bind(qint16(src.hslHue())).bind(quint8(src.hslSaturation())).bind(quint8(src.lightness())) .out(); break;
case QColor::Spec::Hsv : r = r.sequence("HSV" ).bind(qint16(src.hsvHue())).bind(quint8(src.hsvSaturation())).bind(quint8(src.value ())) .out(); break;
case QColor::Spec::Cmyk: r = r.sequence("CMYK" ).bind(quint8(src.cyan ())).bind(quint8(src.magenta ())).bind(quint8(src.yellow ())).bind(quint8(src.black())).out(); break;
switch(c.spec()) {
case QColor::Spec::Rgb : r = r.sequence("RGB" ).bind(quint8(c.red ())).bind(quint8(c.green ())).bind(quint8(c.blue ())) .out(); break;
case QColor::Spec::Hsl : r = r.sequence("HSL" ).bind(qint16(c.hslHue())).bind(quint8(c.hslSaturation())).bind(quint8(c.lightness())) .out(); break;
case QColor::Spec::Hsv : r = r.sequence("HSV" ).bind(qint16(c.hsvHue())).bind(quint8(c.hsvSaturation())).bind(quint8(c.value ())) .out(); break;
case QColor::Spec::Cmyk: r = r.sequence("CMYK" ).bind(quint8(c.cyan ())).bind(quint8(c.magenta ())).bind(quint8(c.yellow ())).bind(quint8(c.black())).out(); break;
default: Q_ASSERT(false);
}
if (src.alpha()<255) { r = r.bind("alpha",src.alpha()); }
if (c.alpha()<255) { r = r.bind("alpha",quint8(c.alpha())); }
return r.bind("base",quint8(255)); // Explicits ARGBCMYKSLV components' base (H base is 360 corresponding to color wheel degrees, with -1 used for gray in addition to S being 0)
// QDebug use of float values removes need for base but may lose precision
}
static Cursor bind(Val<Cursor>&& v, QColor& src) {
return bind(std::move(v),QColor(src));
}
};
// //////////////////////////////////////////////////////////////////////////
// IBind basic implementation example
#include <type_traits>
#include <QtCore/qiodevice.h>
#include <QtCore/qbuffer.h>
#include <QtCore/qbytearray.h>
class TextWriter : public IWriter
{
Q_DISABLE_COPY(TextWriter)
public:
TextWriter(QIODevice* io) : io(io) { Q_ASSERT(io); }
TextWriter(QByteArray* ba) : ba(ba) { Q_ASSERT(ba); }
// Shortcuts
template<typename T> Seq<Cursor> operator<<(T&& t) { return Cursor(this).value().sequence().item().bind(std::forward<T>(t)); }
template<typename T> Cursor bind (T&& t) { return Cursor(this).value() .bind(std::forward<T>(t)); }
protected:
bool _sequence(quint32* =nullptr) { return io->write("["); }
bool _record (quint32* =nullptr) { return io->write("["); }
bool _null ( ) { return true ; }
bool _bind ( const char* s) { return io->write( s ); }
bool _item(QName n) { return io->write(" ") && io->write(n) && io->write(":"); }
bool _item( ) { return io->write(" ") ; }
bool _out ( ) { return io->write("]") ; }
bool _sequence(quint32* =nullptr) { ba->append("["); return true; }
bool _record (quint32* =nullptr) { ba->append("["); return true; }
bool _null ( ) { return true; }
bool _bind ( const char* s) { ba->append( s ); return true; }
bool _bind ( float&& n) { static QUtf8String s; s.setNum(double(n),'g',6); return _bind(s.constData()); } // with QDebug precision
bool _bind ( double&& n) { static QUtf8String s; s.setNum( n ,'g',6); return _bind(s.constData()); } // with QDebug precision
bool _item(QName n) { ba->append(" "); ba->append(n); ba->append(":"); return true; }
bool _item( ) { ba->append(" ") ; return true; }
bool _out ( ) { ba->append("]") ; return true; }
private:
QIODevice* io;
QByteArray* ba;
};
#include <QtCore/qbuffer.h>
class Text
{
QBuffer result;
QUtf8String result;
public:
template<typename T> Text(T&& t) { result.open(QIODevice::WriteOnly); TextWriter(&result).bind(std::forward<T>(t)); }
operator QUtf8String() const { return result.buffer(); }
template<typename T> Text(T&& t) { TextWriter(&result).bind(std::forward<T>(t)); }
operator QUtf8String() const { return result; }
};
// //////////////////////////////////////////////////////////////////////////
......@@ -280,8 +289,8 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b)
ba.clear();
TextWriter(&ba)
<< 1.333333333333f
<< PI
<< ascii
......@@ -365,6 +374,17 @@ int main(int argc, char *argv[])
<< color;
}
STOP("QDataStream",QString::fromUtf8(b.buffer().toHex()));
float f = 1.333333333333f; bool boolean = false;
START {
ba.clear();
ba.append(reinterpret_cast<const char*>(&f ),sizeof(f ));
ba.append(reinterpret_cast<const char*>(&PI ),sizeof(PI ));
ba.append( ascii );
ba.append(reinterpret_cast<const char*>(&boolean),sizeof(boolean));
ba.append(reinterpret_cast<const char*>(&color ),sizeof(color ));
}
STOP("QByteArray",ba.toHex());
QBindable<> writables[5];
START {
writables[0] = 1.333333333333f;
......@@ -397,8 +417,8 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b).bind(transform);
ba.clear();
TextWriter(&ba).bind(transform);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
......@@ -486,8 +506,8 @@ int main(int argc, char *argv[])
}
STOP("QDebug",s);
START {
b.seek(0); b.buffer().clear();
TextWriter(&b).bind(person);
ba.clear();
TextWriter(&ba).bind(person);
}
STOP("Text",QString::fromUtf8(b.buffer()));
START {
......@@ -547,8 +567,8 @@ int main(int argc, char *argv[])
str.clear();
str.append("John");
str.append("Doe");
str.append(reinterpret_cast<char*>(&dbl),sizeof(dbl));
str.append(reinterpret_cast<char*>(&i ),sizeof(i ));
str.append(reinterpret_cast<const char*>(&dbl),sizeof(dbl));
str.append(reinterpret_cast<const char*>(&i ),sizeof(i ));
str.append("+44 1234567");
str.append("+44 2345678");
str.append("unicode is likely U+01 \x01 + U+1F \x1F + U+A4 ¤ U+B0 ° U+D8 Ø U+FF ÿ");
......
Supports Markdown
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