diff options
author | Ran Benita <ran234@gmail.com> | 2016-12-02 22:15:19 +0200 |
---|---|---|
committer | Ran Benita <ran234@gmail.com> | 2016-12-02 23:46:56 +0200 |
commit | b5586a6c4294b46eb23d1fc527ff63dcd27e23ac (patch) | |
tree | a567b29fe33c258006e6ec9b4d51a9acda4d0514 /src/keysym.c | |
parent | 327364d277609600aa19aabd6dc55f2fc7dfb8cf (diff) | |
download | xorg-lib-libxkbcommon-b5586a6c4294b46eb23d1fc527ff63dcd27e23ac.tar.gz |
keysym: fix locale dependence in xkb_keysym_from_name()
We currently use strcasecmp, which is locale-dependent. In particular,
one well-known surprise even if restricted just ASCII input is found in
the tr_TR (Turkish) locale, see e.g.
https://msdn.microsoft.com/en-us/library/ms973919.aspx#stringsinnet20_topic5
We have known to avoid locale-dependent functions before, but in this
case, we forgot.
Fix it by implementing our own simple ASCII-only strcasecmp/strncasecmp.
Might have been possible to use strcasecmp_l() with the C locale, but
went the easy route.
Side advantage is that even this non-optimized version is faster than
the optimized libc one (__strcasecmp_l_sse42) since it doesn't need to
do the locale stuff. xkb_keysym_from_name(), which uses strcasecmp
heavily, becomes faster, and so for example Compose file parsing, which
uses xkb_keysym_from_name() heavily, becomes ~20% faster.
Resolves https://github.com/xkbcommon/libxkbcommon/issues/42
Signed-off-by: Ran Benita <ran234@gmail.com>
Diffstat (limited to 'src/keysym.c')
-rw-r--r-- | src/keysym.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/src/keysym.c b/src/keysym.c index db0e973..9e7b4fb 100644 --- a/src/keysym.c +++ b/src/keysym.c @@ -76,7 +76,7 @@ compare_by_name(const void *a, const void *b) { const char *key = a; const struct name_keysym *entry = b; - return strcasecmp(key, get_name(entry)); + return istrcmp(key, get_name(entry)); } XKB_EXPORT int @@ -109,7 +109,7 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size) /* * Find the correct keysym if one case-insensitive match is given. * - * The name_to_keysym table is sorted by strcasecmp(). So bsearch() may return + * The name_to_keysym table is sorted by istrcmp(). So bsearch() may return * _any_ of all possible case-insensitive duplicates. This function searches the * returned entry @entry, all previous and all next entries that match by * case-insensitive comparison and returns the exact match to @name. If @icase @@ -138,7 +138,7 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase) for (iter = entry - 1; iter >= name_to_keysym; --iter) { if (!icase && strcmp(get_name(iter), name) == 0) return iter; - if (strcasecmp(get_name(iter), get_name(entry)) != 0) + if (istrcmp(get_name(iter), get_name(entry)) != 0) break; if (icase && xkb_keysym_is_lower(iter->keysym)) return iter; @@ -148,7 +148,7 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase) for (iter = entry + 1; iter < last; ++iter) { if (!icase && strcmp(get_name(iter), name) == 0) return iter; - if (strcasecmp(get_name(iter), get_name(entry)) != 0) + if (istrcmp(get_name(iter), get_name(entry)) != 0) break; if (icase && xkb_keysym_is_lower(iter->keysym)) return iter; |