#ifndef MYX_REDIS_LEXER_INL_HPP_ #define MYX_REDIS_LEXER_INL_HPP_ #pragma once #ifndef MYXLIB_HEADER_ONLY #include #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_