keysyms: Add xkb_keysym_is_assigned

Add internal API `xkb_keysym_is_assigned` for tests, guarded by
`ENABLE_PRIVATE_APIS` in order to avoid increasing the size of the installed library.
master
Pierre Le Marre 2023-12-14 09:16:55 +01:00 committed by Wismill
parent 82f138c633
commit 4f52d6068e
5 changed files with 81 additions and 12 deletions

View File

@ -623,6 +623,7 @@ libxkbcommon_test_internal = static_library(
'bench/bench.h', 'bench/bench.h',
libxkbcommon_sources, libxkbcommon_sources,
include_directories: include_directories('src', 'include'), include_directories: include_directories('src', 'include'),
c_args: ['-DENABLE_PRIVATE_APIS'],
) )
test_dep = declare_dependency( test_dep = declare_dependency(
include_directories: include_directories('src', 'include'), include_directories: include_directories('src', 'include'),
@ -652,7 +653,8 @@ if get_option('enable-x11')
endif endif
test( test(
'keysym', 'keysym',
executable('test-keysym', 'test/keysym.c', dependencies: test_dep), executable('test-keysym', 'test/keysym.c', dependencies: test_dep,
c_args: ['-DENABLE_PRIVATE_APIS']),
env: test_env, env: test_env,
) )
test( test(

View File

@ -55,6 +55,36 @@
#include "keysym.h" #include "keysym.h"
#include "ks_tables.h" #include "ks_tables.h"
static ssize_t
find_keysym_index(xkb_keysym_t ks)
{
/* Lower bound:
* keysym_to_name[0].keysym
* == XKB_KEYSYM_MIN_EXPLICIT == XKB_KEYSYM_MIN == 0
* No need to check: xkb_keysym_t is unsigned.
*
* Upper bound:
* keysym_to_name[ARRAY_SIZE(keysym_to_name) - 1].keysym
* == XKB_KEYSYM_MAX_EXPLICIT <= XKB_KEYSYM_MAX
*/
if (ks > XKB_KEYSYM_MAX_EXPLICIT)
return -1;
ssize_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
while (hi >= lo) {
ssize_t mid = (lo + hi) / 2;
if (ks > keysym_to_name[mid].keysym) {
lo = mid + 1;
} else if (ks < keysym_to_name[mid].keysym) {
hi = mid - 1;
} else {
return mid;
}
}
return -1;
}
static inline const char * static inline const char *
get_name(const struct name_keysym *entry) get_name(const struct name_keysym *entry)
{ {
@ -69,17 +99,9 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
return -1; return -1;
} }
int32_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1; ssize_t index = find_keysym_index(ks);
while (hi >= lo) { if (index != -1)
int32_t mid = (lo + hi) / 2; return snprintf(buffer, size, "%s", get_name(&keysym_to_name[index]));
if (ks > keysym_to_name[mid].keysym) {
lo = mid + 1;
} else if (ks < keysym_to_name[mid].keysym) {
hi = mid - 1;
} else {
return snprintf(buffer, size, "%s", get_name(&keysym_to_name[mid]));
}
}
/* Unnamed Unicode codepoint. */ /* Unnamed Unicode codepoint. */
if (ks >= XKB_KEYSYM_UNICODE_MIN && ks <= XKB_KEYSYM_UNICODE_MAX) { if (ks >= XKB_KEYSYM_UNICODE_MIN && ks <= XKB_KEYSYM_UNICODE_MAX) {
@ -91,6 +113,13 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
return snprintf(buffer, size, "0x%08x", ks); return snprintf(buffer, size, "0x%08x", ks);
} }
bool
xkb_keysym_is_assigned(xkb_keysym_t ks)
{
return (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= XKB_KEYSYM_UNICODE_MAX) ||
find_keysym_index(ks) != -1;
}
/* /*
* Parse the numeric part of a 0xXXXX and UXXXX keysym. * Parse the numeric part of a 0xXXXX and UXXXX keysym.
* Not using strtoul -- it's slower and accepts a bunch of stuff * Not using strtoul -- it's slower and accepts a bunch of stuff

View File

@ -50,6 +50,9 @@
#ifndef KEYSYM_H #ifndef KEYSYM_H
#define KEYSYM_H #define KEYSYM_H
#include <stdbool.h>
#include "xkbcommon/xkbcommon.h"
/* /*
* NOTE: this is not defined in xkbcommon.h, because if we did, it may add * NOTE: this is not defined in xkbcommon.h, because if we did, it may add
* overhead for library user: when handling keysyms they would also need to * overhead for library user: when handling keysyms they would also need to
@ -74,6 +77,9 @@
/** Maximum Unicode keysym, correspoding to the maximum Unicode code point */ /** Maximum Unicode keysym, correspoding to the maximum Unicode code point */
#define XKB_KEYSYM_UNICODE_MAX 0x0110ffff #define XKB_KEYSYM_UNICODE_MAX 0x0110ffff
bool
xkb_keysym_is_assigned(xkb_keysym_t ks);
bool bool
xkb_keysym_is_lower(xkb_keysym_t keysym); xkb_keysym_is_lower(xkb_keysym_t keysym);

View File

@ -50,6 +50,9 @@
#ifndef KEYSYM_H #ifndef KEYSYM_H
#define KEYSYM_H #define KEYSYM_H
#include <stdbool.h>
#include "xkbcommon/xkbcommon.h"
/* /*
* NOTE: this is not defined in xkbcommon.h, because if we did, it may add * NOTE: this is not defined in xkbcommon.h, because if we did, it may add
* overhead for library user: when handling keysyms they would also need to * overhead for library user: when handling keysyms they would also need to
@ -74,6 +77,9 @@
/** Maximum Unicode keysym, correspoding to the maximum Unicode code point */ /** Maximum Unicode keysym, correspoding to the maximum Unicode code point */
#define XKB_KEYSYM_UNICODE_MAX 0x0110ffff #define XKB_KEYSYM_UNICODE_MAX 0x0110ffff
bool
xkb_keysym_is_assigned(xkb_keysym_t ks);
bool bool
xkb_keysym_is_lower(xkb_keysym_t keysym); xkb_keysym_is_lower(xkb_keysym_t keysym);

View File

@ -147,6 +147,32 @@ main(void)
assert(XKB_KEYSYM_UNICODE_MIN < XKB_KEYSYM_UNICODE_MAX); assert(XKB_KEYSYM_UNICODE_MIN < XKB_KEYSYM_UNICODE_MAX);
assert(XKB_KEYSYM_UNICODE_MAX <= XKB_KEYSYM_MAX_EXPLICIT); assert(XKB_KEYSYM_UNICODE_MAX <= XKB_KEYSYM_MAX_EXPLICIT);
/* Assigned keysyms */
assert(xkb_keysym_is_assigned(XKB_KEYSYM_MIN));
assert(xkb_keysym_is_assigned(XKB_KEYSYM_MIN_ASSIGNED));
assert(xkb_keysym_is_assigned(XKB_KEY_space));
assert(xkb_keysym_is_assigned(XKB_KEY_nobreakspace));
assert(xkb_keysym_is_assigned(XKB_KEY_Aogonek));
assert(xkb_keysym_is_assigned(XKB_KEY_Hstroke));
assert(xkb_keysym_is_assigned(XKB_KEY_kra));
assert(xkb_keysym_is_assigned(XKB_KEY_braille_dot_1));
assert(xkb_keysym_is_assigned(XKB_KEY_XF86KbdLcdMenu5));
assert(xkb_keysym_is_assigned(XKB_KEY_Shift_L));
assert(xkb_keysym_is_assigned(XKB_KEY_XF86MonBrightnessUp));
assert(xkb_keysym_is_assigned(XKB_KEY_VoidSymbol));
assert(xkb_keysym_is_assigned(XKB_KEYSYM_UNICODE_MIN));
assert(xkb_keysym_is_assigned((XKB_KEYSYM_UNICODE_MIN + XKB_KEYSYM_UNICODE_MAX) / 2));
assert(xkb_keysym_is_assigned(XKB_KEYSYM_UNICODE_MAX));
assert(xkb_keysym_is_assigned(XKB_KEYSYM_MAX_ASSIGNED));
assert(!xkb_keysym_is_assigned(XKB_KEYSYM_MAX));
for (xkb_keysym_t ks = XKB_KEYSYM_MIN; ks <= XKB_KEYSYM_MAX; ks++) {
if (!xkb_keysym_is_assigned(ks))
continue;
/* Check assigned keysyms bounds */
assert(XKB_KEYSYM_MIN_ASSIGNED <= (int32_t)ks && ks <= XKB_KEYSYM_MAX_ASSIGNED);
}
/* Named keysyms */ /* Named keysyms */
assert(test_string("NoSymbol", XKB_KEY_NoSymbol)); assert(test_string("NoSymbol", XKB_KEY_NoSymbol));
assert(test_string("Undo", 0xFF65)); assert(test_string("Undo", 0xFF65));