mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 04:24:32 +00:00
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:
parent
af5c1c8019
commit
925d4df801
|
@ -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>
|
||||
|
|
|
@ -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];
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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,7 +1419,6 @@ _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;
|
||||
|
@ -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);
|
||||
|
@ -1631,24 +1687,10 @@ 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;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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[])
|
||||
{
|
||||
|
@ -251,6 +429,8 @@ main(int argc, char *argv[])
|
|||
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
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue