dix: add helper functions to duplicate and free InputAttributes.

No special memory handling is used to give drivers the maximum flexibility
with the data. Drivers should be able to call realloc on the product string
if needed and perform similar operations.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Dan Nicholson <dbn.lists@gmail.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Peter Hutterer 2010-05-25 17:12:34 +10:00 committed by Keith Packard
parent bf78e11839
commit 86303a338a
3 changed files with 183 additions and 0 deletions

View File

@ -331,3 +331,82 @@ int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
return Success;
}
/**
* Duplicate the InputAttributes in the most obvious way.
* No special memory handling is used to give drivers the maximum
* flexibility with the data. Drivers should be able to call realloc on the
* product string if needed and perform similar operations.
*/
InputAttributes*
DuplicateInputAttributes(InputAttributes *attrs)
{
InputAttributes *new_attr;
int ntags = 0;
char **tags, **new_tags;
if (!attrs)
return NULL;
if (!(new_attr = calloc(1, sizeof(InputAttributes))))
goto unwind;
if (attrs->product && !(new_attr->product = strdup(attrs->product)))
goto unwind;
if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor)))
goto unwind;
if (attrs->device && !(new_attr->device = strdup(attrs->device)))
goto unwind;
new_attr->flags = attrs->flags;
if ((tags = attrs->tags))
{
while(*tags++)
ntags++;
new_attr->tags = calloc(ntags + 1, sizeof(char*));
if (!new_attr->tags)
goto unwind;
tags = attrs->tags;
new_tags = new_attr->tags;
while(*tags)
{
*new_tags = strdup(*tags);
if (!*new_tags)
goto unwind;
tags++;
new_tags++;
}
}
return new_attr;
unwind:
FreeInputAttributes(new_attr);
return NULL;
}
void
FreeInputAttributes(InputAttributes *attrs)
{
char **tags;
if (!attrs)
return;
free(attrs->product);
free(attrs->vendor);
free(attrs->device);
if ((tags = attrs->tags))
while(*tags)
free(*tags++);
free(attrs->tags);
free(attrs);
}

View File

@ -518,6 +518,8 @@ extern int AllocXTestDevice(ClientPtr client,
extern BOOL IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master);
extern DeviceIntPtr GetXTestDevice(DeviceIntPtr master);
extern void SendDevicePresenceEvent(int deviceid, int type);
extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs);
extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs);
/* misc event helpers */
extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);

View File

@ -771,11 +771,112 @@ static void xi_unregister_handlers(void)
}
static void cmp_attr_fields(InputAttributes *attr1,
InputAttributes *attr2)
{
char **tags1, **tags2;
g_assert(attr1 && attr2);
g_assert(attr1 != attr2);
g_assert(attr1->flags == attr2->flags);
if (attr1->product != NULL)
{
g_assert(attr1->product != attr2->product);
g_assert(strcmp(attr1->product, attr2->product) == 0);
} else
g_assert(attr2->product == NULL);
if (attr1->vendor != NULL)
{
g_assert(attr1->vendor != attr2->vendor);
g_assert(strcmp(attr1->vendor, attr2->vendor) == 0);
} else
g_assert(attr2->vendor == NULL);
if (attr1->device != NULL)
{
g_assert(attr1->device != attr2->device);
g_assert(strcmp(attr1->device, attr2->device) == 0);
} else
g_assert(attr2->device == NULL);
tags1 = attr1->tags;
tags2 = attr2->tags;
if (!tags1)
{
g_assert(!tags2);
return;
}
/* check for identical content, but duplicated */
while (*tags1)
{
g_assert(*tags1 != *tags2);
g_assert(strcmp(*tags1, *tags2) == 0);
tags1++;
tags2++;
}
g_assert(!*tags2);
/* check for not sharing memory */
tags1 = attr1->tags;
while (*tags1)
{
tags2 = attr2->tags;
while (*tags2)
g_assert(*tags1 != *tags2++);
tags1++;
}
}
static void dix_input_attributes(void)
{
InputAttributes orig = {0};
InputAttributes *new;
char *tags[4] = {"tag1", "tag2", "tag2", NULL};
new = DuplicateInputAttributes(NULL);
g_assert(!new);
new = DuplicateInputAttributes(&orig);
g_assert(memcpy(&orig, new, sizeof(InputAttributes)));
orig.product = "product name";
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
orig.vendor = "vendor name";
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
orig.device = "device path";
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
orig.flags = 0xF0;
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
orig.tags = tags;
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
}
int main(int argc, char** argv)
{
g_test_init(&argc, &argv,NULL);
g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
g_test_add_func("/dix/input/attributes", dix_input_attributes);
g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
@ -784,5 +885,6 @@ int main(int argc, char** argv)
g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
return g_test_run();
}