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
&& entry
->name
)
43 hashmap_remove(entry
->list
->unique_entries
, entry
->name
);
45 if (!entry
->list
->unique
|| entry
->list
->uptodate
)
46 LIST_REMOVE(entries
, entry
->list
->entries
, entry
);
55 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list_entry
*, udev_list_entry_free
);
57 struct udev_list
*udev_list_new(bool unique
) {
58 struct udev_list
*list
;
60 list
= new(struct udev_list
, 1);
64 *list
= (struct udev_list
) {
71 struct udev_list_entry
*udev_list_entry_add(struct udev_list
*list
, const char *_name
, const char *_value
) {
72 _cleanup_(udev_list_entry_freep
) struct udev_list_entry
*entry
= NULL
;
73 _cleanup_free_
char *name
= NULL
, *value
= NULL
;
83 value
= strdup(_value
);
88 entry
= new(struct udev_list_entry
, 1);
92 *entry
= (struct udev_list_entry
) {
93 .name
= TAKE_PTR(name
),
94 .value
= TAKE_PTR(value
),
98 udev_list_entry_free(hashmap_get(list
->unique_entries
, entry
->name
));
100 if (hashmap_ensure_put(&list
->unique_entries
, &string_hash_ops
, entry
->name
, entry
) < 0)
103 list
->uptodate
= false;
105 LIST_APPEND(entries
, list
->entries
, entry
);
109 return TAKE_PTR(entry
);
112 void udev_list_cleanup(struct udev_list
*list
) {
117 list
->uptodate
= false;
118 hashmap_clear_with_destructor(list
->unique_entries
, udev_list_entry_free
);
120 LIST_FOREACH(entries
, i
, list
->entries
)
121 udev_list_entry_free(i
);
124 struct udev_list
*udev_list_free(struct udev_list
*list
) {
128 udev_list_cleanup(list
);
129 hashmap_free(list
->unique_entries
);
134 static int udev_list_entry_compare_func(struct udev_list_entry
* const *a
, struct udev_list_entry
* const *b
) {
135 return strcmp((*a
)->name
, (*b
)->name
);
138 struct udev_list_entry
*udev_list_get_entry(struct udev_list
*list
) {
142 if (list
->unique
&& !list
->uptodate
) {
145 LIST_HEAD_INIT(list
->entries
);
147 n
= hashmap_size(list
->unique_entries
);
151 LIST_PREPEND(entries
, list
->entries
, hashmap_first(list
->unique_entries
));
153 _cleanup_free_
struct udev_list_entry
**buf
= NULL
;
154 struct udev_list_entry
*entry
, **p
;
156 buf
= new(struct udev_list_entry
*, n
);
161 HASHMAP_FOREACH(entry
, list
->unique_entries
)
164 typesafe_qsort(buf
, n
, udev_list_entry_compare_func
);
166 for (size_t j
= n
; j
> 0; j
--)
167 LIST_PREPEND(entries
, list
->entries
, buf
[j
-1]);
170 list
->uptodate
= true;
173 return list
->entries
;
177 * udev_list_entry_get_next:
178 * @list_entry: current entry
180 * Get the next entry from the list.
182 * Returns: udev_list_entry, #NULL if no more entries are available.
184 _public_
struct udev_list_entry
*udev_list_entry_get_next(struct udev_list_entry
*list_entry
) {
187 if (list_entry
->list
->unique
&& !list_entry
->list
->uptodate
)
189 return list_entry
->entries_next
;
193 * udev_list_entry_get_by_name:
194 * @list_entry: current entry
195 * @name: name string to match
197 * Lookup an entry in the list with a certain name.
199 * Returns: udev_list_entry, #NULL if no matching entry is found.
201 _public_
struct udev_list_entry
*udev_list_entry_get_by_name(struct udev_list_entry
*list_entry
, const char *name
) {
204 if (!list_entry
->list
->unique
|| !list_entry
->list
->uptodate
)
206 return hashmap_get(list_entry
->list
->unique_entries
, name
);
210 * udev_list_entry_get_name:
211 * @list_entry: current entry
213 * Get the name of a list entry.
215 * Returns: the name string of this entry.
217 _public_
const char *udev_list_entry_get_name(struct udev_list_entry
*list_entry
) {
220 return list_entry
->name
;
224 * udev_list_entry_get_value:
225 * @list_entry: current entry
227 * Get the value of list entry.
229 * Returns: the value string of this entry.
231 _public_
const char *udev_list_entry_get_value(struct udev_list_entry
*list_entry
) {
234 return list_entry
->value
;