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

Fixed clang warnings

WIP: QBindTable
parent cc9703a3
......@@ -587,8 +587,8 @@ def writeTsvJson(path, events, fields=['_timestamp','_elapsed_s','_severity','_c
withoutRedundancy = [i for i,n in enumerate(names)
if n not in ['_timestamp','_severity','_function','_path','_line','_count',
'_computer_id','_process_id','_thread_id',
'_user_id','_group_id','_object_id']]
'_computer_id','_process_id','_thread_id',
'_user_id','_group_id','_object_id']]
elapsedSecsField = names.index('_elapsed_s')
j = JsonEncoder()
j.ensure_ascii = False
......
......@@ -32,4 +32,5 @@ HEADERS += \
QBind_impl.h \
QCbor_impl.h \
QJson_impl.h \
QDataStream_impl.h
QDataStream_impl.h \
QBindTable_impl.h
/****************************************************************************
* **
* ** Copyright (C) 2017 MinMaxMedical.
* ** All rights reserved.
* ** Contact: MinMaxMedical <InCAS@MinMaxMedical.com>
* **
* ** This file is part of the modmedLog module.
* **
* ** $QT_BEGIN_LICENSE:BSD$
* ** You may use this file under the terms of the BSD license as follows:
* **
* ** "Redistribution and use in source and binary forms, with or without
* ** modification, are permitted provided that the following conditions are
* ** met:
* ** * Redistributions of source code must retain the above copyright
* ** notice, this list of conditions and the following disclaimer.
* ** * Redistributions in binary form must reproduce the above copyright
* ** notice, this list of conditions and the following disclaimer in
* ** the documentation and/or other materials provided with the
* ** distribution.
* ** * Neither the name of MinMaxMedical S.A.S. and its Subsidiary(-ies) nor
* ** the names of its contributors may be used to endorse or promote
* ** products derived from this software without specific prior written
* ** permission.
* **
* ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
* ** $QT_END_LICENSE$
* **
* ****************************************************************************/
#pragma once
#include <type_traits>
#include <QtCore/qvector.h>
#include <QtCore/qmap.h>
#include "QBind_impl.h"
// //////////////////////////////////////////////////////////////////////////
// QBind<QTableWriter,T> support
/// Binds generically any T that would bind as sequence() of record().bind("k",vk)... as:
/// record()
/// .bind("cols",columnNames,QVector<const char*>())
/// .bind("rows",sequence() of sequence(columnNames.size()).bind(v1)...)
template<class TResult>
class QTableWriter : public QMovedWriter<QTableWriter<TResult>>
{
TResult* top=nullptr;
Names columnNames;
quint32 max=0;
enum : int {
Unsupported=-1,
T=0, //!< table () called and nothing else
S=1, //!< sequence() called and zero or more item()
R=2, //!< record () called, expecting
};
int s=T; // bind depth wrt successive fluent interface calls
int col=-1; // bind state wrt table columnNames
int current=-1; // bind state wrt successive record() bind() calls
QMap<int,QWritable<TResult>> cache; // for record() items bound too soon w.r.t. columnNames
protected:
QTableWriter(const QTableWriter &o) : QMovedWriter<QTableWriter<TResult>>(), top(o.top), columnNames(o.columnNames), max(o.max), s(o.s), col(o.col), current(o.current), cache(o.cache) {} // It is important that scoped copies start again from level 0 to avoid duplicate _out() calls
QTableWriter &operator=(const QTableWriter &) = delete;
public:
Q_ENABLE_MOVE(QTableWriter, std::swap(top, o.top); columnNames=o.columnNames; max=o.max; s=o.s; col=o.col; current=o.current; cache=o.cache; ) // state other than top is copied to facilitate debugging
QTableWriter(TResult* top, const Names& c) : top(top), columnNames(c), max(quint32(columnNames.size())) { /*top._record() && top._item("cols") && top._bind(columnNames) && top._item("rows") */ }
~QTableWriter() {
// if (!(current<int(max)))
// Q_ASSERT(false);
// if (top) { while (T<s || (R<s && 0<current)) _out(); }
}
operator bool() { return top && top->operator bool(); } // for QMovedWriter
protected:
friend class QMovedWriter<QTableWriter>;
// Action \ State(s,col,current) | Expected sequence().record() calls | Cells calls | Unsupported calls
template<class T_> friend class Val; // calls methods below
operator TResult() { return top ? *top : TResult(); }
/**/ bool _null( ) {
/**/ if (s>=R && col==current) {
return ___null ( ); }
else if (s>=R && -1==current) {
return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
template<typename T> bool _bind(T&& t) {
/**/ if (s>=R && col==current) {
return __bind ( t); }
else if (s>=R && -1==current) {
return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
bool _sequence (quint32* rows=nullptr) {
if (s==T && top->_sequence(rows)) {
++s; return true; }
else if (s>=R && col==current) {
++s; return top->_sequence(rows); }
else if (s>=R && -1==current) {
++s; return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
bool _record (quint32* size=nullptr) {
if (s==S && top->_sequence(&max)) {
++s; return __record(); }
else if (s>=R && col==current) {
++s; return top->_record (size); }
else if (s>=R && -1==current) {
++s; return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
template<class T_> friend class Seq; // calls methods below
template<class T_> friend class Rec; // calls methods below
bool _out ( ) {
if (s==S && top->_out ( )) {
--s; return true; }
else if (s==R && top->_out ( )) {
--s; return true; }
else if (s>R && col==current && top->_out()) {
--s; return true; }
else if (s>R && -1==current) {
--s; return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
bool _item ( ) {
if (s==S && top->_item ( )) {
return true; }
else if (s>R && col==current) {
return top->_item ( ); }
else if (s>R && -1==current) {
return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
bool _item ( QByteArray& k) {
current=columnNames.indexOf(k.constData()); // std::enable_if<IsWriter<TResult>>
if (s==R ) {
return __item(k); }
else if (s>R && col==current) {
return top->_item ( k); }
else if (s>R && -1==current) {
return true; /* ignored but let the fluent interface bind the rest */ }
else {
s=Unsupported; return false; } }
// Handling of record items in or out of order using a cache
bool __record() {
col = -1;
cache.clear();
return true;
}
bool __item(QByteArray& k) {
while (col+1<current // previously cached items are ignored
&& cache.contains(col+1)) {
col++;
return top->_item() && cache[col].bind(Val<TResult>(top->_unsafeCopy()));
}
if (col+1==current) {
col++;
return top->_item();
}
else
return true; /* ignored but let the fluent interface bind the rest */
}
bool ___null() {
if (col<current) {
cache.insert(current,QWritable<TResult>(nullptr));
return true;
}
else if (col==current)
return top->_null();
else
return true; /* ignored but let the fluent interface bind the rest */
}
template<typename T>
bool __bind(T&& t) {
if (col<current) {
cache.insert(current,QWritable<TResult>(t));
return true;
}
else if (col==current)
return top->_bind(t);
else
return true; /* ignored but let the fluent interface bind the rest */
}
};
template<class TResult,typename T> struct BindSupport<QTableWriter<TResult>,T> : BindSupport<TResult,T> {};
template<class TResult_>
template<typename T>
TResult_ Val<TResult_>::table(const Names& cols, T&& t) {
Q_ASSERT(cols.size()>0);
auto unsafeCopy(m_out._unsafeCopy());
return QTableWriter<TResult_>(&unsafeCopy,cols).bind(t);
}
// TODO template<class TImpl> class QTableReader
......@@ -119,6 +119,8 @@ struct QBind<TResult, const T&, IsReader<TResult>> { static TResult bind(Val<TRe
// - etc...
// See Person::bind() definition below for an example
#include <QtCore/qvector.h>
struct BindNative {};
struct BindGeneric {};
template<class TImpl, typename T, typename TEnabledIf=void> struct BindSupport : BindGeneric {};
......@@ -128,6 +130,9 @@ template<class TImpl> struct BindSupport<TImpl,void,void> : BindGeneric {};
template<class T_> class Rec; //!< a Record data structure defined below
template<class T_> class Seq; //!< a Sequence data structure defined below
//template<class TResult> class QBindTable;
//using Names = QVector<QByteArray>;
template<class T_> class Val //!< a choice of sequence(), null(), or any value with a textual representation
{
Q_DISABLE_COPY(Val)
......@@ -141,12 +146,16 @@ public:
operator bool() { return m_out.operator bool(); } //!< to drive QBind<TResult,T>() traversal
TImpl* operator->() { return m_out.operator ->(); }
/**/ Seq<T_> sequence (quint32* rows=nullptr) { if (Q_LIKELY(m_out) && m_out->_sequence (rows)) return Seq<T_>(std::move(m_out)); else return Seq<T_>(); }
/**/ Rec<T_> record (quint32* cols=nullptr) { if (Q_LIKELY(m_out) && m_out->_record (cols)) return Rec<T_>(std::move(m_out)); else return Rec<T_>(); }
/**/ T_ null ( ) { if (Q_LIKELY(m_out) && m_out->_null ( )) return std::move(m_out) ; else return T_ (); }
template<typename T> T_ bind ( T&& t) { if (_bind(BindSupport<TImpl, T>(),std::forward<T> (t))) return std::move(m_out) ; else return T_ (); }
/**/ T_ any ( ) { if (_bind(BindSupport<TImpl,void>() )) return std::move(m_out) ; else return T_ (); }
// TODO? add (const char* type) variants for sequence and record to let Writer Impl choose specialised repr (unordered dict..., XML tag)
// TODO template<typename T> T_ table (const Names& cols,T&& t); // TODO return Tab<T_> instead of taking a T&&
/**/ Seq<T_> sequence(quint32* rows=nullptr) { if (Q_LIKELY(m_out) && m_out->_sequence (rows)) return Seq<T_>(std::move(m_out)); else return Seq<T_>(); }
/**/ Rec<T_> record (quint32* cols=nullptr) { if (Q_LIKELY(m_out) && m_out->_record (cols)) return Rec<T_>(std::move(m_out)); else return Rec<T_>(); }
/**/ T_ null ( ) { if (Q_LIKELY(m_out) && m_out->_null ( )) return std::move(m_out) ; else return T_ (); }
template<typename T> T_ bind ( T&& t) { if (_bind(BindSupport<TImpl, T>(),std::forward<T> (t))) return std::move(m_out) ; else return T_ (); }
/**/ T_ any ( ) { if (_bind(BindSupport<TImpl,void>() )) return std::move(m_out) ; else return T_ (); }
// TODO Add bind with default T specialised for Reader/Writer (do not write default?)
T_ bind(const char* const& t); // special handling of both (const char*)'s const& and &&
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( ); }
......@@ -155,6 +164,8 @@ private:
T_ m_out = T_(); //!< moved context of current traversal up to TResult that will reference the val itself (be it a QIODevice or QCborValue)
};
template<class T_> T_ Val<T_>::bind(const char* const& t/*, IsWriter<typename T_::TResult>* =nullptr*/) { const char* s(t); return bind(s) ; } // special handling of both (const char*)'s const& and && as copying a const char* costs nothing
//template<class T_> T_ Val<T_>::bind(const char* const& t, IsReader<typename T_::TResult>* =nullptr ) { QByteArray s ; return bind(s) && s==t; } // special handling of both (const char*)'s const& and && for Reader
template<class T_> class Seq
{
......@@ -305,6 +316,7 @@ protected:
friend class ScopedChoice<Val<TResult>>;
void setChoice(bool) {} // not implemented like reportError
private:
//template<typename TResult> friend class QTableWriter;
template<typename T_> friend class Val;
template<typename T_> friend class Seq;
template<typename T_> friend class Rec;
......@@ -335,9 +347,9 @@ template<class TResult>
struct QBind<TResult, void, IsReader<TResult>> { static TResult bind(Val<TResult> src) {
{
ScopedChoice<Val<TResult>> choice(src);
Seq<TResult> srcSeq; if (srcSeq = src.sequence()) { return srcSeq.out(); }
Rec<TResult> srcRec; if (srcRec = src.record ()) { return srcRec.out(); }
/**/TResult srcRes; QString t; if (srcRes = src.bind (t)) { return srcRes ; } // TODO QByteArray?
Seq<TResult> srcSeq; if ((srcSeq = src.sequence())) { return srcSeq.out(); }
Rec<TResult> srcRec; if ((srcRec = src.record ())) { return srcRec.out(); }
/**/TResult srcRes; QString t; if ((srcRes = src.bind (t))) { return srcRes ; } // TODO QByteArray?
}
return src.null();
}};
......@@ -384,7 +396,7 @@ template<class TResult>
struct QBind<TResult, float&, IsWriter<TResult>> { static TResult bind(Val<TResult> dst, float& src) {
// 8 = std::numeric_limits<float>::max_digits10
char n[1+std::numeric_limits<float>::digits10+1+8+1+1+std::numeric_limits<float>::max_exponent10+1];
sprintf(n, "%.8g", src);
sprintf(n, "%.8g", double(src));
return dst.bind(static_cast<const char*>(n));
}};
......@@ -426,9 +438,9 @@ template<class TResult, typename T>
struct QBind<TResult, QVector<T>&, IsReader<TResult>> { static TResult bind(Val<TResult> src, QVector<T>& dst) {
auto s(src.sequence());
Val<Seq<TResult>> i;
while (i = s.item()) {
while ((i = s.item())) {
T t;
if (s = i.bind(t)) // gives back control to s, enabling the next s.item() call
if((s = i.bind(t))) // gives back control to s, enabling the next s.item() call
dst.append(t);
}
return s;
......@@ -445,11 +457,11 @@ struct QBind<TSrcResult, Val<TDst>&&, IsReader<TSrcResult>> { static TSrcResult
{
ScopedChoice<Val<TSrcResult>> choice(src);
Seq<TSrcResult> srcSeq; Seq<TDst> dstSeq;
if ( srcSeq = src.sequence()) {
if ( (srcSeq = src.sequence())) {
/**/ dstSeq = dst.sequence();
Val<TSrcResult> srcVal; Val<TDst> dstVal;
while (srcVal = srcSeq._unsafeItem()) { // using item()'s Val<Seq<TSrcResult> would cause an infinite compiler loop to generate corresponding QBind<Val<Seq<Seq<...>>,_> functions
while((srcVal = srcSeq._unsafeItem())) { // using item()'s Val<Seq<TSrcResult> would cause an infinite compiler loop to generate corresponding QBind<Val<Seq<Seq<...>>,_> functions
dstVal = dstSeq._unsafeItem();
srcSeq = srcVal.bind(std::move(dstVal));
}
......@@ -458,11 +470,11 @@ struct QBind<TSrcResult, Val<TDst>&&, IsReader<TSrcResult>> { static TSrcResult
return srcSeq.out();
}
Rec<TSrcResult> srcRec; Rec<TDst> dstRec;
if ( srcRec = src.record()) {
if ( (srcRec = src.record())) {
/**/ dstRec = dst.record();
QByteArray srcKey; Val<TSrcResult> srcVal; Val<TDst> dstVal;
while (srcVal = srcRec._unsafeItem(srcKey)) {
while((srcVal = srcRec._unsafeItem(srcKey))) {
dstVal = dstRec._unsafeItem(srcKey);
srcRec = srcVal.bind(std::move(dstVal));
}
......@@ -470,10 +482,10 @@ struct QBind<TSrcResult, Val<TDst>&&, IsReader<TSrcResult>> { static TSrcResult
/**/ dstRec.out();
return srcRec.out();
}
bool b; if (srcRes = src.bind(b)) { dst.bind(b); return srcRes; }
double d; if (srcRes = src.bind(d)) { dst.bind(d); return srcRes; }
bool b; if ((srcRes = src.bind(b))) { dst.bind(b); return srcRes; }
double d; if ((srcRes = src.bind(d))) { dst.bind(d); return srcRes; }
// TODO other native types we do not want to treat as text: qlonglong, qulonglong, float (to optimize CborWriter output)
QString t; if (srcRes = src.bind(t)) { dst.bind(t); return srcRes; }
QString t; if ((srcRes = src.bind(t))) { dst.bind(t); return srcRes; }
}
if (!(srcRes = src.null())) srcRes.reportError("Expected sequence|record|boolean|decimal|text|null");
/**/ dst.null();
......@@ -510,11 +522,11 @@ public:
private:
template<class TRes, typename T>
struct Copy : IWritable<TRes> {
Copy(T&& t) : m_t(std::move(t)) {}
Copy(const T& t) : m_t(t) {}
TRes writeTo(Val<TRes>&& v) const override { return v.bind(m_t); }
template<class TOtherRes> operator Copy<TOtherRes,T>() { return *this; }
private:
const T m_t;
T m_t;
};
};
......@@ -42,6 +42,7 @@
#include <type_traits>
#include <QtCore/qiodevice.h>
#include <QtCore/qendian.h>
#include <QtCore/qstack.h>
#include "QBind_impl.h"
......@@ -50,7 +51,7 @@ namespace cbor {
//! CBOR Major types
//! Encoded in the high 3 bits of the descriptor byte
//! \see http://tools.ietf.org/html/rfc7049#section-2.1
enum MajorTypes {
enum MajorTypes : char {
UnsignedIntegerType = 0,
NegativeIntegerType = 1,
TextStringType = 3,
......@@ -61,7 +62,7 @@ enum MajorTypes {
//! CBOR simple and floating point types
//! Encoded in the low 5 bits of the descriptor byte when the Major Type is 7.
enum SimpleTypes {
enum SimpleTypes : char {
FalseValue = 20,
TrueValue = 21,
NullValue = 22,
......@@ -70,8 +71,8 @@ enum SimpleTypes {
Break = 31
};
enum {
SmallValueBitLength = 5U,
enum : char {
SmallValueBitLength = 5U,
Value8Bit = 24U,
Value16Bit = 25U,
Value32Bit = 26U,
......@@ -81,20 +82,20 @@ enum {
MajorTypeShift = SmallValueBitLength,
};
enum : unsigned char {
BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift),
enum : char {
BreakByte = Break | char(SimpleTypesType << MajorTypeShift),
IndefiniteLengthMapByte = IndefiniteLength | (MapType << MajorTypeShift),
IndefiniteLengthArrayByte = IndefiniteLength | (ArrayType << MajorTypeShift),
NullByte = NullValue | (SimpleTypesType << MajorTypeShift),
TrueByte = TrueValue | (SimpleTypesType << MajorTypeShift),
FalseByte = FalseValue | (SimpleTypesType << MajorTypeShift)
IndefiniteLengthMapByte = IndefiniteLength | char(MapType << MajorTypeShift),
IndefiniteLengthArrayByte = IndefiniteLength | char(ArrayType << MajorTypeShift),
NullByte = NullValue | char(SimpleTypesType << MajorTypeShift),
TrueByte = TrueValue | char(SimpleTypesType << MajorTypeShift),
FalseByte = FalseValue | char(SimpleTypesType << MajorTypeShift)
};
enum tag{
Tag = 192,
DateTime = 0,
CborDocument = 55799,
enum {
Tag = 192,
DateTime = 0,
CborDocument = 55799,
};
} // cbor
......@@ -115,6 +116,7 @@ public:
operator bool() { return io; } // for QMovedWriter
protected:
friend class QMovedWriter<CborWriter>;
//template<class TResult> friend class QTableWriter;
template<class T_> friend class Val; // calls methods below
bool _sequence(quint32* rows=nullptr) { levels.push(rows);
......@@ -124,15 +126,15 @@ protected:
if (cols) return putInteger(cbor:: MapType, *cols );
return io->putChar(cbor::IndefiniteLengthMapByte ); }
bool _null ( ) { return io->putChar(cbor::NullByte ); }
bool _bind ( const char* s) { return putInteger(cbor::TextStringType, strlen(s)) && (io->write(s) || *s=='\0'); }
bool _bind ( const char*& s) { return putInteger(cbor::TextStringType, strlen(s)) && (io->write(s) || *s=='\0'); }
bool _bind ( bool& b) { return io->putChar(b ? cbor::TrueByte : cbor::FalseByte); }
bool _bind ( float& n) { union { float value; quint32 bits; } number = { n };
char bytes[sizeof(number.bits)]; qToBigEndian(number.bits, bytes);
return (io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::SinglePrecisionFloat)
return (io->putChar(char(cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::SinglePrecisionFloat)
&& io->write(bytes, sizeof(bytes))); }
bool _bind ( double& n) { union { double value; quint64 bits; } number = { n };
char bytes[sizeof(number.bits)]; qToBigEndian(number.bits, bytes);
return (io->putChar((cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::DoublePrecisionFloat)
return (io->putChar(char(cbor::SimpleTypesType << cbor::MajorTypeShift) | cbor::DoublePrecisionFloat)
&& io->write(bytes, sizeof(bytes))); }
// This dispatch would be more simple with C++17 constexpr if
......@@ -145,28 +147,28 @@ protected:
template<class T_> friend class Seq; // calls methods below
template<class T_> friend class Rec; // calls methods below
bool _item(QByteArray& k) { return (putInteger(cbor::TextStringType, k.size()) && (io->write(k) || k.isEmpty())); }
bool _item( ) { return true ; }
bool _out ( ) { return levels.pop() ? true : io->putChar (cbor::BreakByte); }
bool _item(QByteArray& k) { return (putInteger(cbor::TextStringType, quint64(k.size())) && (io->write(k) || k.isEmpty())); }
bool _item( ) { return true ; }
bool _out ( ) { return levels.pop() ? true : io->putChar (cbor::BreakByte); }
private:
bool putInteger(char majorType, quint64 n)
{
// See https://tools.ietf.org/html/rfc7049#section-2.2 if more performance is needed
if (n < 24) { return io->putChar((majorType << cbor::MajorTypeShift) | n);
if (n < 24) { return io->putChar(char(majorType << cbor::MajorTypeShift) | char(n));
} else {
char bytes[8];
if (n <= 0xff ) { qToBigEndian(quint8 (n),bytes); return io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value8Bit ) && io->write(bytes,sizeof(quint8 )); }
if (n <= 0xffff ) { qToBigEndian(quint16(n),bytes); return io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value16Bit) && io->write(bytes,sizeof(quint16)); }
if (n <= 0xffffffffL) { qToBigEndian(quint32(n),bytes); return io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value32Bit) && io->write(bytes,sizeof(quint32)); }
else { qToBigEndian( n ,bytes); return io->putChar((majorType << cbor::MajorTypeShift) | cbor::Value64Bit) && io->write(bytes,sizeof(quint64)); }
if (n <= 0xff ) { qToBigEndian(quint8 (n),bytes); return io->putChar(char(majorType << cbor::MajorTypeShift) | cbor::Value8Bit ) && io->write(bytes,sizeof(quint8 )); }
if (n <= 0xffff ) { qToBigEndian(quint16(n),bytes); return io->putChar(char(majorType << cbor::MajorTypeShift) | cbor::Value16Bit) && io->write(bytes,sizeof(quint16)); }
if (n <= 0xffffffffL) { qToBigEndian(quint32(n),bytes); return io->putChar(char(majorType << cbor::MajorTypeShift) | cbor::Value32Bit) && io->write(bytes,sizeof(quint32)); }
else { qToBigEndian( n ,bytes); return io->putChar(char(majorType << cbor::MajorTypeShift) | cbor::Value64Bit) && io->write(bytes,sizeof(quint64)); }
}
}
QIODevice* io = nullptr;
QStack<bool> levels = QStack<bool>(); //!< minimal dynamic context to ensure well-formedness in case TResult is abandoned
};
template<> struct BindSupport<CborWriter,const char*> : BindNative {};
template<> struct BindSupport<CborWriter, bool&> : BindNative {};
template<> struct BindSupport<CborWriter, float&> : BindNative {};
template<> struct BindSupport<CborWriter, double&> : BindNative {};
template<> struct BindSupport<CborWriter,const char*&> : BindNative {};
template<> struct BindSupport<CborWriter, bool&> : BindNative {};
template<> struct BindSupport<CborWriter, float&> : BindNative {};
template<> struct BindSupport<CborWriter, double&> : BindNative {};
template<typename T> struct BindSupport<CborWriter,T&,typename std::enable_if<std::is_integral<T>::value>::type> : BindNative {};
......@@ -178,7 +178,7 @@ protected:
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 steps.size()-outer <= 0 ? value : &(steps[steps.size()-outer-1].item); }
const QJsonValue* current(unsigned outer=0) const { return unsigned(steps.size())-outer <= 0 ? value : &(steps[unsigned(steps.size())-outer-1].item); }
const QJsonValue* value;
struct Step { const char* key=nullptr; int idx=-1; QJsonValue item; Step() = default; };
......@@ -186,7 +186,6 @@ private:
bool isChoice = false;
};
QJsonVisitor::QJsonVisitor(const QJsonValue* v) : QScopedResult(new JsonVisitorImpl(v), true) {}
template<> struct BindSupport<JsonVisitorImpl,const char*> : BindNative {};
template<> struct BindSupport<JsonVisitorImpl, QString&> : BindNative {};
template<> struct BindSupport<JsonVisitorImpl, bool&> : BindNative {};
template<> struct BindSupport<JsonVisitorImpl, double&> : BindNative {};
......@@ -300,7 +299,7 @@ class QJsonReaderImpl
{
Q_DISABLE_COPY(QJsonReaderImpl)
struct Step { int index; const char* end; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {}; };
struct Step { int index; const char* end; Step(int i=-1, const char* e=nullptr) : index(i), end(e) {} };
QIODevice* io;
int line = 0, column = 0, index = -1;
......@@ -320,33 +319,33 @@ protected:
template<class T_> friend class Val; // calls methods below
bool _sequence(quint32* rows=nullptr) { if (get('[', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"]")); return true; } reportError(qBindExpectedSequence); return false; }
bool _record (quint32* cols=nullptr) { if (get('{', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"}")); return true; } reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (get('n', "[{\"ntf-0123456789.") &&
get('u', "[{\"" ) &&
get('l', "[{\"" ) &&
get('l', "[{\"" )) {
return true;
} else { reportError(qBindExpectedNull); return false; } }
bool _bind ( QByteArray& s) { if ( get('"', "[{\"ntf-0123456789.")) { s.clear(); char c;
while ((c=getCharInString()) != '\0' ) { s.append(c); }
return get('"');
} else { reportError(qBindExpectedText); return false; } }
bool _bind ( bool& b) { if (get('t', "[{\"ntf-0123456789.") &&
get('r', "[{\"" ) &&
get('u', "[{\"" ) &&
get('e', "[{\"" )) { b=true;
return true;
} else
if (get('f', "[{\"ntf-0123456789.") &&
get('a', "[{\"" ) &&
get('l', "[{\"" ) &&
get('s', "[{\"" ) &&
get('e', "[{\"" )) { b=false;
return true;
} else { reportError(qBindExpectedBoolean); return false; } }
bool _bind ( float& n) { double d; qlonglong i; bool b; auto r=getNumber(d,i,b); if (r) n=d; return r; }
bool _bind ( double& n) { double d; qlonglong i; bool b; auto r=getNumber(d,i,b); if (r) n=d; return r; }
bool _sequence(quint32* =nullptr) { if (get('[', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"]")); return true; } reportError(qBindExpectedSequence); return false; }
bool _record (quint32* =nullptr) { if (get('{', "[{\"ntf-0123456789.")) { levels.push(Step(-1,"}")); return true; } reportError(qBindExpectedRecord ); return false; }
bool _null ( ) { if (get('n', "[{\"ntf-0123456789.") &&
get('u', "[{\"" ) &&
get('l', "[{\"" ) &&
get('l', "[{\"" )) {