myxlib/src/myx/redis/lexer-inl.hpp

131 lines
2.1 KiB
C++

#ifndef MYX_REDIS_LEXER_INL_HPP_
#define MYX_REDIS_LEXER_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/redis/lexer.hpp>
#endif
namespace myx {
namespace redis {
MYXLIB_INLINE Lexer::Lexer( QIODevice* device, QObject* parent ) :
QObject ( parent ),
m_device( device ),
m_state ( kDoingNothing ),
m_crlf ( 0 ),
m_length( 0 )
{
connect( device, &QIODevice::readyRead, this, &Lexer::readData );
}
MYXLIB_INLINE void Lexer::readData()
{
m_buffer.append( m_device->readAll() );
while ( true )
{
if ( ( m_state == kDoingNothing ) && !readCharacter() )
{
break;
}
switch ( m_state )
{
case kReadingLength:
case kReadingUnsafeString:
if ( !readUnsafeString() ) { return; }
break;
case kReadingSafeString:
if ( !readSafeString() ) { return; }
break;
case kDoingNothing:
break;
}
if ( m_state != kReadingSafeString )
{
m_state = kDoingNothing;
}
}
} // Lexer::readData
MYXLIB_INLINE 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 = kReadingUnsafeString; break;
case '$':
m_state = kReadingLength; break;
}
Q_EMIT character( c );
return( true );
} // Lexer::readCharacter
MYXLIB_INLINE 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 == kReadingLength )
{
m_length = s.toInt();
m_state = kReadingSafeString;
}
else
{
Q_EMIT unsafeString( s );
}
m_crlf = 0;
return( true );
} // Lexer::readUnsafeString
MYXLIB_INLINE 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 = kDoingNothing;
return( true );
}
} // namespace redis
} // namespace myx
#endif // ifndef MYX_REDIS_LEXER_INL_HPP_