Optimize Regex patterns (#39)

* Remove unused device and stamp from swipe_impl

* Use constants for regex patterns

* Compile regex outside of buffer function to avoid runtime hiccup

* Catch dash symbol before event, remove trimming
This commit is contained in:
Rico Tiongson 2019-02-07 13:14:53 +08:00 committed by GitHub
parent 4795a68600
commit 2843b9d3ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -56,10 +56,9 @@ extern "C" {
/* FORWARD DECLARATIONS */ /* FORWARD DECLARATIONS */
namespace util { namespace util {
string join(cstr, string[], int); extern const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN;
string build_gesture_begin(); extern const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN;
string build_gesture_update(); extern const char* GESTURE_SWIPE_END_REGEX_PATTERN;
string build_gesture_end();
map<string, string> read_config_file(const char*); map<string, string> read_config_file(const char*);
} }
@ -90,7 +89,7 @@ int main(int argc, char** args) {
} }
struct swipe_gesture { struct swipe_gesture {
string device, stamp, fingers; string fingers;
string dx, dy, udx, udy; string dx, dy, udx, udy;
xdo_t* xdo; xdo_t* xdo;
virtual void on_update() = 0; virtual void on_update() = 0;
@ -207,14 +206,17 @@ namespace service {
} }
namespace service { namespace service {
// process regex at compile time
const regex gesture_begin(util::GESTURE_SWIPE_BEGIN_REGEX_PATTERN);
const regex gesture_update(util::GESTURE_SWIPE_UPDATE_REGEX_PATTERN);
const regex gesture_end(util::GESTURE_SWIPE_END_REGEX_PATTERN);
// parses output from libinput debug-events // parses output from libinput debug-events
void buffer() { void buffer() {
// check first if $user // check first if $user
ios::sync_with_stdio(false); ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0); cin.tie(0); cout.tie(0);
const regex gesture_begin(util::build_gesture_begin());
const regex gesture_update(util::build_gesture_update());
const regex gesture_end(util::build_gesture_end());
string sentence; string sentence;
// read config file // read config file
auto config = util::read_config_file(conf_filename().data()); auto config = util::read_config_file(conf_filename().data());
@ -234,25 +236,19 @@ namespace service {
auto data = sentence.data(); auto data = sentence.data();
cmatch matches; cmatch matches;
if (regex_match(data, matches, gesture_begin)) { if (regex_match(data, matches, gesture_begin)) {
swipe.device = matches[1]; swipe.fingers = matches[1];
swipe.stamp = matches[2];
swipe.fingers = matches[3];
swipe.on_begin(); swipe.on_begin();
} }
else if (regex_match(data, matches, gesture_end)) { else if (regex_match(data, matches, gesture_end)) {
swipe.device = matches[1]; swipe.fingers = matches[1];
swipe.stamp = matches[2];
swipe.fingers = matches[3];
swipe.on_end(); swipe.on_end();
} }
else if (regex_match(data, matches, gesture_update)) { else if (regex_match(data, matches, gesture_update)) {
swipe.device = matches[1]; swipe.fingers = matches[1];
swipe.stamp = matches[2]; swipe.dx = matches[2];
swipe.fingers = matches[3]; swipe.dy = matches[3];
swipe.dx = matches[4]; swipe.udx = matches[4];
swipe.dy = matches[5]; swipe.udy = matches[5];
swipe.udx = matches[6];
swipe.udy = matches[7];
swipe.on_update(); swipe.on_update();
} }
} }
@ -337,50 +333,76 @@ namespace service {
namespace util { namespace util {
string number_regex() {
return "-?\\d+(?:\\.\\d+)";
}
string join(cstr delim, string arr[], int n) { /**
string ans = arr[0]; * Regex pattern for the libinput entry for start of swipe.
for (int i = 1; i < n; ++i) { * Extracts one match for the number of fingers used during the swipe.
ans += delim; *
ans += arr[i]; * eg. event15 GESTURE_SWIPE_BEGIN +34.33s 3
} * ^
return ans; * fingers
} */
const char* GESTURE_SWIPE_BEGIN_REGEX_PATTERN =
"^" // start of string
"[ -]event\\d+" // event
"\\s+GESTURE_SWIPE_BEGIN" // gesture
"\\s+\\S+" // timestamp
"\\s+(\\d+)" // fingers
"$" // end of string
;
string build_gesture_begin() { /**
string device = "\\s*(\\S+)\\s*"; * Regex pattern for the libinput entry for the end of swipe.
string gesture = "\\s*GESTURE_SWIPE_BEGIN\\s*"; * Extracts one match for the number of fingers used during the swipe.
string seconds = "\\s*(\\S+)\\s*"; *
string fingers = "\\s*(\\d+)\\s*"; * eg. event15 GESTURE_SWIPE_END +35.03s 3
string arr[] = {device, gesture, seconds, fingers}; * ^
return join("\\s+", arr, 4); * fingers
} */
const char* GESTURE_SWIPE_END_REGEX_PATTERN =
"^" // start of string
"[ -]event\\d+" // event
"\\s+GESTURE_SWIPE_END" // gesture
"\\s+\\S+" // timestamp
"\\s+(\\d+)" // fingers
"$" // end of string
;
string build_gesture_update() { // matches signed decimal numbers (eg. "6.02" "-1.1")
string device = "\\s*(\\S+)\\s*"; #define CF_NUMBER_REGEX "-?\\d+(?:\\.\\d+)"
string gesture = "\\s*GESTURE_SWIPE_UPDATE\\s*";
string seconds = "\\s*(\\S+)\\s*";
string fingers = "\\s*(\\d+)\\s*";
string num_1 = "\\s*(" + number_regex() + ")\\s*";
string num_2 = num_1;
string num_div = num_1 + "/" + num_2;
string num_accel = "\\s*\\(\\s*" + num_div + "\\s*unaccelerated\\s*\\)\\s*";
string arr[] = {device, gesture, seconds, fingers, num_div, num_accel};
return join("\\s+", arr, 6);
}
string build_gesture_end() { // matches and extracts a space-prefixed signed fraction (eg. "-3.00/ 5.12")
string device = "\\s*(\\S+)\\s*"; #define CF_NUMBER_DIVISION "\\s*(" CF_NUMBER_REGEX ")/\\s*(" CF_NUMBER_REGEX ")"
string gesture = "\\s*GESTURE_SWIPE_END\\s*";
string seconds = "\\s*(\\S+)\\s*";
string fingers = "\\s*(\\d+)\\s*";
string arr[] = {device, gesture, seconds, fingers};
return join("\\s+", arr, 4);
}
/**
* Regex pattern for the libinput entry for during a swipe.
* Extracts number of fingers used and the speed (normal and accelerated) of the swipe.
*
* eg. event15 GESTURE_SWIPE_UPDATE +34.70s 3 -0.12/ 4.99 (-0.33/13.50 unaccelerated)
* ^ ^ ^ ^ ^
* fingers dx dy udx udy
*/
const char* GESTURE_SWIPE_UPDATE_REGEX_PATTERN =
"^" // start of string
"[ -]event\\d+" // event
"\\s+GESTURE_SWIPE_UPDATE" // gesture
"\\s+\\S+" // timestamp
"\\s+(\\d+)" // fingers
"\\s+" CF_NUMBER_DIVISION // speed (dx/dy)
"\\s+\\(" CF_NUMBER_DIVISION "\\s+unaccelerated\\)" // unaccelerated speed (udx/udy)
"$" // end of string
;
// delete macros
#undef CF_NUMBER_DIVISION
#undef CF_NUMBER_EXTRACT
#undef CF_NUMBER_REGEX
/**
* A utility method for reading the config file.
*
* @param filename (const char*) the path of the config file.
*/
map<string, string> read_config_file(const char* filename) { map<string, string> read_config_file(const char* filename) {
map<string, string> conf; map<string, string> conf;
ifstream fin(filename); ifstream fin(filename);