Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Commit

Permalink
sol-bus: Add a helper to parse dictionaries
Browse files Browse the repository at this point in the history
In D-Bus, there isn't the concept of dictionaries, only dictionary
entries and arrays, and using them is pretty common, so it makes sense
to provide a helper to parse dictionaries.

Signed-off-by: Vinicius Costa Gomes <[email protected]>
  • Loading branch information
vcgomes committed May 27, 2016
1 parent e4765f6 commit 4e5ff14
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/lib/common/sol-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,3 +950,67 @@ sol_bus_log_callback(sd_bus_message *reply, void *userdata,

return -1;
}

SOL_API int
sol_bus_parse_dict(sd_bus_message *m, const struct sol_bus_dict_entry *dict)
{
int r;

r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
SOL_INT_CHECK(r, < 0, r);

do {
const struct sol_bus_dict_entry *entry;
const char *member, *contents;
char type;

r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
if (r <= 0) {
r = 0;
break;
}

r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
SOL_INT_CHECK_GOTO(r, < 0, end);

r = sd_bus_message_peek_type(m, &type, &contents);
SOL_INT_CHECK_GOTO(r, < 0, end);

for (entry = dict; entry && entry->name; entry++) {
if (streq(entry->name, member))
break;
}

if (entry->name) {
size_t len;

r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
SOL_INT_CHECK_GOTO(r, < 0, end);

len = strlen(contents);

if (entry->type == 'v' && entry->parse_variant)
r = entry->parse_variant(m, entry->value);
else if (len == 1 && entry->type == contents[0])
r = sd_bus_message_read_basic(m, entry->type, entry->value);
else {
SOL_WRN("Invalid type in message '%s', expecting '%c'",
contents, entry->type);
r = -EINVAL;
}
SOL_INT_CHECK_GOTO(r, < 0, end);

r = sd_bus_message_exit_container(m);
SOL_INT_CHECK_GOTO(r, < 0, end);
} else {
r = sd_bus_message_skip(m, "v");
SOL_INT_CHECK_GOTO(r, < 0, end);
}

r = sd_bus_message_exit_container(m);
SOL_INT_CHECK_GOTO(r, < 0, end);
} while (1);

end:
return r;
}
41 changes: 41 additions & 0 deletions src/lib/common/sol-bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,44 @@ int sol_bus_remove_interfaces_watch(struct sol_bus_client *client,
*/
int sol_bus_log_callback(sd_bus_message *reply, void *userdata,
sd_bus_error *ret_error);

/**
* @brief Represents an entry in a D-Bus dictionary
*
* A common idiom in D-Bus is having an array of type 'a{sv}', representing
* a dictionary, this struct and sol_bus_parse_dict() help parsing those
* data structures.
*/
struct sol_bus_dict_entry {
/**
* @brief The name of the dictionary entry
*/
const char *name;
/**
* @brief The type of value of the property in the dictionary
*
* It can be any of the basic types, or 'v' (SD_BUS_TYPE_VARIANT), in
* case the type is not basic, the function parse_variant() will be called.
*/
char type;
/**
* @brief In which place to store the parsed value
*/
void *value;
/**
* @brief Function to be called in case the value being parsed is not basic.
*/
int (*parse_variant)(sd_bus_message *m, void *value);
};

/**
* @brief Helper to parse D-Bus dictionaries
*
* @see #sol_bus_dict_entry, the @a dict array must be terminated by an empty entry.
*
* @param m D-Bus message containing the D-Bus dictionary array
* @param dict Dictionary representation, informing how to parse the dictionary.
*
* @return 0 on success, -errno otherwise.
*/
int sol_bus_parse_dict(sd_bus_message *m, const struct sol_bus_dict_entry *dict);

0 comments on commit 4e5ff14

Please sign in to comment.