/**
 * nm_setting_vlan_add_priority_str
 * @setting: the #NMSettingVlan
 * @map: the type of priority map
 * @str: the string which contains a priority map, like "3:7"
 *
 * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map
 * or the #NMSettingVlan:egress_priority_map properties.  The priority map maps
 * the Linux SKB priorities to 802.1p priorities.
 *
 * Returns: TRUE if the entry was successfully added to the list, or it
 * overwrote the old value, FALSE if error
 */
gboolean
nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
                                  NMVlanPriorityMap map,
                                  const char *str)
{
	NMSettingVlanPrivate *priv = NULL;
	GSList *list = NULL, *iter = NULL;
	PriorityMap *item = NULL;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
	g_return_val_if_fail (str && str[0], FALSE);

	priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
	list = get_map (setting, map);

	item = priority_map_new_from_str (map, str);
	g_return_val_if_fail (item != NULL, FALSE);

	/* Duplicates get replaced */
	for (iter = list; iter; iter = g_slist_next (iter)) {
		PriorityMap *p = iter->data;

		if (p->from == item->from) {
			p->to = item->to;
			g_free (item);
			return TRUE;
		}
	}

	set_map (setting, map, g_slist_append (list, item));
	return TRUE;
}
/**
 * nm_setting_vlan_add_priority:
 * @map: the type of priority map
 * @setting: the #NMSettingVlan
 * @from: the priority to map to @to
 * @to: the priority to map @from to
 *
 * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or
 * #NMSettingVlan:egress_priority_map properties of the setting. If @from is
 * already in the given priority map, this function will overwrite the
 * existing entry with the new @to.
 *
 * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN
 * Priority Code Point (PCP) value, and @to is the Linux SKB priority value.
 *
 * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and
 * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value.
 *
 * Returns: TRUE if the new priority mapping was successfully added to the
 * list, FALSE if error
 */
gboolean
nm_setting_vlan_add_priority (NMSettingVlan *setting,
                              NMVlanPriorityMap map,
                              guint32 from,
                              guint32 to)
{
	GSList *list = NULL, *iter = NULL;
	PriorityMap *item;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);

	list = get_map (setting, map);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		item = iter->data;
		if (item->from == from) {
			item->to = to;
			return TRUE;
		}
	}

	item = g_malloc0 (sizeof (PriorityMap));
	item->from = from;
	item->to = to;
	set_map (setting, map, g_slist_append (list, item));

	return TRUE;
}
/**
 * nm_setting_vlan_add_priority:
 * @setting: the #NMSettingVlan
 * @map: the type of priority map
 * @from: the priority to map to @to
 * @to: the priority to map @from to
 *
 * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or
 * #NMSettingVlan:egress_priority_map properties of the setting. If @from is
 * already in the given priority map, this function will overwrite the
 * existing entry with the new @to.
 *
 * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN
 * Priority Code Point (PCP) value, and @to is the Linux SKB priority value.
 *
 * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and
 * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value.
 *
 * Returns: %TRUE if the new priority mapping was successfully added to the
 * list, %FALSE if error
 */
gboolean
nm_setting_vlan_add_priority (NMSettingVlan *setting,
                              NMVlanPriorityMap map,
                              guint32 from,
                              guint32 to)
{
	GSList *list = NULL;
	NMVlanQosMapping *item;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);

	list = get_map (setting, map);
	if (check_replace_duplicate_priority (list, from, to)) {
		if (map == NM_VLAN_INGRESS_MAP)
			g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
		else
			g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
		return TRUE;
	}

	item = g_malloc0 (sizeof (NMVlanQosMapping));
	item->from = from;
	item->to = to;
	set_map (setting, map, g_slist_insert_sorted (list, item, prio_map_compare));

	return TRUE;
}
/**
 * nm_setting_vlan_add_priority_str:
 * @setting: the #NMSettingVlan
 * @map: the type of priority map
 * @str: the string which contains a priority map, like "3:7"
 *
 * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map
 * or the #NMSettingVlan:egress_priority_map properties.  The priority map maps
 * the Linux SKB priorities to 802.1p priorities.
 *
 * Returns: %TRUE if the entry was successfully added to the list, or it
 * overwrote the old value, %FALSE if error
 */
gboolean
nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
                                  NMVlanPriorityMap map,
                                  const char *str)
{
	GSList *list = NULL;
	NMVlanQosMapping *item = NULL;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
	g_return_val_if_fail (str && str[0], FALSE);

	list = get_map (setting, map);

	item = priority_map_new_from_str (map, str);
	if (!item)
		g_return_val_if_reached (FALSE);

	/* Duplicates get replaced */
	if (check_replace_duplicate_priority (list, item->from, item->to)) {
		g_free (item);
		if (map == NM_VLAN_INGRESS_MAP)
			g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
		else
			g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
		return TRUE;
	}

	set_map (setting, map, g_slist_insert_sorted (list, item, prio_map_compare));
	return TRUE;
}
/**
 * nm_setting_vlan_get_num_priorities:
 * @map: the type of priority map
 * @setting: the #NMSettingVlan
 *
 * Returns the number of entires in the
 * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
 * properties of this setting.
 *
 * Returns: return the number of ingress/egress priority entries, -1 if error
 **/
gint32
nm_setting_vlan_get_num_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
{
	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), -1);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, -1);

	return g_slist_length (get_map (setting, map));
}
/**
 * nm_setting_vlan_clear_priorities:
 * @map: the type of priority map
 * @setting: the #NMSettingVlan
 *
 * Clear all the entires from #NMSettingVlan:ingress_priority_map or
 * #NMSettingVlan:egress_priority_map properties.
 */
void
nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
{
	GSList *list = NULL;

	g_return_if_fail (NM_IS_SETTING_VLAN (setting));
	g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);

	list = get_map (setting, map);
	nm_utils_slist_free (list, g_free);
	set_map (setting, map, NULL);
}
/**
 * nm_setting_vlan_remove_priority:
 * @map: the type of priority map
 * @setting: the #NMSettingVlan
 * @idx: the zero-based index of the priority map to remove
 *
 * Removes the priority map at index @idx from the
 * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
 * properties.
 */
void
nm_setting_vlan_remove_priority (NMSettingVlan *setting,
                                 NMVlanPriorityMap map,
                                 guint32 idx)
{
	GSList *list = NULL, *item = NULL;

	g_return_if_fail (NM_IS_SETTING_VLAN (setting));
	g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);

	list = get_map (setting, map);
	g_return_if_fail (idx < g_slist_length (list));

	item = g_slist_nth_data (list, idx);
	priority_map_free ((PriorityMap *) item);
	set_map (setting, map, g_slist_delete_link (list, item));
}
/**
 * nm_setting_vlan_remove_priority_str_by_value:
 * @setting: the #NMSettingVlan
 * @map: the type of priority map
 * @str: the string which contains a priority map, like "3:7"
 *
 * Removes the priority map @str from the #NMSettingVlan:ingress_priority_map
 * or #NMSettingVlan:egress_priority_map (according to @map argument)
 * properties.
 *
 * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
 */
gboolean
nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
                                              NMVlanPriorityMap map,
                                              const char *str)
{
	NMVlanQosMapping *item;
	gboolean found;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);

	item = priority_map_new_from_str (map, str);
	if (!item)
		return FALSE;

	found = nm_setting_vlan_remove_priority_by_value (setting, map, item->from, item->to);
	g_free (item);
	return found;
}
/**
 * nm_setting_vlan_remove_priority_by_value:
 * @setting: the #NMSettingVlan
 * @map: the type of priority map
 * @from: the priority to map to @to
 * @to: the priority to map @from to
 *
 * Removes the priority map @form:@to from the #NMSettingVlan:ingress_priority_map
 * or #NMSettingVlan:egress_priority_map (according to @map argument)
 * properties.
 *
 * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
 */
gboolean
nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
                                          NMVlanPriorityMap map,
                                          guint32 from,
                                          guint32 to)
{
	GSList *list = NULL, *iter = NULL;
	NMVlanQosMapping *item;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);

	list = get_map (setting, map);
	for (iter = list; iter; iter = g_slist_next (iter)) {
		item = iter->data;
		if (item->from == from && item->to == to) {
			priority_map_free ((NMVlanQosMapping *) (iter->data));
			set_map (setting, map, g_slist_delete_link (list, iter));
			return TRUE;
		}
	}
	return FALSE;
}
/**
 * nm_setting_vlan_get_priority:
 * @map: the type of priority map
 * @setting: the #NMSettingVlan
 * @idx: the zero-based index of the ingress/egress priority map entry
 * @out_from: (out): on return the value of the priority map's 'from' item
 * @out_to: (out): on return the value of priority map's 'to' item
 *
 * Retrieve one of the entries of the #NMSettingVlan:ingress_priority_map
 * or #NMSettingVlan:egress_priority_map properties of this setting.
 *
 * Returns: %TRUE if a priority map was returned, %FALSE if error
 **/
gboolean
nm_setting_vlan_get_priority (NMSettingVlan *setting,
                              NMVlanPriorityMap map,
                              guint32 idx,
                              guint32 *out_from,
                              guint32 *out_to)
{
	GSList *list = NULL;
	PriorityMap *item = NULL;

	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
	g_return_val_if_fail (out_from != NULL, FALSE);
	g_return_val_if_fail (out_to != NULL, FALSE);

	list = get_map (setting, map);
	g_return_val_if_fail (idx < g_slist_length (list), FALSE);

	item = g_slist_nth_data (list, idx);
	g_assert (item);
	*out_from = item->from;
	*out_to = item->to;
	return TRUE;
}
/**
 * nm_setting_vlan_get_flags:
 * @setting: the #NMSettingVlan
 *
 * Returns: the #NMSettingVlan:flags property of the setting
 **/
guint32
nm_setting_vlan_get_flags (NMSettingVlan *setting)
{
	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), 0);
	return NM_SETTING_VLAN_GET_PRIVATE (setting)->flags;
}
/**
 * nm_setting_vlan_get_parent:
 * @setting: the #NMSettingVlan
 *
 * Returns: the #NMSettingVlan:parent property of the setting
 **/
const char *
nm_setting_vlan_get_parent (NMSettingVlan *setting)
{
	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
	return NM_SETTING_VLAN_GET_PRIVATE (setting)->parent;
}
/**
 * nm_setting_vlan_get_interface_name:
 * @setting: the #NMSettingVlan
 *
 * Returns: the #NMSettingVlan:interface_name property of the setting
 **/
const char *
nm_setting_vlan_get_interface_name (NMSettingVlan *setting)
{
	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
	return NM_SETTING_VLAN_GET_PRIVATE (setting)->iface_name;
}