man nm-settings-nmcli: add "Valid values" field

Show a new field called "Valid values" in those properties that only
accept a limited set of values, like enums, ints with a valid range of
values, etc.

As there is some complex logic behind getting this information, this
logic has been put in nm-meta-setting-desc and nm-enum-utils so they can
be re-used, avoiding duplicity and errors. Some refactor has been done
in nm-meta-setting-desc in this direction, too.
This commit is contained in:
Íñigo Huguet 2023-09-05 13:42:31 +02:00
parent af5c1c8019
commit 925d4df801
8 changed files with 1197 additions and 538 deletions

View file

@ -176,6 +176,11 @@
Format: <xsl:value-of select="@type"/>
</para>
</xsl:if>
<xsl:if test="@values">
<para>
Valid values: <xsl:value-of select="@values"/>
</para>
</xsl:if>
</listitem>
</varlistentry>
</xsl:template>

View file

@ -320,53 +320,117 @@ _nm_utils_enum_from_str_full(GType type,
const char **
_nm_utils_enum_get_values(GType type, int from, int to)
{
GTypeClass *klass;
GPtrArray *array;
int i;
char sbuf[64];
int i;
GArray *values_full = _nm_utils_enum_get_values_full(type, from, to, NULL);
GPtrArray *values = g_ptr_array_sized_new(values_full->len + 1);
klass = g_type_class_ref(type);
array = g_ptr_array_new();
for (i = 0; i < values_full->len; i++) {
NMUtilsEnumValueInfoFull *v = &g_array_index(values_full, NMUtilsEnumValueInfoFull, i);
g_ptr_array_add(values, (gpointer) v->nick);
}
g_ptr_array_add(values, NULL);
g_array_unref(values_full);
return (const char **) g_ptr_array_free(values, FALSE);
}
static void
_free_value_info_full(NMUtilsEnumValueInfoFull *value_info_full)
{
g_free(value_info_full->aliases);
}
static void
_init_value_info_full(NMUtilsEnumValueInfoFull *v, bool is_flag, const char *nick, int value)
{
char sbuf[64];
const char *value_str = is_flag ? g_intern_string(nm_sprintf_buf(sbuf, "0x%x", value))
: g_intern_string(nm_sprintf_buf(sbuf, "%d", value));
v->nick = _enum_is_valid_enum_nick(nick) ? nick : value_str;
v->aliases = NULL;
v->value_str = value_str;
v->value = value;
}
/**
* _nm_utils_enum_get_values_full:
* @type: the enum or flags type
* @from: lowest value to return
* @to: highest value to return
* @value_infos: (nullable): additional value aliases
*
* Get the enum or flags values within the given range, putting together the
* value, name and aliases of each of them.
*
* If @value_infos is NULL, no memory will be allocated and deallocated for the
* aliases and #NMUtilsEnumValueInfoFull:aliases will be NULL in the returned
* data.
*
* The caller is responsible of releasing the container, but not the contained
* data. Only #NMUtilsEnumValueInfoFull:aliases can be stolen (and set to NULL),
* and then the caller becomes the responsible to release it.
*
* Return: (transfer container): an array of #NMUtilsEnumValueInfoFull.
*/
GArray *
_nm_utils_enum_get_values_full(GType type,
int from,
int to,
const NMUtilsEnumValueInfo *value_infos)
{
NMUtilsEnumValueInfoFull v;
GArray *array;
int i;
nm_auto_unref_gtypeclass GTypeClass *klass = g_type_class_ref(type);
g_return_val_if_fail(G_IS_ENUM_CLASS(klass) || G_IS_FLAGS_CLASS(klass), NULL);
_ASSERT_enum_values_info(type, value_infos);
array = g_array_new(FALSE, FALSE, sizeof(NMUtilsEnumValueInfoFull));
if (G_IS_ENUM_CLASS(klass)) {
GEnumClass *enum_class = G_ENUM_CLASS(klass);
GEnumValue *enum_value;
for (i = 0; i < enum_class->n_values; i++) {
enum_value = &enum_class->values[i];
if (enum_value->value >= from && enum_value->value <= to) {
if (_enum_is_valid_enum_nick(enum_value->value_nick))
g_ptr_array_add(array, (gpointer) enum_value->value_nick);
else
g_ptr_array_add(
array,
(gpointer) g_intern_string(nm_sprintf_buf(sbuf, "%d", enum_value->value)));
}
}
} else if (G_IS_FLAGS_CLASS(klass)) {
GFlagsClass *flags_class = G_FLAGS_CLASS(klass);
GFlagsValue *flags_value;
GEnumValue *enum_val = &enum_class->values[i];
for (i = 0; i < flags_class->n_values; i++) {
flags_value = &flags_class->values[i];
if (flags_value->value >= (guint) from && flags_value->value <= (guint) to) {
if (_enum_is_valid_flags_nick(flags_value->value_nick))
g_ptr_array_add(array, (gpointer) flags_value->value_nick);
else
g_ptr_array_add(
array,
(gpointer) g_intern_string(
nm_sprintf_buf(sbuf, "0x%x", (unsigned) flags_value->value)));
if (enum_val->value >= from && enum_val->value <= to) {
_init_value_info_full(&v, FALSE, enum_val->value_nick, enum_val->value);
g_array_append_val(array, v);
}
}
} else {
g_type_class_unref(klass);
g_ptr_array_free(array, TRUE);
g_return_val_if_reached(NULL);
GFlagsClass *flags_class = G_FLAGS_CLASS(klass);
for (i = 0; i < flags_class->n_values; i++) {
GFlagsValue *flags_val = &flags_class->values[i];
if (flags_val->value >= (guint) from && flags_val->value <= (guint) to) {
_init_value_info_full(&v, TRUE, flags_val->value_nick, flags_val->value);
g_array_append_val(array, v);
}
}
}
g_type_class_unref(klass);
g_ptr_array_add(array, NULL);
if (value_infos) {
g_array_set_clear_func(array, (GDestroyNotify) _free_value_info_full);
return (const char **) g_ptr_array_free(array, FALSE);
for (i = 0; i < array->len; i++) {
NMUtilsEnumValueInfoFull *vi_full = &g_array_index(array, NMUtilsEnumValueInfoFull, i);
GPtrArray *aliases = g_ptr_array_new();
const NMUtilsEnumValueInfo *vi;
for (vi = value_infos; vi && vi->nick; vi++) {
if (vi->value == vi_full->value)
g_ptr_array_add(aliases, (gpointer) vi->nick);
}
g_ptr_array_add(aliases, NULL);
vi_full->aliases = (const char **) g_ptr_array_free(aliases, FALSE);
}
}
return array;
}

View file

@ -15,6 +15,13 @@ typedef struct _NMUtilsEnumValueInfo {
int value;
} NMUtilsEnumValueInfo;
typedef struct _NMUtilsEnumValueInfoFull {
const char *nick;
const char **aliases;
const char *value_str;
int value;
} NMUtilsEnumValueInfoFull;
char *_nm_utils_enum_to_str_full(GType type,
int value,
const char *sep,
@ -27,6 +34,11 @@ gboolean _nm_utils_enum_from_str_full(GType type,
const char **_nm_utils_enum_get_values(GType type, int from, int to);
GArray *_nm_utils_enum_get_values_full(GType type,
int from,
int to,
const NMUtilsEnumValueInfo *value_infos);
/*****************************************************************************/
#endif /* __NM_ENUM_UTILS_H__ */

View file

@ -46,22 +46,16 @@ _gobject_property_get_gtype(GObject *gobject, const char *property_name)
g_return_val_if_reached(G_TYPE_INVALID);
}
static GType
_gtype_property_get_gtype(GType gtype, const char *property_name)
static GParamSpec *
_property_get_spec(const NMMetaPropertyInfo *property_info)
{
/* given @gtype, a type for a GObject, lookup the property @property_name
* and return its value_type. */
if (G_TYPE_IS_CLASSED(gtype)) {
GParamSpec *param_spec;
nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref(gtype);
nm_auto_unref_gtypeclass NMSettingClass *setting_class =
g_type_class_ref(property_info->setting_info->general->get_setting_gtype());
GParamSpec *param_spec =
g_object_class_find_property(G_OBJECT_CLASS(setting_class), property_info->property_name);
if (G_IS_OBJECT_CLASS(gtypeclass)) {
param_spec = g_object_class_find_property(G_OBJECT_CLASS(gtypeclass), property_name);
if (param_spec)
return param_spec->value_type;
}
}
g_return_val_if_reached(G_TYPE_INVALID);
nm_assert(param_spec);
return param_spec;
}
/*****************************************************************************/
@ -1225,6 +1219,113 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
/*****************************************************************************/
/**
* nm_meta_property_int_get_range:
* @property_info: a #NMMetaProperty info of a int, uint, int64 or uint64 property
* @out_min: (out): low value of the property's valid range
* @out_max: (out): high value of the property's valid range
*
* Returns: FALSE if the full range of the type is returned, TRUE if it's smaller
*/
gboolean
nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
NMMetaSignUnsignInt64 *out_min,
NMMetaSignUnsignInt64 *out_max)
{
GParamSpec *pspec = _property_get_spec(property_info);
g_return_val_if_fail(
NM_IN_SET(pspec->value_type, G_TYPE_UINT, G_TYPE_UINT64, G_TYPE_INT, G_TYPE_INT64),
FALSE);
if (property_info->property_typ_data
&& (property_info->property_typ_data->subtype.gobject_int.min.u64
|| property_info->property_typ_data->subtype.gobject_int.max.u64)) {
*out_min = property_info->property_typ_data->subtype.gobject_int.min;
*out_max = property_info->property_typ_data->subtype.gobject_int.max;
return TRUE;
}
switch (pspec->value_type) {
case G_TYPE_UINT:
out_min->u64 = ((GParamSpecUInt *) pspec)->minimum;
out_max->u64 = ((GParamSpecUInt *) pspec)->maximum;
return out_min->u64 != 0 || out_max->u64 != G_MAXUINT;
case G_TYPE_UINT64:
out_min->u64 = ((GParamSpecUInt64 *) pspec)->minimum;
out_max->u64 = ((GParamSpecUInt64 *) pspec)->maximum;
return out_min->u64 != 0 || out_max->u64 != G_MAXUINT64;
case G_TYPE_INT:
out_min->i64 = ((GParamSpecInt *) pspec)->minimum;
out_max->i64 = ((GParamSpecInt *) pspec)->maximum;
return out_min->i64 != G_MININT || out_max->i64 != G_MAXINT;
case G_TYPE_INT64:
out_min->i64 = ((GParamSpecInt64 *) pspec)->minimum;
out_max->i64 = ((GParamSpecInt64 *) pspec)->maximum;
return out_min->i64 != G_MININT64 || out_max->i64 != G_MAXINT64;
default:
g_return_val_if_reached(FALSE);
}
}
/**
* nm_meta_property_enum_get_type:
* @property_info: a #NMMetaPropertyInfo of an enum or flags type property
*
* Returns: the #GType of the property, or G_TYPE_INVALID on error
*/
GType
nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info)
{
GType gtype = _property_get_spec(property_info)->value_type;
if (property_info->property_typ_data
&& property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
/* if the property is already enum, don't set get_gtype: it's redundant and error prone */
g_return_val_if_fail(NM_IN_SET(gtype, G_TYPE_INT, G_TYPE_UINT), G_TYPE_INVALID);
return property_info->property_typ_data->subtype.gobject_enum.get_gtype();
}
g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), G_TYPE_INVALID);
return gtype;
}
/**
* nm_meta_property_enum_get_range:
* @property_info: a #NMMetaProperty info of an enum or flags type property
* @out_min: (out): low value of the property's valid range
* @out_max: (out): high value of the property's valid range
*
* Returns: FALSE if the full range of the type is returned, TRUE if it's smaller
*/
gboolean
nm_meta_property_enum_get_range(const NMMetaPropertyInfo *property_info, int *out_min, int *out_max)
{
GType gtype = nm_meta_property_enum_get_type(property_info);
if (property_info->property_typ_data
&& (property_info->property_typ_data->subtype.gobject_enum.min
|| property_info->property_typ_data->subtype.gobject_enum.max)) {
*out_min = property_info->property_typ_data->subtype.gobject_enum.min;
*out_max = property_info->property_typ_data->subtype.gobject_enum.max;
return TRUE;
}
if (G_TYPE_IS_ENUM(gtype)) {
*out_min = G_MININT;
*out_max = G_MAXINT;
} else if (G_TYPE_IS_FLAGS(gtype)) {
*out_min = 0;
*out_max = (int) G_MAXUINT;
} else {
g_assert_not_reached();
}
return FALSE;
}
/*****************************************************************************/
static gboolean
_set_fcn_gobject_string(ARGS_SET_FCN)
{
@ -1318,10 +1419,9 @@ _set_fcn_gobject_int(ARGS_SET_FCN)
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
gboolean is_uint64;
NMMetaSignUnsignInt64 v;
gboolean has_minmax = FALSE;
NMMetaSignUnsignInt64 min = {0};
NMMetaSignUnsignInt64 max = {0};
guint base = 10;
NMMetaSignUnsignInt64 min = {0};
NMMetaSignUnsignInt64 max = {0};
guint base = 10;
const NMMetaUtilsIntValueInfo *value_infos;
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
@ -1351,53 +1451,9 @@ _set_fcn_gobject_int(ARGS_SET_FCN)
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
base = property_info->property_typ_data->subtype.gobject_int.base;
if ((is_uint64
&& (property_info->property_typ_data->subtype.gobject_int.min.u64
|| property_info->property_typ_data->subtype.gobject_int.max.u64))
|| (!is_uint64
&& (property_info->property_typ_data->subtype.gobject_int.min.i64
|| property_info->property_typ_data->subtype.gobject_int.max.i64))) {
min = property_info->property_typ_data->subtype.gobject_int.min;
max = property_info->property_typ_data->subtype.gobject_int.max;
has_minmax = TRUE;
}
}
if (!has_minmax) {
switch (pspec->value_type) {
case G_TYPE_INT:
{
const GParamSpecInt *p = (GParamSpecInt *) pspec;
min.i64 = p->minimum;
max.i64 = p->maximum;
} break;
case G_TYPE_UINT:
{
const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
min.u64 = p->minimum;
max.u64 = p->maximum;
} break;
case G_TYPE_INT64:
{
const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
min.i64 = p->minimum;
max.i64 = p->maximum;
} break;
case G_TYPE_UINT64:
{
const GParamSpecUInt64 *p = (GParamSpecUInt64 *) pspec;
min.u64 = p->minimum;
max.u64 = p->maximum;
} break;
default:
g_return_val_if_reached(FALSE);
}
}
nm_meta_property_int_get_range(property_info, &min, &max);
if (is_uint64)
v.u64 = _nm_utils_ascii_str_to_uint64(value, base, min.u64, max.u64, 0);
@ -1629,26 +1685,12 @@ _set_fcn_gobject_enum(ARGS_SET_FCN)
fail:
if (error) {
gs_free const char **valid_all = NULL;
gs_free const char *valid_str = NULL;
gboolean has_minmax = FALSE;
int min = G_MININT;
int max = G_MAXINT;
if (property_info->property_typ_data) {
if (property_info->property_typ_data->subtype.gobject_enum.min
|| property_info->property_typ_data->subtype.gobject_enum.max) {
min = property_info->property_typ_data->subtype.gobject_enum.min;
max = property_info->property_typ_data->subtype.gobject_enum.max;
has_minmax = TRUE;
}
}
if (!has_minmax && is_flags) {
min = 0;
max = (int) G_MAXUINT;
}
gs_free const char **valid_all = NULL;
gs_free const char *valid_str = NULL;
int min;
int max;
nm_meta_property_enum_get_range(property_info, &min, &max);
valid_all = nm_utils_enum_get_values(gtype, min, max);
valid_str = g_strjoinv(",", (char **) valid_all);
if (is_flags) {
@ -1674,40 +1716,13 @@ static const char *const *
_values_fcn_gobject_enum(ARGS_VALUES_FCN)
{
const NMUtilsEnumValueInfo *value_infos = NULL;
GType gtype = 0;
gboolean has_gtype = FALSE;
gboolean has_minmax = FALSE;
int min = G_MININT;
int max = G_MAXINT;
GType gtype;
int min;
int max;
char **v;
if (property_info->property_typ_data) {
if (property_info->property_typ_data->subtype.gobject_enum.min
|| property_info->property_typ_data->subtype.gobject_enum.max) {
min = property_info->property_typ_data->subtype.gobject_enum.min;
max = property_info->property_typ_data->subtype.gobject_enum.max;
has_minmax = TRUE;
}
if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
has_gtype = TRUE;
}
}
if (!has_gtype) {
gtype = _gtype_property_get_gtype(property_info->setting_info->general->get_setting_gtype(),
property_info->property_name);
}
if (!has_minmax && G_TYPE_IS_CLASSED(gtype)) {
nm_auto_unref_gtypeclass GTypeClass *class = NULL;
class = g_type_class_ref(gtype);
if (G_IS_FLAGS_CLASS(class)) {
min = 0;
max = (int) G_MAXUINT;
}
}
gtype = nm_meta_property_enum_get_type(property_info);
nm_meta_property_enum_get_range(property_info, &min, &max);
/* There is a problem. For flags, we don't expand to all the values that we could
* complete for. We only expand to a single flag "FLAG1", but if the property

View file

@ -505,6 +505,16 @@ const NMMetaSettingValidPartItem *const *
nm_meta_setting_info_valid_parts_for_slave_type(const char *slave_type,
const char **out_slave_name);
gboolean nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
NMMetaSignUnsignInt64 *out_min,
NMMetaSignUnsignInt64 *out_max);
gboolean nm_meta_property_enum_get_range(const NMMetaPropertyInfo *property_info,
int *out_min,
int *out_max);
GType nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info);
/*****************************************************************************/
typedef enum {

View file

@ -4,6 +4,7 @@
#include "libnmc-setting/nm-meta-setting-desc.h"
#include "libnmc-setting/nm-meta-setting-base.h"
#include "libnm-glib-aux/nm-enum-utils.h"
#include "nm-core-enum-types.h"
#include <stdarg.h>
#include <stdlib.h>
@ -70,7 +71,7 @@ _property_get_gtype(const NMMetaPropertyInfo *prop_info)
}
static char *
_get_enum_format(GType g_type)
get_enum_format(GType g_type)
{
if (G_TYPE_IS_FLAGS(g_type))
return g_strdup_printf("flags (%s)", g_type_name(g_type));
@ -78,22 +79,6 @@ _get_enum_format(GType g_type)
return g_strdup_printf("choice (%s)", g_type_name(g_type));
}
static char *
get_enum_format(const NMMetaPropertyInfo *prop_info)
{
GType gtype = G_TYPE_INVALID;
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
if (prop_typ_data && prop_typ_data->subtype.gobject_enum.get_gtype)
gtype = prop_typ_data->subtype.gobject_enum.get_gtype();
else
gtype = _property_get_gtype(prop_info);
prop_assert(gtype != G_TYPE_INVALID, prop_info, "unknown property's enum type");
return _get_enum_format(gtype);
}
static char *
get_mac_format(const NMMetaPropertyInfo *prop_info)
{
@ -185,11 +170,11 @@ get_property_format(const NMMetaPropertyInfo *prop_info)
case NM_META_PROPERTY_TYPE_FORMAT_STRING:
return g_strdup("string");
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
return get_enum_format(prop_info);
return get_enum_format(nm_meta_property_enum_get_type(prop_info));
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
return _get_enum_format(NM_TYPE_SETTING_SECRET_FLAGS);
return get_enum_format(NM_TYPE_SETTING_SECRET_FLAGS);
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
return _get_enum_format(NM_TYPE_SETTING_DCB_FLAGS);
return get_enum_format(NM_TYPE_SETTING_DCB_FLAGS);
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
return g_strdup("boolean");
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
@ -224,6 +209,199 @@ get_property_format(const NMMetaPropertyInfo *prop_info)
}
}
#define append_vals(to, ...) \
G_STMT_START \
{ \
size_t i; \
const char *from[] = {__VA_ARGS__}; \
for (i = 0; i < NM_N_ELEMENTS(from); i++) \
g_ptr_array_add((to), g_strdup(from[i])); \
} \
G_STMT_END
static void
append_connection_types(GPtrArray *valid_values)
{
size_t i;
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
/* If the setting has a priority of a base-type, it's a valid value for connection.type */
NMSettingPriority pri =
_nm_setting_type_get_base_type_priority(nm_meta_setting_infos[i].get_setting_gtype());
if (pri != NM_SETTING_PRIORITY_INVALID)
g_ptr_array_add(valid_values, g_strdup(nm_meta_setting_infos[i].setting_name));
}
}
static void
append_int_valid_range(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
{
NMMetaSignUnsignInt64 min;
NMMetaSignUnsignInt64 max;
nm_meta_property_int_get_range(prop_info, &min, &max);
if (NM_IN_SET(_property_get_gtype(prop_info), G_TYPE_UINT, G_TYPE_UINT64))
g_ptr_array_add(valid_values, g_strdup_printf("%lu - %lu", min.u64, max.u64));
else
g_ptr_array_add(valid_values, g_strdup_printf("%ld - %ld", min.i64, max.i64));
}
static void
_append_enum_valid_values(GType g_type,
int min,
int max,
const NMUtilsEnumValueInfo *value_infos,
GPtrArray *valid_values)
{
size_t i;
const char **alias;
GString *names = g_string_sized_new(64);
GArray *values = _nm_utils_enum_get_values_full(g_type, min, max, value_infos);
for (i = 0; i < values->len; i++) {
NMUtilsEnumValueInfoFull *val = &g_array_index(values, NMUtilsEnumValueInfoFull, i);
g_string_assign(names, val->nick);
if (val->aliases) {
for (alias = val->aliases; *alias; alias++) {
g_string_append_c(names, '/');
g_string_append(names, *alias);
}
}
g_ptr_array_add(valid_values, g_strdup_printf("%s (%s)", names->str, val->value_str));
}
g_string_free(names, TRUE);
g_array_unref(values);
}
static void
append_enum_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
{
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
const NMUtilsEnumValueInfo *value_infos;
GType gtype;
int min;
int max;
gtype = nm_meta_property_enum_get_type(prop_info);
nm_meta_property_enum_get_range(prop_info, &min, &max);
value_infos = prop_typ_data ? prop_typ_data->subtype.gobject_enum.value_infos : NULL;
_append_enum_valid_values(gtype, min, max, value_infos, valid_values);
}
static void
append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
{
NMEthtoolID ethtool_id;
prop_assert(prop_info->property_typ_data, prop_info, "missing .property_typ_data");
ethtool_id = prop_info->property_typ_data->subtype.ethtool.ethtool_id;
if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id))
g_ptr_array_add(valid_values, g_strdup_printf("0 - %u", G_MAXUINT32));
else if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id))
append_vals(valid_values, "on", "off", "ignore");
}
static void
append_dcb_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
{
guint max;
guint other;
prop_assert(prop_info->property_typ_data, prop_info, "missing .property_typ_data");
max = prop_info->property_typ_data->subtype.dcb.max;
other = prop_info->property_typ_data->subtype.dcb.other;
if (max != 0)
g_ptr_array_add(valid_values, g_strdup_printf("0 - %u", max));
if (other != 0 && (!max || other > max))
g_ptr_array_add(valid_values, g_strdup_printf("%u", other));
}
static GPtrArray *
get_property_valid_values(const NMMetaPropertyInfo *prop_info)
{
const NMMetaPropertyType *prop_type = prop_info->property_type;
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
NMMetaPropertyTypeFormat fmt = prop_type->doc_format;
GPtrArray *valid_values = g_ptr_array_new_full(16, g_free);
/* connection.type is generated differently */
if (prop_info->setting_info->general->meta_type == NM_META_SETTING_TYPE_CONNECTION
&& !nm_strcmp0(prop_info->property_name, "type")) {
append_connection_types(valid_values);
return valid_values;
}
/* If it's a list, get the format of the items, but only if we can process it
* (prop_typ_data->subtype is of type multilist, so we can't process ints or enums) */
if (fmt == NM_META_PROPERTY_TYPE_FORMAT_MULTILIST && prop_typ_data) {
switch (prop_typ_data->list_items_doc_format) {
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
case NM_META_PROPERTY_TYPE_FORMAT_DCB_BOOL:
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
case NM_META_PROPERTY_TYPE_FORMAT_ETHTOOL:
fmt = prop_typ_data->list_items_doc_format;
break;
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
prop_warn(prop_info, "unknown enum type, can't get valid values");
break;
case NM_META_PROPERTY_TYPE_FORMAT_INT:
prop_warn(prop_info, "can't check for valid range in multilists");
break;
default:
/* Other types probably don't need to show "Valid values" */
break;
}
}
switch (fmt) {
case NM_META_PROPERTY_TYPE_FORMAT_INT:
append_int_valid_range(prop_info, valid_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
append_enum_valid_values(prop_info, valid_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
_append_enum_valid_values(NM_TYPE_SETTING_SECRET_FLAGS, 0, G_MAXUINT, NULL, valid_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
_append_enum_valid_values(NM_TYPE_SETTING_DCB_FLAGS, 0, G_MAXUINT, NULL, valid_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
case NM_META_PROPERTY_TYPE_FORMAT_DCB_BOOL:
append_vals(valid_values, "true/yes/on", "false/no/off");
break;
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
append_vals(valid_values, "true/yes/on", "false/no/off", "default/unknown");
break;
case NM_META_PROPERTY_TYPE_FORMAT_ETHTOOL:
append_ethtool_valid_values(prop_info, valid_values);
break;
case NM_META_PROPERTY_TYPE_FORMAT_DCB:
append_dcb_valid_values(prop_info, valid_values);
break;
default:
break;
}
if (prop_typ_data && prop_typ_data->values_static) {
const char *const *v;
for (v = prop_typ_data->values_static; *v; v++)
g_ptr_array_add(valid_values, g_strdup(*v));
}
return valid_values;
}
int
main(int argc, char *argv[])
{
@ -246,11 +424,13 @@ main(int argc, char *argv[])
g_print(" >\n");
for (i_property = 0; i_property < sett_info->properties_num; i_property++) {
const NMMetaPropertyInfo *prop_info = sett_info->properties[i_property];
gs_free char *name = NULL;
gs_free char *alias = NULL;
gs_free char *descr = NULL;
gs_free char *fmt = NULL;
const NMMetaPropertyInfo *prop_info = sett_info->properties[i_property];
gs_free char *name = NULL;
gs_free char *alias = NULL;
gs_free char *descr = NULL;
gs_free char *fmt = NULL;
gs_unref_ptrarray GPtrArray *vals_arr = NULL;
gs_free char *vals_str = NULL;
g_print("%s<property", _indent_level(2 * INDENT));
g_print(" name=%s", name = _xml_escape_attribute(prop_info->property_name));
@ -281,6 +461,15 @@ main(int argc, char *argv[])
_indent_level(2 * INDENT + 10),
_xml_escape_attribute(fmt));
vals_arr = get_property_valid_values(prop_info);
if (vals_arr->len) {
g_ptr_array_add(vals_arr, NULL);
vals_str = g_strjoinv(", ", (char **) vals_arr->pdata);
g_print("\n%svalues=%s",
_indent_level(2 * INDENT + 10),
_xml_escape_attribute(vals_str));
}
g_print(" />\n");
}

File diff suppressed because it is too large Load diff

View file

@ -296,6 +296,7 @@ for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name):
else:
node_set_attr(property_node, "type", properties_attrs)
node_set_attr(property_node, "values", properties_attrs)
node_set_attr(property_node, "default", properties_attrs)
node_set_attr(property_node, "alias", properties_attrs)