/*
* Copyright © 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Christian J. Kellner
*/
#include "config.h"
#include "bolt-enums.h"
#include "bolt-error.h"
#include
#if !GLIB_CHECK_VERSION(2, 57, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
#endif
gboolean
bolt_enum_class_validate (GEnumClass *enum_class,
gint value,
GError **error)
{
const char *name;
gboolean oob;
if (enum_class == NULL)
{
name = g_type_name_from_class ((GTypeClass *) enum_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"could not determine enum class for '%s'",
name);
return FALSE;
}
oob = value < enum_class->minimum || value > enum_class->maximum;
if (oob)
{
name = g_type_name_from_class ((GTypeClass *) enum_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"enum value '%d' is out of bounds for '%s'",
value, name);
return FALSE;
}
return TRUE;
}
gboolean
bolt_enum_validate (GType enum_type,
gint value,
GError **error)
{
g_autoptr(GEnumClass) klass = g_type_class_ref (enum_type);
return bolt_enum_class_validate (klass, value, error);
}
const char *
bolt_enum_to_string (GType enum_type,
gint value,
GError **error)
{
g_autoptr(GEnumClass) klass = NULL;
GEnumValue *ev;
klass = g_type_class_ref (enum_type);
if (!bolt_enum_class_validate (klass, value, error))
return NULL;
ev = g_enum_get_value (klass, value);
return ev->value_nick;
}
gint
bolt_enum_from_string (GType enum_type,
const char *string,
GError **error)
{
g_autoptr(GEnumClass) klass = NULL;
const char *name;
GEnumValue *ev;
klass = g_type_class_ref (enum_type);
if (klass == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"could not determine enum class");
return -1;
}
if (string == NULL)
{
name = g_type_name_from_class ((GTypeClass *) klass);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"empty string passed for enum class for '%s'",
name);
return -1;
}
ev = g_enum_get_value_by_nick (klass, string);
if (ev == NULL)
{
name = g_type_name (enum_type);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"invalid string '%s' for enum '%s'", string, name);
return -1;
}
return ev->value;
}
char *
bolt_flags_class_to_string (GFlagsClass *flags_class,
guint value,
GError **error)
{
g_autoptr(GString) str = NULL;
const char *name;
GFlagsValue *fv;
if (flags_class == NULL)
{
name = g_type_name_from_class ((GTypeClass *) flags_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"could not determine flags class for '%s'",
name);
return FALSE;
}
fv = g_flags_get_first_value (flags_class, value);
if (fv == NULL)
{
if (value == 0)
return g_strdup ("");
name = g_type_name_from_class ((GTypeClass *) flags_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"invalid value '%u' for flags '%s'", value, name);
return NULL;
}
value &= ~fv->value;
str = g_string_new (fv->value_nick);
while (value != 0 &&
(fv = g_flags_get_first_value (flags_class, value)) != NULL)
{
g_string_append (str, " | ");
g_string_append (str, fv->value_nick);
value &= ~fv->value;
}
if (value != 0)
{
name = g_type_name_from_class ((GTypeClass *) flags_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"unhandled value '%u' for flags '%s'", value, name);
return NULL;
}
return g_string_free (g_steal_pointer (&str), FALSE);
}
gboolean
bolt_flags_class_from_string (GFlagsClass *flags_class,
const char *string,
guint *flags_out,
GError **error)
{
g_auto(GStrv) vals = NULL;
const char *name;
guint flags = 0;
if (flags_class == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"could not determine flags class");
return FALSE;
}
if (string == NULL)
{
name = g_type_name_from_class ((GTypeClass *) flags_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"empty string passed for flags class for '%s'",
name);
return FALSE;
}
vals = g_strsplit (string, "|", -1);
for (guint i = 0; vals[i]; i++)
{
GFlagsValue *fv;
char *nick;
nick = g_strstrip (vals[i]);
fv = g_flags_get_value_by_nick (flags_class, nick);
if (fv == NULL)
{
name = g_type_name_from_class ((GTypeClass *) flags_class);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"invalid flag '%s' for flags '%s'", string, name);
return FALSE;
}
flags |= fv->value;
}
if (flags_out != NULL)
*flags_out = flags;
return TRUE;
}
char *
bolt_flags_to_string (GType flags_type,
guint value,
GError **error)
{
g_autoptr(GFlagsClass) klass = NULL;
klass = g_type_class_ref (flags_type);
return bolt_flags_class_to_string (klass, value, error);
}
gboolean
bolt_flags_from_string (GType flags_type,
const char *string,
guint *flags_out,
GError **error)
{
g_autoptr(GFlagsClass) klass = NULL;
klass = g_type_class_ref (flags_type);
return bolt_flags_class_from_string (klass, string, flags_out, error);
}
gboolean
bolt_flags_update (guint from,
guint *to,
guint mask)
{
guint val;
gboolean chg;
g_return_val_if_fail (to != NULL, FALSE);
val = *to & ~mask; /* clear all bits in mask */
val = val | (from & mask); /* set all bits in from and mask */
chg = *to != val;
*to = val;
return chg;
}
const char *
bolt_status_to_string (BoltStatus status)
{
return bolt_enum_to_string (BOLT_TYPE_STATUS, status, NULL);
}
gboolean
bolt_status_is_authorized (BoltStatus status)
{
return status == BOLT_STATUS_AUTHORIZED ||
status == BOLT_STATUS_AUTHORIZED_SECURE ||
status == BOLT_STATUS_AUTHORIZED_NEWKEY;
}
gboolean
bolt_status_is_pending (BoltStatus status)
{
return status == BOLT_STATUS_AUTH_ERROR ||
status == BOLT_STATUS_CONNECTED;
}
gboolean
bolt_status_validate (BoltStatus status)
{
return bolt_enum_validate (BOLT_TYPE_STATUS, status, NULL);
}
gboolean
bolt_status_is_connected (BoltStatus status)
{
return status > BOLT_STATUS_DISCONNECTED;
}
BoltSecurity
bolt_security_from_string (const char *str)
{
return bolt_enum_from_string (BOLT_TYPE_SECURITY, str, NULL);
}
const char *
bolt_security_to_string (BoltSecurity security)
{
return bolt_enum_to_string (BOLT_TYPE_SECURITY, security, NULL);
}
gboolean
bolt_security_validate (BoltSecurity security)
{
return bolt_enum_validate (BOLT_TYPE_SECURITY, security, NULL);
}
gboolean
bolt_security_allows_pcie (BoltSecurity security)
{
gboolean pcie = FALSE;
switch (security)
{
case BOLT_SECURITY_NONE:
case BOLT_SECURITY_USER:
case BOLT_SECURITY_SECURE:
pcie = TRUE;
break;
case BOLT_SECURITY_DPONLY:
case BOLT_SECURITY_USBONLY:
case BOLT_SECURITY_UNKNOWN:
pcie = FALSE;
break;
}
return pcie;
}
BoltPolicy
bolt_policy_from_string (const char *str)
{
return bolt_enum_from_string (BOLT_TYPE_POLICY, str, NULL);
}
const char *
bolt_policy_to_string (BoltPolicy policy)
{
return bolt_enum_to_string (BOLT_TYPE_POLICY, policy, NULL);
}
gboolean
bolt_policy_validate (BoltPolicy policy)
{
return bolt_enum_validate (BOLT_TYPE_POLICY, policy, NULL);
}
BoltDeviceType
bolt_device_type_from_string (const char *str)
{
return bolt_enum_from_string (BOLT_TYPE_DEVICE_TYPE, str, NULL);
}
const char *
bolt_device_type_to_string (BoltDeviceType type)
{
return bolt_enum_to_string (BOLT_TYPE_DEVICE_TYPE, type, NULL);
}
gboolean
bolt_device_type_validate (BoltDeviceType type)
{
return bolt_enum_validate (BOLT_TYPE_DEVICE_TYPE, type, NULL);
}
gboolean
bolt_device_type_is_host (BoltDeviceType type)
{
return type == BOLT_DEVICE_HOST;
}