mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 06:50:05 +01:00
Split utility functions into separate source files
libinput-util.h is getting a bit of a catchall bucket and it includes things like libinput-private.h which in turn includes libwacom. This makes libinput-util.h less useful for bits that only need e.g. the string processing utilities. So let's split them all up in to separate files, to be used as-needed. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
00f3345b80
commit
c84366e85e
16 changed files with 1270 additions and 898 deletions
42
meson.build
42
meson.build
|
|
@ -218,9 +218,45 @@ else
|
|||
endif
|
||||
|
||||
############ libinput-util.a ############
|
||||
|
||||
# Basic compilation test to make sure the headers include and define all the
|
||||
# necessary bits.
|
||||
util_headers = [
|
||||
'util-bits.h',
|
||||
'util-list.h',
|
||||
'util-macros.h',
|
||||
'util-matrix.h',
|
||||
'util-prop-parsers.h',
|
||||
'util-ratelimit.h',
|
||||
'util-strings.h',
|
||||
'util-time.h',
|
||||
]
|
||||
foreach h: util_headers
|
||||
c = configuration_data()
|
||||
c.set_quoted('FILE', h)
|
||||
testfile = configure_file(input : 'test/test-util-includes.c',
|
||||
output : 'test-util-includes-@0@.c'.format(h),
|
||||
configuration : c)
|
||||
executable('test-build-@0@'.format(h),
|
||||
testfile, join_paths(dir_src, h),
|
||||
include_directories : [includes_src, includes_include],
|
||||
install : false)
|
||||
endforeach
|
||||
|
||||
src_libinput_util = [
|
||||
'src/libinput-util.c',
|
||||
'src/libinput-util.h'
|
||||
'src/util-bits.h',
|
||||
'src/util-list.c',
|
||||
'src/util-list.h',
|
||||
'src/util-macros.h',
|
||||
'src/util-matrix.h',
|
||||
'src/util-ratelimit.c',
|
||||
'src/util-ratelimit.h',
|
||||
'src/util-strings.h',
|
||||
'src/util-strings.c',
|
||||
'src/util-time.h',
|
||||
'src/util-prop-parsers.h',
|
||||
'src/util-prop-parsers.c',
|
||||
'src/libinput-util.h',
|
||||
]
|
||||
libinput_util = static_library('libinput-util',
|
||||
src_libinput_util,
|
||||
|
|
@ -836,7 +872,6 @@ if get_option('tests')
|
|||
|
||||
test_utils_sources = [
|
||||
'src/libinput-util.h',
|
||||
'src/libinput-util.c',
|
||||
'test/test-utils.c',
|
||||
]
|
||||
test_utils = executable('test-utils',
|
||||
|
|
@ -850,7 +885,6 @@ if get_option('tests')
|
|||
|
||||
libinput_test_runner_sources = litest_sources + [
|
||||
'src/libinput-util.h',
|
||||
'src/libinput-util.c',
|
||||
'test/test-udev.c',
|
||||
'test/test-path.c',
|
||||
'test/test-pointer.c',
|
||||
|
|
|
|||
|
|
@ -31,29 +31,18 @@
|
|||
#warning "libinput relies on assert(). #defining NDEBUG is not recommended"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "libinput.h"
|
||||
|
||||
#include "util-bits.h"
|
||||
#include "util-macros.h"
|
||||
#include "util-list.h"
|
||||
#include "util-matrix.h"
|
||||
#include "util-strings.h"
|
||||
#include "util-ratelimit.h"
|
||||
#include "util-prop-parsers.h"
|
||||
#include "util-time.h"
|
||||
|
||||
#define VENDOR_ID_APPLE 0x5ac
|
||||
#define VENDOR_ID_CHICONY 0x4f2
|
||||
#define VENDOR_ID_LOGITECH 0x46d
|
||||
|
|
@ -68,74 +57,6 @@
|
|||
#define DEFAULT_MOUSE_DPI 1000
|
||||
#define DEFAULT_TRACKPOINT_SENSITIVITY 128
|
||||
|
||||
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
|
||||
#define ANSI_RED "\x1B[0;31m"
|
||||
#define ANSI_GREEN "\x1B[0;32m"
|
||||
#define ANSI_YELLOW "\x1B[0;33m"
|
||||
#define ANSI_BLUE "\x1B[0;34m"
|
||||
#define ANSI_MAGENTA "\x1B[0;35m"
|
||||
#define ANSI_CYAN "\x1B[0;36m"
|
||||
#define ANSI_BRIGHT_RED "\x1B[0;31;1m"
|
||||
#define ANSI_BRIGHT_GREEN "\x1B[0;32;1m"
|
||||
#define ANSI_BRIGHT_YELLOW "\x1B[0;33;1m"
|
||||
#define ANSI_BRIGHT_BLUE "\x1B[0;34;1m"
|
||||
#define ANSI_BRIGHT_MAGENTA "\x1B[0;35;1m"
|
||||
#define ANSI_BRIGHT_CYAN "\x1B[0;36;1m"
|
||||
#define ANSI_NORMAL "\x1B[0m"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
#define bit(x_) (1UL << (x_))
|
||||
/*
|
||||
* This list data structure is a verbatim copy from wayland-util.h from the
|
||||
* Wayland project; except that wl_ prefix has been removed.
|
||||
*/
|
||||
|
||||
struct list {
|
||||
struct list *prev;
|
||||
struct list *next;
|
||||
};
|
||||
|
||||
void list_init(struct list *list);
|
||||
void list_insert(struct list *list, struct list *elm);
|
||||
void list_append(struct list *list, struct list *elm);
|
||||
void list_remove(struct list *elm);
|
||||
bool list_empty(const struct list *list);
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
(__typeof__(type) *)((char *)(ptr) - \
|
||||
offsetof(__typeof__(type), member))
|
||||
|
||||
#define list_first_entry(head, pos, member) \
|
||||
container_of((head)->next, __typeof__(*pos), member)
|
||||
|
||||
#define list_for_each(pos, head, member) \
|
||||
for (pos = 0, pos = list_first_entry(head, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_first_entry(&pos->member, pos, member))
|
||||
|
||||
#define list_for_each_safe(pos, tmp, head, member) \
|
||||
for (pos = 0, tmp = 0, \
|
||||
pos = list_first_entry(head, pos, member), \
|
||||
tmp = list_first_entry(&pos->member, tmp, member); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = list_first_entry(&pos->member, tmp, member))
|
||||
|
||||
#define NBITS(b) (b * 8)
|
||||
#define LONG_BITS (sizeof(long) * 8)
|
||||
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
#define ARRAY_FOR_EACH(_arr, _elem) \
|
||||
for (size_t _i = 0; _i < ARRAY_LENGTH(_arr) && (_elem = &_arr[_i]); _i++)
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define streq(s1, s2) (strcmp((s1), (s2)) == 0)
|
||||
#define strneq(s1, s2, n) (strncmp((s1), (s2), (n)) == 0)
|
||||
|
||||
#define NCHARS(x) ((size_t)(((x) + 7) / 8))
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
#define debug_trace(...) \
|
||||
do { \
|
||||
|
|
@ -148,557 +69,4 @@ bool list_empty(const struct list *list);
|
|||
|
||||
#define LIBINPUT_EXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
static inline void *
|
||||
zalloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
/* We never need to alloc anything more than 1,5 MB so we can assume
|
||||
* if we ever get above that something's going wrong */
|
||||
if (size > 1536 * 1024)
|
||||
assert(!"bug: internal malloc size limit exceeded");
|
||||
|
||||
p = calloc(1, size);
|
||||
if (!p)
|
||||
abort();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* strdup guaranteed to succeed. If the input string is NULL, the output
|
||||
* string is NULL. If the input string is a string pointer, we strdup or
|
||||
* abort on failure.
|
||||
*/
|
||||
static inline char*
|
||||
safe_strdup(const char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
s = strdup(str);
|
||||
if (!s)
|
||||
abort();
|
||||
return s;
|
||||
}
|
||||
|
||||
/* This bitfield helper implementation is taken from from libevdev-util.h,
|
||||
* except that it has been modified to work with arrays of unsigned chars
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
bit_is_set(const unsigned char *array, int bit)
|
||||
{
|
||||
return !!(array[bit / 8] & (1 << (bit % 8)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_bit(unsigned char *array, int bit)
|
||||
{
|
||||
array[bit / 8] |= (1 << (bit % 8));
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_bit(unsigned char *array, int bit)
|
||||
{
|
||||
array[bit / 8] &= ~(1 << (bit % 8));
|
||||
}
|
||||
|
||||
static inline void
|
||||
msleep(unsigned int ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
long_bit_is_set(const unsigned long *array, int bit)
|
||||
{
|
||||
return !!(array[bit / LONG_BITS] & (1ULL << (bit % LONG_BITS)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_set_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] |= (1ULL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_clear_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] &= ~(1ULL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_set_bit_state(unsigned long *array, int bit, int state)
|
||||
{
|
||||
if (state)
|
||||
long_set_bit(array, bit);
|
||||
else
|
||||
long_clear_bit(array, bit);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
long_any_bit_set(unsigned long *array, size_t size)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (array[i] != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline double
|
||||
deg2rad(int degree)
|
||||
{
|
||||
return M_PI * degree / 180.0;
|
||||
}
|
||||
|
||||
struct matrix {
|
||||
float val[3][3]; /* [row][col] */
|
||||
};
|
||||
|
||||
static inline void
|
||||
matrix_init_identity(struct matrix *m)
|
||||
{
|
||||
memset(m, 0, sizeof(*m));
|
||||
m->val[0][0] = 1;
|
||||
m->val[1][1] = 1;
|
||||
m->val[2][2] = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_from_farray6(struct matrix *m, const float values[6])
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = values[0];
|
||||
m->val[0][1] = values[1];
|
||||
m->val[0][2] = values[2];
|
||||
m->val[1][0] = values[3];
|
||||
m->val[1][1] = values[4];
|
||||
m->val[1][2] = values[5];
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_scale(struct matrix *m, float sx, float sy)
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = sx;
|
||||
m->val[1][1] = sy;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_translate(struct matrix *m, float x, float y)
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][2] = x;
|
||||
m->val[1][2] = y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_rotate(struct matrix *m, int degrees)
|
||||
{
|
||||
double s, c;
|
||||
|
||||
s = sin(deg2rad(degrees));
|
||||
c = cos(deg2rad(degrees));
|
||||
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = c;
|
||||
m->val[0][1] = -s;
|
||||
m->val[1][0] = s;
|
||||
m->val[1][1] = c;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
matrix_is_identity(const struct matrix *m)
|
||||
{
|
||||
return (m->val[0][0] == 1 &&
|
||||
m->val[0][1] == 0 &&
|
||||
m->val[0][2] == 0 &&
|
||||
m->val[1][0] == 0 &&
|
||||
m->val[1][1] == 1 &&
|
||||
m->val[1][2] == 0 &&
|
||||
m->val[2][0] == 0 &&
|
||||
m->val[2][1] == 0 &&
|
||||
m->val[2][2] == 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_mult(struct matrix *dest,
|
||||
const struct matrix *m1,
|
||||
const struct matrix *m2)
|
||||
{
|
||||
struct matrix m; /* allow for dest == m1 or dest == m2 */
|
||||
int row, col, i;
|
||||
|
||||
for (row = 0; row < 3; row++) {
|
||||
for (col = 0; col < 3; col++) {
|
||||
double v = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
v += m1->val[row][i] * m2->val[i][col];
|
||||
}
|
||||
m.val[row][col] = v;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(dest, &m, sizeof(m));
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_mult_vec(const struct matrix *m, int *x, int *y)
|
||||
{
|
||||
int tx, ty;
|
||||
|
||||
tx = *x * m->val[0][0] + *y * m->val[0][1] + m->val[0][2];
|
||||
ty = *x * m->val[1][0] + *y * m->val[1][1] + m->val[1][2];
|
||||
|
||||
*x = tx;
|
||||
*y = ty;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_to_farray6(const struct matrix *m, float out[6])
|
||||
{
|
||||
out[0] = m->val[0][0];
|
||||
out[1] = m->val[0][1];
|
||||
out[2] = m->val[0][2];
|
||||
out[3] = m->val[1][0];
|
||||
out[4] = m->val[1][1];
|
||||
out[5] = m->val[1][2];
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_to_relative(struct matrix *dest, const struct matrix *src)
|
||||
{
|
||||
matrix_init_identity(dest);
|
||||
dest->val[0][0] = src->val[0][0];
|
||||
dest->val[0][1] = src->val[0][1];
|
||||
dest->val[1][0] = src->val[1][0];
|
||||
dest->val[1][1] = src->val[1][1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for asprintf that ensures the passed in-pointer is set
|
||||
* to NULL upon error.
|
||||
* The standard asprintf() call does not guarantee the passed in pointer
|
||||
* will be NULL'ed upon failure, whereas this wrapper does.
|
||||
*
|
||||
* @param strp pointer to set to newly allocated string.
|
||||
* This pointer should be passed to free() to release when done.
|
||||
* @param fmt the format string to use for printing.
|
||||
* @return The number of bytes printed (excluding the null byte terminator)
|
||||
* upon success or -1 upon failure. In the case of failure the pointer is set
|
||||
* to NULL.
|
||||
*/
|
||||
LIBINPUT_ATTRIBUTE_PRINTF(2, 3)
|
||||
static inline int
|
||||
xasprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
int rc = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
rc = vasprintf(strp, fmt, args);
|
||||
va_end(args);
|
||||
if ((rc == -1) && strp)
|
||||
*strp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum ratelimit_state {
|
||||
RATELIMIT_EXCEEDED,
|
||||
RATELIMIT_THRESHOLD,
|
||||
RATELIMIT_PASS,
|
||||
};
|
||||
|
||||
struct ratelimit {
|
||||
uint64_t interval;
|
||||
uint64_t begin;
|
||||
unsigned int burst;
|
||||
unsigned int num;
|
||||
};
|
||||
|
||||
void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst);
|
||||
enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
||||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
int parse_mouse_wheel_click_count_property(const char *prop);
|
||||
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
||||
bool parse_calibration_property(const char *prop, float calibration[6]);
|
||||
bool parse_range_property(const char *prop, int *hi, int *lo);
|
||||
#define EVENT_CODE_UNDEFINED 0xffff
|
||||
bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents);
|
||||
|
||||
enum tpkbcombo_layout {
|
||||
TPKBCOMBO_LAYOUT_UNKNOWN,
|
||||
TPKBCOMBO_LAYOUT_BELOW,
|
||||
};
|
||||
bool parse_tpkbcombo_layout_poperty(const char *prop,
|
||||
enum tpkbcombo_layout *layout);
|
||||
|
||||
enum switch_reliability {
|
||||
RELIABILITY_UNKNOWN,
|
||||
RELIABILITY_RELIABLE,
|
||||
RELIABILITY_WRITE_OPEN,
|
||||
};
|
||||
|
||||
bool
|
||||
parse_switch_reliability_property(const char *prop,
|
||||
enum switch_reliability *reliability);
|
||||
|
||||
static inline uint64_t
|
||||
us(uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ns2us(uint64_t ns)
|
||||
{
|
||||
return us(ns / 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ms2us(uint64_t ms)
|
||||
{
|
||||
return us(ms * 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
s2us(uint64_t s)
|
||||
{
|
||||
return ms2us(s * 1000);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
us2ms(uint64_t us)
|
||||
{
|
||||
return (uint32_t)(us / 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
tv2us(const struct timeval *tv)
|
||||
{
|
||||
return s2us(tv->tv_sec) + tv->tv_usec;
|
||||
}
|
||||
|
||||
static inline struct timeval
|
||||
us2tv(uint64_t time)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = time / ms2us(1000);
|
||||
tv.tv_usec = time % ms2us(1000);
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi_base(const char *str, int *val, int base)
|
||||
{
|
||||
char *endptr;
|
||||
long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtol(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if (v > INT_MAX || v < INT_MIN)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi(const char *str, int *val)
|
||||
{
|
||||
return safe_atoi_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou_base(const char *str, unsigned int *val, int base)
|
||||
{
|
||||
char *endptr;
|
||||
unsigned long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtoul(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if ((long)v < 0)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou(const char *str, unsigned int *val)
|
||||
{
|
||||
return safe_atou_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atod(const char *str, double *val)
|
||||
{
|
||||
char *endptr;
|
||||
double v;
|
||||
#ifdef HAVE_LOCALE_H
|
||||
locale_t c_locale;
|
||||
#endif
|
||||
size_t slen = strlen(str);
|
||||
|
||||
/* We don't have a use-case where we want to accept hex for a double
|
||||
* or any of the other values strtod can parse */
|
||||
for (size_t i = 0; i < slen; i++) {
|
||||
char c = str[i];
|
||||
|
||||
if (isdigit(c))
|
||||
continue;
|
||||
switch(c) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '.':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
/* Create a "C" locale to force strtod to use '.' as separator */
|
||||
c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||
if (c_locale == (locale_t)0)
|
||||
return false;
|
||||
|
||||
errno = 0;
|
||||
v = strtod_l(str, &endptr, c_locale);
|
||||
freelocale(c_locale);
|
||||
#else
|
||||
/* No locale support in provided libc, assume it already uses '.' */
|
||||
errno = 0;
|
||||
v = strtod(str, &endptr);
|
||||
#endif
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
if (v != 0.0 && !isnormal(v))
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
char **strv_from_string(const char *string, const char *separator);
|
||||
char *strv_join(char **strv, const char *separator);
|
||||
|
||||
static inline void
|
||||
strv_free(char **strv) {
|
||||
char **s = strv;
|
||||
|
||||
if (!strv)
|
||||
return;
|
||||
|
||||
while (*s != NULL) {
|
||||
free(*s);
|
||||
*s = (char*)0x1; /* detect use-after-free */
|
||||
s++;
|
||||
}
|
||||
|
||||
free (strv);
|
||||
}
|
||||
|
||||
struct key_value_str{
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct key_value_double {
|
||||
double key;
|
||||
double value;
|
||||
};
|
||||
|
||||
static inline ssize_t
|
||||
kv_double_from_string(const char *string,
|
||||
const char *pair_separator,
|
||||
const char *kv_separator,
|
||||
struct key_value_double **result_out)
|
||||
|
||||
{
|
||||
char **pairs;
|
||||
char **pair;
|
||||
struct key_value_double *result = NULL;
|
||||
ssize_t npairs = 0;
|
||||
unsigned int idx = 0;
|
||||
|
||||
if (!pair_separator || pair_separator[0] == '\0' ||
|
||||
!kv_separator || kv_separator[0] == '\0')
|
||||
return -1;
|
||||
|
||||
pairs = strv_from_string(string, pair_separator);
|
||||
if (!pairs)
|
||||
return -1;
|
||||
|
||||
for (pair = pairs; *pair; pair++)
|
||||
npairs++;
|
||||
|
||||
if (npairs == 0)
|
||||
goto error;
|
||||
|
||||
result = zalloc(npairs * sizeof *result);
|
||||
|
||||
for (pair = pairs; *pair; pair++) {
|
||||
char **kv = strv_from_string(*pair, kv_separator);
|
||||
double k, v;
|
||||
|
||||
if (!kv || !kv[0] || !kv[1] || kv[2] ||
|
||||
!safe_atod(kv[0], &k) ||
|
||||
!safe_atod(kv[1], &v)) {
|
||||
strv_free(kv);
|
||||
goto error;
|
||||
}
|
||||
|
||||
result[idx].key = k;
|
||||
result[idx].value = v;
|
||||
idx++;
|
||||
|
||||
strv_free(kv);
|
||||
}
|
||||
|
||||
strv_free(pairs);
|
||||
|
||||
*result_out = result;
|
||||
|
||||
return npairs;
|
||||
|
||||
error:
|
||||
strv_free(pairs);
|
||||
free(result);
|
||||
return -1;
|
||||
}
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
101
src/util-bits.h
Normal file
101
src/util-bits.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define bit(x_) (1UL << (x_))
|
||||
#define NBITS(b) (b * 8)
|
||||
#define LONG_BITS (sizeof(long) * 8)
|
||||
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
|
||||
#define NCHARS(x) ((size_t)(((x) + 7) / 8))
|
||||
|
||||
|
||||
/* This bitfield helper implementation is taken from from libevdev-util.h,
|
||||
* except that it has been modified to work with arrays of unsigned chars
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
bit_is_set(const unsigned char *array, int bit)
|
||||
{
|
||||
return !!(array[bit / 8] & (1 << (bit % 8)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_bit(unsigned char *array, int bit)
|
||||
{
|
||||
array[bit / 8] |= (1 << (bit % 8));
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_bit(unsigned char *array, int bit)
|
||||
{
|
||||
array[bit / 8] &= ~(1 << (bit % 8));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
long_bit_is_set(const unsigned long *array, int bit)
|
||||
{
|
||||
return !!(array[bit / LONG_BITS] & (1ULL << (bit % LONG_BITS)));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_set_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] |= (1ULL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_clear_bit(unsigned long *array, int bit)
|
||||
{
|
||||
array[bit / LONG_BITS] &= ~(1ULL << (bit % LONG_BITS));
|
||||
}
|
||||
|
||||
static inline void
|
||||
long_set_bit_state(unsigned long *array, int bit, int state)
|
||||
{
|
||||
if (state)
|
||||
long_set_bit(array, bit);
|
||||
else
|
||||
long_clear_bit(array, bit);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
long_any_bit_set(unsigned long *array, size_t size)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (array[i] != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
88
src/util-list.c
Normal file
88
src/util-list.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-list.h"
|
||||
|
||||
void
|
||||
list_init(struct list *list)
|
||||
{
|
||||
list->prev = list;
|
||||
list->next = list;
|
||||
}
|
||||
|
||||
void
|
||||
list_insert(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->prev = list;
|
||||
elm->next = list->next;
|
||||
list->next = elm;
|
||||
elm->next->prev = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_append(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->next = list;
|
||||
elm->prev = list->prev;
|
||||
list->prev = elm;
|
||||
elm->prev->next = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_remove(struct list *elm)
|
||||
{
|
||||
assert((elm->next != NULL && elm->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
elm->prev->next = elm->next;
|
||||
elm->next->prev = elm->prev;
|
||||
elm->next = NULL;
|
||||
elm->prev = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
list_empty(const struct list *list)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
return list->next == list;
|
||||
}
|
||||
66
src/util-list.h
Normal file
66
src/util-list.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* This list data structure is a verbatim copy from wayland-util.h from the
|
||||
* Wayland project; except that wl_ prefix has been removed.
|
||||
*/
|
||||
|
||||
struct list {
|
||||
struct list *prev;
|
||||
struct list *next;
|
||||
};
|
||||
|
||||
void list_init(struct list *list);
|
||||
void list_insert(struct list *list, struct list *elm);
|
||||
void list_append(struct list *list, struct list *elm);
|
||||
void list_remove(struct list *elm);
|
||||
bool list_empty(const struct list *list);
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
(__typeof__(type) *)((char *)(ptr) - \
|
||||
offsetof(__typeof__(type), member))
|
||||
|
||||
#define list_first_entry(head, pos, member) \
|
||||
container_of((head)->next, __typeof__(*pos), member)
|
||||
|
||||
#define list_for_each(pos, head, member) \
|
||||
for (pos = 0, pos = list_first_entry(head, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_first_entry(&pos->member, pos, member))
|
||||
|
||||
#define list_for_each_safe(pos, tmp, head, member) \
|
||||
for (pos = 0, tmp = 0, \
|
||||
pos = list_first_entry(head, pos, member), \
|
||||
tmp = list_first_entry(&pos->member, tmp, member); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = list_first_entry(&pos->member, tmp, member))
|
||||
52
src/util-macros.h
Normal file
52
src/util-macros.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
#define ARRAY_FOR_EACH(_arr, _elem) \
|
||||
for (size_t _i = 0; _i < ARRAY_LENGTH(_arr) && (_elem = &_arr[_i]); _i++)
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
|
||||
#define ANSI_RED "\x1B[0;31m"
|
||||
#define ANSI_GREEN "\x1B[0;32m"
|
||||
#define ANSI_YELLOW "\x1B[0;33m"
|
||||
#define ANSI_BLUE "\x1B[0;34m"
|
||||
#define ANSI_MAGENTA "\x1B[0;35m"
|
||||
#define ANSI_CYAN "\x1B[0;36m"
|
||||
#define ANSI_BRIGHT_RED "\x1B[0;31;1m"
|
||||
#define ANSI_BRIGHT_GREEN "\x1B[0;32;1m"
|
||||
#define ANSI_BRIGHT_YELLOW "\x1B[0;33;1m"
|
||||
#define ANSI_BRIGHT_BLUE "\x1B[0;34;1m"
|
||||
#define ANSI_BRIGHT_MAGENTA "\x1B[0;35;1m"
|
||||
#define ANSI_BRIGHT_CYAN "\x1B[0;36;1m"
|
||||
#define ANSI_NORMAL "\x1B[0m"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
162
src/util-matrix.h
Normal file
162
src/util-matrix.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
struct matrix {
|
||||
float val[3][3]; /* [row][col] */
|
||||
};
|
||||
|
||||
static inline double
|
||||
deg2rad(int degree)
|
||||
{
|
||||
return M_PI * degree / 180.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_identity(struct matrix *m)
|
||||
{
|
||||
memset(m, 0, sizeof(*m));
|
||||
m->val[0][0] = 1;
|
||||
m->val[1][1] = 1;
|
||||
m->val[2][2] = 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_from_farray6(struct matrix *m, const float values[6])
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = values[0];
|
||||
m->val[0][1] = values[1];
|
||||
m->val[0][2] = values[2];
|
||||
m->val[1][0] = values[3];
|
||||
m->val[1][1] = values[4];
|
||||
m->val[1][2] = values[5];
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_scale(struct matrix *m, float sx, float sy)
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = sx;
|
||||
m->val[1][1] = sy;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_translate(struct matrix *m, float x, float y)
|
||||
{
|
||||
matrix_init_identity(m);
|
||||
m->val[0][2] = x;
|
||||
m->val[1][2] = y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_init_rotate(struct matrix *m, int degrees)
|
||||
{
|
||||
double s, c;
|
||||
|
||||
s = sin(deg2rad(degrees));
|
||||
c = cos(deg2rad(degrees));
|
||||
|
||||
matrix_init_identity(m);
|
||||
m->val[0][0] = c;
|
||||
m->val[0][1] = -s;
|
||||
m->val[1][0] = s;
|
||||
m->val[1][1] = c;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
matrix_is_identity(const struct matrix *m)
|
||||
{
|
||||
return (m->val[0][0] == 1 &&
|
||||
m->val[0][1] == 0 &&
|
||||
m->val[0][2] == 0 &&
|
||||
m->val[1][0] == 0 &&
|
||||
m->val[1][1] == 1 &&
|
||||
m->val[1][2] == 0 &&
|
||||
m->val[2][0] == 0 &&
|
||||
m->val[2][1] == 0 &&
|
||||
m->val[2][2] == 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_mult(struct matrix *dest,
|
||||
const struct matrix *m1,
|
||||
const struct matrix *m2)
|
||||
{
|
||||
struct matrix m; /* allow for dest == m1 or dest == m2 */
|
||||
int row, col, i;
|
||||
|
||||
for (row = 0; row < 3; row++) {
|
||||
for (col = 0; col < 3; col++) {
|
||||
double v = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
v += m1->val[row][i] * m2->val[i][col];
|
||||
}
|
||||
m.val[row][col] = v;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(dest, &m, sizeof(m));
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_mult_vec(const struct matrix *m, int *x, int *y)
|
||||
{
|
||||
int tx, ty;
|
||||
|
||||
tx = *x * m->val[0][0] + *y * m->val[0][1] + m->val[0][2];
|
||||
ty = *x * m->val[1][0] + *y * m->val[1][1] + m->val[1][2];
|
||||
|
||||
*x = tx;
|
||||
*y = ty;
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_to_farray6(const struct matrix *m, float out[6])
|
||||
{
|
||||
out[0] = m->val[0][0];
|
||||
out[1] = m->val[0][1];
|
||||
out[2] = m->val[0][2];
|
||||
out[3] = m->val[1][0];
|
||||
out[4] = m->val[1][1];
|
||||
out[5] = m->val[1][2];
|
||||
}
|
||||
|
||||
static inline void
|
||||
matrix_to_relative(struct matrix *dest, const struct matrix *src)
|
||||
{
|
||||
matrix_init_identity(dest);
|
||||
dest->val[0][0] = src->val[0][0];
|
||||
dest->val[0][1] = src->val[0][1];
|
||||
dest->val[1][0] = src->val[1][0];
|
||||
dest->val[1][1] = src->val[1][1];
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
* Copyright © 2013-2019 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -23,127 +21,13 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This list data structure is verbatim copy from wayland-util.h from the
|
||||
* Wayland project; except that wl_ prefix has been removed.
|
||||
*/
|
||||
#include "util-prop-parsers.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
void
|
||||
list_init(struct list *list)
|
||||
{
|
||||
list->prev = list;
|
||||
list->next = list;
|
||||
}
|
||||
|
||||
void
|
||||
list_insert(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->prev = list;
|
||||
elm->next = list->next;
|
||||
list->next = elm;
|
||||
elm->next->prev = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_append(struct list *list, struct list *elm)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
|
||||
!"elm->next|prev is not NULL, list node used twice?");
|
||||
|
||||
elm->next = list;
|
||||
elm->prev = list->prev;
|
||||
list->prev = elm;
|
||||
elm->prev->next = elm;
|
||||
}
|
||||
|
||||
void
|
||||
list_remove(struct list *elm)
|
||||
{
|
||||
assert((elm->next != NULL && elm->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
elm->prev->next = elm->next;
|
||||
elm->next->prev = elm->prev;
|
||||
elm->next = NULL;
|
||||
elm->prev = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
list_empty(const struct list *list)
|
||||
{
|
||||
assert((list->next != NULL && list->prev != NULL) ||
|
||||
!"list->next|prev is NULL, possibly missing list_init()");
|
||||
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
void
|
||||
ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst)
|
||||
{
|
||||
r->interval = ival_us;
|
||||
r->begin = 0;
|
||||
r->burst = burst;
|
||||
r->num = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform rate-limit test. Returns RATELIMIT_PASS if the rate-limited action
|
||||
* is still allowed, RATELIMIT_THRESHOLD if the limit has been reached with
|
||||
* this call, and RATELIMIT_EXCEEDED if you're beyond the threshold.
|
||||
* It's safe to treat the return-value as boolean, if you're not interested in
|
||||
* the exact state. It evaluates to "true" if the threshold hasn't been
|
||||
* exceeded, yet.
|
||||
*
|
||||
* The ratelimit object must be initialized via ratelimit_init().
|
||||
*
|
||||
* Modelled after Linux' lib/ratelimit.c by Dave Young
|
||||
* <hidave.darkstar@gmail.com>, which is licensed GPLv2.
|
||||
*/
|
||||
enum ratelimit_state
|
||||
ratelimit_test(struct ratelimit *r)
|
||||
{
|
||||
struct timespec ts;
|
||||
uint64_t utime;
|
||||
|
||||
if (r->interval <= 0 || r->burst <= 0)
|
||||
return RATELIMIT_PASS;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
utime = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
|
||||
|
||||
if (r->begin <= 0 || r->begin + r->interval < utime) {
|
||||
/* reset counter */
|
||||
r->begin = utime;
|
||||
r->num = 1;
|
||||
return RATELIMIT_PASS;
|
||||
} else if (r->num < r->burst) {
|
||||
/* continue burst */
|
||||
return (++r->num == r->burst) ? RATELIMIT_THRESHOLD
|
||||
: RATELIMIT_PASS;
|
||||
}
|
||||
|
||||
return RATELIMIT_EXCEEDED;
|
||||
}
|
||||
#include "util-macros.h"
|
||||
#include "util-strings.h"
|
||||
|
||||
/* Helper function to parse the mouse DPI tag from udev.
|
||||
* The tag is of the form:
|
||||
|
|
@ -517,133 +401,3 @@ out:
|
|||
strv_free(strv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next word in a string pointed to by state before the first
|
||||
* separator character. Call repeatedly to tokenize a whole string.
|
||||
*
|
||||
* @param state Current state
|
||||
* @param len String length of the word returned
|
||||
* @param separators List of separator characters
|
||||
*
|
||||
* @return The first word in *state, NOT null-terminated
|
||||
*/
|
||||
static const char *
|
||||
next_word(const char **state, size_t *len, const char *separators)
|
||||
{
|
||||
const char *next = *state;
|
||||
size_t l;
|
||||
|
||||
if (!*next)
|
||||
return NULL;
|
||||
|
||||
next += strspn(next, separators);
|
||||
if (!*next) {
|
||||
*state = next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = strcspn(next, separators);
|
||||
*state = next + l;
|
||||
*len = l;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a null-terminated string array with the tokens in the input
|
||||
* string, e.g. "one two\tthree" with a separator list of " \t" will return
|
||||
* an array [ "one", "two", "three", NULL ].
|
||||
*
|
||||
* Use strv_free() to free the array.
|
||||
*
|
||||
* @param in Input string
|
||||
* @param separators List of separator characters
|
||||
*
|
||||
* @return A null-terminated string array or NULL on errors
|
||||
*/
|
||||
char **
|
||||
strv_from_string(const char *in, const char *separators)
|
||||
{
|
||||
const char *s, *word;
|
||||
char **strv = NULL;
|
||||
int nelems = 0, idx;
|
||||
size_t l;
|
||||
|
||||
assert(in != NULL);
|
||||
|
||||
s = in;
|
||||
while ((word = next_word(&s, &l, separators)) != NULL)
|
||||
nelems++;
|
||||
|
||||
if (nelems == 0)
|
||||
return NULL;
|
||||
|
||||
nelems++; /* NULL-terminated */
|
||||
strv = zalloc(nelems * sizeof *strv);
|
||||
|
||||
idx = 0;
|
||||
|
||||
s = in;
|
||||
while ((word = next_word(&s, &l, separators)) != NULL) {
|
||||
char *copy = strndup(word, l);
|
||||
if (!copy) {
|
||||
strv_free(strv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strv[idx++] = copy;
|
||||
}
|
||||
|
||||
return strv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a newly allocated string with all elements joined by the
|
||||
* joiner, same as Python's string.join() basically.
|
||||
* A strv of ["one", "two", "three", NULL] with a joiner of ", " results
|
||||
* in "one, two, three".
|
||||
*
|
||||
* An empty strv ([NULL]) returns NULL, same for passing NULL as either
|
||||
* argument.
|
||||
*
|
||||
* @param strv Input string arrray
|
||||
* @param joiner Joiner between the elements in the final string
|
||||
*
|
||||
* @return A null-terminated string joining all elements
|
||||
*/
|
||||
char *
|
||||
strv_join(char **strv, const char *joiner)
|
||||
{
|
||||
char **s;
|
||||
char *str;
|
||||
size_t slen = 0;
|
||||
size_t count = 0;
|
||||
|
||||
if (!strv || !joiner)
|
||||
return NULL;
|
||||
|
||||
if (strv[0] == NULL)
|
||||
return NULL;
|
||||
|
||||
for (s = strv, count = 0; *s; s++, count++) {
|
||||
slen += strlen(*s);
|
||||
}
|
||||
|
||||
assert(slen < 1000);
|
||||
assert(strlen(joiner) < 1000);
|
||||
assert(count > 0);
|
||||
assert(count < 100);
|
||||
|
||||
slen += (count - 1) * strlen(joiner);
|
||||
|
||||
str = zalloc(slen + 1); /* trailing \0 */
|
||||
for (s = strv; *s; s++) {
|
||||
strcat(str, *s);
|
||||
--count;
|
||||
if (count > 0)
|
||||
strcat(str, joiner);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
56
src/util-prop-parsers.h
Normal file
56
src/util-prop-parsers.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright © 2013-2019 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
int parse_mouse_wheel_click_count_property(const char *prop);
|
||||
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
||||
bool parse_calibration_property(const char *prop, float calibration[6]);
|
||||
bool parse_range_property(const char *prop, int *hi, int *lo);
|
||||
#define EVENT_CODE_UNDEFINED 0xffff
|
||||
bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents);
|
||||
|
||||
enum tpkbcombo_layout {
|
||||
TPKBCOMBO_LAYOUT_UNKNOWN,
|
||||
TPKBCOMBO_LAYOUT_BELOW,
|
||||
};
|
||||
bool parse_tpkbcombo_layout_poperty(const char *prop,
|
||||
enum tpkbcombo_layout *layout);
|
||||
|
||||
enum switch_reliability {
|
||||
RELIABILITY_UNKNOWN,
|
||||
RELIABILITY_RELIABLE,
|
||||
RELIABILITY_WRITE_OPEN,
|
||||
};
|
||||
|
||||
bool
|
||||
parse_switch_reliability_property(const char *prop,
|
||||
enum switch_reliability *reliability);
|
||||
79
src/util-ratelimit.c
Normal file
79
src/util-ratelimit.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Intel Corporation
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "util-ratelimit.h"
|
||||
#include "util-time.h"
|
||||
|
||||
void
|
||||
ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst)
|
||||
{
|
||||
r->interval = ival_us;
|
||||
r->begin = 0;
|
||||
r->burst = burst;
|
||||
r->num = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform rate-limit test. Returns RATELIMIT_PASS if the rate-limited action
|
||||
* is still allowed, RATELIMIT_THRESHOLD if the limit has been reached with
|
||||
* this call, and RATELIMIT_EXCEEDED if you're beyond the threshold.
|
||||
* It's safe to treat the return-value as boolean, if you're not interested in
|
||||
* the exact state. It evaluates to "true" if the threshold hasn't been
|
||||
* exceeded, yet.
|
||||
*
|
||||
* The ratelimit object must be initialized via ratelimit_init().
|
||||
*
|
||||
* Modelled after Linux' lib/ratelimit.c by Dave Young
|
||||
* <hidave.darkstar@gmail.com>, which is licensed GPLv2.
|
||||
*/
|
||||
enum ratelimit_state
|
||||
ratelimit_test(struct ratelimit *r)
|
||||
{
|
||||
struct timespec ts;
|
||||
uint64_t utime;
|
||||
|
||||
if (r->interval <= 0 || r->burst <= 0)
|
||||
return RATELIMIT_PASS;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
utime = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
|
||||
|
||||
if (r->begin <= 0 || r->begin + r->interval < utime) {
|
||||
/* reset counter */
|
||||
r->begin = utime;
|
||||
r->num = 1;
|
||||
return RATELIMIT_PASS;
|
||||
} else if (r->num < r->burst) {
|
||||
/* continue burst */
|
||||
return (++r->num == r->burst) ? RATELIMIT_THRESHOLD
|
||||
: RATELIMIT_PASS;
|
||||
}
|
||||
|
||||
return RATELIMIT_EXCEEDED;
|
||||
}
|
||||
45
src/util-ratelimit.h
Normal file
45
src/util-ratelimit.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum ratelimit_state {
|
||||
RATELIMIT_EXCEEDED,
|
||||
RATELIMIT_THRESHOLD,
|
||||
RATELIMIT_PASS,
|
||||
};
|
||||
|
||||
struct ratelimit {
|
||||
uint64_t interval;
|
||||
uint64_t begin;
|
||||
unsigned int burst;
|
||||
unsigned int num;
|
||||
};
|
||||
|
||||
void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst);
|
||||
enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
||||
157
src/util-strings.c
Normal file
157
src/util-strings.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "util-strings.h"
|
||||
|
||||
/**
|
||||
* Return the next word in a string pointed to by state before the first
|
||||
* separator character. Call repeatedly to tokenize a whole string.
|
||||
*
|
||||
* @param state Current state
|
||||
* @param len String length of the word returned
|
||||
* @param separators List of separator characters
|
||||
*
|
||||
* @return The first word in *state, NOT null-terminated
|
||||
*/
|
||||
static const char *
|
||||
next_word(const char **state, size_t *len, const char *separators)
|
||||
{
|
||||
const char *next = *state;
|
||||
size_t l;
|
||||
|
||||
if (!*next)
|
||||
return NULL;
|
||||
|
||||
next += strspn(next, separators);
|
||||
if (!*next) {
|
||||
*state = next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l = strcspn(next, separators);
|
||||
*state = next + l;
|
||||
*len = l;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a null-terminated string array with the tokens in the input
|
||||
* string, e.g. "one two\tthree" with a separator list of " \t" will return
|
||||
* an array [ "one", "two", "three", NULL ].
|
||||
*
|
||||
* Use strv_free() to free the array.
|
||||
*
|
||||
* @param in Input string
|
||||
* @param separators List of separator characters
|
||||
*
|
||||
* @return A null-terminated string array or NULL on errors
|
||||
*/
|
||||
char **
|
||||
strv_from_string(const char *in, const char *separators)
|
||||
{
|
||||
const char *s, *word;
|
||||
char **strv = NULL;
|
||||
int nelems = 0, idx;
|
||||
size_t l;
|
||||
|
||||
assert(in != NULL);
|
||||
|
||||
s = in;
|
||||
while ((word = next_word(&s, &l, separators)) != NULL)
|
||||
nelems++;
|
||||
|
||||
if (nelems == 0)
|
||||
return NULL;
|
||||
|
||||
nelems++; /* NULL-terminated */
|
||||
strv = zalloc(nelems * sizeof *strv);
|
||||
|
||||
idx = 0;
|
||||
|
||||
s = in;
|
||||
while ((word = next_word(&s, &l, separators)) != NULL) {
|
||||
char *copy = strndup(word, l);
|
||||
if (!copy) {
|
||||
strv_free(strv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strv[idx++] = copy;
|
||||
}
|
||||
|
||||
return strv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a newly allocated string with all elements joined by the
|
||||
* joiner, same as Python's string.join() basically.
|
||||
* A strv of ["one", "two", "three", NULL] with a joiner of ", " results
|
||||
* in "one, two, three".
|
||||
*
|
||||
* An empty strv ([NULL]) returns NULL, same for passing NULL as either
|
||||
* argument.
|
||||
*
|
||||
* @param strv Input string arrray
|
||||
* @param joiner Joiner between the elements in the final string
|
||||
*
|
||||
* @return A null-terminated string joining all elements
|
||||
*/
|
||||
char *
|
||||
strv_join(char **strv, const char *joiner)
|
||||
{
|
||||
char **s;
|
||||
char *str;
|
||||
size_t slen = 0;
|
||||
size_t count = 0;
|
||||
|
||||
if (!strv || !joiner)
|
||||
return NULL;
|
||||
|
||||
if (strv[0] == NULL)
|
||||
return NULL;
|
||||
|
||||
for (s = strv, count = 0; *s; s++, count++) {
|
||||
slen += strlen(*s);
|
||||
}
|
||||
|
||||
assert(slen < 1000);
|
||||
assert(strlen(joiner) < 1000);
|
||||
assert(count > 0);
|
||||
assert(count < 100);
|
||||
|
||||
slen += (count - 1) * strlen(joiner);
|
||||
|
||||
str = zalloc(slen + 1); /* trailing \0 */
|
||||
for (s = strv; *s; s++) {
|
||||
strcat(str, *s);
|
||||
--count;
|
||||
if (count > 0)
|
||||
strcat(str, joiner);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
314
src/util-strings.h
Normal file
314
src/util-strings.h
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#define streq(s1, s2) (strcmp((s1), (s2)) == 0)
|
||||
#define strneq(s1, s2, n) (strncmp((s1), (s2), (n)) == 0)
|
||||
|
||||
static inline void *
|
||||
zalloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
/* We never need to alloc anything more than 1,5 MB so we can assume
|
||||
* if we ever get above that something's going wrong */
|
||||
if (size > 1536 * 1024)
|
||||
assert(!"bug: internal malloc size limit exceeded");
|
||||
|
||||
p = calloc(1, size);
|
||||
if (!p)
|
||||
abort();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* strdup guaranteed to succeed. If the input string is NULL, the output
|
||||
* string is NULL. If the input string is a string pointer, we strdup or
|
||||
* abort on failure.
|
||||
*/
|
||||
static inline char*
|
||||
safe_strdup(const char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
s = strdup(str);
|
||||
if (!s)
|
||||
abort();
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper for asprintf that ensures the passed in-pointer is set
|
||||
* to NULL upon error.
|
||||
* The standard asprintf() call does not guarantee the passed in pointer
|
||||
* will be NULL'ed upon failure, whereas this wrapper does.
|
||||
*
|
||||
* @param strp pointer to set to newly allocated string.
|
||||
* This pointer should be passed to free() to release when done.
|
||||
* @param fmt the format string to use for printing.
|
||||
* @return The number of bytes printed (excluding the null byte terminator)
|
||||
* upon success or -1 upon failure. In the case of failure the pointer is set
|
||||
* to NULL.
|
||||
*/
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
static inline int
|
||||
xasprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
int rc = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
rc = vasprintf(strp, fmt, args);
|
||||
va_end(args);
|
||||
if ((rc == -1) && strp)
|
||||
*strp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi_base(const char *str, int *val, int base)
|
||||
{
|
||||
char *endptr;
|
||||
long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtol(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if (v > INT_MAX || v < INT_MIN)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atoi(const char *str, int *val)
|
||||
{
|
||||
return safe_atoi_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou_base(const char *str, unsigned int *val, int base)
|
||||
{
|
||||
char *endptr;
|
||||
unsigned long v;
|
||||
|
||||
assert(base == 10 || base == 16 || base == 8);
|
||||
|
||||
errno = 0;
|
||||
v = strtoul(str, &endptr, base);
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
|
||||
if ((long)v < 0)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atou(const char *str, unsigned int *val)
|
||||
{
|
||||
return safe_atou_base(str, val, 10);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
safe_atod(const char *str, double *val)
|
||||
{
|
||||
char *endptr;
|
||||
double v;
|
||||
#ifdef HAVE_LOCALE_H
|
||||
locale_t c_locale;
|
||||
#endif
|
||||
size_t slen = strlen(str);
|
||||
|
||||
/* We don't have a use-case where we want to accept hex for a double
|
||||
* or any of the other values strtod can parse */
|
||||
for (size_t i = 0; i < slen; i++) {
|
||||
char c = str[i];
|
||||
|
||||
if (isdigit(c))
|
||||
continue;
|
||||
switch(c) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '.':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
/* Create a "C" locale to force strtod to use '.' as separator */
|
||||
c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||
if (c_locale == (locale_t)0)
|
||||
return false;
|
||||
|
||||
errno = 0;
|
||||
v = strtod_l(str, &endptr, c_locale);
|
||||
freelocale(c_locale);
|
||||
#else
|
||||
/* No locale support in provided libc, assume it already uses '.' */
|
||||
errno = 0;
|
||||
v = strtod(str, &endptr);
|
||||
#endif
|
||||
if (errno > 0)
|
||||
return false;
|
||||
if (str == endptr)
|
||||
return false;
|
||||
if (*str != '\0' && *endptr != '\0')
|
||||
return false;
|
||||
if (v != 0.0 && !isnormal(v))
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
char **strv_from_string(const char *string, const char *separator);
|
||||
char *strv_join(char **strv, const char *separator);
|
||||
|
||||
static inline void
|
||||
strv_free(char **strv) {
|
||||
char **s = strv;
|
||||
|
||||
if (!strv)
|
||||
return;
|
||||
|
||||
while (*s != NULL) {
|
||||
free(*s);
|
||||
*s = (char*)0x1; /* detect use-after-free */
|
||||
s++;
|
||||
}
|
||||
|
||||
free (strv);
|
||||
}
|
||||
|
||||
struct key_value_str{
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct key_value_double {
|
||||
double key;
|
||||
double value;
|
||||
};
|
||||
|
||||
static inline ssize_t
|
||||
kv_double_from_string(const char *string,
|
||||
const char *pair_separator,
|
||||
const char *kv_separator,
|
||||
struct key_value_double **result_out)
|
||||
|
||||
{
|
||||
char **pairs;
|
||||
char **pair;
|
||||
struct key_value_double *result = NULL;
|
||||
ssize_t npairs = 0;
|
||||
unsigned int idx = 0;
|
||||
|
||||
if (!pair_separator || pair_separator[0] == '\0' ||
|
||||
!kv_separator || kv_separator[0] == '\0')
|
||||
return -1;
|
||||
|
||||
pairs = strv_from_string(string, pair_separator);
|
||||
if (!pairs)
|
||||
return -1;
|
||||
|
||||
for (pair = pairs; *pair; pair++)
|
||||
npairs++;
|
||||
|
||||
if (npairs == 0)
|
||||
goto error;
|
||||
|
||||
result = zalloc(npairs * sizeof *result);
|
||||
|
||||
for (pair = pairs; *pair; pair++) {
|
||||
char **kv = strv_from_string(*pair, kv_separator);
|
||||
double k, v;
|
||||
|
||||
if (!kv || !kv[0] || !kv[1] || kv[2] ||
|
||||
!safe_atod(kv[0], &k) ||
|
||||
!safe_atod(kv[1], &v)) {
|
||||
strv_free(kv);
|
||||
goto error;
|
||||
}
|
||||
|
||||
result[idx].key = k;
|
||||
result[idx].value = v;
|
||||
idx++;
|
||||
|
||||
strv_free(kv);
|
||||
}
|
||||
|
||||
strv_free(pairs);
|
||||
|
||||
*result_out = result;
|
||||
|
||||
return npairs;
|
||||
|
||||
error:
|
||||
strv_free(pairs);
|
||||
free(result);
|
||||
return -1;
|
||||
}
|
||||
83
src/util-time.h
Normal file
83
src/util-time.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright © 2013-2019 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static inline void
|
||||
msleep(unsigned int ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
us(uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ns2us(uint64_t ns)
|
||||
{
|
||||
return us(ns / 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ms2us(uint64_t ms)
|
||||
{
|
||||
return us(ms * 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
s2us(uint64_t s)
|
||||
{
|
||||
return ms2us(s * 1000);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
us2ms(uint64_t us)
|
||||
{
|
||||
return (uint32_t)(us / 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
tv2us(const struct timeval *tv)
|
||||
{
|
||||
return s2us(tv->tv_sec) + tv->tv_usec;
|
||||
}
|
||||
|
||||
static inline struct timeval
|
||||
us2tv(uint64_t time)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = time / ms2us(1000);
|
||||
tv.tv_usec = time % ms2us(1000);
|
||||
|
||||
return tv;
|
||||
}
|
||||
6
test/test-util-includes.c
Normal file
6
test/test-util-includes.c
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* compile test for the util files */
|
||||
#include @FILE@
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -24,11 +24,18 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <libinput-util.h>
|
||||
|
||||
#include <valgrind/valgrind.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "util-list.h"
|
||||
#include "util-strings.h"
|
||||
#include "util-time.h"
|
||||
#include "util-prop-parsers.h"
|
||||
#include "util-macros.h"
|
||||
#include "util-bits.h"
|
||||
#include "util-ratelimit.h"
|
||||
#include "util-matrix.h"
|
||||
|
||||
#define TEST_VERSIONSORT
|
||||
#include "libinput-versionsort.h"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue