cli: simplify tracking of parent column in PrintDataCol structure

PrintDataCol contains a reference to the parent structure, for which
it was created. Previously, that was expressed via the "parent_idx"
field, which is an index into the list of all PrintDataCol entries.

That is inconvenient. Resolve the index to the actual pointer.

Note that during _output_selection_append() we still need to use
the index instead of resolving the pointer right away. That is because
_output_selection_append() grows the GArray into which the parent_idx
pointers to. So, obtaining the real pointer at that point would result
in using a dangling pointer later on.

Introduce a new step _output_selection_complete() which converts the
index into the actual pointer.
This commit is contained in:
Thomas Haller
2018-05-02 16:36:28 +02:00
parent ac07cbb98b
commit 66e5f13307

View File

@@ -654,16 +654,24 @@ nmc_free_output_field_values (NmcOutputField fields_array[])
#define PRINT_DATA_COL_PARENT_NIL (G_MAXUINT)
typedef struct {
typedef struct _PrintDataCol {
union {
const struct _PrintDataCol *parent_col;
/* while constructing the list of columns in _output_selection_append(), we keep track
* of the parent by index. The reason is, that at that point our columns are still
* tracked in a GArray which is growing (hence, the pointers are changing).
* Later, _output_selection_complete() converts the index into the actual pointer.
*/
guint _parent_idx;
};
const NMMetaSelectionItem *selection_item;
guint parent_idx;
guint self_idx;
bool is_leaf;
} PrintDataCol;
static gboolean
_output_selection_append (GArray *cols,
const char *fields_prefix,
guint parent_idx,
const NMMetaSelectionItem *selection_item,
GPtrArray *gfree_keeper,
@@ -681,7 +689,7 @@ _output_selection_append (GArray *cols,
{
PrintDataCol col = {
.selection_item = selection_item,
.parent_idx = parent_idx,
._parent_idx = parent_idx,
.self_idx = col_idx,
.is_leaf = TRUE,
};
@@ -727,8 +735,11 @@ _output_selection_append (GArray *cols,
for (i = 0; i < selection->num; i++) {
si = &selection->items[i];
if (!_output_selection_append (cols, si->self_selection, col_idx,
si, gfree_keeper, error))
if (!_output_selection_append (cols,
col_idx,
si,
gfree_keeper,
error))
return FALSE;
}
@@ -741,6 +752,26 @@ _output_selection_append (GArray *cols,
return TRUE;
}
static void
_output_selection_complete (GArray *cols)
{
guint i;
nm_assert (cols);
nm_assert (g_array_get_element_size (cols) == sizeof (PrintDataCol));
for (i = 0; i < cols->len; i++) {
PrintDataCol *col = &g_array_index (cols, PrintDataCol, i);
if (col->_parent_idx == PRINT_DATA_COL_PARENT_NIL)
col->parent_col = NULL;
else {
nm_assert (col->_parent_idx < i);
col->parent_col = &g_array_index (cols, PrintDataCol, col->_parent_idx);
}
}
}
/*****************************************************************************/
/**
@@ -789,11 +820,13 @@ _output_selection_parse (const NMMetaAbstractInfo *const*fields,
for (i = 0; i < selection->num; i++) {
const NMMetaSelectionItem *si = &selection->items[i];
if (!_output_selection_append (cols, NULL, PRINT_DATA_COL_PARENT_NIL,
if (!_output_selection_append (cols, PRINT_DATA_COL_PARENT_NIL,
si, gfree_keeper, error))
return FALSE;
}
_output_selection_complete (cols);
*out_cols = g_steal_pointer (&cols);
*out_gfree_keeper = g_steal_pointer (&gfree_keeper);
return TRUE;
@@ -1006,12 +1039,12 @@ _print_fill (const NmcConfig *nmc_config,
header_cell->title = nm_meta_abstract_info_get_name (info, TRUE);
if ( nmc_config->multiline_output
&& col->parent_idx != PRINT_DATA_COL_PARENT_NIL
&& col->parent_col
&& NM_IN_SET (info->meta_type,
&nm_meta_type_property_info,
&nmc_meta_type_generic_info)) {
header_cell->title = g_strdup_printf ("%s.%s",
nm_meta_abstract_info_get_name (cols[col->parent_idx].selection_item->info, FALSE),
nm_meta_abstract_info_get_name (col->parent_col->selection_item->info, FALSE),
header_cell->title);
header_cell->title_to_free = TRUE;
}