Commit 397c8329 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

Tag utf8 data in API but use QByteArray internally

parent 4a60576d
#include "QBind_impl.h"
QIdentifier::QIdentifier(QName n) : QBytes(QByteArray(n.ascii(), n.size())) { /* no need to check QName content */ }
QIdentifier::QIdentifier(QName n) : QData(QByteArray(n.ascii(), n.size())) { /* no need to check QName content */ }
......@@ -51,20 +51,6 @@
#include <QtCore/qbytearray.h>
//! Explicitely utf8 encoded string of char
//! \warning This implementation opportunistically uses inheritance whereas QBind only needs distinct types
//! for QString, QByteArray, and utf8 strings to avoid costly utf8-utf16 conversions and bytes-utf8 ambiguities
class QUtf8String : public QByteArray
{
public:
using QByteArray::QByteArray;
QUtf8String(const QByteArray& o) : QByteArray(o) {}
QUtf8String() : QByteArray() {}
const char* utf8() const { return constData() ; }
};
#include <QtCore/qmetatype.h>
Q_DECLARE_METATYPE(QUtf8String)
// Content tags
struct AsciiIdentifier {}; //!< [0-9A-Za-z_] ASCII subset
struct AsciiPrintable {}; //!< [0x20..0x7F) ASCII subset
......@@ -75,14 +61,14 @@ struct Utf8Mime {};
//! Associates a QByteArray with a Content tag type to allow static checks and optimizations when data is transferred
template<class TContent>
class QBytes
class QData
{
public:
using Content = TContent;
QBytes() = default;
explicit QBytes( QByteArray&& b) : m_bytes(b) {}
explicit QBytes(const QByteArray& b) : m_bytes(b) {}
QData() = default;
explicit QData( QByteArray&& b) : m_bytes(b) {}
explicit QData(const QByteArray& b) : m_bytes(b) {}
constexpr inline bool isNull() const noexcept { return m_bytes.isNull(); }
constexpr inline int size() const noexcept { return m_bytes.size (); }
......@@ -91,25 +77,27 @@ public:
inline bool operator!=(const char *s) const noexcept { return m_bytes!=s; }
inline operator QByteArray() const noexcept { return m_bytes ; }
inline const char* constData() const noexcept { return m_bytes.data(); }
inline QByteArray& data() noexcept { return m_bytes ; }
inline const char* constData() const noexcept { return m_bytes.constData(); }
inline QByteArray& bytes() noexcept { return m_bytes ; }
protected:
QByteArray m_bytes;
};
using QUtf8Bytes = QBytes<Utf8>;
Q_DECLARE_METATYPE(QUtf8Bytes)
//! Explicitely utf8 encoded string of char
using QUtf8String = QData<Utf8>;
#include <QtCore/qmetatype.h>
Q_DECLARE_METATYPE(QUtf8String)
using QAsciiPrintable = QBytes<AsciiPrintable>;
using QAsciiPrintable = QData<AsciiPrintable>;
Q_DECLARE_METATYPE(QAsciiPrintable)
#include <QtCore/qstring.h>
class QName;
class QIdentifier : public QBytes<AsciiIdentifier>
class QIdentifier : public QData<AsciiIdentifier>
{
public:
using QBytes::QBytes;
using QData::QData;
QIdentifier() = default;
QIdentifier(QName n);
inline operator QLatin1String() const noexcept { return QLatin1String(m_bytes); }
......@@ -156,7 +144,7 @@ public:
constexpr inline operator QLatin1String() const noexcept { return m_ascii ; }
inline QIdentifier toIdentifier() const noexcept { return QIdentifier(QByteArray(m_ascii.data(), m_ascii.size())); }
inline QUtf8Bytes toUtf8() const noexcept { return QUtf8Bytes (QByteArray(m_ascii.data(), m_ascii.size())); }
inline QUtf8String toUtf8() const noexcept { return QUtf8String(QByteArray(m_ascii.data(), m_ascii.size())); }
inline bool operator==(const char *s) const noexcept { return m_ascii==s; }
inline bool operator!=(const char *s) const noexcept { return m_ascii!=s; }
private:
......@@ -639,9 +627,9 @@ struct IWriter : public IBind
virtual bool _bind( quint32&& n) { return _bind(quint64(n)); }
virtual bool _bind( qint64&& n) { const int s=66; char c[s]; return _bind( qlltoa2(c+s, n)); }
virtual bool _bind( quint64&& n) { const int s=66; char c[s]; return _bind(qulltoa2(c+s, n)); }
virtual bool _bind( float&& n) { static QUtf8String s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( double&& n) { static QUtf8String s; s.setNum( n ,'g',std::numeric_limits< double>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( QByteArray&& s) { QUtf8String hex(s.size()*2+2+1,'\0'); hex.append("0x"); hex.append(s.toHex()); return _bind(hex.constData()); }
virtual bool _bind( float&& n) { static QByteArray s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( double&& n) { static QByteArray s; s.setNum( n ,'g',std::numeric_limits< double>::max_digits10); return _bind(s.constData()); } // with specific precision
virtual bool _bind( QByteArray&& s) { QByteArray hex(s.size()*2+2+1,'\0'); hex.append("0x").append(s.toHex()) ; return _bind(hex.constData()); }
virtual bool _bind( QVariant&& src) {
if (src.canConvert<QVariantList>()) {
QSequentialIterable ts = src.value<QSequentialIterable>();
......@@ -739,18 +727,18 @@ struct IReader : public IBind
virtual bool _item( QName u) { QIdentifier s; return _item(s) && s.constData()==u; }
virtual bool _bind(QUtf8String& u) = 0;
virtual bool _bind( QString& s) { QUtf8String u; if (!_bind(u)) return false; s=QString::fromUtf8(u); return true; }
virtual bool _bind( bool& b) { QUtf8String u; if (!_bind(u)) return false; if (u.toLower()=="true") { b=true; } else if (u.toLower()=="false") { b=false; } else { _reportError(qBindExpectedBoolean); return false; } return true; }
virtual bool _bind( qint8& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool _bind( quint8& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool _bind( qint16& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint16>::min() || std::numeric_limits< qint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool _bind( quint16& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool _bind( qint32& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint32>::min() || std::numeric_limits< qint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool _bind( quint32& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool _bind( qint64& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; qint64 v; v=s.toLongLong (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( quint64& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; quint64 v; v=s.toULongLong(&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( float& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; float v; v=s.toFloat (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( double& n) { QUtf8String s; if (!_bind(s)) return false; bool isOk=false; double v; v=s.toDouble (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( QString& s) { QByteArray u; if (!_bind(u)) return false; s=QString::fromUtf8(u); return true; }
virtual bool _bind( bool& b) { QByteArray u; if (!_bind(u)) return false; if (u.toLower()=="true") { b=true; } else if (u.toLower()=="false") { b=false; } else { _reportError(qBindExpectedBoolean); return false; } return true; }
virtual bool _bind( qint8& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint8>::min() || std::numeric_limits< qint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint8(l); return true; }
virtual bool _bind( quint8& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits< quint8>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= quint8(l); return true; }
virtual bool _bind( qint16& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint16>::min() || std::numeric_limits< qint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint16(l); return true; }
virtual bool _bind( quint16& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits<quint16>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint16(l); return true; }
virtual bool _bind( qint32& n) { qint64 l; if (!_bind(l)) return false; if (l<std::numeric_limits< qint32>::min() || std::numeric_limits< qint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n= qint32(l); return true; }
virtual bool _bind( quint32& n) { quint64 l; if (!_bind(l)) return false; if ( std::numeric_limits<quint32>::max()<l) { _reportError(qBindExpectedSmallerNumber); return false; } n=quint32(l); return true; }
virtual bool _bind( qint64& n) { QByteArray s; if (!_bind(s)) return false; bool isOk=false; qint64 v; v=s.toLongLong (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( quint64& n) { QByteArray s; if (!_bind(s)) return false; bool isOk=false; quint64 v; v=s.toULongLong(&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( float& n) { QByteArray s; if (!_bind(s)) return false; bool isOk=false; float v; v=s.toFloat (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( double& n) { QByteArray s; if (!_bind(s)) return false; bool isOk=false; double v; v=s.toDouble (&isOk); if (isOk) { n=v; return true; } _reportError(qBindExpectedDecimal); return false; }
virtual bool _bind( QByteArray& b) { QUtf8String s; if (!_bind(s)) return false; return toByteArray(b, s); }
virtual bool _bind( QVariant& dst) {
_setChoice(true);
......@@ -825,11 +813,12 @@ struct IReader : public IBind
}
protected:
bool toByteArray(QByteArray& b, QUtf8String s) {
if (!s.startsWith("0x") || s.size()%2==1) return false;
QByteArray bytes = s.bytes();
if (!bytes.startsWith("0x") || s.size()%2==1) return false;
b.reserve((s.size()-2)/2);
auto toHex = [](char a) -> char { return '0'<=a && a<='9' ? a-'0' : 'A'<=a && a<='F' ? a-'A' : 'a'<=a && a<='f' ? a-'a' : -1; };
for (int i=0; i < b.size(); i++) {
char highDigit=toHex(s[2+2*i]), lowDigit=toHex(s[2+2*i+1]);
char highDigit=toHex(bytes[2+2*i]), lowDigit=toHex(bytes[2+2*i+1]);
if (highDigit<0 || lowDigit<0)
return false;
b.append(char(highDigit<<4)+lowDigit);
......
......@@ -232,14 +232,14 @@ public:
QCborVisitor(QCborValue* v) : cbor(v) { Q_ASSERT(v); }
void reset(QCborValue* v) { cbor=v; Q_ASSERT(v); steps.resize(0); errors.resize(0); }
struct Error { QName error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error.utf8())+' '+path); } };
struct Error { QName error; QByteArray path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error.utf8())+' '+path); } };
QVector<Error> errors;
QUtf8String currentPath() {
QUtf8String path;
QByteArray currentPath() {
QByteArray path;
Q_FOREACH(Step s, steps) {
if (!s.key.isNull()) { path.append('{').append( s.key.utf8()); }
else { path.append('[').append(QUtf8String::number(s.idx )); }
if (!s.key.isNull()) { path.append('{').append( s.key.utf8()); }
else { path.append('[').append(QByteArray::number(s.idx )); }
}
return path;
}
......@@ -252,7 +252,7 @@ protected:
bool _sequence(quint32* =nullptr) { if (current().isArray ()) { steps.push(Step()); return true; } _reportError(qBindExpectedSequence); return false; }
bool _record (quint32* =nullptr) { if (current().isMap ()) { steps.push(Step()); return true; } _reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (current().isNull ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s) ) { u = s.toUtf8() ; return true; } return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s) ) { u.bytes() = s.toUtf8 (); return true; } return false; }
bool _bind ( QString& v) { if (current().isString ()) { v = current().toString (); return true; } _reportError(qBindExpectedText ); return false; }
bool _bind ( bool& v) { if (current().isBool ()) { v = current().toBool (); return true; } _reportError(qBindExpectedBoolean ); return false; }
bool _bind ( qint64& t) { if (current().isInteger ()) { t = current().toInteger (); return true; } _reportError(qBindExpectedInteger ); return false; }
......@@ -290,7 +290,7 @@ class QCborReader : public IReader, public QCborStreamReader
public:
QCborReader(QIODevice* io) : QCborStreamReader(io), cacheVisitor(&cachedValue) { Q_ASSERT(io); }
struct Error { QName error; qint64 index; QCborError cborError; template<class T> T bind(Val<T>&& value) { QUtf8String utf8(error.utf8()); utf8.append(' ').append(QUtf8String::number(index)); return value.bind(utf8.constData()); } };
struct Error { QName error; qint64 index; QCborError cborError; template<class T> T bind(Val<T>&& value) { QByteArray utf8(error.utf8()); utf8.append(' ').append(QByteArray::number(index)); return value.bind(utf8.constData()); } };
QVector<Error> errors;
// Shortcuts
......@@ -305,7 +305,7 @@ protected:
skipTag(); if (isMap () && enterContainer()) { levels.push(Level()); return true; } _reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (caching) { cacheLevel++; return caching->_null() && cacheOut(); }
skipTag(); if (isNull () && next ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s)) { u = s.toUtf8(); return true; } return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s)) { u.bytes() = s.toUtf8(); return true; } return false; }
bool _bind ( QString& s) { if (caching) { cacheLevel++; return caching->_bind(s) && cacheOut(); }
skipTag(); if (isString()) {
s.resize(0);
......
......@@ -110,7 +110,7 @@ public:
QAsciiPrintable currentPath() {
QByteArray path;
Q_FOREACH(Step s, steps) {
if (!s.key.isNull()) { path.append('{').append(s.key.data() ); } // QByteArray& provides size
if (!s.key.isNull()) { path.append('{').append(s.key.bytes() ); } // QByteArray& provides size
else { path.append('[').append(QByteArray::number(s.idx)); }
}
return QAsciiPrintable(path);
......@@ -126,7 +126,7 @@ protected:
bool _record (quint32* =nullptr) { if (current().isObject()) { steps.push(Step());
return true; } _reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (current().isNull ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s) ) { u = s.toUtf8() ; return true; } return false; }
bool _bind ( QUtf8String& u) { QString s; if (_bind(s) ) { u.bytes() = s.toUtf8 (); return true; } return false; }
bool _bind ( QString& v) { if (current().isString()) { v = current().toString(); return true; } _reportError(qBindExpectedText ); return false; }
bool _bind ( bool& v) { if (current().isBool ()) { v = current().toBool (); return true; } _reportError(qBindExpectedBoolean ); return false; }
bool _bind ( qint64& t) { double d; if (_bind(d) ) { t = qint64(d) ; return true; } return false; }
......@@ -174,10 +174,10 @@ protected:
bool _bind ( const char* u8) { return putString( u8 ); }
// JSON literals
bool _bind ( bool&& n) { return io->write( n?"true":"false" ); }
bool _bind ( float&& n) { return io->write(QUtf8String::number(n,'g',std::numeric_limits< float>::max_digits10)); }
bool _bind ( double&& n) { return io->write(QUtf8String::number(n,'g',std::numeric_limits<double>::max_digits10)); }
bool _bind ( quint64&& t) { return io->write(QUtf8String::number(t)); }
bool _bind ( qint64&& t) { return io->write(QUtf8String::number(t)); }
bool _bind ( float&& n) { return io->write(QByteArray::number(n,'g',std::numeric_limits< float>::max_digits10)); }
bool _bind ( double&& n) { return io->write(QByteArray::number(n,'g',std::numeric_limits<double>::max_digits10)); }
bool _bind ( quint64&& t) { return io->write(QByteArray::number(t)); }
bool _bind ( qint64&& t) { return io->write(QByteArray::number(t)); }
bool _item(QName n) { auto r=(io->write(levels.last().sep) || *levels.last().sep=='\0') && putString(n.utf8()) && io->write(":"); levels.last().sep = ","; return r; }
bool _item( ) { auto r=(io->write(levels.last().sep) || *levels.last().sep=='\0') ; levels.last().sep = ","; return r; }
......@@ -228,7 +228,7 @@ public:
QJsonReader(QIODevice* io) : io(io), cacheWriter(&cachedValue), cacheReader(&cachedValue) { Q_ASSERT(io); }
struct Step { int index; const char* end; QMap<QIdentifier,QJsonValue/*TODO QVariant for meta() support*/> cachedItems; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {} };
struct Error { QName error; int line; int column; int index; template<class T> T bind(Val<T>&& value) { QUtf8String utf8(error.utf8()); utf8.append(' ').append(QUtf8String::number(line)).append(':').append(QUtf8String::number(column)); return value.bind(utf8); } };
struct Error { QName error; int line; int column; int index; template<class T> T bind(Val<T>&& value) { QByteArray utf8(error.utf8()); utf8.append(' ').append(QByteArray::number(line)).append(':').append(QByteArray::number(column)); return value.bind(utf8); } };
QVector<Error> errors;
// Shortcuts
......@@ -250,10 +250,10 @@ protected:
return true;
} else { _reportError(qBindExpectedNull); return false; } }
bool _bind ( QUtf8String& s) { if (caching) { cacheLevel++; return caching->_bind(s.constData()) && cacheOut(); }
QUtf8String u;
QByteArray u;
if ( get('"', "[{\"ntf-0123456789.")) { u.resize(0); char c;
while ((c=getCharInString()) != '\0' ) { u.append(c); }
s=u;
s=QUtf8String(u);
return get('"');
} else { _reportError(qBindExpectedText); return false; } }
bool _bind ( QString& s) { QUtf8String u; if (_bind(u)) { s = QString::fromUtf8(u); return true; } return false; }
......
......@@ -76,7 +76,7 @@ protected:
if (meta.find(qmColumns)!=meta.end()) {
metaColumnNames=true;
int i=0;
Q_FOREACH(auto k,meta[qmColumns].data().split(',')) {
Q_FOREACH(auto k,meta[qmColumns].bytes().split(',')) {
m->insertColumn(i);
m->setHeaderData(i,Qt::Horizontal,k);
columnNames.insert(i,k);
......@@ -84,7 +84,7 @@ protected:
}
}
if (meta.find(qmSizes)!=meta.end()) {
Q_FOREACH(auto k,meta[qmSizes].data().split(',')) {
Q_FOREACH(auto k,meta[qmSizes].bytes().split(',')) {
int i = k.toInt();
if (0<i) sizes.append(i);
}
......@@ -275,7 +275,7 @@ private:
// Supported QMetaData
QIdentifier childrenName;
QList<QUtf8String> columnNames;
QList<QByteArray> columnNames;
bool metaColumnNames=false;
QVector<int> sizes;
};
......
......@@ -95,14 +95,14 @@ public:
Q_ENABLE_MOVE(QSettingsReader, std::swap(isChoice, o.isChoice); )
QSettingsReader(QSettings* s) : settings(s) { Q_ASSERT(s); levels.push(Level(QName(""))); }
struct Error { QName error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error.utf8())+' '+path); } };
struct Error { QName error; QByteArray path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error.utf8())+' '+path); } };
QVector<Error> errors;
QUtf8String currentPath() {
QUtf8String path;
QByteArray currentPath() {
QByteArray path;
Q_FOREACH(Level l, levels) {
if (l.key.isNull()) { path.append('/').append( l.key.utf8()); }
else { path.append('/').append(QUtf8String::number(l.idx )); }
else { path.append('/').append(QByteArray::number(l.idx )); }
}
return path;
}
......
......@@ -101,14 +101,14 @@ public:
QVariantVisitor(const QVariant* v) : value(v) { Q_ASSERT(v); }
void reset(const QVariant* v) { value=v; Q_ASSERT(v); levels.resize(0); errors.resize(0); }
struct Error { QName error; QUtf8String path; template<class T> T bind(Val<T>&& value) { return value.bind(QUtf8String(error)+' '+path); } };
struct Error { QName error; QByteArray path; template<class T> T bind(Val<T>&& value) { return value.bind(QByteArray(error.utf8())+' '+path); } };
QVector<Error> errors;
QUtf8String currentPath() {
QUtf8String path;
QByteArray currentPath() {
QByteArray path;
Q_FOREACH(Level l, levels) {
if (l.key.isNull()) { path.append('{').append(l.key.utf8(), l.key.size()); }
else { path.append('[').append(QUtf8String::number(l.idx)); }
else { path.append('[').append(QByteArray::number(l.idx)); }
}
return path;
}
......
......@@ -80,9 +80,9 @@ protected:
bool _bind ( bool&& b) { writeText(QName("boolean"), b ? "true" : "false"); return true; }
bool _bind ( qint64&& n) { const int s=66; char c[s]; writeText(QName("integer"), qlltoa2(c+s, n)); return true; }
bool _bind ( quint64&& n) { const int s=66; char c[s]; writeText(QName("integer"), qulltoa2(c+s, n)); return true; }
bool _bind ( float&& n) { static QUtf8String s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); writeText(QName("decimal" ), s ); return true; } // with specific precision
bool _bind ( double&& n) { static QUtf8String s; s.setNum( n ,'g',std::numeric_limits< double>::max_digits10); writeText(QName("decimal" ), s ); return true; } // with specific precision
bool _bind ( QByteArray&& s) { QUtf8String hex(s.size()*2+2+1,'\0'); hex.append("0x"); hex.append(s.toHex().toUpper()) ; writeText(QName("hexBinary"), hex); return true; }
bool _bind ( float&& n) { static QByteArray s; s.setNum(double(n),'g',std::numeric_limits< float>::max_digits10); writeText(QName("decimal" ), s); return true; } // with specific precision
bool _bind ( double&& n) { static QByteArray s; s.setNum( n ,'g',std::numeric_limits< double>::max_digits10); writeText(QName("decimal" ), s); return true; } // with specific precision
bool _bind ( QByteArray&& s) { QByteArray hex(s.size()*2+2+1,'\0'); hex.append("0x").append(s.toHex().toUpper()) ; writeText(QName("hexBinary"), hex); return true; }
bool _isOk() noexcept { return !io->hasError(); }
......
......@@ -161,7 +161,7 @@ struct QBind<QColor> {
v=v.meta(m);
auto dataStreamVersion = m.find(qmDataStreamVersion);
if (dataStreamVersion!=m.end()) {
if (dataStreamVersion->second.data().toInt()<7) { v->reportError(QName("Unsupported QDataStream.version()"));
if (dataStreamVersion->second.bytes().toInt()<7) { v->reportError(QName("Unsupported QDataStream.version()"));
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()));
......@@ -200,8 +200,8 @@ protected:
bool _record (quint32* =nullptr) { utf8->append("["); return true; }
bool _null ( ) { return true; }
bool _bind ( const char* s) { utf8->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 _bind ( float&& n) { static QByteArray s; s.setNum(double(n),'g',6); return _bind(s.constData()); } // with QDebug precision
bool _bind ( double&& n) { static QByteArray s; s.setNum( n ,'g',6); return _bind(s.constData()); } // with QDebug precision
bool _item(QName n) { utf8->append(" ").append(n.utf8()).append(":"); return true; }
bool _item( ) { utf8->append(" ") ; return true; }
......@@ -214,10 +214,12 @@ private:
class Text
{
QUtf8String result;
QByteArray result;
public:
template<typename T> Text(T&& t) { TextWriter(&result).bind(std::forward<T>(t)); }
operator QUtf8String() const { return result; }
const QByteArray& utf8() const { return result; }
/**/ QByteArray& utf8() { return result; }
operator QByteArray() const { return result; }
};
// //////////////////////////////////////////////////////////////////////////
......@@ -343,7 +345,7 @@ int main(int argc, char *argv[])
.bind(color)
;
}
STOP("Variant",QUtf8String(Text(v)));
STOP("Variant",Text(v).utf8());
START {
ba.resize(0);
QCborWriter(&ba).value().sequence(5)
......@@ -459,7 +461,7 @@ int main(int argc, char *argv[])
v.clear();
QVariantBuilder(&v).bind(transform);
}
STOP("Variant",QUtf8String(Text(v)));
STOP("Variant",Text(v).utf8());
START {
b.seek(0); b.buffer().resize(0);
QCborWriter(&ba).bind(transform);
......@@ -550,7 +552,7 @@ int main(int argc, char *argv[])
v.clear();
QVariantBuilder(&v).bind(person);
}
STOP("Variant",QUtf8String(Text(v)));
STOP("Variant",Text(v).utf8());
START {
ba.resize(0);
QCborWriter(&ba).bind(person);
......@@ -675,7 +677,7 @@ int main(int argc, char *argv[])
v.clear();
QVariantBuilder(&v).bind(phone);
}
STOP("Variant",QUtf8String(Text(v)));
STOP("Variant",Text(v).utf8());
START {
ba.resize(0);
QCborWriter(&ba).bind(phone);
......@@ -744,7 +746,7 @@ int main(int argc, char *argv[])
r.bind(p);
readerErrors = r.errors;
}
STOP("Json>P",QString(Text(p)+" | "+Text(readerErrors)))
STOP("Json>P",Text(p).utf8()+" | "+Text(readerErrors))
START {
roundtrip.seek(0);
QJsonWriter(&roundtrip).bind(p);
......@@ -756,7 +758,7 @@ int main(int argc, char *argv[])
r.bind(p);
readerErrors = r.errors;
}
STOP("Json>P",QString(Text(p)+" | "+Text(readerErrors)))
STOP("Json>P",Text(p).utf8()+" | "+Text(readerErrors))
//---------------------------------------------------------------------
START {
jv = QJsonValue();
......@@ -769,7 +771,7 @@ int main(int argc, char *argv[])
r.bind(p);
visitorErrors = r.errors;
}
STOP("JsonValue>P",QString(Text(p)+" | "+Text(visitorErrors)))
STOP("JsonValue>P",Text(p).utf8()+" | "+Text(visitorErrors))
//---------------------------------------------------------------------
START {
roundtrip.seek(0); jv = QJsonValue();
......@@ -806,7 +808,7 @@ int main(int argc, char *argv[])
r.bind(p);
readerErrors = r.errors;
}
STOP("Cbor>P",QString(Text(p)+" | "+Text(readerErrors)))
STOP("Cbor>P",Text(p).utf8()+" | "+Text(readerErrors))
START {
roundtrip.buffer().resize(0);
QCborWriter(&roundtrip.buffer()).bind(p);
......@@ -818,7 +820,7 @@ int main(int argc, char *argv[])
r.bind(p);
readerErrors = r.errors;
}
STOP("Cbor>P",QString(Text(p)+" | "+Text(readerErrors)))
STOP("Cbor>P",Text(p).utf8()+" | "+Text(readerErrors))
//---------------------------------------------------------------------
QCborStreamReader reader(roundtrip.buffer());
bool parsed;
......@@ -908,7 +910,7 @@ int main(int argc, char *argv[])
reader.leaveContainer();
reader.reset();
}
STOP("QCborStream>P",QString(Text(p)+" | "+Text(parsed)))
STOP("QCborStream>P",Text(p).utf8()+" | "+Text(parsed))
//---------------------------------------------------------------------
START {
cv = QCborValue();
......@@ -921,7 +923,7 @@ int main(int argc, char *argv[])
r.bind(p);
visitorErrors = r.errors;
}
STOP("CborValue>P",QString(Text(p)+" | "+Text(visitorErrors)))
STOP("CborValue>P",Text(p).utf8()+" | "+Text(visitorErrors))
//---------------------------------------------------------------------
START {
roundtrip.seek(0); cv = QCborValue();
......@@ -942,7 +944,7 @@ int main(int argc, char *argv[])
r.bind(QJsonWriter(&b).value());
readerErrors = r.errors;
}
STOP("Cbor>Json",QString(b.buffer()+" | "+Text(readerErrors)))
STOP("Cbor>Json",b.buffer()+" | "+Text(readerErrors))
}
GROUP_STOP
GROUP("Person<>Settings")//====================================================
......@@ -956,13 +958,13 @@ int main(int argc, char *argv[])
START {
QSettingsWriter(&nat).bind(person);
}
STOP("P>Settings",QString(Text(person)))
STOP("P>Settings",Text(person).utf8())
START {
QSettingsReader r(&nat);
r.bind(person);
errors = r.errors;
}
STOP("Settings>P",QString(Text(person)+" | "+Text(errors)))
STOP("Settings>P",Text(person).utf8()+" | "+Text(errors))
START {
QSettingsWriter(&ini).bind(person);
}
......
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