Commit 9e809e33 authored by EXT Arnaud Clère's avatar EXT Arnaud Clère

Merge branch 'master' of https://gricad-gitlab.univ-grenoble-alpes.fr/

modmed/modmedLog
parents b345b8cf 432faf9a
BSD 3-Clause License
Copyright (c) 2015, MinMaxMedical
All rights reserved.
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 the copyright holder 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 HOLDER 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.
# modmedLog
The open source modmedLog C++ library allows producing analyzable traces from
existing standard C++ tracepoints, and then improving them while refactoring the
source code.
It is designed to provide JSON traces compatible with ParTraP tools and is
provided AS-IS according to the BSD license.
It is not actively developed anymore, but there is still ongoing work to
integrate modmedLog features to the [Qt framework](https://www.qt.io/) based on
the [QBind proof-of-concept](/tests/QBind).
\ No newline at end of file
......@@ -9,7 +9,7 @@ QIdentifierLiteral qBindExpectedBytes ("ExpectedBytes" );
QIdentifierLiteral qBindExpectedInteger ("ExpectedInteger" );
QIdentifierLiteral qBindExpectedDecimal ("ExpectedDecimal" );
QIdentifierLiteral qBindExpectedSmallerNumber ("ExpectedSmallerNumber" );
QIdentifierLiteral qBindExpectedPositiveNumber("ExpectedPositiveNumber");
QIdentifierLiteral qBindExpectedPositiveInteger("ExpectedPositiveInteger");
QIdentifierLiteral qBindExpectedBoolean ("ExpectedBoolean" );
QIdentifierLiteral qBindExpectedConstant ("ExpectedConstant" );
......
......@@ -63,7 +63,7 @@ extern QIdentifierLiteral qBindExpectedBytes ;
extern QIdentifierLiteral qBindExpectedInteger ;
extern QIdentifierLiteral qBindExpectedDecimal ;
extern QIdentifierLiteral qBindExpectedSmallerNumber ;
extern QIdentifierLiteral qBindExpectedPositiveNumber;
extern QIdentifierLiteral qBindExpectedPositiveInteger;
extern QIdentifierLiteral qBindExpectedBoolean ;
extern QIdentifierLiteral qBindExpectedConstant ;
......@@ -148,9 +148,9 @@ template<> struct BindSupport< QVariant> : BindNative {};
struct QAbstractValue {
virtual ~QAbstractValue() = default;
virtual QValueMode mode() const = 0; //!< \remark a static constexpr QValueMode Mode did not exhibit noticeable performance improvements and may trigger twice more code generation for Read/Write independant QBind like Person::bind
virtual QValueMode mode() const noexcept = 0; //!< \remark a static constexpr QValueMode Mode did not exhibit noticeable performance improvements and may trigger twice more code generation for Read/Write independant QBind like Person::bind
virtual bool _isOk() = 0; //!< Current operation status
virtual bool _isOk() const noexcept = 0; //!< Current operation status
virtual bool trySequence(quint32* size=nullptr) = 0;
virtual bool tryRecord (quint32* size=nullptr) = 0;
......@@ -523,7 +523,7 @@ struct QAbstractValueWriter : public QAbstractValue
virtual QValueMode mode() const noexcept { return QValueMode::Write; }
virtual bool _isOk() noexcept { return true; } //!< Write status ignored by default (no need to test intermediate status to choose between trySequence(), etc.
virtual bool _isOk() const noexcept { return true; } //!< Write status ignored by default (no need to test intermediate status to choose between trySequence(), etc.
virtual bool tryItem( ) = 0;
virtual bool tryItem(QIdentifier& n) = 0;
......@@ -756,9 +756,9 @@ protected:
const QByteArray& bytes = s.utf8();
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; };
auto fromHex = [](char a) -> char { return '0'<=a && a<='9' ? a-'0' : 'A'<=a && a<='F' ? a-'A'+10 : 'a'<=a && a<='f' ? a-'a'+10 : -1; };
for (int i=0; i < b.size(); i++) {
char highDigit=toHex(bytes[2+2*i]), lowDigit=toHex(bytes[2+2*i+1]);
char highDigit=fromHex(bytes[2+2*i]), lowDigit=fromHex(bytes[2+2*i+1]);
if (highDigit<0 || lowDigit<0)
return false;
b.append(char(highDigit<<4)+lowDigit);
......
......@@ -112,7 +112,7 @@ public:
/**/ QSeq<QValueStatus> sequence(quint32* s=nullptr) { return QValueStatus(this).value().sequence(s); }
template<typename T> QValueStatus bind ( T&& t) { return QValueStatus(this).value().bind(std::forward<T>(t)); }
protected:
bool _isOk() noexcept { return io; }
bool _isOk() const noexcept { return io; }
bool trySequence(quint32* rows=nullptr) { levels.push_back(rows);
if (Q_LIKELY(rows)) { putInteger (*rows , cbor::ArrayType); }
......@@ -253,12 +253,12 @@ protected:
bool trySequence(quint32* =nullptr) { if (current().isArray ()) { steps.push(Step()); return true; } _reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (current().isMap ()) { steps.push(Step()); return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current().isNull ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s) ) { u . set (s.toUtf8() ); return true; } return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s) ) { u = s .toUtf8 (); return true; } return false; }
bool tryBind ( QString& v) { if (current().isString ()) { v = current().toString (); return true; } _reportError(qBindExpectedText ); return false; }
bool tryBind ( bool& v) { if (current().isBool ()) { v = current().toBool (); return true; } _reportError(qBindExpectedBoolean ); return false; }
bool tryBind ( qint64& t) { if (current().isInteger ()) { t = current().toInteger (); return true; } _reportError(qBindExpectedInteger ); return false; }
bool tryBind ( quint64& t) { qint64 i; if (tryBind(i) ) { t = quint64(i) ; return true; } return false; }
bool tryBind ( float& v) { double d; if (tryBind(d) ) { v = float(d) ; return true; } return false; }
bool tryBind ( quint64& t) { qint64 i; if (tryBind(i) ) { t = quint64(i) ; return true; } return false; }
bool tryBind ( float& v) { double d; if (tryBind(d) ) { v = float(d) ; return true; } return false; }
bool tryBind ( double& v) { if (current().isDouble ()) { v = current().toDouble (); return true; } _reportError(qBindExpectedDecimal ); return false; }
bool tryBind ( QByteArray& v) { QString s; if (current().isByteArray()) { v = current().toByteArray(); return true; } _reportError(qBindExpectedBytes ); return false; }
......@@ -267,7 +267,7 @@ protected:
bool tryItem( ) { steps.last().idx++; return !(steps.last().item = current(1).toArray(). at(steps.last().idx )).isUndefined(); }
bool tryOut ( ) { steps.pop() ; return true; }
bool _isOk() { return cbor; }
bool _isOk() const noexcept { return cbor; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral e) { if (!isChoice) errors.append(Error{ e, currentPath() }); }
private:
......@@ -304,7 +304,7 @@ protected:
skipTag(); if (isMap () && enterContainer()) { levels.push(Level()); return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (caching) { cacheLevel++; return caching->tryNull() && cacheOut(); }
skipTag(); if (isNull () && next ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s)) { u.set(s.toUtf8()); return true; } return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s)) { u = s.toUtf8(); return true; } return false; }
bool tryBind ( QString& s) { if (caching) { cacheLevel++; return caching->tryBind(s) && cacheOut(); }
skipTag(); if (isString()) {
s.resize(0);
......@@ -355,7 +355,7 @@ protected:
bool tryBind ( quint64& t) { if (caching) { cacheLevel++; return caching->tryBind(t) && cacheOut(); }
quint64 i; bool neg;
if (!getInteger(i,neg)) { _reportError(qBindExpectedInteger ); return false; }
if ( neg ) { _reportError(qBindExpectedPositiveNumber); return false; }
if ( neg ) { _reportError(qBindExpectedPositiveInteger); return false; }
t=i; return true; }
bool tryBind ( qint64& t) { if (caching) { cacheLevel++; return caching->tryBind(t) && cacheOut(); }
quint64 i; bool neg;
......@@ -427,7 +427,7 @@ protected:
return leaveContainer(); }
bool _any() { return next(); }
bool _isOk() { return lastError()==QCborError::NoError; }
bool _isOk() const noexcept { return const_cast<QCborReader*>(this)->lastError()==QCborError::NoError; }
void _setChoice(bool b) { isChoice = b; }
void _reportError(QIdentifierLiteral e) { if (!isChoice) errors.append(Error{ e, currentOffset(), lastError() }); }
private:
......
......@@ -13,7 +13,7 @@ struct Latin1 { static bool isValid(const char* s, int size); };
struct Utf8 { static bool isValid(const char* s, int size); };
template<class TContent> class QDataView;
// ...
//! Associates a QByteArray with TContent type to allow static checks and optimizations when data is transferred
template<class TContent> class QData
{
......@@ -30,10 +30,10 @@ public:
constexpr bool isNull() const noexcept { return m_bytes.isNull (); }
constexpr bool isEmpty() const noexcept { return m_bytes.isEmpty(); }
constexpr int size() const noexcept { return m_bytes.size (); }
constexpr const char* data() const noexcept { return m_bytes.data(); }
constexpr const char* data() const noexcept { return m_bytes.data (); }
void set(QByteArray&& b) noexcept { m_bytes=b; }
void set(QByteArray& b) noexcept { m_bytes=b; }
QData& operator=( QByteArray&& b) noexcept { m_bytes=b; Q_ASSERT(Content::isValid(m_bytes.data(), m_bytes.size())); return *this; }
QData& operator=(const QByteArray& b) noexcept { m_bytes=b; Q_ASSERT(Content::isValid(m_bytes.data(), m_bytes.size())); return *this; }
protected:
template<class T> friend bool operator==(const QData <T> &a, const QData <T> &b) noexcept;
template<class T> friend bool operator!=(const QData <T> &a, const QData <T> &b) noexcept;
......@@ -159,8 +159,9 @@ class QUtf8Data : public QData<Utf8>
{
public:
using QData::QData;
using QData::operator=;
const QByteArray& utf8() const noexcept { return m_bytes; }
const QByteArray utf8() const noexcept { return m_bytes; }
protected:
friend QDataStream &operator<<(QDataStream &out, const QUtf8Data &p) { return out << QString(p.m_bytes); }
friend QDataStream &operator>>(QDataStream &out, QUtf8Data &p) { QString s; out >> s; p.m_bytes = s.toUtf8(); return out; }
......@@ -174,7 +175,7 @@ class QAsciiData : public QData<Ascii>
public:
using QData::QData;
const QByteArray& utf8() const noexcept { return m_bytes; }
const QByteArray utf8() const noexcept { return m_bytes; }
constexpr QLatin1String latin1() const noexcept { return QLatin1String(m_bytes.data(), m_bytes.size()); }
};
Q_DECLARE_METATYPE(QAsciiData)
......
......@@ -89,7 +89,7 @@ protected:
bool tryBind ( QByteArray&& t) { *io << t; return true; }
bool tryBind ( QVariant&& t) { *io << t; return true; }
bool _isOk() noexcept { return io && io->status()==QDataStream::Ok; }
bool _isOk() const noexcept { return io && io->status()==QDataStream::Ok; }
bool tryOut ( ) { return true; }
bool tryItem( ) { return true; }
......
......@@ -126,7 +126,7 @@ protected:
bool tryRecord (quint32* =nullptr) { if (current().isObject()) { steps.push(Step());
return true; } _reportError(qBindExpectedRecord ); return false; }
bool tryNull ( ) { if (current().isNull ()) { return true; } _reportError(qBindExpectedNull ); return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s) ) { u . set(s.toUtf8() ); return true; } return false; }
bool tryBind ( QUtf8Data& u) { QString s; if (tryBind(s) ) { u = s .toUtf8 (); return true; } return false; }
bool tryBind ( QString& v) { if (current().isString()) { v = current().toString(); return true; } _reportError(qBindExpectedText ); return false; }
bool tryBind ( bool& v) { if (current().isBool ()) { v = current().toBool (); return true; } _reportError(qBindExpectedBoolean ); return false; }
bool tryBind ( qint64& t) { double d; if (tryBind(d) ) { t = qint64(d) ; return true; } return false; }
......@@ -139,7 +139,7 @@ protected:
bool tryItem( ) { steps.last().idx++; return !(steps.last().item = current(1).toArray (). at(steps.last().idx )).isUndefined(); }
bool tryOut ( ) { steps.removeLast(); return true; }
bool _isOk() { return true; }
bool _isOk() const noexcept { return true; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral e) { if (!isChoice) errors.append(Error{ e, currentPath() }); }
private:
......@@ -300,7 +300,7 @@ protected:
auto r=getNumber();
if (r==None) return false; // already reported qBindExpectedDecimal
if (r==FloatingPoint) { _reportError(qBindExpectedInteger); return false; }
if (neg) { _reportError(qBindExpectedPositiveNumber); return false; }
if (neg) { _reportError(qBindExpectedPositiveInteger); return false; }
t = i ; cachedNumber=None; return true; }
bool tryBind ( qint64& t) { if (caching) { cacheLevel++; return caching->tryBind(double(t)) && cacheOut(); }
auto r=getNumber();
......@@ -379,7 +379,7 @@ protected:
level.index++;
return true; }
bool _isOk() { return io; }
bool _isOk() const noexcept { return io; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral e) { if (!isChoice) errors.append(Error{ e, line, column, index }); }
private:
......
......@@ -222,7 +222,7 @@ public:
QModelWriter(QAbstractItemModel* m, bool rowFirst=true) : QModelBind(m, rowFirst), w(&ba) {}
virtual QValueMode mode() const noexcept { return QValueMode::Write; }
virtual bool _isOk() noexcept { return true; } //!< Write status ignored by default (no need to test intermediate status to choose between trySequence(), etc.
virtual bool _isOk() const noexcept { return true; } //!< Write status ignored by default (no need to test intermediate status to choose between trySequence(), etc.
protected:
virtual bool tryOut() {
d--;
......@@ -410,7 +410,7 @@ public:
QModelReader(QAbstractItemModel* m, bool rowFirst=true) : QModelBind(m, rowFirst), r(&io) { io.open(QIODevice::ReadOnly); }
virtual QValueMode mode() const noexcept { return QValueMode::Read; }
virtual bool _isOk() noexcept { return true; } //!< Read status ignored by default (QAbstractItemModel is not sequential)
virtual bool _isOk() const noexcept { return true; } //!< Read status ignored by default (QAbstractItemModel is not sequential)
protected:
virtual bool tryOut() {
if (I<=d) {
......
......@@ -119,16 +119,16 @@ protected:
bool tryBind( bool& t) { return set(t, qBindExpectedBoolean); }
bool tryBind( QByteArray& t) { return set(t, qBindExpectedBytes ); }
// Convert numerical types to strictly larger ones // TODO convert all compatible values
bool tryBind( qint8& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint16& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint32& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint64& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( quint8& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint16& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint32& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( quint64& t) { return set(t, qBindExpectedPositiveNumber); }
bool tryBind( float& t) { return set(t, qBindExpectedDecimal ); }
bool tryBind( double& t) { return set(t, qBindExpectedDecimal ); }
bool tryBind( qint8& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint16& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint32& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( qint64& t) { return set(t, qBindExpectedInteger ); }
bool tryBind( quint8& t) { return set(t, qBindExpectedPositiveInteger); }
bool tryBind( quint16& t) { return set(t, qBindExpectedPositiveInteger); }
bool tryBind( quint32& t) { return set(t, qBindExpectedPositiveInteger); }
bool tryBind( quint64& t) { return set(t, qBindExpectedPositiveInteger); }
bool tryBind( float& t) { return set(t, qBindExpectedDecimal ); }
bool tryBind( double& t) { return set(t, qBindExpectedDecimal ); }
bool trySequence(quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level( )); return true; } _reportError(qBindExpectedSequence); return false; }
bool tryRecord (quint32* =nullptr) { if (levels.last().isGroup) { levels.push(Level(qBindExpectedItem)); return true; } _reportError(qBindExpectedRecord ); return false; }
......@@ -138,7 +138,7 @@ protected:
bool tryItem( ) { levels.last().idx++ ; return true; }
bool tryOut ( ) { levels.pop(); settings->endGroup(); return true; }
bool _isOk() { return settings; }
bool _isOk() const noexcept { return settings; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral error) { if (!isChoice) errors.append(Error{ error, currentPath() }); }
private:
......
......@@ -155,16 +155,16 @@ protected:
current()->type()==qMetaTypeId< qint16>()||
current()->type()==qMetaTypeId< qint32>()||
current()->type()==qMetaTypeId< qint64>()) { t = current()->value< qint64>(); return true; } _reportError(qBindExpectedInteger ); return false; }
bool tryBind( quint8& t) { if (current()->type()==qMetaTypeId< quint8>()) { t = current()->value< quint8>(); return true; } _reportError(qBindExpectedPositiveNumber); return false; }
bool tryBind( quint8& t) { if (current()->type()==qMetaTypeId< quint8>()) { t = current()->value< quint8>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint16& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()) { t = current()->value< quint16>(); return true; } _reportError(qBindExpectedPositiveNumber); return false; }
current()->type()==qMetaTypeId< quint16>()) { t = current()->value< quint16>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint32& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()||
current()->type()==qMetaTypeId< quint32>()) { t = current()->value< quint32>(); return true; } _reportError(qBindExpectedPositiveNumber); return false; }
current()->type()==qMetaTypeId< quint32>()) { t = current()->value< quint32>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( quint64& t) { if (current()->type()==qMetaTypeId< quint8>()||
current()->type()==qMetaTypeId< quint16>()||
current()->type()==qMetaTypeId< quint32>()||
current()->type()==qMetaTypeId< quint64>()) { t = current()->value< quint64>(); return true; } _reportError(qBindExpectedPositiveNumber); return false; }
current()->type()==qMetaTypeId< quint64>()) { t = current()->value< quint64>(); return true; } _reportError(qBindExpectedPositiveInteger); return false; }
bool tryBind( float& t) { if (current()->type()==qMetaTypeId< float>()) { t = current()->value< float>(); return true; } _reportError(qBindExpectedDecimal ); return false; }
bool tryBind( double& t) { if (current()->type()==qMetaTypeId< float>()||
current()->type()==qMetaTypeId< double>()) { t = current()->value< double>(); return true; } _reportError(qBindExpectedDecimal ); return false; }
......@@ -177,7 +177,7 @@ protected:
bool tryItem( ) { levels.last().idx++; return (levels.last().item = current(1)->toList().value( levels.last().idx , QVariant())).isValid(); }
bool tryOut ( ) { levels.pop() ; return true; }
bool _isOk() { return value; }
bool _isOk() const noexcept { return value; }
void _setChoice(bool v) { isChoice=v; }
void _reportError(QIdentifierLiteral error) { if (!isChoice) errors.append(Error{ error, currentPath() }); }
private:
......
......@@ -85,7 +85,7 @@ protected:
bool tryBind ( double&& n) { static QString s; s.setNum( n ,'g',std::numeric_limits<double>::max_digits10); writeText("decimal" , s); return true; } // with specific precision
bool tryBind ( QByteArray&& s) { QString h; h.reserve(s.size()*2+2+1); h.append("0x").append(s.toHex().toUpper()) ; writeText("hexBinary", h); return true; }
bool _isOk() noexcept { return !io->hasError(); }
bool _isOk() const noexcept { return !io->hasError(); }
bool tryOut ( ) { io->writeEndElement(); return true; }
bool tryItem( ) { return true; }
......
......@@ -13,7 +13,7 @@ allowing to analyse how software is used in the field and diagnose complex issue
high-performance and structured data. But analysing unexpected uses and issues in the field requires a lot more
tracepoints than can be conveniently defined statically.
> **DISLAIMER:** QBind is not currently unit-tested but provided with a [sample and benchmark](main.cpp).
> **DISCLAIMER:** QBind is not currently unit-tested but provided with a [sample and benchmark](main.cpp).
> Also, the implementation is written in a concise style that supported the multiple refactorings but does not help explaining it.
> This is especially true for the various QAbstractValue implementations. The README and [DESIGN](DESIGN.md) documentation should be read
> before trying to understand the implementation.
......
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