summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Rajnoha <prajnoha@redhat.com>2015-05-21 15:28:19 +0200
committerPeter Rajnoha <prajnoha@redhat.com>2015-07-14 11:15:55 +0200
commitf6bacd28c50f4c7d9bdae14aae7128683b673e93 (patch)
treef805a6eb9b1be55acbffcf044cc36f01069a351b
parent589e1e58853e083ee95a2720b5d8826505df33b2 (diff)
downloadlvm2-f6bacd28c50f4c7d9bdae14aae7128683b673e93.tar.gz
report: add support for string list decorations (prefix and suffix for list items)
This patch extends string list reporting in libdevmapper so that list item decorations (prefixes and suffixes) are automatically recognized. When such decoration is recognized, it's not accounted for while processing selection over the item. For example, if "[" and "]" is recognized as item decoration, then "[abc]" is equal to "abc" when it comes to selection. This allows for string list items to be reported with arbitrary marks or flags (by means of a prefix or suffix) while selection criteria still applies for such items.
-rw-r--r--lib/report/report.c9
-rw-r--r--libdm/.exported_symbols.DM_1_02_1012
-rw-r--r--libdm/libdevmapper.h6
-rw-r--r--libdm/libdm-report.c114
4 files changed, 109 insertions, 22 deletions
diff --git a/lib/report/report.c b/lib/report/report.c
index 0d31f1df4..c1147220b 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1224,6 +1224,15 @@ static int _field_set_string_list(struct dm_report *rh, struct dm_report_field *
: dm_report_field_string_list_unsorted(rh, field, list, cmd->report_list_item_separator);
}
+static int _field_set_string_list_decorated(struct dm_report *rh, struct dm_report_field *field,
+ const struct dm_list *list, void *private, int sorted,
+ const char *prefix_list[], const char *suffix_list[])
+{
+ struct cmd_context *cmd = (struct cmd_context *) private;
+ return sorted ? dm_report_field_string_list_decorated(rh, field, list, cmd->report_list_item_separator, prefix_list, suffix_list)
+ : dm_report_field_string_list_unsorted_decorated(rh, field, list, cmd->report_list_item_separator, prefix_list, suffix_list);
+}
+
/*
* Data-munging functions to prepare each data type for display and sorting
*/
diff --git a/libdm/.exported_symbols.DM_1_02_101 b/libdm/.exported_symbols.DM_1_02_101
index 75089ba8b..d901de011 100644
--- a/libdm/.exported_symbols.DM_1_02_101
+++ b/libdm/.exported_symbols.DM_1_02_101
@@ -1,2 +1,4 @@
dm_report_value_cache_set
dm_report_value_cache_get
+dm_report_field_string_list_decorated
+dm_report_field_string_list_unsorted_decorated
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index aad2971af..242e87540 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -1859,6 +1859,12 @@ int dm_report_field_string_list(struct dm_report *rh, struct dm_report_field *fi
const struct dm_list *data, const char *delimiter);
int dm_report_field_string_list_unsorted(struct dm_report *rh, struct dm_report_field *field,
const struct dm_list *data, const char *delimiter);
+int dm_report_field_string_list_decorated(struct dm_report *rh, struct dm_report_field *field,
+ const struct dm_list *data, const char *delimiter,
+ const char *prefix_list[], const char *suffix_list[]);
+int dm_report_field_string_list_unsorted_decorated(struct dm_report *rh, struct dm_report_field *field,
+ const struct dm_list *data, const char *delimiter,
+ const char *prefix_listp[], const char *suffix_list[]);
int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field,
const int32_t *data);
int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field,
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index c08dcab29..2770fd1aa 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -347,6 +347,7 @@ int dm_report_field_percent(struct dm_report *rh,
}
struct str_list_sort_value_item {
+ unsigned rpos;
unsigned pos;
size_t len;
};
@@ -358,6 +359,7 @@ struct str_list_sort_value {
struct str_list_sort_item {
const char *str;
+ size_t str_len;
struct str_list_sort_value_item item;
};
@@ -366,21 +368,66 @@ static int _str_list_sort_item_cmp(const void *a, const void *b)
const struct str_list_sort_item *slsi_a = (const struct str_list_sort_item *) a;
const struct str_list_sort_item *slsi_b = (const struct str_list_sort_item *) b;
- return strcmp(slsi_a->str, slsi_b->str);
+ if (slsi_a->item.len == slsi_b->item.len)
+ return strncmp(slsi_a->str + slsi_a->item.rpos, slsi_b->str + slsi_b->item.rpos, slsi_a->item.len);
+
+ return slsi_a->item.len > slsi_b->item.len ? 1 : -1;
+}
+
+static void _set_str_list_sort_value_item(const char *item_str, unsigned offset,
+ const char *prefix_list[], const char *suffix_list[],
+ struct str_list_sort_value_item *item)
+{
+ const char **pprefix = prefix_list;
+ const char **psuffix = suffix_list;
+ size_t prefix_len, suffix_len;
+ size_t len = strlen(item_str);
+ const char *p_start, *p_end;
+
+ item->rpos = 0;
+ item->pos = offset;
+ item->len = len;
+
+ if (!prefix_list && !suffix_list)
+ return;
+
+ p_start = item_str;
+ p_end = item_str + len;
+
+ while (pprefix && *pprefix) {
+ prefix_len = strlen(*pprefix);
+ if (!strncmp(p_start, *pprefix, prefix_len))
+ p_start += prefix_len;
+ pprefix++;
+ }
+
+ while (psuffix && *psuffix) {
+ suffix_len = strlen(*psuffix);
+ if ((p_end - p_start >= suffix_len) &&
+ !strncmp(p_end - suffix_len, *psuffix, suffix_len))
+ p_end -= suffix_len;
+ psuffix++;
+ }
+
+ item->rpos = p_start - item_str;
+ item->pos = item->rpos + offset;
+ item->len = p_end - p_start;
}
static int _report_field_string_list(struct dm_report *rh,
struct dm_report_field *field,
const struct dm_list *data,
const char *delimiter,
- int sort)
+ int sort,
+ const char *prefix_list[],
+ const char *suffix_list[])
{
static const char _string_list_grow_object_failed_msg[] = "dm_report_field_string_list: dm_pool_grow_object_failed";
struct str_list_sort_value *sort_value = NULL;
unsigned int list_size, pos, i;
struct str_list_sort_item *arr = NULL;
struct dm_str_list *sl;
- size_t delimiter_len, len;
+ size_t delimiter_len;
void *object;
int r = 0;
@@ -432,9 +479,10 @@ static int _report_field_string_list(struct dm_report *rh,
log_error("dm_report_field_string_list: dm_pool_strdup failed");
goto out;
}
- sort_value->items[1].pos = 0;
- sort_value->items[1].len = strlen(sl->str);
+
+ _set_str_list_sort_value_item(sl->str, 0, prefix_list, suffix_list, &sort_value->items[1]);
field->sort_value = sort_value;
+
return 1;
}
@@ -453,21 +501,22 @@ static int _report_field_string_list(struct dm_report *rh,
delimiter = ",";
delimiter_len = strlen(delimiter);
- i = pos = len = 0;
+ i = pos = 0;
dm_list_iterate_items(sl, data) {
arr[i].str = sl->str;
+ arr[i].str_len = strlen(arr[i].str);
+
if (!sort) {
/* sorted outpud not required - report the list as it is */
- len = strlen(sl->str);
- if (!dm_pool_grow_object(rh->mem, arr[i].str, len) ||
+ if (!dm_pool_grow_object(rh->mem, arr[i].str, arr[i].str_len) ||
(i+1 != list_size && !dm_pool_grow_object(rh->mem, delimiter, delimiter_len))) {
log_error(_string_list_grow_object_failed_msg);
goto out;
}
- arr[i].item.pos = pos;
- arr[i].item.len = len;
- pos = i+1 == list_size ? pos+len : pos+len+delimiter_len;
}
+
+ _set_str_list_sort_value_item(arr[i].str, pos, prefix_list, suffix_list, &arr[i].item);
+ pos = i+1 == list_size ? pos+arr[i].str_len : pos+arr[i].str_len+delimiter_len;
i++;
}
@@ -476,8 +525,7 @@ static int _report_field_string_list(struct dm_report *rh,
for (i = 0, pos = 0; i < list_size; i++) {
if (sort) {
/* sorted output required - report the list as sorted */
- len = strlen(arr[i].str);
- if (!dm_pool_grow_object(rh->mem, arr[i].str, len) ||
+ if (!dm_pool_grow_object(rh->mem, arr[i].str, arr[i].str_len) ||
(i+1 != list_size && !dm_pool_grow_object(rh->mem, delimiter, delimiter_len))) {
log_error(_string_list_grow_object_failed_msg);
goto out;
@@ -487,13 +535,10 @@ static int _report_field_string_list(struct dm_report *rh,
* element in report_string for sort_value.
* Use i+1 here since items[0] stores list size!!!
*/
- sort_value->items[i+1].pos = pos;
- sort_value->items[i+1].len = len;
- pos = i+1 == list_size ? pos+len : pos+len+delimiter_len;
- } else {
- sort_value->items[i+1].pos = arr[i].item.pos;
- sort_value->items[i+1].len = arr[i].item.len;
- }
+ _set_str_list_sort_value_item(arr[i].str, pos, prefix_list, suffix_list, &sort_value->items[i+1]);
+ pos = i+1 == list_size ? pos+arr[i].str_len : pos+arr[i].str_len+delimiter_len;
+ } else
+ sort_value->items[i+1] = arr[i].item;
}
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
@@ -519,7 +564,7 @@ int dm_report_field_string_list(struct dm_report *rh,
const struct dm_list *data,
const char *delimiter)
{
- return _report_field_string_list(rh, field, data, delimiter, 1);
+ return _report_field_string_list(rh, field, data, delimiter, 1, NULL, NULL);
}
int dm_report_field_string_list_unsorted(struct dm_report *rh,
@@ -532,7 +577,32 @@ int dm_report_field_string_list_unsorted(struct dm_report *rh,
* Having the raw value always sorted helps when matching selection list
* with selection criteria.
*/
- return _report_field_string_list(rh, field, data, delimiter, 0);
+ return _report_field_string_list(rh, field, data, delimiter, 0, NULL, NULL);
+}
+
+int dm_report_field_string_list_decorated(struct dm_report *rh,
+ struct dm_report_field *field,
+ const struct dm_list *data,
+ const char *delimiter,
+ const char *prefix_list[],
+ const char *suffix_list[])
+{
+ return _report_field_string_list(rh, field, data, delimiter, 1, prefix_list, suffix_list);
+}
+
+int dm_report_field_string_list_unsorted_decorated(struct dm_report *rh,
+ struct dm_report_field *field,
+ const struct dm_list *data,
+ const char *delimiter,
+ const char *prefix_list[],
+ const char *suffix_list[])
+{
+ /*
+ * The raw value is always sorted, just the string reported is unsorted.
+ * Having the raw value always sorted helps when matching selection list
+ * with selection criteria.
+ */
+ return _report_field_string_list(rh, field, data, delimiter, 0, prefix_list, suffix_list);
}
int dm_report_field_int(struct dm_report *rh,