Add initial keyboard_input parser and tests
The current implementation SEGFAULTs when F characters are followed by end of string.
This commit is contained in:
@@ -17,7 +17,8 @@ SOURCES += src/main.cpp\
|
||||
src/openvr/ivrinput.cpp \
|
||||
src/utils/setup.cpp \
|
||||
src/utils/paths.cpp \
|
||||
src/openvr/overlay_utils.cpp
|
||||
src/openvr/overlay_utils.cpp \
|
||||
src/keyboard_input/input_parser.cpp
|
||||
|
||||
HEADERS += src/overlaycontroller.h \
|
||||
src/tabcontrollers/AudioTabController.h \
|
||||
@@ -45,7 +46,8 @@ HEADERS += src/overlaycontroller.h \
|
||||
src/openvr/ivrinput.h \
|
||||
src/utils/setup.h \
|
||||
src/utils/paths.h \
|
||||
src/openvr/overlay_utils.h
|
||||
src/openvr/overlay_utils.h \
|
||||
src/keyboard_input/input_parser.h
|
||||
|
||||
win32 {
|
||||
SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "input_parser.h"
|
||||
|
||||
std::optional<Token> getModifier( const char& character )
|
||||
{
|
||||
switch ( character )
|
||||
{
|
||||
case '^':
|
||||
return Token::MODIFIER_CTRL;
|
||||
case '*':
|
||||
return Token::MODIFIER_ALT;
|
||||
case '>':
|
||||
return Token::MODIFIER_SHIFT;
|
||||
case '/':
|
||||
return Token::MODIFIER_ALTGR;
|
||||
case '#':
|
||||
return Token::MODIFIER_SUPER;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Token> getNumberOrLetter( const char& character )
|
||||
{
|
||||
if ( islower( character ) || isdigit( character ) )
|
||||
{
|
||||
return static_cast<Token>( character );
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Token> getFunctionNumber( const char& character )
|
||||
{
|
||||
switch ( character )
|
||||
{
|
||||
case '1':
|
||||
return Token::KEY_F1;
|
||||
case '2':
|
||||
return Token::KEY_F2;
|
||||
case '3':
|
||||
return Token::KEY_F3;
|
||||
case '4':
|
||||
return Token::KEY_F4;
|
||||
case '5':
|
||||
return Token::KEY_F5;
|
||||
case '6':
|
||||
return Token::KEY_F6;
|
||||
case '7':
|
||||
return Token::KEY_F7;
|
||||
case '8':
|
||||
return Token::KEY_F8;
|
||||
case '9':
|
||||
return Token::KEY_F9;
|
||||
|
||||
default:
|
||||
// LOG incorrect character
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Token> ParseKeyboardInputsToTokens( const std::string inputs )
|
||||
{
|
||||
std::vector<Token> tokens{};
|
||||
|
||||
for ( auto ch = inputs.begin(); ch != inputs.end(); ++ch )
|
||||
{
|
||||
if ( const auto c = getNumberOrLetter( *ch ); c.has_value() )
|
||||
{
|
||||
tokens.push_back( *c );
|
||||
continue;
|
||||
}
|
||||
if ( const auto c = getModifier( *ch ); c.has_value() )
|
||||
{
|
||||
tokens.push_back( *c );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !isupper( *ch ) )
|
||||
{
|
||||
// LOG incorrect character
|
||||
continue;
|
||||
}
|
||||
// Everything below is upper case
|
||||
|
||||
if ( *ch == 'F' )
|
||||
{
|
||||
++ch;
|
||||
const auto token = getFunctionNumber( *ch );
|
||||
if ( token.has_value() )
|
||||
{
|
||||
tokens.push_back( *token );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spec says to abort on errors and submit correct values before
|
||||
// error.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cctype>
|
||||
#include <optional>
|
||||
|
||||
enum class Token
|
||||
{
|
||||
// Literals
|
||||
KEY_a = 'a',
|
||||
KEY_b = 'b',
|
||||
KEY_c = 'c',
|
||||
KEY_d = 'd',
|
||||
KEY_e = 'e',
|
||||
KEY_f = 'f',
|
||||
KEY_g = 'g',
|
||||
KEY_h = 'h',
|
||||
KEY_i = 'i',
|
||||
KEY_j = 'j',
|
||||
KEY_k = 'k',
|
||||
KEY_l = 'l',
|
||||
KEY_m = 'm',
|
||||
KEY_n = 'n',
|
||||
KEY_o = 'o',
|
||||
KEY_p = 'p',
|
||||
KEY_q = 'q',
|
||||
KEY_r = 'r',
|
||||
KEY_s = 's',
|
||||
KEY_t = 't',
|
||||
KEY_u = 'u',
|
||||
KEY_v = 'v',
|
||||
KEY_w = 'w',
|
||||
KEY_x = 'x',
|
||||
KEY_y = 'y',
|
||||
KEY_z = 'z',
|
||||
|
||||
KEY_0 = '0',
|
||||
KEY_1 = '1',
|
||||
KEY_2 = '2',
|
||||
KEY_3 = '3',
|
||||
KEY_4 = '4',
|
||||
KEY_5 = '5',
|
||||
KEY_6 = '6',
|
||||
KEY_7 = '7',
|
||||
KEY_8 = '8',
|
||||
KEY_9 = '9',
|
||||
|
||||
KEY_F1,
|
||||
KEY_F2,
|
||||
KEY_F3,
|
||||
KEY_F4,
|
||||
KEY_F5,
|
||||
KEY_F6,
|
||||
KEY_F7,
|
||||
KEY_F8,
|
||||
KEY_F9,
|
||||
|
||||
KEY_BACKSPACE,
|
||||
KEY_SPACE,
|
||||
KEY_TAB,
|
||||
KEY_ESC,
|
||||
KEY_INS,
|
||||
KEY_DEL,
|
||||
KEY_END,
|
||||
KEY_PGDN,
|
||||
KEY_PGUP,
|
||||
KEY_CAPS,
|
||||
KEY_PRNSCRN,
|
||||
KEY_PAUSE,
|
||||
KEY_SCRLOCK,
|
||||
KEY_LEFTARROW,
|
||||
KEY_RIGHTARROW,
|
||||
KEY_UPARROW,
|
||||
KEY_DOWNARROW,
|
||||
KEY_KPSLASH,
|
||||
KEY_KPSTAR,
|
||||
KEY_KPMINUS,
|
||||
KEY_KPPLUS,
|
||||
|
||||
// Misc tokens
|
||||
TOKEN_NEW_SEQUENCE,
|
||||
|
||||
// Modifiers
|
||||
MODIFIER_CTRL,
|
||||
MODIFIER_ALT,
|
||||
MODIFIER_SHIFT,
|
||||
MODIFIER_ALTGR,
|
||||
MODIFIER_SUPER,
|
||||
};
|
||||
|
||||
std::vector<Token> ParseKeyboardInputsToTokens( std::string inputs );
|
||||
@@ -0,0 +1,16 @@
|
||||
QT += testlib
|
||||
QT -= gui
|
||||
CONFIG += c++1z
|
||||
|
||||
CONFIG += qt console warn_on depend_includepath testcase
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += ../../src/keyboard_input
|
||||
|
||||
SOURCES += tst_parsertest.cpp \
|
||||
../../src/keyboard_input/input_parser.cpp
|
||||
|
||||
HEADERS += \
|
||||
../../src/keyboard_input/input_parser.h
|
||||
@@ -0,0 +1,169 @@
|
||||
#include <QtTest>
|
||||
#include <QDebug>
|
||||
#include "input_parser.h"
|
||||
|
||||
// add necessary includes here
|
||||
|
||||
class ParserTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void singleCharacters();
|
||||
void singleCharactersShouldFail();
|
||||
|
||||
void severalCharacters();
|
||||
void severalCharactersShouldFail();
|
||||
|
||||
void singleDigit();
|
||||
void singleDigitShouldFail();
|
||||
|
||||
void severalDigits();
|
||||
void severalDigitsShouldFail();
|
||||
|
||||
void Modifiers();
|
||||
|
||||
void functionKeys();
|
||||
};
|
||||
|
||||
const std::string alphabet = "abcdefghijklmnopqrstuvxyz";
|
||||
const std::string digits = "0123456789";
|
||||
|
||||
void ParserTest::singleCharacters()
|
||||
{
|
||||
for ( const auto letter : alphabet )
|
||||
{
|
||||
const auto l = std::string( &letter );
|
||||
const auto t = std::vector<Token>( { static_cast<Token>( letter ) } );
|
||||
QCOMPARE( ParseKeyboardInputsToTokens( l ), t );
|
||||
}
|
||||
}
|
||||
|
||||
void ParserTest::singleCharactersShouldFail()
|
||||
{
|
||||
for ( const auto letter : alphabet )
|
||||
{
|
||||
const auto l = std::string( &letter );
|
||||
const auto t
|
||||
= std::vector<Token>( { static_cast<Token>( letter + 1 ) } );
|
||||
QVERIFY( ParseKeyboardInputsToTokens( l ) != t );
|
||||
}
|
||||
}
|
||||
|
||||
void ParserTest::severalCharacters()
|
||||
{
|
||||
const auto tokens = ParseKeyboardInputsToTokens( "mad" );
|
||||
const auto e
|
||||
= std::vector<Token>( { Token::KEY_m, Token::KEY_a, Token::KEY_d } );
|
||||
QCOMPARE( tokens, e );
|
||||
}
|
||||
|
||||
void ParserTest::severalCharactersShouldFail()
|
||||
{
|
||||
const auto tokens = ParseKeyboardInputsToTokens( "mad" );
|
||||
const auto e
|
||||
= std::vector<Token>( { Token::KEY_m, Token::KEY_e, Token::KEY_d } );
|
||||
QVERIFY( tokens != e );
|
||||
}
|
||||
|
||||
void ParserTest::singleDigit()
|
||||
{
|
||||
for ( const auto n : digits )
|
||||
{
|
||||
const auto l = std::string( &n );
|
||||
const auto t = std::vector<Token>( { static_cast<Token>( n ) } );
|
||||
QCOMPARE( ParseKeyboardInputsToTokens( l ), t );
|
||||
}
|
||||
}
|
||||
|
||||
void ParserTest::singleDigitShouldFail()
|
||||
{
|
||||
for ( const auto n : digits )
|
||||
{
|
||||
const auto l = std::string( &n );
|
||||
const auto t = std::vector<Token>( { static_cast<Token>( n + 1 ) } );
|
||||
QVERIFY( ParseKeyboardInputsToTokens( l ) != t );
|
||||
}
|
||||
}
|
||||
|
||||
void ParserTest::severalDigits()
|
||||
{
|
||||
const auto t = ParseKeyboardInputsToTokens( "123" );
|
||||
const auto e
|
||||
= std::vector<Token>( { Token::KEY_1, Token::KEY_2, Token::KEY_3 } );
|
||||
QVERIFY( t == e );
|
||||
}
|
||||
|
||||
void ParserTest::severalDigitsShouldFail()
|
||||
{
|
||||
const auto t = ParseKeyboardInputsToTokens( "123" );
|
||||
const auto e
|
||||
= std::vector<Token>( { Token::KEY_1, Token::KEY_3, Token::KEY_2 } );
|
||||
QVERIFY( t != e );
|
||||
}
|
||||
|
||||
void ParserTest::Modifiers()
|
||||
{
|
||||
auto t = ParseKeyboardInputsToTokens( "^" );
|
||||
auto e = std::vector<Token>( { Token::MODIFIER_CTRL } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "*" );
|
||||
e = std::vector<Token>( { Token::MODIFIER_ALT } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( ">" );
|
||||
e = std::vector<Token>( { Token::MODIFIER_SHIFT } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "/" );
|
||||
e = std::vector<Token>( { Token::MODIFIER_ALTGR } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "#" );
|
||||
e = std::vector<Token>( { Token::MODIFIER_SUPER } );
|
||||
QVERIFY( t == e );
|
||||
}
|
||||
|
||||
void ParserTest::functionKeys()
|
||||
{
|
||||
auto t = ParseKeyboardInputsToTokens( "F1" );
|
||||
auto e = std::vector<Token>( { Token::KEY_F1 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F2" );
|
||||
e = std::vector<Token>( { Token::KEY_F2 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F3" );
|
||||
e = std::vector<Token>( { Token::KEY_F3 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F4" );
|
||||
e = std::vector<Token>( { Token::KEY_F4 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F5" );
|
||||
e = std::vector<Token>( { Token::KEY_F5 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F6" );
|
||||
e = std::vector<Token>( { Token::KEY_F6 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F7" );
|
||||
e = std::vector<Token>( { Token::KEY_F7 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F8" );
|
||||
e = std::vector<Token>( { Token::KEY_F8 } );
|
||||
QVERIFY( t == e );
|
||||
|
||||
t = ParseKeyboardInputsToTokens( "F9" );
|
||||
e = std::vector<Token>( { Token::KEY_F9 } );
|
||||
QVERIFY( t == e );
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN( ParserTest )
|
||||
|
||||
#include "tst_parsertest.moc"
|
||||
Reference in New Issue
Block a user