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 4c7a2f99 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère
Browse files

Replaced QByteArray with QUtf8String alias to document utf8 encoded

parts
parent 514ac585
......@@ -91,7 +91,8 @@ private:
#include <QtCore/qstring.h>
using MetaData = std::map<Name,QString>;
//! QMetaData is data about current data (e.g. tag, attribute, style, etc.)
using QMetaData = std::map<Name,QString>;
static Name qmType = "type";
......@@ -174,8 +175,7 @@ public:
/**/ operator bool() { return m_out.operator bool(); } //!< to drive QBind<TResult,T>() traversal
TImpl* operator ->() { return m_out.operator ->(); }
/**/ Val<T_> meta ( MetaData&& m) { auto mref=m; return meta(mref); }
/**/ Val<T_> meta ( MetaData& m) { if (Q_LIKELY(m_out)) m_out->_meta(m); return std::move(*this); }
/**/ Val<T_> meta ( QMetaData& m) { if (Q_LIKELY(m_out)) m_out->_meta(m); return std::move(*this); }
// TODO ? Add bind with default T specialised for Reader/Writer
/**/ Seq<T_> sequence(quint32* s=nullptr) { if (Q_LIKELY(m_out) && m_out->_sequence ( s)) return Seq<T_>(std::move(m_out)); else return Seq<T_>(); }
......@@ -185,6 +185,10 @@ public:
/**/ T_ any ( ) { if (_bind(BindSupport<TImpl,void>() )) return std::move(m_out) ; else return T_ (); }
T_ bind(const char* const& t); // special handling of both (const char*)'s const& and &&
/**/ Val<T_> meta (QMetaData&& m) { auto v=m; return meta ( v); }
/**/ Seq<T_> sequence( quint32 s) { return sequence(&s); }
/**/ Rec<T_> record ( quint32 s) { return record (&s); }
private:
template<typename T> bool _bind(BindNative , T&& t) { return Q_LIKELY(m_out) && m_out->_bind( std::forward<T>(t)); }
/**/ bool _bind(BindNative ) { return Q_LIKELY(m_out) && m_out->_bind( ); }
......@@ -217,8 +221,8 @@ public:
TResult result() { return operator TResult(); }
// Shortcuts
/**/ Val<Seq<T_>> meta ( MetaData&& m) { return item().meta ( m); }
/**/ Val<Seq<T_>> meta ( MetaData& m) { return item().meta ( m); }
/**/ Val<Seq<T_>> meta ( QMetaData&& m) { return item().meta ( m); }
/**/ Val<Seq<T_>> meta ( QMetaData& m) { return item().meta ( m); }
/**/ Seq<Seq<T_>> sequence(quint32* s=nullptr) { return item().sequence ( s); }
/**/ Rec<Seq<T_>> record (quint32* s=nullptr) { return item().record ( s); }
/**/ Seq<T_> null ( ) { return item().null ( ); }
......@@ -250,24 +254,24 @@ public:
/**/ operator bool() { return m_out.operator bool(); } //!< to drive QBind<TResult,T>() traversal
TImpl* operator ->() { return m_out.operator ->(); }
Val<Rec<T_>> item( Name name) { QByteArray n(name); // TODO use QByteArray::fromRawData(key,int(strlen(key)) for Writers
if (Q_LIKELY(m_out) && m_out->_item(n )) return Val<Rec<T_>>(std::move(*this)); else return Val<Rec<T_>>(); }
Val<Rec<T_>> item(QByteArray& name) { if (Q_LIKELY(m_out) && m_out->_item(name)) return Val<Rec<T_>>(std::move(*this)); else return Val<Rec<T_>>(); }
/**/ T_ out ( ) { if (Q_LIKELY(m_out) && m_out->_out ( )) return std::move(m_out) ; else return T_ (); }
Val<Rec<T_>> item( Name name) { QUtf8String n(name); // TODO use QUtf8String::fromRawData(key,int(strlen(key)) for Writers
if (Q_LIKELY(m_out) && m_out->_item(n )) return Val<Rec<T_>>(std::move(*this)); else return Val<Rec<T_>>(); }
Val<Rec<T_>> item(QUtf8String& name) { if (Q_LIKELY(m_out) && m_out->_item(name)) return Val<Rec<T_>>(std::move(*this)); else return Val<Rec<T_>>(); }
/**/ T_ out ( ) { if (Q_LIKELY(m_out) && m_out->_out ( )) return std::move(m_out) ; else return T_ (); }
operator TResult() { return out(); /* calls T_::operator TResult() if T_ != TResult */ }
TResult result() { return operator TResult(); }
// Shortcuts
/**/ Val<Rec<T_>> meta (Name n, MetaData&& m) { return item(n).meta ( m); }
/**/ Val<Rec<T_>> meta (Name n, MetaData& m) { return item(n).meta ( m); }
/**/ Val<Rec<T_>> meta (Name n, QMetaData&& m) { return item(n).meta ( m); }
/**/ Val<Rec<T_>> meta (Name n, QMetaData& m) { return item(n).meta ( m); }
/**/ Seq<Rec<T_>> sequence(Name n, quint32* s=nullptr) { return item(n).sequence ( s); }
/**/ Rec<Rec<T_>> record (Name n, quint32* s=nullptr) { return item(n).record ( s); }
/**/ Rec<T_> null (Name n ) { return item(n).null ( ); }
template<typename T> Rec<T_> bind (Name n, T&& t) { return item(n).bind(std::forward<T>(t)); }
private:
template<class TSrcResult, typename TDst, typename TEnabledIf> friend struct QBind; // restricting to <TSrcResult, Val<TDst>&&, IsReader<TSrcResult>>; is not possible in C++11
Val<TResult> _unsafeItem(QByteArray& key) { if (Q_LIKELY(m_out) && m_out->_item(key)) return Val<TResult>(m_out._unsafeCopy()); else return Val<TResult>(); }
Val<TResult> _unsafeItem(QUtf8String& key) { if (Q_LIKELY(m_out) && m_out->_item(key)) return Val<TResult>(m_out._unsafeCopy()); else return Val<TResult>(); }
friend class Val<Rec<T_>>;
friend class Seq<Rec<T_>>;
......@@ -304,8 +308,8 @@ public:
Val<TResult> value() { return Val<TResult>(std::move(*static_cast<TResult*>(this))); }
// Shortcuts
/**/ Val<TResult> meta ( MetaData&& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( MetaData& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( QMetaData&& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( QMetaData& m) { return value().meta ( m); }
/**/ Seq<TResult> sequence(quint32* s=nullptr) { return value().sequence ( s); }
/**/ Rec<TResult> record (quint32* s=nullptr) { return value().record ( s); }
/**/ TResult null ( ) { return value().null ( ); }
......@@ -328,7 +332,7 @@ private:
//! \warning
//! - it may be difficult to correctly implement a TResult derived from QBaseWriter with internal state (need to understand move semantics)
//! - TResult unsafeCopy copies do not share state (such as the whole path to the current value or errors or "choice" mode)
//! - TResult are not pimpled (use QBaseReader if needed)
//! - TResult are not pimpled (use QWriter+IWriter if needed)
template<class TResult_>
class QBaseWriter
{
......@@ -345,8 +349,8 @@ public:
Val<TResult> value() { return Val<TResult>(std::move(*static_cast<TResult*>(this))); }
// Shortcuts
/**/ Val<TResult> meta ( MetaData&& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( MetaData& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( QMetaData&& m) { return value().meta ( m); }
/**/ Val<TResult> meta ( QMetaData& m) { return value().meta ( m); }
/**/ Seq<TResult> sequence(quint32* s=nullptr) { return value().sequence ( s); }
/**/ Rec<TResult> record (quint32* s=nullptr) { return value().record ( s); }
/**/ TResult null ( ) { return value().null ( ); }
......@@ -374,36 +378,35 @@ struct IWriter
//! Write status for current value
virtual bool _isOk() { return true; }
//! Meta data is data about current data (e.g. tag, attribute, style, etc.)
//! \warning It is ignored by default and subject to various interpretation, so users should meta data standards or adopt existing ones like XSD for sake of interoperability
virtual void _meta ( MetaData& ) {}
virtual bool _sequence(quint32* size=nullptr) = 0;
virtual bool _record (quint32* size=nullptr) = 0;
virtual bool _null ( ) = 0;
virtual bool _item ( QByteArray& k) = 0;
virtual bool _item ( QUtf8String& name) = 0; // TODO Implement _item(Name n) instead
virtual bool _item ( ) = 0;
virtual bool _bind ( const char* utf8) = 0;
//! End of sequence or record
//! Few IWriter need to process this (contiguous IWriter need to mark the end of indefinite sequences and records for instance)
virtual bool _out() { return true; }
virtual bool _bind ( const char* s) = 0;
virtual bool _out ( ) { return true; }
virtual bool _bind ( QString& s) { return _bind(s.toUtf8().constData()); }
virtual bool _bind ( bool& s) { return _bind(s ? "true" : "false"); }
virtual bool _bind ( float& n) { auto s(QByteArray::number(double(n),'g',std::numeric_limits< float>::max_digits10)); return _bind(s.constData()); } // with specific precision
virtual bool _bind ( double& n) { auto s(QByteArray::number( n ,'g',std::numeric_limits<double>::max_digits10)); return _bind(s.constData()); } // with specific precision
virtual bool _bind( QString& s) { return _bind(s.toUtf8().constData()); }
virtual bool _bind( bool& s) { return _bind(s ? "true" : "false"); }
virtual bool _bind( float& n) { auto s(QByteArray::number(double(n),'g',std::numeric_limits< float>::max_digits10)); return _bind(s.constData()); } // with specific precision
virtual bool _bind( double& n) { auto s(QByteArray::number( n ,'g',std::numeric_limits<double>::max_digits10)); return _bind(s.constData()); } // with specific precision
#if Q_CC_MSVC
# define ulltoa _ui64toa
# define lltoa _i64toa
#endif
virtual bool _bind ( qulonglong& s) { char n[1+std::numeric_limits<qulonglong>::digits10+1]; ulltoa(s,n,sizeof(n)); return _bind(static_cast<const char*>(n)); } // handling all unsigned integral types
virtual bool _bind ( qlonglong& s) { char n[1+std::numeric_limits< qlonglong>::digits10+1]; lltoa(s,n,sizeof(n)); return _bind(static_cast<const char*>(n)); } // handling all signed integral types
virtual bool _bind ( QByteArray& s) { QByteArray hex("0x"); hex.append(s.toHex()); return _bind(hex.constData()); }
virtual bool _bind(qulonglong& s) { char n[1+std::numeric_limits<qulonglong>::digits10+1]; ulltoa(s,n,sizeof(n)); return _bind(static_cast<const char*>(n)); } // handling all unsigned integral types
virtual bool _bind( qlonglong& s) { char n[1+std::numeric_limits< qlonglong>::digits10+1]; lltoa(s,n,sizeof(n)); return _bind(static_cast<const char*>(n)); } // handling all signed integral types
virtual bool _bind(QByteArray& s) { QByteArray hex("0x"); hex.append(s.toHex()); return _bind(hex.constData()); }
// TODO QChar, QDateTime, QDate, QTime, QUuid, QUrl, QRegularExpression
//! \warning QMetaData is ignored by default and subject to various interpretation, so users should define or adopt existing meta data standards like XSD for sake of interoperability
virtual void _meta( QMetaData& ) {}
};
//! Writer with standard native types that replaces compile-time TResult with runtime IWriter
......@@ -423,18 +426,18 @@ protected:
friend class QBaseWriter<QWriter>;
template<class T_> friend class Val; // enables calling methods below
void _meta ( MetaData& m) { Q_ASSERT(impl); impl->_meta ( m); }
void _meta ( QMetaData& m) { Q_ASSERT(impl); impl->_meta (m); }
bool _sequence(quint32* cols=nullptr) { Q_ASSERT(impl); return impl->_sequence(cols); }
bool _record (quint32* rows=nullptr) { Q_ASSERT(impl); return impl->_record (rows); }
bool _null ( ) { Q_ASSERT(impl); return impl->_null ( ); }
bool _sequence(quint32* s=nullptr) { Q_ASSERT(impl); return impl->_sequence(s); }
bool _record (quint32* s=nullptr) { Q_ASSERT(impl); return impl->_record (s); }
bool _null ( ) { Q_ASSERT(impl); return impl->_null ( ); }
bool _bind ( QByteArray& v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( QString& v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( const char* v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( bool& v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( float& v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( double& v) { Q_ASSERT(impl); return impl->_bind ( v); }
bool _bind ( QByteArray& v) { Q_ASSERT(impl); return impl->_bind (v); }
bool _bind ( QString& v) { Q_ASSERT(impl); return impl->_bind (v); }
bool _bind ( const char* v) { Q_ASSERT(impl); return impl->_bind (v); }
bool _bind ( bool& v) { Q_ASSERT(impl); return impl->_bind (v); }
bool _bind ( float& v) { Q_ASSERT(impl); return impl->_bind (v); }
bool _bind ( double& v) { Q_ASSERT(impl); return impl->_bind (v); }
template<typename T> typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, bool>::type _bind(T& t) { Q_ASSERT(impl); qulonglong u(t); return impl->_bind(u); }
template<typename T> typename std::enable_if<std::is_integral<T>::value && std:: is_signed<T>::value, bool>::type _bind(T& t) { Q_ASSERT(impl); qlonglong s(t); return impl->_bind(s); }
......@@ -444,9 +447,9 @@ protected:
template<class T_> friend class Seq; // enables calling methods below
template<class T_> friend class Rec;
bool _item(QByteArray& k) { Q_ASSERT(impl); return impl->_item(k); }
bool _item( ) { Q_ASSERT(impl); return impl->_item( ); }
bool _out ( ) { Q_ASSERT(impl); return impl->_out ( ); }
bool _item(QUtf8String& k) { Q_ASSERT(impl); return impl->_item(k); }
bool _item( ) { Q_ASSERT(impl); return impl->_item( ); }
bool _out ( ) { Q_ASSERT(impl); return impl->_out ( ); }
private:
IWriter* impl = nullptr; // this state has noticeable performance cost but guarantees well-formedness through a unique valid instance of QWriter (with impl != nullptr)
};
......@@ -595,7 +598,7 @@ struct QBind<TResult, QString&, IsWriter<TResult>> { static TResult bind(Val<TRe
template<class TResult>
struct QBind<TResult, QString&, IsReader<TResult>> { static TResult bind(Val<TResult> src, QString& dst) {
QByteArray ba;
auto r = src.bind(ba);
auto r = src.bind(ba); // FIXME QByteArray is raw data that does not necessarily represent a utf8 string
if (r) {
dst = QString::fromUtf8(ba);
}
......@@ -662,11 +665,11 @@ struct QBind<TResult, QMap<QString,T>&, IsWriter<TResult>> { static TResult bind
template<class TResult, typename T>
struct QBind<TResult, QMap<QString,T>&, IsReader<TResult>> { static TResult bind(Val<TResult> src, QMap<QString,T>& dst) {
auto s(src.record());
QByteArray k; Val<Rec<TResult>> i;
while ((i = s.item(k))) {
T v;
if ((s = i.bind(v)))
dst.insert(QString::fromUtf8(k),v);
QUtf8String name; Val<Rec<TResult>> i;
while ((i = s.item(name))) {
T value;
if ((s = i.bind(value)))
dst.insert(QString::fromUtf8(name),value);
}
return s;
}};
......@@ -713,7 +716,7 @@ struct QBind<TSrcResult, Val<TDst>&&, IsReader<TSrcResult>> { static TSrcResult
if ( (srcRec = src.record())) {
/**/ dstRec = dst.record();
QByteArray srcKey; Val<TSrcResult> srcVal; Val<TDst> dstVal;
QUtf8String srcKey; Val<TSrcResult> srcVal; Val<TDst> dstVal;
while((srcVal = srcRec._unsafeItem(srcKey))) {
dstVal = dstRec._unsafeItem(srcKey);
srcRec = srcVal.bind(std::move(dstVal));
......
......@@ -109,8 +109,8 @@ public:
// Shortcuts
/**/ Val<QWriter> value ( ) { return QWriter(this).value ( ); }
/**/ Val<QWriter> meta ( MetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( MetaData& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData& m) { return QWriter(this).meta ( m); }
/**/ Seq<QWriter> sequence(quint32* s=nullptr) { return QWriter(this).sequence ( s); }
/**/ Rec<QWriter> record (quint32* s=nullptr) { return QWriter(this).record ( s); }
/**/ QWriter null ( ) { return QWriter(this).null ( ); }
......@@ -151,9 +151,9 @@ protected:
bool _bind(qulonglong& v) { return _bind(v, nullptr); }
bool _bind( qlonglong& v) { return _bind(v, nullptr); }
bool _item(QByteArray& k) { return (Q_LIKELY(putInteger(quint64(k.size()), cbor::TextStringType)) && (Q_LIKELY(io->write(k)) || k.isEmpty())); }
bool _item( ) { return true ; }
bool _out ( ) { bool definite = levels.back(); levels.pop_back(); return definite ? true : putSimpleValue(cbor::Break); }
bool _item(QUtf8String& k) { return (Q_LIKELY(putInteger(quint64(k.size()), cbor::TextStringType)) && (Q_LIKELY(io->write(k)) || k.isEmpty())); }
bool _item( ) { return true ; }
bool _out ( ) { bool definite = levels.back(); levels.pop_back(); return definite ? true : putSimpleValue(cbor::Break); }
private:
inline bool putMajorValue (cbor:: MajorValue v, cbor::MajorType majorType) { return io->putChar (v|char ( majorType << 5)); }
inline bool putSimpleValue(cbor::SimpleValue v ) { return io->putChar (v|char (cbor::SimpleValueType << 5)); }
......@@ -209,7 +209,7 @@ class QCborReaderImpl
public:
QCborReaderImpl(QCborStreamReader* io) : io(io) { Q_ASSERT(io); }
struct Error { const char* error; qint64 index; template<class T> T bind(Val<T> value) { QByteArray ba(error); ba.append(' ').append(QByteArray::number(index)); return value.bind(ba.constData()); } };
struct Error { const char* error; qint64 index; template<class T> T bind(Val<T> value) { QUtf8String utf8(error); utf8.append(' ').append(QUtf8String::number(index)); return value.bind(utf8.constData()); } };
QVector<Error> errors;
protected:
friend class QScopedChoice<Val<QCborReader>>;
......@@ -287,7 +287,7 @@ protected:
template<class T_> friend class Rec; // calls methods below
// TODO cache key:value pairs coming out of order wrt to T items() calls
bool _item(QByteArray& k) { if (!io->hasNext()) {
bool _item(QUtf8String& k) { if (!io->hasNext()) {
return false;
}
QString s;
......@@ -371,7 +371,7 @@ protected:
virtual bool _bind ( qulonglong& n) { double d(n); return _bind(d); }
virtual bool _bind ( qlonglong& n) { double d(n); return _bind(d); }
virtual bool _item(QByteArray& k) { levels.last().key=k ; return true; }
virtual bool _item(QUtf8String& k) { levels.last().key=k ; return true; }
virtual bool _item( ) { levels.last().key=nullptr; return true; }
virtual bool _out ( ) { auto level = levels.pop(); set(!level.key.isNull() ? QCborValue(level.object) : QCborValue(level.array)); return true; }
private:
......@@ -388,7 +388,7 @@ private:
}
QCborValue* value;
struct Step { QByteArray key; /* TODO union */ QCborMap object; QCborArray array; Step(const char* k=nullptr) : key(k) {} };
struct Step { QUtf8String key; /* TODO union */ QCborMap object; QCborArray array; Step(const char* k=nullptr) : key(k) {} };
QStack<Step> levels = QStack<Step>(); //!< minimal dynamic context to implement out() and ensure actual building in case QCborBuilderImpl is abandoned
};
......
......@@ -82,9 +82,9 @@ protected:
template<class T_> friend class Seq; // calls methods below
template<class T_> friend class Rec; // calls methods below
bool _item(QByteArray& k) { Q_UNUSED(k); return true; } // record keys are implicit, maps should be serialized as a sequence of records with key and value items
bool _item( ) { return true; }
bool _out( ) { return true; }
bool _item(QUtf8String&) { return true; } // record keys are implicit, maps should be serialized as a sequence of records with key and value items
bool _item( ) { return true; }
bool _out( ) { return true; }
private:
QDataStream* io;
};
......
......@@ -61,18 +61,18 @@ public:
// Shortcuts
template<typename T> QWriter bind(T&& t) { return QWriter(this).bind(std::forward<T>(t)); }
protected:
virtual bool _sequence(quint32* rows=nullptr) { Q_UNUSED(rows); levels.push(Step(nullptr)); return true; }
virtual bool _record (quint32* cols=nullptr) { Q_UNUSED(cols); levels.push(Step("" )); return true; }
virtual bool _null ( ) { set(QJsonValue( )); return true; }
virtual bool _bind ( const char* s) { set(QJsonValue(s)); return true; }
virtual bool _bind ( bool& b) { set(QJsonValue(b)); return true; }
virtual bool _bind ( double& d) { set(QJsonValue(d)); return true; }
virtual bool _bind ( qulonglong& n) { double d(n); return _bind(d); }
virtual bool _bind ( qlonglong& n) { double d(n); return _bind(d); }
virtual bool _item(QByteArray& k) { levels.last().key=k ; return true; }
virtual bool _item( ) { levels.last().key=nullptr; return true; }
virtual bool _out ( ) { auto level = levels.pop(); set(!level.key.isNull() ? QJsonValue(level.object) : QJsonValue(level.array)); return true; }
bool _sequence(quint32* rows=nullptr) { Q_UNUSED(rows); levels.push(Step(nullptr)); return true; }
bool _record (quint32* cols=nullptr) { Q_UNUSED(cols); levels.push(Step("" )); return true; }
bool _null ( ) { set(QJsonValue( )); return true; }
bool _bind ( const char* s) { set(QJsonValue(s)); return true; }
bool _bind ( bool& b) { set(QJsonValue(b)); return true; }
bool _bind ( double& d) { set(QJsonValue(d)); return true; }
bool _bind ( qulonglong& n) { double d(n); return _bind(d); }
bool _bind ( qlonglong& n) { double d(n); return _bind(d); }
bool _item(QUtf8String& k) { levels.last().key=k ; return true; }
bool _item( ) { levels.last().key=nullptr; return true; }
bool _out ( ) { auto level = levels.pop(); set(!level.key.isNull() ? QJsonValue(level.object) : QJsonValue(level.array)); return true; }
private:
void set(const QJsonValue& v) {
if (levels.isEmpty()) {
......@@ -87,7 +87,7 @@ private:
}
QJsonValue* value;
struct Step { QByteArray key; /* TODO union */ QJsonObject object; QJsonArray array; Step(const char* k=nullptr) : key(k) {} };
struct Step { QUtf8String key; /* TODO union */ QJsonObject object; QJsonArray array; Step(const char* k=nullptr) : key(k) {} };
QStack<Step> levels = QStack<Step>(); //!< minimal dynamic context to implement out() and ensure actual building in case QJsonBuilderImpl is abandoned
};
......@@ -111,11 +111,11 @@ class QJsonVisitorImpl
public:
QJsonVisitorImpl(const QJsonValue* v) : value(v) { Q_ASSERT(v); }
struct Error { const char* error; QByteArray path; template<class T> T bind(Val<T> value) { return value.bind(QByteArray(error)+' '+path); } };
struct Error { const char* error; QUtf8String path; template<class T> T bind(Val<T> value) { return value.bind(QUtf8String(error)+' '+path); } };
QVector<Error> errors;
QByteArray currentPath() {
QByteArray path;
QUtf8String currentPath() {
QUtf8String path;
Q_FOREACH(Step s, steps) {
if (s.key) {
path.append('{').append(s.key);
......@@ -148,9 +148,9 @@ protected:
template<class T_> friend class Seq; // calls methods below
template<class T_> friend class Rec; // calls methods below
bool _item(QByteArray& k) { steps.last().key=k; return !(steps.last().item = current(1)->toObject().value(QString::fromUtf8(steps.last().key))).isUndefined(); }
bool _item( ) { steps.last().idx++; return !(steps.last().item = current(1)->toArray (). at( steps.last().idx )).isUndefined(); }
bool _out ( ) { steps.pop() ; return true; }
bool _item(QUtf8String& k) { steps.last().key=k; return !(steps.last().item = current(1)->toObject().value(QString::fromUtf8(steps.last().key))).isUndefined(); }
bool _item( ) { steps.last().idx++; return !(steps.last().item = current(1)->toArray (). at( steps.last().idx )).isUndefined(); }
bool _out ( ) { steps.pop() ; return true; }
private:
const QJsonValue* current(unsigned outer=0) const { return unsigned(steps.size())-outer <= 0 ? value : &(steps[unsigned(steps.size())-outer-1].item); }
......@@ -176,8 +176,8 @@ public:
// Shortcuts
/**/ Val<QWriter> value ( ) { return QWriter(this).value ( ); }
/**/ Val<QWriter> meta ( MetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( MetaData& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData& m) { return QWriter(this).meta ( m); }
/**/ Seq<QWriter> sequence(quint32* s=nullptr) { return QWriter(this).sequence ( s); }
/**/ Rec<QWriter> record (quint32* s=nullptr) { return QWriter(this).record ( s); }
/**/ QWriter null ( ) { return QWriter(this).null ( ); }
......@@ -188,21 +188,21 @@ protected:
bool _null ( ) { return io->write( "null"); }
bool _bind ( const char* s) { return putString( s ); }
bool _bind ( bool& n) { return io->write( n?"true":"false" ); }
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 ( 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)); }
// This dispatch would be more simple with C++17 constexpr if
template<typename T> bool _bind(T t, typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type* =nullptr) {
return io->write(QByteArray::number(qulonglong(t))); }
return io->write(QUtf8String::number(qulonglong(t))); }
template<typename T> bool _bind(T t, typename std::enable_if<std::is_integral<T>::value && std:: is_signed<T>::value>::type* =nullptr) {
return io->write(QByteArray::number( qlonglong(t))); }
return io->write(QUtf8String::number( qlonglong(t))); }
bool _bind(qulonglong& v) { return _bind(v, nullptr); }
bool _bind( qlonglong& v) { return _bind(v, nullptr); }
bool _item(QByteArray& k) { auto r=(io->write(levels.last().sep) || *levels.last().sep=='\0') && putString(k) && 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; }
bool _out ( ) { return io->write(levels.pop() .end); }
bool _item(QUtf8String& k) { auto r=(io->write(levels.last().sep) || *levels.last().sep=='\0') && putString(k) && 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; }
bool _out ( ) { return io->write(levels.pop() .end); }
private:
struct Step { const char* sep; const char* end; };
......@@ -265,7 +265,7 @@ class QJsonReaderImpl
public:
QJsonReaderImpl(QIODevice* io) : io(io) { Q_ASSERT(io); }
struct Error { const char* error; int line; int column; int index; template<class T> T bind(Val<T> value) { QByteArray ba(error); ba.append(' ').append(QByteArray::number(line)).append(':').append(QByteArray::number(column)); return value.bind(ba.constData()); } };
struct Error { const char* error; int line; int column; int index; template<class T> T bind(Val<T> value) { QUtf8String utf8(error); utf8.append(' ').append(QUtf8String::number(line)).append(':').append(QUtf8String::number(column)); return value.bind(utf8.constData()); } };
QVector<Error> errors;
protected:
friend class QScopedChoice<Val<QJsonReader>>;
......@@ -284,7 +284,8 @@ protected:
get('l', "[{\"" )) {
return true;
} else { reportError(qBindExpectedNull); return false; } }
bool _bind ( QByteArray& s) { if ( get('"', "[{\"ntf-0123456789.")) { s.clear(); char c;
bool _bind ( QByteArray& s) { // FIXME Use QString instead of QByteArray
if ( get('"', "[{\"ntf-0123456789.")) { s.clear(); char c;
while ((c=getCharInString()) != '\0' ) { s.append(c); }
return get('"');
} else { reportError(qBindExpectedText); return false; } }
......@@ -312,7 +313,7 @@ protected:
double d; qlonglong i; bool isNegative;
auto r=getNumber(d, i, isNegative); if (r) t=(isNegative?-i:i); return r; }
bool _bind ( ) { isChoice=true; QByteArray t; double d; bool b;
bool _bind ( ) { isChoice=true; QByteArray t; double d; bool b; // FIXME Use QString instead of QByteArray
( (_sequence() && _out())
|| _null()
|| _bind(b)
......@@ -327,23 +328,23 @@ protected:
template<class T_> friend class Rec; // calls methods below
// TODO cache key:value pairs coming out of order wrt to T items() calls
bool _item(QByteArray& k) { Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
}
level.index++;
return _bind(k) && get(':',level.end); }
bool _item( ) { Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
}
level.index++;
return true; }
bool _out ( ) { auto level = levels.pop();
while (get(',', level.end)) {
_bind();
}
return get(*level.end, "}"); }
bool _item(QUtf8String& k) { Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
}
level.index++;
return _bind(k) && get(':',level.end); }
bool _item( ) { Step& level = levels.last();
if (-1 < level.index && !get(',',level.end)) {
return false;
}
level.index++;
return true; }
bool _out ( ) { auto level = levels.pop();
while (get(',', level.end)) {
_bind();
}
return get(*level.end, "}"); }
private:
bool getNumber(double& d, qlonglong&i, bool& isNegative) {
......@@ -451,7 +452,7 @@ private:
};
QJsonReader::QJsonReader(QIODevice* io) : QBaseReader(new QJsonReaderImpl(io), true) {}
template<> struct BindSupport<QJsonReaderImpl, void> : BindNative {};
template<> struct BindSupport<QJsonReaderImpl,QByteArray&> : BindNative {};
template<> struct BindSupport<QJsonReaderImpl,QByteArray&> : BindNative {}; // FIXME Use QString instead of QByteArray
template<> struct BindSupport<QJsonReaderImpl, bool&> : BindNative {};
template<> struct BindSupport<QJsonReaderImpl, float&> : BindNative {};
template<> struct BindSupport<QJsonReaderImpl, double&> : BindNative {};
......
......@@ -61,9 +61,9 @@ class QModelWriter : public IWriter
public:
QModelWriter(QAbstractItemModel* m) : m(m) { Q_ASSERT(m); }
Val<QWriter> meta(MetaData&& m) { return QWriter(this).meta(m); }
Val<QWriter> meta(QMetaData&& m) { return QWriter(this).meta(m); }
protected:
void _meta(MetaData& meta) {
void _meta(QMetaData& meta) {
if (meta.find(qmChildren)!=meta.end()) {
childrenName = meta[qmChildren].toUtf8();
}
......@@ -96,13 +96,13 @@ protected:
bool _sequence (quint32* s=nullptr) { if (d==T) { ++d; return true; } return false; }
bool _record (quint32* s=nullptr) { if (d==S) { ++d; return true; } return false; }
bool _item ( ) { if (d==S) { m->insertRows (idx.row(),1); idx=idx.siblingAtRow (idx.row()+1 ); return true; } return false; }
bool _item ( QByteArray& k) { if (d==R) { // TODO Handle childrenName and names.indexOf(k)<0
bool _item ( QUtf8String& k) { if (d==R) { // TODO Handle childrenName and names.indexOf(k)<0
idx=idx.siblingAtColumn(names.indexOf(k)); return true; } return false; }
private:
QAbstractItemModel* m;
QModelIndex idx;
QByteArray childrenName;
QByteArrayList names;
QUtf8String childrenName;
QList<QUtf8String> names;
QVector<int> sizes;
int d=T; // bind depth wrt successive fluent interface calls
......
......@@ -56,8 +56,8 @@ public:
// Shortcuts
/**/ Val<QWriter> value ( ) { return QWriter(this).value ( ); }
/**/ Val<QWriter> meta ( MetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( MetaData& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData&& m) { return QWriter(this).meta ( m); }
/**/ Val<QWriter> meta ( QMetaData& m) { return QWriter(this).meta ( m); }
/**/ Seq<QWriter> sequence(quint32* s=nullptr) { return QWriter(this).sequence ( s); }
/**/ Rec<QWriter> record (quint32* s=nullptr) { return QWriter(this).record ( s); }
/**/ QWriter null ( ) { return QWriter(this).null ( ); }
......@@ -71,9 +71,9 @@ protected:
bool _sequence(quint32* rows=nullptr) { Q_UNUSED(rows); levels.push(Step(nullptr)); return true; }
bool _record (quint32* cols=nullptr) { Q_UNUSED(cols); levels.push(Step("" )); return true; }
bool _item(QByteArray& k) { levels.last().key=k ; return true; }
bool _item( ) { levels.last().key=nullptr; return true; }
bool _out ( ) { auto level = levels.pop(); set(!level.key.isNull() ? QVariant(level.object) : QVariant(level.array)); return true; }
bool _item(QUtf8String& k) { levels.last().key=k ; return true; }
bool _item( ) { levels.last().key=nullptr; return true; }
bool _out ( ) { auto level = levels.pop(); set(!level.key.isNull() ? QVariant(level.object) : QVariant(level.array)); return true; }
private: