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/openvr/ivrinput.cpp \
|
||||||
src/utils/setup.cpp \
|
src/utils/setup.cpp \
|
||||||
src/utils/paths.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 \
|
HEADERS += src/overlaycontroller.h \
|
||||||
src/tabcontrollers/AudioTabController.h \
|
src/tabcontrollers/AudioTabController.h \
|
||||||
@@ -45,7 +46,8 @@ HEADERS += src/overlaycontroller.h \
|
|||||||
src/openvr/ivrinput.h \
|
src/openvr/ivrinput.h \
|
||||||
src/utils/setup.h \
|
src/utils/setup.h \
|
||||||
src/utils/paths.h \
|
src/utils/paths.h \
|
||||||
src/openvr/overlay_utils.h
|
src/openvr/overlay_utils.h \
|
||||||
|
src/keyboard_input/input_parser.h
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \
|
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