4 This file is part of PulseAudio.
6 Copyright 2007 Lennart Poettering
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <pulse/xmalloc.h>
31 #include <pulse/utf8.h>
33 #include <pulsecore/hashmap.h>
34 #include <pulsecore/strbuf.h>
35 #include <pulsecore/core-util.h>
45 #define MAKE_HASHMAP(p) ((pa_hashmap*) (p))
46 #define MAKE_PROPLIST(p) ((pa_proplist*) (p))
48 static pa_bool_t
property_name_valid(const char *key
) {
50 if (!pa_utf8_valid(key
))
59 static void property_free(struct property
*prop
) {
63 pa_xfree(prop
->value
);
67 pa_proplist
* pa_proplist_new(void) {
68 return MAKE_PROPLIST(pa_hashmap_new(pa_idxset_string_hash_func
, pa_idxset_string_compare_func
));
71 void pa_proplist_free(pa_proplist
* p
) {
75 pa_hashmap_free(MAKE_HASHMAP(p
), NULL
, NULL
);
78 /** Will accept only valid UTF-8 */
79 int pa_proplist_sets(pa_proplist
*p
, const char *key
, const char *value
) {
80 struct property
*prop
;
81 pa_bool_t add
= FALSE
;
86 if (!property_name_valid(key
) || !pa_utf8_valid(value
))
89 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
))) {
90 prop
= pa_xnew(struct property
, 1);
91 prop
->key
= pa_xstrdup(key
);
94 pa_xfree(prop
->value
);
96 prop
->value
= pa_xstrdup(value
);
97 prop
->nbytes
= strlen(value
)+1;
100 pa_hashmap_put(MAKE_HASHMAP(p
), prop
->key
, prop
);
105 int pa_proplist_set(pa_proplist
*p
, const char *key
, const void *data
, size_t nbytes
) {
106 struct property
*prop
;
107 pa_bool_t add
= FALSE
;
112 if (!property_name_valid(key
))
115 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
))) {
116 prop
= pa_xnew(struct property
, 1);
117 prop
->key
= pa_xstrdup(key
);
120 pa_xfree(prop
->value
);
122 prop
->value
= pa_xmemdup(data
, nbytes
);
123 prop
->nbytes
= nbytes
;
126 pa_hashmap_put(MAKE_HASHMAP(p
), prop
->key
, prop
);
131 const char *pa_proplist_gets(pa_proplist
*p
, const char *key
) {
132 struct property
*prop
;
137 if (!property_name_valid(key
))
140 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
143 if (prop
->nbytes
<= 0)
146 if (((char*) prop
->value
)[prop
->nbytes
-1] != 0)
149 if (strlen((char*) prop
->value
) != prop
->nbytes
-1)
152 if (!pa_utf8_valid((char*) prop
->value
))
155 return (char*) prop
->value
;
158 int pa_proplist_get(pa_proplist
*p
, const char *key
, const void **data
, size_t *nbytes
) {
159 struct property
*prop
;
164 if (!property_name_valid(key
))
167 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
171 *nbytes
= prop
->nbytes
;
176 void pa_proplist_update(pa_proplist
*p
, pa_update_mode_t mode
, pa_proplist
*other
) {
177 struct property
*prop
;
181 pa_assert(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
);
184 if (mode
== PA_UPDATE_SET
)
185 pa_proplist_clear(p
);
187 while ((prop
= pa_hashmap_iterate(MAKE_HASHMAP(other
), &state
, NULL
))) {
189 if (mode
== PA_UPDATE_MERGE
&& pa_proplist_contains(p
, prop
->key
))
192 pa_assert_se(pa_proplist_set(p
, prop
->key
, prop
->value
, prop
->nbytes
) == 0);
196 int pa_proplist_unset(pa_proplist
*p
, const char *key
) {
197 struct property
*prop
;
202 if (!property_name_valid(key
))
205 if (!(prop
= pa_hashmap_remove(MAKE_HASHMAP(p
), key
)))
212 int pa_proplist_unset_many(pa_proplist
*p
, const char * const keys
[]) {
213 const char * const * k
;
219 for (k
= keys
; *k
; k
++)
220 if (!property_name_valid(*k
))
223 for (k
= keys
; *k
; k
++)
224 if (pa_proplist_unset(p
, *k
) >= 0)
230 const char *pa_proplist_iterate(pa_proplist
*p
, void **state
) {
231 struct property
*prop
;
233 if (!(prop
= pa_hashmap_iterate(MAKE_HASHMAP(p
), state
, NULL
)))
239 char *pa_proplist_to_string(pa_proplist
*p
) {
246 buf
= pa_strbuf_new();
248 while ((key
= pa_proplist_iterate(p
, &state
))) {
252 if ((v
= pa_proplist_gets(p
, key
)))
253 pa_strbuf_printf(buf
, "%s = \"%s\"\n", key
, v
);
259 pa_assert_se(pa_proplist_get(p
, key
, &value
, &nbytes
) == 0);
260 c
= pa_xnew(char, nbytes
*2+1);
261 pa_hexstr((const uint8_t*) value
, nbytes
, c
, nbytes
*2+1);
263 pa_strbuf_printf(buf
, "%s = hex:%s\n", key
, c
);
268 return pa_strbuf_tostring_free(buf
);
271 int pa_proplist_contains(pa_proplist
*p
, const char *key
) {
275 if (!property_name_valid(key
))
278 if (!(pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
284 void pa_proplist_clear(pa_proplist
*p
) {
285 struct property
*prop
;
288 while ((prop
= pa_hashmap_steal_first(MAKE_HASHMAP(p
))))
292 pa_proplist
* pa_proplist_copy(pa_proplist
*template) {
295 pa_assert_se(p
= pa_proplist_new());
298 pa_proplist_update(p
, PA_UPDATE_REPLACE
, template);