1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
;
162 buf
= new(struct udev_list_entry
*, n
);
167 HASHMAP_FOREACH(entry
, list
->unique_entries
)
170 typesafe_qsort(buf
, n
, udev_list_entry_compare_func
);
172 for (j
= n
; j
> 0; j
--)
173 LIST_PREPEND(entries
, list
->entries
, buf
[j
-1]);
176 list
->uptodate
= true;
179 return list
->entries
;
183 * udev_list_entry_get_next:
184 * @list_entry: current entry
186 * Get the next entry from the list.
188 * Returns: udev_list_entry, #NULL if no more entries are available.
190 _public_
struct udev_list_entry
*udev_list_entry_get_next(struct udev_list_entry
*list_entry
) {
193 if (list_entry
->list
->unique
&& !list_entry
->list
->uptodate
)
195 return list_entry
->entries_next
;
199 * udev_list_entry_get_by_name:
200 * @list_entry: current entry
201 * @name: name string to match
203 * Lookup an entry in the list with a certain name.
205 * Returns: udev_list_entry, #NULL if no matching entry is found.
207 _public_
struct udev_list_entry
*udev_list_entry_get_by_name(struct udev_list_entry
*list_entry
, const char *name
) {
210 if (!list_entry
->list
->unique
|| !list_entry
->list
->uptodate
)
212 return hashmap_get(list_entry
->list
->unique_entries
, name
);
216 * udev_list_entry_get_name:
217 * @list_entry: current entry
219 * Get the name of a list entry.
221 * Returns: the name string of this entry.
223 _public_
const char *udev_list_entry_get_name(struct udev_list_entry
*list_entry
) {
226 return list_entry
->name
;
230 * udev_list_entry_get_value:
231 * @list_entry: current entry
233 * Get the value of list entry.
235 * Returns: the value string of this entry.
237 _public_
const char *udev_list_entry_get_value(struct udev_list_entry
*list_entry
) {
240 return list_entry
->value
;