static bool DoesStrMatch ( const char * const strBegin, const char * const strEnd, const char * const match, const bool isCaseSensitive ) { const size_t len = strEnd - strBegin; assert( len > 0 ); size_t i; for ( i = 0; i < len; ++i ) { const char m = match[ i ]; if ( m == 0 ) return false; const char c = strBegin[ i ]; assert( c != 0 ); // Otherwise, toupper() may not be reliable. assert( IsPrintableAscii( m ) ); if ( c == m ) continue; if ( !isCaseSensitive && toupper( c ) == toupper( m ) ) continue; return false; } if ( match[ i ] != 0 ) return false; return true; }
void CGenericSerialConsole::InsertChar ( const uint8_t c ) { // If not printable... if ( !IsPrintableAscii( c ) ) { Bell(); return; } const uint32_t nextEndPos = ( m_cmdEndPos + 1 ) % BUF_LEN; // If command full... if ( GetCircularDistance( m_cmdBeginPos, nextEndPos, BUF_LEN ) > MAX_SINGLE_CMD_LEN ) { Bell(); return; } // If the command is empty or the cursor is at the end, append the new character. if ( m_cursorPos == m_cmdEndPos ) { m_buffer[ m_cmdEndPos ] = c; PrintChar( c ); m_cursorPos = nextEndPos; m_cmdEndPos = nextEndPos; return; } // NOTE: If the following logic changes much, remeber to update MAX_TX_BUFFER_SIZE_NEEDED. // Shift characters upwards one position. for ( uint32_t i = nextEndPos; i != m_cursorPos; i = GetCircularPosMinusOne( i, BUF_LEN ) ) m_buffer[ i ] = m_buffer[ GetCircularPosMinusOne( i, BUF_LEN ) ]; // Insert new character. m_buffer[ m_cursorPos ] = c; // Print all characters. for ( uint32_t i = m_cursorPos; i != nextEndPos; i = ( i + 1 ) % BUF_LEN ) PrintChar( m_buffer[ i ] ); // Move the terminal cursor left to match our current cursor position. const uint32_t distanceToEnd = GetCircularDistance( m_cursorPos, m_cmdEndPos, BUF_LEN ); assert( distanceToEnd > 0 ); Printf( "\x1B[%uD", unsigned( distanceToEnd ) ); // Move left n positions. m_cursorPos = (m_cursorPos + 1) % BUF_LEN; m_cmdEndPos = nextEndPos; }
const char * CGenericSerialConsole::AddChar ( const uint8_t c, uint32_t * const retCmdLen ) { // Trace the incoming characters. if ( false ) { if ( IsPrintableAscii(c) ) SerialPrintf( "0x%02X (%3u, %c)" DBG_EOL, c, c, c ); else SerialPrintf( "0x%02X (%3u)" DBG_EOL, c, c ); } bool isCmdReady = false; switch ( m_state ) { case stIdle: isCmdReady = ProcessChar( c ); break; case stEscapeReceived: if ( c == '[' ) // CSI (0x5B) { m_state = stEscapeBracketReceived; } else { Bell(); m_state = stIdle; } break; case stEscapeBracketReceived: ProcessCharAfterEscapeBracket( c ); break; default: assert( false ); break; } if ( false ) { SerialPrintf( "Char: 0x%02X, cmd begin: %u, end: %u, len: %u, pos: %u" DBG_EOL, c, unsigned( m_cmdBeginPos ), unsigned( m_cmdEndPos ), unsigned( GetCircularDistance( m_cmdBeginPos, m_cmdEndPos, BUF_LEN ) ), unsigned( m_cursorPos ) ); } if ( isCmdReady ) { assert( m_cmdBeginPos < BUF_LEN ); assert( m_cmdEndPos < BUF_LEN ); m_buffer[ m_cmdEndPos ] = 0; const uint32_t cmdLen = GetCircularDistance( m_cmdBeginPos, m_cmdEndPos, BUF_LEN ); char * const first = &m_buffer[0]; char * const last = &m_buffer[BUF_LEN]; char * const middle = &m_buffer[m_cmdBeginPos]; std::rotate( first, middle, last ); assert( cmdLen < BUF_LEN ); m_cmdBeginPos = cmdLen; m_cmdEndPos = cmdLen; m_cursorPos = cmdLen; // SerialPrint( "Command ready." DBG_EOL ); assert( strlen( m_buffer ) == cmdLen ); *retCmdLen = cmdLen; return m_buffer; } else { *retCmdLen = 0; return NULL; } }