1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
5 #include "libudev-list-internal.h"
10 * SECTION:libudev-list
11 * @short_description: list operation
13 * Libudev list operations.
19 * Opaque object representing one entry in a list. An entry contains
20 * contains a name, and optionally a value.
22 struct udev_list_entry
{
23 struct udev_list
*list
;
27 LIST_FIELDS(struct udev_list_entry
, entries
);
31 Hashmap
*unique_entries
;
32 LIST_HEAD(struct udev_list_entry
, entries
);
37 static struct udev_list_entry
*udev_list_entry_free(struct udev_list_entry
*entry
) {
42 if (entry
->list
->unique
)
43 hashmap_remove(entry
->list
->unique_entries
, entry
->name
);
45 LIST_REMOVE(entries
, entry
->list
->entries
, entry
);
54 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list_entry
*, udev_list_entry_free
);
56 struct udev_list
*udev_list_new(bool unique
) {
57 struct udev_list
*list
;
59 list
= new(struct udev_list
, 1);
63 *list
= (struct udev_list
) {
70 struct udev_list_entry
*udev_list_entry_add(struct udev_list
*list
, const char *_name
, const char *_value
) {
71 _cleanup_(udev_list_entry_freep
) struct udev_list_entry
*entry
= NULL
;
72 _cleanup_free_
char *name
= NULL
, *value
= NULL
;
82 value
= strdup(_value
);
87 entry
= new(struct udev_list_entry
, 1);
91 *entry
= (struct udev_list_entry
) {
93 .name
= TAKE_PTR(name
),
94 .value
= TAKE_PTR(value
),
98 r
= hashmap_ensure_allocated(&list
->unique_entries
, &string_hash_ops
);
102 udev_list_entry_free(hashmap_get(list
->unique_entries
, entry
->name
));
104 r
= hashmap_put(list
->unique_entries
, entry
->name
, entry
);
108 list
->uptodate
= false;
110 LIST_APPEND(entries
, list
->entries
, entry
);
112 return TAKE_PTR(entry
);
115 void udev_list_cleanup(struct udev_list
*list
) {
116 struct udev_list_entry
*i
, *n
;
122 hashmap_clear_with_destructor(list
->unique_entries
, udev_list_entry_free
);
123 list
->uptodate
= false;
125 LIST_FOREACH_SAFE(entries
, i
, n
, list
->entries
)
126 udev_list_entry_free(i
);
129 struct udev_list
*udev_list_free(struct udev_list
*list
) {
133 udev_list_cleanup(list
);
134 hashmap_free(list
->unique_entries
);
139 static int udev_list_entry_compare_func(struct udev_list_entry
* const *a
, struct udev_list_entry
* const *b
) {
140 return strcmp((*a
)->name
, (*b
)->name
);
143 struct udev_list_entry
*udev_list_get_entry(struct udev_list
*list
) {
147 if (list
->unique
&& !list
->uptodate
) {
150 LIST_HEAD_INIT(list
->entries
);
152 n
= hashmap_size(list
->unique_entries
);
156 LIST_PREPEND(entries
, list
->entries
, hashmap_first(list
->unique_entries
));
158 _cleanup_free_
struct udev_list_entry
**buf
= NULL
;
159 struct udev_list_entry
*entry
, **p
;
163 buf
= new(struct udev_list_entry
*, n
);
168 HASHMAP_FOREACH(entry
, list
->unique_entries
, i
)
171 typesafe_qsort(buf
, n
, udev_list_entry_compare_func
);
173 for (j
= n
; j
> 0; j
--)
174 LIST_PREPEND(entries
, list
->entries
, buf
[j
-1]);
177 list
->uptodate
= true;
180 return list
->entries
;
184 * udev_list_entry_get_next:
185 * @list_entry: current entry
187 * Get the next entry from the list.
189 * Returns: udev_list_entry, #NULL if no more entries are available.
191 _public_
struct udev_list_entry
*udev_list_entry_get_next(struct udev_list_entry
*list_entry
) {
194 if (list_entry
->list
->unique
&& !list_entry
->list
->uptodate
)
196 return list_entry
->entries_next
;
200 * udev_list_entry_get_by_name:
201 * @list_entry: current entry
202 * @name: name string to match
204 * Lookup an entry in the list with a certain name.
206 * Returns: udev_list_entry, #NULL if no matching entry is found.
208 _public_
struct udev_list_entry
*udev_list_entry_get_by_name(struct udev_list_entry
*list_entry
, const char *name
) {
211 if (!list_entry
->list
->unique
|| !list_entry
->list
->uptodate
)
213 return hashmap_get(list_entry
->list
->unique_entries
, name
);
217 * udev_list_entry_get_name:
218 * @list_entry: current entry
220 * Get the name of a list entry.
222 * Returns: the name string of this entry.
224 _public_
const char *udev_list_entry_get_name(struct udev_list_entry
*list_entry
) {
227 return list_entry
->name
;
231 * udev_list_entry_get_value:
232 * @list_entry: current entry
234 * Get the value of list entry.
236 * Returns: the value string of this entry.
238 _public_
const char *udev_list_entry_get_value(struct udev_list_entry
*list_entry
) {
241 return list_entry
->value
;