myxlib/src/myx/redis/lexer.cpp

116 lines
1.8 KiB
C++

#include "lexer.hpp"
using namespace qxredis;
Lexer::Lexer( QIODevice* device, QObject* parent ) :
QObject ( parent ),
m_device( device ),
m_state ( DoingNothing ),
m_crlf ( 0 ),
m_length( 0 )
{
connect( device, &QIODevice::readyRead, this, &Lexer::readData );
}
void Lexer::readData()
{
m_buffer.append( m_device->readAll() );
while ( true )
{
if ( ( m_state == DoingNothing ) && !readCharacter() )
{
break;
}
switch ( m_state )
{
case ReadingLength:
case ReadingUnsafeString:
if ( !readUnsafeString() ) { return; }
break;
case ReadingSafeString:
if ( !readSafeString() ) { return; }
break;
case DoingNothing:
break;
}
if ( m_state != ReadingSafeString )
{
m_state = DoingNothing;
}
}
} // Lexer::readData
bool Lexer::readCharacter()
{
if ( m_buffer.isEmpty() )
{
return( false );
}
char c = m_buffer.at( 0 );
m_buffer.remove( 0, 1 );
switch ( c )
{
case '+':
case '-':
case ':':
case '*':
m_state = ReadingUnsafeString; break;
case '$':
m_state = ReadingLength; break;
}
Q_EMIT character( c );
return( true );
} // Lexer::readCharacter
bool Lexer::readUnsafeString()
{
m_crlf = m_buffer.indexOf( "\r\n", m_crlf );
if ( m_crlf == -1 )
{
m_crlf = m_buffer.size();
return( false );
}
QString s = m_buffer.mid( 0, m_crlf );
m_buffer.remove( 0, m_crlf + 2 );
if ( m_state == ReadingLength )
{
m_length = s.toInt();
m_state = ReadingSafeString;
}
else
{
Q_EMIT unsafeString( s );
}
m_crlf = 0;
return( true );
} // Lexer::readUnsafeString
bool Lexer::readSafeString()
{
if ( m_buffer.size() - m_length < 2 )
{
return( false );
}
QByteArray d = m_buffer.mid( 0, m_length );
m_buffer.remove( 0, m_length + 2 );
Q_EMIT safeString( d );
m_state = DoingNothing;
return( true );
}