Skip to content

Instantly share code, notes, and snippets.

@buzzySmile
Created September 23, 2014 07:55
Show Gist options
  • Save buzzySmile/fcea874c12a27f9d911d to your computer and use it in GitHub Desktop.
Save buzzySmile/fcea874c12a27f9d911d to your computer and use it in GitHub Desktop.
Final-State-Mashine-based data parser. Data message(QByteArray) has to have token, body and checksum.
#include "QFsmDataParser.h"
QFsmDataParser::QFsmDataParser(const QByteArray &token, int _size):
m_Token(token),
m_iSize(_size)
{
reset();
}
QFsmDataParser::~QFsmDataParser()
{
}
void QFsmDataParser::reset()
{
m_state = fNone;
}
bool QFsmDataParser::getToken()
{
qDebug("-token searching...");
// search first occurrence of Token
int iTokenIndex = m_DataArray.indexOf(m_Token);
if ( iTokenIndex != -1 ) {
m_DataArray.remove(0, iTokenIndex);
qDebug("+Token detected (index: "+QString::number(iTokenIndex)+")");
return true;
}
qDebug(m_DataArray);
qDebug(" Token detect ERROR! (index: "+QString::number(iTokenIndex)+")");
// чистим все данные, кроме последнего байта, он может входить
// в токен с учетом последующего фрагмента информации
m_DataArray.remove(0, m_DataArray.size()-1);
return false;
}
bool QFsmDataParser::getBody()
{
if (m_DataArray.size() >= m_iSize) {
qDebug("+Size correct -> ");
return true;
}
else {
qDebug(" Insufficient INFO size ");
return false;
}
}
bool QFsmDataParser::getChecksum()
{
if(!checkSum(m_DataArray.left(m_iSize)))
{
qDebug(" Info Checksum ERROR! ");
m_DataArray.remove(0, m_iSize);
return false;
}
else {
LOGDATA("+FullDks correct. ->");
return true;
}
}
void QFsmDataParser::handleData(const QByteArray &sample)
{
m_DataArray.append(sample);
while (m_DataArray.size() > 1)
{
switch(m_state){
case fNone:
if(getToken()) m_state = fToken;
break;
case fToken:
if(getBody()) m_state = fBody;
else return;
case fBody:
if(getChecksum()) m_state = fChecksum;
else reset();
break;
case fChecksum:
emit readyParse(m_DataArray);
m_DataArray.remove(0, m_iSize);
reset();
break;
default:
qDebug("UNKNOWN STATE");
break;
}
}
}
bool QFsmDataParser::checkSum(const QByteArray &buffer)
{
quint8 CheckSum = 0;
for(int ix = 0; ix < buffer.size(); ix++ )
CheckSum += buffer[ix];
if(CheckSum == 0)
return true;
else
return false;
}
#include <QObject>
#include <QTimer>
#include <QByteArray>
class QFsmDataParser : public QObject
{
Q_OBJECT
Q_ENUMS(sFlags)
public:
explicit QFsmDataParser(const QByteArray &token, int _size=5);
~QFsmDataParser();
enum sFlags {
fNone = 0x0, // нет значимых данных
fToken = 0x1, // найден признак начала
fBody = 0x2, // успешно получено тело
fChecksum = 0x3 // корректная контрольная сумма пакета
};
sFlags getState() const { return m_state; }
bool isEmpty() const { return (m_state == fNone); }
bool isComplete() const { return (m_state == fChecksum); }
void reset();
private:
sFlags m_state;
QByteArray m_Token;
int m_iSize;
QByteArray m_DataArray;
bool getToken();
bool getBody();
bool getChecksum();
bool checkSum(const QByteArray &buffer);
signals:
void readyParse(QByteArray info);
public slots:
void handleData(const QByteArray &sample);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment