[PATCH 2/4] input: make InputOption opaque, provide interface functions.
Peter Hutterer
peter.hutterer at who-t.net
Wed Aug 10 20:20:50 PDT 2011
InputOptions is not switched to use struct list for a future patch to unify
it with the XF86OptionRec.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
config/config-backends.h | 2 +-
config/config.c | 22 ------
config/udev.c | 35 ++++------
dix/inpututils.c | 145 ++++++++++++++++++++++++++++++++++++++++
hw/xfree86/common/xf86Xinput.c | 28 ++++----
include/input.h | 17 +++--
include/inputstr.h | 7 ++
test/input.c | 58 ++++++++++++++++
8 files changed, 251 insertions(+), 63 deletions(-)
diff --git a/config/config-backends.h b/config/config-backends.h
index 0d36d72..35ab8a0 100644
--- a/config/config-backends.h
+++ b/config/config-backends.h
@@ -27,10 +27,10 @@
#include <dix-config.h>
#endif
#include "input.h"
+#include "list.h"
void remove_devices(const char *backend, const char *config_info);
BOOL device_is_duplicate(const char *config_info);
-InputOption* add_option(InputOption **options, const char *key, const char *value);
#ifdef CONFIG_UDEV
int config_udev_init(void);
diff --git a/config/config.c b/config/config.c
index af8f4f9..9c28785 100644
--- a/config/config.c
+++ b/config/config.c
@@ -122,25 +122,3 @@ device_is_duplicate(const char *config_info)
return FALSE;
}
-/**
- * Allocate a new option and append to the list.
- *
- * @return A pointer to the newly allocated InputOption struct.
- */
-InputOption*
-add_option(InputOption **options, const char *key, const char *value)
-{
- if (!value || *value == '\0')
- return NULL;
-
- for (; *options; options = &(*options)->next)
- ;
- *options = calloc(sizeof(**options), 1);
- if (!*options) /* Yeesh. */
- return NULL;
- (*options)->key = strdup(key);
- (*options)->value = strdup(value);
- (*options)->next = NULL;
-
- return *options;
-}
diff --git a/config/udev.c b/config/udev.c
index c17c4fd..2ab9260 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -60,7 +60,7 @@ device_added(struct udev_device *udev_device)
const char *syspath;
const char *tags_prop;
const char *key, *value, *tmp;
- InputOption *options = NULL, *tmpo;
+ InputOption *input_options;
InputAttributes attrs = {};
DeviceIntPtr dev = NULL;
struct udev_list_entry *set, *entry;
@@ -94,8 +94,9 @@ device_added(struct udev_device *udev_device)
return;
}
- if (!add_option(&options, "_source", "server/udev"))
- goto unwind;
+ input_options = input_option_new(NULL, "_source", "server/udev");
+ if (!input_options)
+ return;
name = udev_device_get_property_value(udev_device, "ID_MODEL");
LOG_SYSATTR(path, "ID_MODEL", name);
@@ -144,10 +145,9 @@ device_added(struct udev_device *udev_device)
name = "(unnamed)";
else
attrs.product = strdup(name);
- add_option(&options, "name", name);
-
- add_option(&options, "path", path);
- add_option(&options, "device", path);
+ input_options = input_option_new(input_options, "name", name);
+ input_options = input_option_new(input_options, "path", path);
+ input_options = input_option_new(input_options, "device", path);
if (path)
attrs.device = strdup(path);
@@ -177,15 +177,15 @@ device_added(struct udev_device *udev_device)
LOG_PROPERTY(path, key, value);
tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
if (!strcasecmp(tmp, "rules"))
- add_option(&options, "xkb_rules", value);
+ input_options = input_option_new(input_options, "xkb_rules", value);
else if (!strcasecmp(tmp, "layout"))
- add_option(&options, "xkb_layout", value);
+ input_options = input_option_new(input_options, "xkb_layout", value);
else if (!strcasecmp(tmp, "variant"))
- add_option(&options, "xkb_variant", value);
+ input_options = input_option_new(input_options, "xkb_variant", value);
else if (!strcasecmp(tmp, "model"))
- add_option(&options, "xkb_model", value);
+ input_options = input_option_new(input_options, "xkb_model", value);
else if (!strcasecmp(tmp, "options"))
- add_option(&options, "xkb_options", value);
+ input_options = input_option_new(input_options, "xkb_options", value);
} else if (!strcmp(key, "ID_VENDOR")) {
LOG_PROPERTY(path, key, value);
attrs.vendor = strdup(value);
@@ -210,22 +210,17 @@ device_added(struct udev_device *udev_device)
}
}
- add_option(&options, "config_info", config_info);
+ input_options = input_option_new(input_options, "config_info", config_info);
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
name, path);
- rc = NewInputDeviceRequest(options, &attrs, &dev);
+ rc = NewInputDeviceRequest(input_options, &attrs, &dev);
if (rc != Success)
goto unwind;
unwind:
free(config_info);
- while ((tmpo = options)) {
- options = tmpo->next;
- free(tmpo->key); /* NULL if dev != NULL */
- free(tmpo->value); /* NULL if dev != NULL */
- free(tmpo);
- }
+ input_option_free_list(&input_options);
free(attrs.usb_id);
free(attrs.pnp_id);
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 9632076..ed600c4 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -598,3 +598,148 @@ void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
event->deviceid = dev->id;
event->sourceid = dev->id;
}
+
+/**
+ * Delete the element with the key from the list, freeing all memory
+ * associated with the element..
+ */
+static void
+input_option_free(InputOption *o)
+{
+ free(o->key);
+ free(o->value);
+ free(o);
+}
+
+/*
+ * Create a new InputOption with the key/value pair provided.
+ * If a list is provided, the new options is added to the list and the list
+ * is returned.
+ *
+ * If a new option is added to a list that already contains that option, the
+ * previous option is overwritten.
+ *
+ * @param list The list to add to.
+ * @param key Option key, will be copied.
+ * @param value Option value, will be copied.
+ *
+ * @return If list is not NULL, the list with the new option added. If list
+ * is NULL, a new option list with one element. On failure, NULL is
+ * returned.
+ */
+InputOption*
+input_option_new(InputOption* list, const char *key, const char *value)
+{
+ InputOption *opt = NULL;
+
+ if (!key)
+ return NULL;
+
+ if (list)
+ {
+ nt_list_for_each_entry(opt, list, next)
+ {
+ if (strcmp(input_option_get_key(opt), key) == 0)
+ {
+ input_option_set_value(opt, value);
+ return list;
+ }
+ }
+ }
+
+ opt = calloc(1, sizeof(InputOption));
+ if (!opt)
+ goto error;
+ nt_list_init(opt, next);
+
+ input_option_set_key(opt, key);
+ input_option_set_value(opt, value);
+
+ if (list)
+ {
+ nt_list_append(opt, list, InputOption, next);
+ return list;
+ } else
+ return opt;
+
+error:
+ input_option_free(opt);
+ return NULL;
+}
+
+InputOption*
+input_option_free_element(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, next) {
+ if (strcmp(input_option_get_key(element), key) == 0) {
+ nt_list_del(element, list, InputOption, next);
+ input_option_free(element);
+ break;
+ }
+ }
+ return list;
+}
+
+/**
+ * Free the list pointed at by opt.
+ */
+void
+input_option_free_list(InputOption **opt)
+{
+ InputOption *element, *tmp;
+
+ nt_list_for_each_entry_safe(element, tmp, *opt, next) {
+ nt_list_del(element, *opt, InputOption, next);
+ input_option_free(element);
+ }
+ *opt = NULL;
+}
+
+
+/**
+ * Find the InputOption with the given option name.
+ *
+ * @return The InputOption or NULL if not present.
+ */
+InputOption*
+input_option_find(InputOption *list, const char *key)
+{
+ InputOption *element;
+
+ nt_list_for_each_entry(element, list, next) {
+ if (strcmp(input_option_get_key(element), key) == 0)
+ return element;
+ }
+
+ return NULL;
+}
+
+const char*
+input_option_get_key(const InputOption *opt)
+{
+ return opt->key;
+}
+
+const char*
+input_option_get_value(const InputOption *opt)
+{
+ return opt->value;
+}
+
+void
+input_option_set_key(InputOption *opt, const char *key)
+{
+ free(opt->key);
+ if (key)
+ opt->key = strdup(key);
+}
+
+void
+input_option_set_value(InputOption *opt, const char *value)
+{
+ free(opt->value);
+ if (value)
+ opt->value = strdup(value);
+}
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index cecf4ff..444efec 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -879,35 +879,35 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
if (!pInfo)
return BadAlloc;
- for (option = options; option; option = option->next) {
- if (strcasecmp(option->key, "driver") == 0) {
+ nt_list_for_each_entry(option, options, next) {
+ if (strcasecmp(input_option_get_key(option), "driver") == 0) {
if (pInfo->driver) {
rval = BadRequest;
goto unwind;
}
- pInfo->driver = xstrdup(option->value);
+ pInfo->driver = xstrdup(input_option_get_value(option));
if (!pInfo->driver) {
rval = BadAlloc;
goto unwind;
}
}
- if (strcasecmp(option->key, "name") == 0 ||
- strcasecmp(option->key, "identifier") == 0) {
+ if (strcasecmp(input_option_get_key(option), "name") == 0 ||
+ strcasecmp(input_option_get_key(option), "identifier") == 0) {
if (pInfo->name) {
rval = BadRequest;
goto unwind;
}
- pInfo->name = xstrdup(option->value);
+ pInfo->name = xstrdup(input_option_get_value(option));
if (!pInfo->name) {
rval = BadAlloc;
goto unwind;
}
}
- if (strcmp(option->key, "_source") == 0 &&
- (strcmp(option->value, "server/hal") == 0 ||
- strcmp(option->value, "server/udev") == 0)) {
+ if (strcmp(input_option_get_key(option), "_source") == 0 &&
+ (strcmp(input_option_get_value(option), "server/hal") == 0 ||
+ strcmp(input_option_get_value(option), "server/udev") == 0)) {
is_auto = 1;
if (!xf86Info.autoAddDevices) {
rval = BadMatch;
@@ -916,13 +916,11 @@ NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
}
}
- for (option = options; option; option = option->next) {
- /* Steal option key/value strings from the provided list.
- * We need those strings, the InputOption list doesn't. */
+ nt_list_for_each_entry(option, options, next) {
+ /* Copy option key/value strings from the provided list */
pInfo->options = xf86addNewOption(pInfo->options,
- option->key, option->value);
- option->key = NULL;
- option->value = NULL;
+ strdup(input_option_get_key(option)),
+ strdup(input_option_get_value(option)));
}
/* Apply InputClass settings */
diff --git a/include/input.h b/include/input.h
index 5377a0c..0258f4f 100644
--- a/include/input.h
+++ b/include/input.h
@@ -56,6 +56,7 @@ SOFTWARE.
#include "window.h" /* for WindowPtr */
#include "xkbrules.h"
#include "events.h"
+#include "list.h"
#define DEVICE_INIT 0
#define DEVICE_ON 1
@@ -202,11 +203,7 @@ typedef struct {
extern _X_EXPORT KeybdCtrl defaultKeyboardControl;
extern _X_EXPORT PtrCtrl defaultPointerControl;
-typedef struct _InputOption {
- char *key;
- char *value;
- struct _InputOption *next;
-} InputOption;
+typedef struct _InputOption InputOption;
typedef struct _InputAttributes {
char *product;
@@ -595,4 +592,14 @@ extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest,
const ValuatorMask *src);
extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum);
+/* InputOption handling interface */
+extern _X_EXPORT InputOption* input_option_new(InputOption *list, const char *key, const char *value);
+extern _X_EXPORT void input_option_free_list(InputOption **opt);
+extern _X_EXPORT InputOption* input_option_free_element(InputOption *opt, const char *key);
+extern _X_EXPORT InputOption* input_option_find(InputOption *list, const char *key);
+extern _X_EXPORT const char* input_option_get_key(const InputOption *opt);
+extern _X_EXPORT const char* input_option_get_value(const InputOption *opt);
+extern _X_EXPORT void input_option_set_key(InputOption *opt, const char* key);
+extern _X_EXPORT void input_option_set_value(InputOption *opt, const char* value);
+
#endif /* INPUT_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index 838f9f0..480e956 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -602,4 +602,11 @@ static inline WindowPtr DeepestSpriteWin(SpritePtr sprite)
return sprite->spriteTrace[sprite->spriteTraceGood - 1];
}
+struct _InputOption {
+ char *key;
+ char *value;
+ struct _InputOption *next;
+};
+
+
#endif /* INPUTSTRUCT_H */
diff --git a/test/input.c b/test/input.c
index c2b0eb0..30321ed 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1308,6 +1308,63 @@ static void dix_get_master(void)
}
+static void input_option_test(void)
+{
+ InputOption *list = NULL;
+ InputOption *opt;
+ const char *val;
+
+ printf("Testing input_option list interface\n");
+
+ list = input_option_new(list, "key", "value");
+ assert(list);
+ opt = input_option_find(list, "key");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "value") == 0);
+
+ list = input_option_new(list, "2", "v2");
+ opt = input_option_find(list, "key");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "value") == 0);
+
+ opt = input_option_find(list, "2");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "v2") == 0);
+
+ list = input_option_new(list, "3", "v3");
+
+ /* search, delete */
+ opt = input_option_find(list, "key");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "value") == 0);
+ list = input_option_free_element(list, "key");
+ opt = input_option_find(list, "key");
+ assert(opt == NULL);
+
+ opt = input_option_find(list, "2");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "v2") == 0);
+ list = input_option_free_element(list, "2");
+ opt = input_option_find(list, "2");
+ assert(opt == NULL);
+
+ opt = input_option_find(list, "3");
+ val = input_option_get_value(opt);
+ assert(strcmp(val, "v3") == 0);
+ list = input_option_free_element(list, "3");
+ opt = input_option_find(list, "3");
+ assert(opt == NULL);
+
+ /* recreate */
+ list = input_option_new(list, "3", "v3");
+ list = input_option_new(list, "3", "v3");
+ list = input_option_new(list, "3", "v3");
+ input_option_free_list(&list);
+
+ assert(list == NULL);
+}
+
+
int main(int argc, char** argv)
{
dix_input_valuator_masks();
@@ -1324,6 +1381,7 @@ int main(int argc, char** argv)
xi_unregister_handlers();
dix_valuator_alloc();
dix_get_master();
+ input_option_test();
return 0;
}
--
1.7.6
More information about the xorg-devel
mailing list