mirror of https://github.com/nirenjan/libx52.git
feat(libx52io): Add _from_str and from_str_nocase APIs
This change add APIs to convert the string forms of the axis and button names back to their corresponding enum identifiers. This is effectively built such that a roundtrip of _to_str and _from_str will return the same input. The _nocase variants handle case insensitive matching of the names by folding of the ASCII alphabets A-Z and a-z only, so it doesn't depend on localization.pull/67/head
parent
0fdcb725af
commit
c49689c1ee
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libx52io.h"
|
||||
#include "gettext.h"
|
||||
|
||||
|
|
@ -16,6 +17,28 @@
|
|||
* on one to the enumeration definitions.
|
||||
*/
|
||||
|
||||
/* Locale-independent: only ASCII A–Z fold with a–z; digits and underscore unchanged */
|
||||
static int x52io_ascii_strcasecmp(const char *a, const char *b)
|
||||
{
|
||||
for (;;) {
|
||||
unsigned char ca = (unsigned char)*a++;
|
||||
unsigned char cb = (unsigned char)*b++;
|
||||
|
||||
if (ca >= 'A' && ca <= 'Z') {
|
||||
ca = (unsigned char)(ca - 'A' + 'a');
|
||||
}
|
||||
if (cb >= 'A' && cb <= 'Z') {
|
||||
cb = (unsigned char)(cb - 'A' + 'a');
|
||||
}
|
||||
if (ca != cb) {
|
||||
return (int)ca - (int)cb;
|
||||
}
|
||||
if (ca == '\0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* String mapping for axis */
|
||||
static const char * _x52io_axis_str[LIBX52IO_AXIS_MAX] = {
|
||||
[LIBX52IO_AXIS_X] = "ABS_X",
|
||||
|
|
@ -92,6 +115,78 @@ const char * libx52io_button_to_str(libx52io_button button)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int libx52io_axis_from_str(const char *str, libx52io_axis *axis)
|
||||
{
|
||||
libx52io_axis i;
|
||||
|
||||
if (!str || !axis) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (i = LIBX52IO_AXIS_X; i < LIBX52IO_AXIS_MAX; i++) {
|
||||
if (strcmp(str, _x52io_axis_str[i]) == 0) {
|
||||
*axis = i;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_button_from_str(const char *str, libx52io_button *button)
|
||||
{
|
||||
libx52io_button b;
|
||||
|
||||
if (!str || !button) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
if (strcmp(str, _x52io_button_str[b]) == 0) {
|
||||
*button = b;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_axis_from_str_nocase(const char *str, libx52io_axis *axis)
|
||||
{
|
||||
libx52io_axis i;
|
||||
|
||||
if (!str || !axis) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (i = LIBX52IO_AXIS_X; i < LIBX52IO_AXIS_MAX; i++) {
|
||||
if (x52io_ascii_strcasecmp(str, _x52io_axis_str[i]) == 0) {
|
||||
*axis = i;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
int libx52io_button_from_str_nocase(const char *str, libx52io_button *button)
|
||||
{
|
||||
libx52io_button b;
|
||||
|
||||
if (!str || !button) {
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
for (b = LIBX52IO_BTN_TRIGGER; b < LIBX52IO_BUTTON_MAX; b++) {
|
||||
if (x52io_ascii_strcasecmp(str, _x52io_button_str[b]) == 0) {
|
||||
*button = b;
|
||||
return LIBX52IO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return LIBX52IO_ERROR_INVALID;
|
||||
}
|
||||
|
||||
/* Error buffer used for building custom error strings */
|
||||
static char error_buffer[256];
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,62 @@ LIBX52IO_API const char *libx52io_axis_to_str(libx52io_axis axis);
|
|||
*/
|
||||
LIBX52IO_API const char *libx52io_button_to_str(libx52io_button button);
|
||||
|
||||
/**
|
||||
* @brief Parse the string representation of an axis.
|
||||
*
|
||||
* Accepts tokens as returned by \ref libx52io_axis_to_str (e.g. \c ABS_X).
|
||||
*
|
||||
* @param[in] str NUL-terminated axis name
|
||||
* @param[out] axis Receives the axis ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a axis is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_axis_from_str(const char *str, libx52io_axis *axis);
|
||||
|
||||
/**
|
||||
* @brief Parse the string representation of a button.
|
||||
*
|
||||
* Accepts tokens as returned by \ref libx52io_button_to_str (e.g. \c BTN_FIRE).
|
||||
*
|
||||
* @param[in] str NUL-terminated button name
|
||||
* @param[out] button Receives the button ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a button is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_button_from_str(const char *str, libx52io_button *button);
|
||||
|
||||
/**
|
||||
* @brief Parse an axis name with ASCII case-insensitive matching.
|
||||
*
|
||||
* Like \ref libx52io_axis_from_str, but treats ASCII letters \c A– \c Z the same
|
||||
* as \c a– \c z. Digits, underscore, and NUL must match exactly. Matching is
|
||||
* not locale-dependent.
|
||||
*
|
||||
* @param[in] str NUL-terminated axis name
|
||||
* @param[out] axis Receives the axis ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a axis is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_axis_from_str_nocase(const char *str, libx52io_axis *axis);
|
||||
|
||||
/**
|
||||
* @brief Parse a button name with ASCII case-insensitive matching.
|
||||
*
|
||||
* Like \ref libx52io_button_from_str, but treats ASCII letters \c A– \c Z the same
|
||||
* as \c a– \c z. Digits, underscore, and NUL must match exactly. Matching is
|
||||
* not locale-dependent.
|
||||
*
|
||||
* @param[in] str NUL-terminated button name
|
||||
* @param[out] button Receives the button ID on success
|
||||
*
|
||||
* @returns \ref LIBX52IO_SUCCESS if \a str was recognized,
|
||||
* \ref LIBX52IO_ERROR_INVALID if \a str or \a button is NULL or \a str is unknown.
|
||||
*/
|
||||
LIBX52IO_API int libx52io_button_from_str_nocase(const char *str, libx52io_button *button);
|
||||
|
||||
/**
|
||||
* @brief Get the vendor ID of the connected X52 device.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
libx52io_version = '1.0.0'
|
||||
libx52io_version = '1.1.0'
|
||||
|
||||
libx52io_files = files(
|
||||
'io_core.c',
|
||||
|
|
@ -37,4 +37,11 @@ test_parser = executable('test-parser', 'test_parser.c', libx52io_files,
|
|||
)
|
||||
test('test-parser', test_parser, protocol: 'tap')
|
||||
|
||||
test_io_strings = executable('test-io-strings', 'test_io_strings.c', libx52io_files,
|
||||
build_by_default: false,
|
||||
dependencies: [dep_cmocka, dep_hidapi, dep_intl],
|
||||
include_directories: [includes],
|
||||
)
|
||||
test('test-io-strings', test_io_strings, protocol: 'tap')
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: libx52 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
|
||||
"POT-Creation-Date: 2026-04-01 20:47-0700\n"
|
||||
"POT-Creation-Date: 2026-04-03 18:06-0700\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -17,11 +17,11 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:101 vkm/vkm_common.c:25
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:196 vkm/vkm_common.c:25
|
||||
msgid "Success"
|
||||
msgstr ""
|
||||
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:102
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:197
|
||||
msgid "Initialization failure"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ msgstr ""
|
|||
msgid "System call interrupted"
|
||||
msgstr ""
|
||||
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:125 vkm/vkm_common.c:52
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:220 vkm/vkm_common.c:52
|
||||
#, c-format
|
||||
msgid "Unknown error %d"
|
||||
msgstr ""
|
||||
|
|
@ -213,23 +213,23 @@ msgstr ""
|
|||
msgid "Unknown LED ID %d"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:103
|
||||
#: libx52io/io_strings.c:198
|
||||
msgid "No device"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:104
|
||||
#: libx52io/io_strings.c:199
|
||||
msgid "Invalid arguments"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:105
|
||||
#: libx52io/io_strings.c:200
|
||||
msgid "Connection failure"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:106
|
||||
#: libx52io/io_strings.c:201
|
||||
msgid "I/O error"
|
||||
msgstr ""
|
||||
|
||||
#: libx52io/io_strings.c:107
|
||||
#: libx52io/io_strings.c:202
|
||||
msgid "Read timeout"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
18
po/xx_PL.po
18
po/xx_PL.po
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: libx52 0.2.3\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
|
||||
"POT-Creation-Date: 2026-04-01 20:47-0700\n"
|
||||
"POT-Creation-Date: 2026-04-03 18:06-0700\n"
|
||||
"PO-Revision-Date: 2026-04-01 20:50-0700\n"
|
||||
"Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n"
|
||||
"Language-Team: Dummy Language for testing i18n\n"
|
||||
|
|
@ -17,11 +17,11 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.4.2\n"
|
||||
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:101 vkm/vkm_common.c:25
|
||||
#: libx52/x52_strerror.c:23 libx52io/io_strings.c:196 vkm/vkm_common.c:25
|
||||
msgid "Success"
|
||||
msgstr "Uccesssay"
|
||||
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:102
|
||||
#: libx52/x52_strerror.c:24 libx52io/io_strings.c:197
|
||||
msgid "Initialization failure"
|
||||
msgstr "Initializationay ailurefay"
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ msgstr "Ipepay erroray"
|
|||
msgid "System call interrupted"
|
||||
msgstr "Ystemsay allcay interrupteday"
|
||||
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:125 vkm/vkm_common.c:52
|
||||
#: libx52/x52_strerror.c:66 libx52io/io_strings.c:220 vkm/vkm_common.c:52
|
||||
#, c-format
|
||||
msgid "Unknown error %d"
|
||||
msgstr "Unknownay erroray %d"
|
||||
|
|
@ -213,23 +213,23 @@ msgstr "Ottlethray"
|
|||
msgid "Unknown LED ID %d"
|
||||
msgstr "Unknownay EDLay IDay %d"
|
||||
|
||||
#: libx52io/io_strings.c:103
|
||||
#: libx52io/io_strings.c:198
|
||||
msgid "No device"
|
||||
msgstr "Onay eviceday"
|
||||
|
||||
#: libx52io/io_strings.c:104
|
||||
#: libx52io/io_strings.c:199
|
||||
msgid "Invalid arguments"
|
||||
msgstr "Invaliday argumentsay"
|
||||
|
||||
#: libx52io/io_strings.c:105
|
||||
#: libx52io/io_strings.c:200
|
||||
msgid "Connection failure"
|
||||
msgstr "Onnectioncay ailurefay"
|
||||
|
||||
#: libx52io/io_strings.c:106
|
||||
#: libx52io/io_strings.c:201
|
||||
msgid "I/O error"
|
||||
msgstr "I/O erroray"
|
||||
|
||||
#: libx52io/io_strings.c:107
|
||||
#: libx52io/io_strings.c:202
|
||||
msgid "Read timeout"
|
||||
msgstr "Eadray imeouttay"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue